diff --git a/src/scripts/deck.js b/src/scripts/deck.js
index 3a00c74..56b5234 100644
--- a/src/scripts/deck.js
+++ b/src/scripts/deck.js
@@ -50,7 +50,19 @@ export const createDeck = (deckList, id, x, y) => {
if (failed.length > 0) {
const errorElement = document.createElement("div")
errorElement.classList.add("deck-parse-errors")
- errorElement.innerHTML = `Unrecognized cards (not loaded):
${failed.map(n => `- ${n}
`).join("")}
`
+
+ const heading = document.createElement("strong")
+ heading.textContent = "Unrecognized cards (not loaded):"
+ errorElement.appendChild(heading)
+
+ const list = document.createElement("ul")
+ for (const name of failed) {
+ const item = document.createElement("li")
+ item.textContent = name
+ list.appendChild(item)
+ }
+ errorElement.appendChild(list)
+
document.querySelector("#card-layer").appendChild(errorElement)
}
diff --git a/src/scripts/deck.test.js b/src/scripts/deck.test.js
index 32b213f..9d83f0f 100644
--- a/src/scripts/deck.test.js
+++ b/src/scripts/deck.test.js
@@ -130,6 +130,14 @@ describe('createDeck', () => {
expect(document.querySelector('.deck-parse-errors')).not.toBeNull()
})
+ it('renders HTML characters in failed card names as escaped text, not live markup', () => {
+ createDeck('1x
', 'test-deck', '0px', '0px')
+ const errors = document.querySelector('.deck-parse-errors')
+ expect(errors).not.toBeNull()
+ expect(errors.querySelector('img')).toBeNull()
+ expect(errors.textContent).toContain('
')
+ })
+
it('adds red-tint class and sets title to "no cards left" when all cards are drawn', () => {
const el = createDeck('2x Hedge Fund', 'test-deck', '0px', '0px')
el.dispatchEvent(new MouseEvent('mousedown', { bubbles: true }))