export class AbbreviationTooltips extends HTMLElement { static get observedAttributes() { return ["data-text", "data-abbrevmap"]; } static get defaultAbbrevMap() { return { "#": "Hinweis auf weitere Informationen in der Anmerkung.", $: "vermutlich", "+++": "Inhalte aus mehreren Almanachen interpoliert", B: "Blatt", BB: "Blätter", C: "Corrigenda", Diagr: "Diagramm", G: "Graphik", "G-Verz": "Verzeichnis der Kupfer u. ä.", GG: "Graphiken", Hrsg: "Herausgeber", "I-Verz": "Inhaltsverzeichnis", Kal: "Kalendarium", Kr: "Karte", MusB: "Musikbeigabe", MusBB: "Musikbeigaben", S: "Seite", SS: "Seiten", Sp: "Spiegel", T: "Titel", TG: "Titelgraphik, Titelportrait etc", "TG r": "Titelgraphik, Titelportrait etc recto", "TG v": "Titelgraphik, Titelportrait etc verso", Tab: "Tabelle", UG: "Umschlaggraphik", "UG r": "Umschlaggraphik recto", "UG v": "Umschlaggraphik verso", VB: "Vorsatzblatt", Vf: "Verfasser", VrlgM: "Verlagsmitteilung", Vrwrt: "Vorwort", ar: "arabische Paginierung", ar1: "erste arabische Paginierung", ar2: "zweite arabische Paginierung", ar3: "dritte arabische Paginierung", ar4: "vierte arabische Paginierung", ar5: "fünfte arabische Paginierung", ar6: "sechste arabische Paginierung", ar7: "siebte arabische Paginierung", gA: "graphische Anleitung", gT: "graphischer Titel", gTzA: "graphische Tanzanleitung", nT: "Nachtitel", röm: "römische Paginierung", röm1: "erste römische Paginierung", röm2: "zweite römische Paginierung", röm3: "dritte römische Paginierung", röm4: "vierte römische Paginierung", röm5: "fünfte römische Paginierung", röm6: "sechste römische Paginierung", röm7: "siebte römische Paginierung", vT: "Vortitel", zT: "Zwischentitel", "§§": "Hinweis auf Mängel im Almanach (Beschädigungen, fehlende Graphiken, unvollständige Sammlungen etc) in der Anmerkung", }; } constructor() { super(); this._abbrevMap = AbbreviationTooltips.defaultAbbrevMap; } connectedCallback() { this.render(); } attributeChangedCallback(name, oldVal, newVal) { if (oldVal !== newVal) { if (name === "data-abbrevmap") { this._parseAndSetAbbrevMap(newVal); } this.render(); } } _parseAndSetAbbrevMap(jsonStr) { if (!jsonStr) { this._abbrevMap = AbbreviationTooltips.defaultAbbrevMap; return; } try { this._abbrevMap = JSON.parse(jsonStr); } catch { this._abbrevMap = AbbreviationTooltips.defaultAbbrevMap; } } setAbbrevMap(map) { if (typeof map === "object" && map !== null) { this._abbrevMap = map; this.render(); } } get text() { return this.getAttribute("data-text") || ""; } set text(value) { this.setAttribute("data-text", value); } render() { this.innerHTML = this.transformText(this.text, this._abbrevMap); } transformText(text, abbrevMap) { let result = ""; let i = 0; while (i < text.length) { // Only match if at start of text or preceded by a boundary character if (i > 0 && !this.isSpaceOrPunct(text[i - 1])) { result += text[i]; i++; continue; } const matchObj = this.findLongestAbbrevAt(text, i, abbrevMap); if (matchObj) { const { match, meaning } = matchObj; result += `
${meaning}
${match}
`; i += match.length; } else { result += text[i]; i++; } } return result; } findLongestAbbrevAt(text, i, abbrevMap) { let bestKey = null; let bestLength = 0; for (const key of Object.keys(abbrevMap)) { if (text.startsWith(key, i)) { if (key.length > bestLength) { bestKey = key; bestLength = key.length; } } } if (bestKey) { return { match: bestKey, meaning: abbrevMap[bestKey] }; } return null; } isSpaceOrPunct(ch) { // Adjust if you want a different set of punctuation recognized return /\s|[.,;:!?]/.test(ch); } }