Skip to content

Commit abe24f2

Browse files
cubapthehabes
andauthored
Use safe DOM manipulation for UI messages (#508)
* Use safe DOM manipulation for UI messages Replace direct innerHTML usage with replaceChildren/createElement/textContent to render error and loading UI. Adds fallbacks for missing tagName/message values and constructs DOM nodes programmatically (components/simple-transcription, interfaces/transcription, interfaces/custom, interfaces/manage-columns) to avoid accidental HTML injection and preserve existing DOM structure. * Changes during review * Changes during review --------- Co-authored-by: Bryan Haberberger <bryan.j.haberberger@slu.edu>
1 parent 8b7f2b5 commit abe24f2

File tree

4 files changed

+40
-13
lines changed

4 files changed

+40
-13
lines changed

components/simple-transcription/index.js

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -830,7 +830,7 @@ export default class SimpleTranscriptionInterface extends HTMLElement {
830830
const tagName = tool.custom?.tagName
831831
if (tagName && tool.url) {
832832
if (customElements.get(tagName)) {
833-
rightPane.innerHTML = `<${tagName}></${tagName}>`
833+
rightPane.replaceChildren(document.createElement(tagName))
834834
return
835835
}
836836

@@ -844,10 +844,13 @@ export default class SimpleTranscriptionInterface extends HTMLElement {
844844
script.src = tool.url
845845
script.id = scriptId
846846
script.onload = () => {
847-
rightPane.innerHTML = `<${tagName}></${tagName}>`
847+
rightPane.replaceChildren(document.createElement(tagName))
848848
}
849849
script.onerror = () => {
850-
rightPane.innerHTML = `<p>Failed to load tool: ${tagName}</p>`
850+
rightPane.replaceChildren()
851+
const message = document.createElement('p')
852+
message.textContent = `Failed to load tool: ${tagName ?? 'unknown tool'}`
853+
rightPane.appendChild(message)
851854
}
852855
document.head.appendChild(script)
853856
return
@@ -922,7 +925,10 @@ export default class SimpleTranscriptionInterface extends HTMLElement {
922925
}
923926

924927
// Fallback message for tools that don't have proper configuration
925-
rightPane.innerHTML = `<p>${tool.label ?? tool.custom?.tagName ?? 'Tool'} - functionality coming soon...</p>`
928+
rightPane.replaceChildren()
929+
const message = document.createElement('p')
930+
message.textContent = `${tool.label ?? tool.custom?.tagName ?? 'Tool'} - functionality coming soon...`
931+
rightPane.appendChild(message)
926932
this.checkMagnifierVisibility?.()
927933
}
928934

interfaces/custom/index.html

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -308,7 +308,11 @@ <h3>${namespace}</h3>
308308
}
309309

310310
function showError(message) {
311-
errorContainer.innerHTML = `<div class="error">${message}</div>`
311+
errorContainer.innerHTML = ''
312+
const errorMessage = document.createElement('div')
313+
errorMessage.className = 'error'
314+
errorMessage.textContent = message ?? 'An unknown error occurred'
315+
errorContainer.appendChild(errorMessage)
312316
setTimeout(() => {
313317
errorContainer.innerHTML = ''
314318
}, 5000)

interfaces/manage-columns/index.js

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -895,12 +895,23 @@ class TpenManageColumns extends HTMLElement {
895895
return { imgUrl, imgWidth, imgHeight }
896896
}
897897

898-
showError(message) {
899-
this.container.innerHTML = `<div class="error-message"><strong>Error:</strong> ${message}</div>`
898+
showError(message) {
899+
this.container.replaceChildren()
900+
const wrapper = document.createElement('div')
901+
wrapper.className = 'error-message'
902+
const strong = document.createElement('strong')
903+
strong.textContent = 'Error:'
904+
const textNode = document.createTextNode(` ${message ?? ''}`)
905+
wrapper.append(strong, textNode)
906+
this.container.appendChild(wrapper)
900907
}
901908

902-
showLoading(message = "Loading...") {
903-
this.container.innerHTML = `<div class="loading">${message}</div>`
909+
showLoading(message = 'Loading...') {
910+
this.container.replaceChildren()
911+
const wrapper = document.createElement('div')
912+
wrapper.className = 'loading'
913+
wrapper.textContent = message ?? 'Loading...'
914+
this.container.appendChild(wrapper)
904915
}
905916

906917
async renderImage(imgUrl) {

interfaces/transcription/index.js

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -369,7 +369,7 @@ export default class TranscriptionInterface extends HTMLElement {
369369
if (tagName && tool.url) {
370370
// Dynamically load the script if not already loaded
371371
if (customElements.get(tagName)) {
372-
rightPane.innerHTML = `<${tagName}></${tagName}>`
372+
rightPane.replaceChildren(document.createElement(tagName))
373373
return
374374
}
375375
const scriptId = `tool-script-${tool.toolName}`
@@ -382,10 +382,13 @@ export default class TranscriptionInterface extends HTMLElement {
382382
script.src = tool.url
383383
script.id = scriptId
384384
script.onload = () => {
385-
rightPane.innerHTML = `<${tagName}></${tagName}>`
385+
rightPane.replaceChildren(document.createElement(tagName))
386386
}
387387
script.onerror = () => {
388-
rightPane.innerHTML = `<p>Failed to load tool: ${tagName}</p>`
388+
rightPane.replaceChildren()
389+
const message = document.createElement('p')
390+
message.textContent = `Failed to load tool: ${tagName ?? 'unknown tool'}`
391+
rightPane.appendChild(message)
389392
}
390393
document.head.appendChild(script)
391394
return
@@ -448,7 +451,10 @@ export default class TranscriptionInterface extends HTMLElement {
448451
return
449452
}
450453

451-
rightPane.innerHTML = `<p>${tool.label ?? tool.custom?.tagName ?? 'Tool'} - functionality coming soon...</p>`
454+
rightPane.replaceChildren()
455+
const message = document.createElement('p')
456+
message.textContent = `${tool.label ?? tool.custom?.tagName ?? 'Tool'} - functionality coming soon...`
457+
rightPane.appendChild(message)
452458
this.checkMagnifierVisibility()
453459
}
454460

0 commit comments

Comments
 (0)