diff --git a/src/core/operations/ToHTMLEntity.mjs b/src/core/operations/ToHTMLEntity.mjs
index f2a57a43..75a82018 100644
--- a/src/core/operations/ToHTMLEntity.mjs
+++ b/src/core/operations/ToHTMLEntity.mjs
@@ -405,7 +405,7 @@ const byteToEntity = {
989: "ϝ",
1008: "ϰ",
1009: "ϱ",
- 1013: "ε,",
+ 1013: "ε",
1014: "϶",
1025: "Ё",
1026: "Ђ",
@@ -660,7 +660,7 @@ const byteToEntity = {
8649: "⇉",
8650: "⇊",
8651: "⇋",
- 8652: "⇌;",
+ 8652: "⇌",
8653: "⇍",
8654: "⇎",
8655: "⇏",
@@ -782,7 +782,7 @@ const byteToEntity = {
8814: "≮",
8815: "≯",
8816: "≰",
- 8817: "≱;",
+ 8817: "≱",
8818: "≲",
8819: "≳",
8820: "≴",
diff --git a/tests/node/index.mjs b/tests/node/index.mjs
index 360bf481..e53ca7b2 100644
--- a/tests/node/index.mjs
+++ b/tests/node/index.mjs
@@ -24,6 +24,7 @@ import "./tests/Dish.mjs";
import "./tests/NodeDish.mjs";
import "./tests/Utils.mjs";
import "./tests/Categories.mjs";
+import "./tests/ToHTMLEntity.mjs";
import "./tests/lib/BigIntUtils.mjs";
import "./tests/lib/ChartsProtocolPrototypePollution.mjs";
diff --git a/tests/node/tests/ToHTMLEntity.mjs b/tests/node/tests/ToHTMLEntity.mjs
new file mode 100644
index 00000000..43d8cb49
--- /dev/null
+++ b/tests/node/tests/ToHTMLEntity.mjs
@@ -0,0 +1,33 @@
+import TestRegister from "../../lib/TestRegister.mjs";
+import ToHTMLEntity from "../../../src/core/operations/ToHTMLEntity.mjs";
+import it from "../assertionHandler.mjs";
+import assert from "assert";
+
+TestRegister.addApiTests([
+ it("To HTML Entity: every named entity in the table is well-formed", () => {
+ // "Convert all characters" emits an entity for every code point, so a
+ // correct table yields an unbroken stream of entity tokens. A malformed
+ // value such as "≱;" or "ε," leaves stray characters between
+ // tokens, which the walk below flags and reports with surrounding context.
+ let input = "";
+ for (let cp = 0; cp <= 0xFFFF; cp++) {
+ if (cp >= 0xD800 && cp <= 0xDFFF) continue; // skip surrogate range
+ input += String.fromCodePoint(cp);
+ }
+ const output = new ToHTMLEntity().run(input, [true, "Named entities"]);
+
+ const tokenRe = /[0-9]+;|[0-9a-fA-F]+;|&[A-Za-z][A-Za-z0-9]*;/y;
+ const malformed = [];
+ let pos = 0;
+ while (pos < output.length) {
+ tokenRe.lastIndex = pos;
+ if (tokenRe.exec(output)) {
+ pos = tokenRe.lastIndex;
+ } else {
+ malformed.push(output.slice(Math.max(0, pos - 12), pos + 12));
+ pos++;
+ }
+ }
+ assert.deepStrictEqual(malformed, [], `Malformed entity value(s) near: ${JSON.stringify(malformed)}`);
+ }),
+]);