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);
}
}