Created
May 22, 2023 13:44
-
-
Save Caellian/7c20bb4c75c255b63fcf9c5c160a488e to your computer and use it in GitHub Desktop.
Obsidian dictionary view
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
.dictionary-view { | |
display: contents; | |
} | |
.dictionary-view * { | |
box-sizing: border-box; | |
padding: 0; | |
margin: 0; | |
} | |
.dictionary-view .search-bar { | |
display: flex; | |
margin-inline: auto; | |
align-items: center; | |
width: fit-content; | |
max-width: 100%; | |
height: fit-content; | |
gap: 0.25rem; | |
padding: 0.5rem; | |
padding-left: 2rem; | |
background-color: var(--background-secondary-alt); | |
border-radius: 100vh; | |
} | |
.dictionary-view .search-bar input[type="search"] { | |
display: inline-block; | |
background-color: var(--color-base-10); | |
width: 100%; | |
max-width: 40vw; | |
border: none; | |
outline: none; | |
border-bottom: 2px solid var(--color-accent); | |
border-radius: 0.2rem 0.2rem 0 0; | |
font-size: 1.2rem; | |
} | |
.dictionary-view .search-bar svg { | |
height: 2rem; | |
aspect-ratio: 1 / 1; | |
fill: var(--color-accent); | |
} | |
.dictionary-view table { | |
width: 100%; | |
} | |
.dictionary-view ul.results { | |
display: flex; | |
flex-direction: column; | |
gap: 0.2rem; | |
list-style: none; | |
} | |
.dictionary-view h6.letter-group { | |
font-size: 2rem; | |
color: var(--color-accent); | |
margin-block: 1rem; | |
padding-inline: 0.5rem; | |
border-bottom: 2px solid var(--color-base-10); | |
} | |
.dictionary-view .word { | |
display: grid; | |
grid-template-columns: 2fr auto 5fr; | |
} | |
.dictionary-view .word .name { | |
text-decoration: none; | |
} | |
.dictionary-view .word .name span { | |
font-weight: bold; | |
} | |
.dictionary-view .word .icon { | |
fill: var(--background-secondary-alt); | |
width: 2rem; | |
height: 2rem; | |
} | |
.dictionary-view .word .icon.menu-right { | |
fill: var(--color-accent); | |
} | |
.dictionary-view .word .translations { | |
display: flex; | |
gap: 1rem; | |
align-items: flex-start; | |
padding: 0.5rem; | |
height: min-content; | |
background-color: var(--color-base-10); | |
border-radius: 0.25rem; | |
} | |
.dictionary-view .word .translations .icon.translate { | |
display: inline-block; | |
fill: var(--color-blue); | |
flex-shrink: 0; | |
width: 1.25em; | |
height: 1.25em; | |
} | |
.dictionary-view .word .translations ul { | |
flex-grow: 1; | |
display: flex; | |
flex-wrap: wrap; | |
gap: 0.25rem; | |
list-style: none; | |
} | |
.dictionary-view .word .translations ul li { | |
background-color: var(--color-base-20); | |
padding: 0.25rem 0.5rem; | |
border-radius: 0.25rem; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const {} = input; | |
const IconMagnify = | |
'<svg class="icon magnify" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><title>magnify</title><path d="M9.5,3A6.5,6.5 0 0,1 16,9.5C16,11.11 15.41,12.59 14.44,13.73L14.71,14H15.5L20.5,19L19,20.5L14,15.5V14.71L13.73,14.44C12.59,15.41 11.11,16 9.5,16A6.5,6.5 0 0,1 3,9.5A6.5,6.5 0 0,1 9.5,3M9.5,5C7,5 5,7 5,9.5C5,12 7,14 9.5,14C12,14 14,12 14,9.5C14,7 12,5 9.5,5Z" /></svg>'; | |
const IconTranslate = | |
'<svg class="icon translate" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><title>translate</title><path d="M12.87,15.07L10.33,12.56L10.36,12.53C12.1,10.59 13.34,8.36 14.07,6H17V4H10V2H8V4H1V6H12.17C11.5,7.92 10.44,9.75 9,11.35C8.07,10.32 7.3,9.19 6.69,8H4.69C5.42,9.63 6.42,11.17 7.67,12.56L2.58,17.58L4,19L9,14L12.11,17.11L12.87,15.07M18.5,10H16.5L12,22H14L15.12,19H19.87L21,22H23L18.5,10M15.88,17L17.5,12.67L19.12,17H15.88Z" /></svg>'; | |
const IconMenuRight = | |
'<svg class="icon menu-right" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><title>menu-right</title><path d="M10,17L15,12L10,7V17Z" /></svg>'; | |
/** | |
* | |
*/ | |
class Word { | |
constructor(value, definition, translations) { | |
this.value = value; | |
this.definition = definition; | |
this.translations = translations; | |
} | |
} | |
function renderTranslation(word, filter = "") { | |
let [key, value, source] = word; | |
let wordName = ""; | |
if (filter === "") { | |
wordName = `<a class="name internal-link" href="${source}">${key}</a>`; | |
} else { | |
const index = key.toLowerCase().indexOf(filter.toLowerCase()); | |
const before = key.slice(0, index); | |
const found = key.slice(index, index + filter.length); | |
const after = key.slice(index + filter.length); | |
wordName = `<a class="name internal-link" href="${source}">${before}<span>${found}</span>${after}</a>`; | |
} | |
const valueList = value | |
.split(",") | |
.map((it) => `<li>${it.trim()}</li>`) | |
.join(""); | |
return `<li class="word">${wordName}${IconMenuRight}<div class="translations">${IconTranslate}<ul>${valueList}</ul></div></li>`; | |
} | |
function buildDictionary() { | |
const translationFiles = dv.pagePaths("#translation"); | |
const words = {}; | |
for (const source of translationFiles) { | |
// if d source and target language ok | |
const pageLists = dv.page(source).file.lists; | |
for (const line of pageLists) { | |
let text = line.text; | |
if (text.toLowerCase().includes("#translation") && text.includes("->")) { | |
text = text.replace("#translation", ""); | |
let [key, value] = text.split("->"); | |
key = key.trim(); | |
value = value.trim(); | |
let first = key.toLowerCase().charAt(0); | |
if (first in words) { | |
words[first].push([key, value, source]); | |
} else { | |
words[first] = [[key, value, source]]; | |
} | |
} | |
} | |
} | |
return { | |
words, | |
render: function (filter = "") { | |
var result = []; | |
for (const letter of Object.keys(words)) { | |
const drawn = words[letter].filter(([key]) => | |
key.toLowerCase().includes(filter.toLowerCase()) | |
); | |
if (drawn.length > 0) { | |
result.push(`<h6 class="letter-group">${letter.toUpperCase()}</h6>`); | |
for (const word of drawn) { | |
result.push(renderTranslation(word, filter)); | |
} | |
} | |
} | |
return result.join(""); | |
}, | |
}; | |
} | |
const dictionary = buildDictionary(); | |
const content = dv.el( | |
"div", | |
`<div class="search-bar"><input type="search"/>${IconMagnify}</div><ul class="results">${dictionary.render()}</ul>`, | |
{ | |
cls: "dictionary-view", | |
} | |
); | |
const resultList = content.querySelector(".results"); | |
function onSearchChange(e) { | |
resultList.innerHTML = `${dictionary.render(e.target.value)}`; | |
} | |
const searchInput = content.querySelector('input[type="search"]'); | |
searchInput.addEventListener("input", onSearchChange); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment