From 7eb33c0d084e5c17cb3fbd579e0ee7ef3e254b1b Mon Sep 17 00:00:00 2001 From: Mihaela Mihaljevic Date: Tue, 9 Jun 2026 07:39:32 +0200 Subject: [PATCH] feat(html): full HTML 4.01 named entity set (#84) --- CHANGELOG.md | 1 + README.md | 2 +- Sources/HTML/HTMLEntities.swift | 9 +--- Sources/HTML/HTMLEntityTable.swift | 75 ++++++++++++++++++++++++++++++ Tests/HTMLTokenizerTests.swift | 11 +++++ 5 files changed, 89 insertions(+), 9 deletions(-) create mode 100644 Sources/HTML/HTMLEntityTable.swift diff --git a/CHANGELOG.md b/CHANGELOG.md index 7cdab55..e11ce63 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added +- HTML named character references: the full HTML 4.01 entity set (#84), about 250 references across the Latin-1, special, and symbol (Greek, mathematical, arrow, card-suit) groups, replacing the previous 16-entry stopgap. Decoding stays longest-match with an optional trailing semicolon and the existing numeric-reference validation. This matches libxml2's entity coverage; the much larger WHATWG superset of mostly-astral mathematical references is not vendored. - HTML5 select content model (#83, stage 10): a `` closes the open one rather than nesting, and an ``/``/`") == "hello") #expect(text("") == "\nhello") } + + @Test("The HTML4 named entity set decodes across its categories") + func test_namedEntitySet() { + #expect(text("

½Á×

") == "\u{BD}\u{C1}\u{D7}") // Latin-1 + #expect(text("

Œ†—

") == "\u{152}\u{2020}\u{2014}") // special + #expect(text("

αΩπ

") == "\u{3B1}\u{3A9}\u{3C0}") // Greek + #expect(text("

∀∑∞≠

") == "\u{2200}\u{2211}\u{221E}\u{2260}") // math + #expect(text("

←→⇔

") == "\u{2190}\u{2192}\u{21D4}") // arrows + #expect(text("

♥♦♠

") == "\u{2665}\u{2666}\u{2660}") // suits + #expect(text("

© ®

") == "\u{A9} \u{AE}") // semicolon-less + } }