generated from boboko/starter
61 lines
2.4 KiB
JavaScript
61 lines
2.4 KiB
JavaScript
/**
|
||
* Strip Greek tonos (accent marks) from text inside elements that have the
|
||
* `uppercase` CSS class.
|
||
*
|
||
* In Greek typography, capital letters do not carry the tonos accent.
|
||
* CSS `text-transform: uppercase` uppercases the glyph but leaves the tonos
|
||
* in place, producing visually incorrect output (e.g. Ά instead of Α).
|
||
* This utility rewrites the text nodes directly so the rendered result is clean.
|
||
*
|
||
* The diaeresis (ϊ, ϋ) is preserved — it is retained in Greek uppercase.
|
||
*
|
||
* Runs once on DOMContentLoaded and then watches for dynamically added nodes
|
||
* via MutationObserver.
|
||
*/
|
||
|
||
const ACCENT_MAP = {
|
||
// Lowercase with tonos → without tonos
|
||
'ά': 'α', 'έ': 'ε', 'ή': 'η', 'ί': 'ι', 'ό': 'ο', 'ύ': 'υ', 'ώ': 'ω',
|
||
// Uppercase with tonos → without tonos (for already-uppercased text)
|
||
'Ά': 'Α', 'Έ': 'Ε', 'Ή': 'Η', 'Ί': 'Ι', 'Ό': 'Ο', 'Ύ': 'Υ', 'Ώ': 'Ω',
|
||
// Combined tonos + diaeresis → diaeresis only (preserve the diaeresis)
|
||
'ΐ': 'ϊ', 'ΰ': 'ϋ',
|
||
}
|
||
|
||
const ACCENT_RE = /[άέήίόύώΆΈΉΊΌΎΏΐΰ]/g
|
||
|
||
function stripAccents(str) {
|
||
return str.replace(ACCENT_RE, c => ACCENT_MAP[c] ?? c)
|
||
}
|
||
|
||
function processElement(el) {
|
||
const walker = document.createTreeWalker(el, NodeFilter.SHOW_TEXT)
|
||
let node
|
||
while ((node = walker.nextNode())) {
|
||
const val = node.nodeValue
|
||
if (val && /[άέήίόύώΆΈΉΊΌΎΏΐΰ]/.test(val)) {
|
||
node.nodeValue = stripAccents(val)
|
||
}
|
||
}
|
||
}
|
||
|
||
function applyToPage() {
|
||
document.querySelectorAll('.uppercase').forEach(processElement)
|
||
}
|
||
|
||
// ── Initial pass ──────────────────────────────────────────────────────────────
|
||
document.addEventListener('DOMContentLoaded', applyToPage)
|
||
|
||
// ── Observe dynamic additions ─────────────────────────────────────────────────
|
||
const observer = new MutationObserver(mutations => {
|
||
for (const { addedNodes } of mutations) {
|
||
for (const node of addedNodes) {
|
||
if (node.nodeType !== Node.ELEMENT_NODE) continue
|
||
if (node.classList?.contains('uppercase')) processElement(node)
|
||
node.querySelectorAll?.('.uppercase').forEach(processElement)
|
||
}
|
||
}
|
||
})
|
||
|
||
observer.observe(document.body, { childList: true, subtree: true })
|