Files
3dealer/resources/js/utils/strip-accents.js
T

61 lines
2.4 KiB
JavaScript
Raw Normal View History

2026-07-31 17:41:55 +03:00
/**
* 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 })