Skip to content

Commit a512e48

Browse files
committed
DAB: Parse xml string as html
Per sillsdev/app-builders#2219 (comment)
1 parent 367ad79 commit a512e48

1 file changed

Lines changed: 7 additions & 15 deletions

File tree

src/lib/lexicon/components/EntryView.svelte

Lines changed: 7 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -63,27 +63,19 @@
6363
}
6464
6565
const parser = new DOMParser();
66-
// TODO: find better solution for <default font> replacement (this was causing xml parse errors)
67-
const xmlDoc = parser.parseFromString(
68-
xmlString.replaceAll("'<default font>',", ''),
69-
'text/xml'
70-
);
66+
// parse as HTML instead of XML. HTML parsing is very forgiving, so we won't really get any parse errors
67+
const htmlDoc = parser.parseFromString(xmlString, 'text/html');
7168
7269
// Collect audio elements to add at the end
7370
// eslint-disable-next-line svelte/prefer-svelte-reactivity
7471
const audioElements = new Map<string, string>();
7572
76-
const parseError = xmlDoc.querySelector('parsererror');
77-
if (parseError) {
78-
console.error('XML parsing error:', parseError.textContent);
79-
return `<span class="text-error">Error parsing XML: Invalid format</span>`;
80-
}
81-
8273
function processNode(node: Node, parentHasSenseNumber = false): string {
8374
if (node.nodeType === Node.TEXT_NODE) {
8475
return node.nodeValue?.trim() ?? '';
8576
} else if (node.nodeType === Node.ELEMENT_NODE) {
8677
const el = node as HTMLElement;
78+
const tagName = el.tagName.toLowerCase();
8779
let isSenseNumber = el.classList.contains('sensenumber');
8880
8981
let parentContainsSenseNumber =
@@ -92,7 +84,7 @@
9284
child.classList.contains('sensenumber')
9385
);
9486
95-
if (el.tagName === 'a' && el.hasAttribute('href')) {
87+
if (tagName === 'a' && el.hasAttribute('href')) {
9688
const href = el.getAttribute('href');
9789
let dataAttributes = '';
9890
let linkText = el.childNodes
@@ -116,7 +108,7 @@
116108
} else {
117109
return createElementString(el, parentContainsSenseNumber || isSenseNumber);
118110
}
119-
} else if (el.tagName === 'audio-link' && el.hasAttribute('src')) {
111+
} else if (tagName === 'audio-link' && el.hasAttribute('src')) {
120112
// Handle audio-link tag - create audio element and clickable link
121113
const audioFile = el.getAttribute('src');
122114
const src = clips[`./${audioFile}`] ?? 'clips/' + audioFile;
@@ -127,7 +119,7 @@
127119
128120
// Add just the inline clickable icon - no audio element here
129121
return `<button type="button" class="audio-link" data-audio-id="${audioId}" aria-label="Play audio" style="display: inline-block; vertical-align: middle; margin: 0 2px; width: 24px; height: 24px; overflow: visible;"><svg fill="currentColor" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24" style="display: block; overflow: visible;"><path d="M14 20.725v-2.05q2.25-.65 3.625-2.5t1.375-4.2q0-2.35-1.375-4.2T14 5.275v-2.05q3.1.7 5.05 3.137Q21 8.8 21 11.975q0 3.175-1.95 5.612-1.95 2.438-5.05 3.138ZM3 15V9h4l5-5v16l-5-5Zm11 1V7.95q1.175.55 1.838 1.65.662 1.1.662 2.4q0 1.275-.662 2.362Q15.175 15.45 14 16Z"/></svg></button>`;
130-
} else if (el.tagName === 'img' && el.hasAttribute('src')) {
122+
} else if (tagName === 'img' && el.hasAttribute('src')) {
131123
const src = el.getAttribute('src')?.replace(/^illustrations\//, '');
132124
const hashedSrc = src && illustrations[`./${src}`];
133125
if (!hashedSrc) {
@@ -168,7 +160,7 @@
168160
}
169161
170162
return (
171-
processNode(xmlDoc.documentElement) +
163+
processNode(htmlDoc.documentElement) +
172164
audioElements
173165
.entries()
174166
.map(

0 commit comments

Comments
 (0)