entities 7.0.1 → 8.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (143) hide show
  1. package/dist/decode-codepoint.d.ts +28 -0
  2. package/dist/decode-codepoint.d.ts.map +1 -0
  3. package/dist/decode-codepoint.js +61 -0
  4. package/dist/decode-codepoint.js.map +1 -0
  5. package/dist/{esm/decode.d.ts → decode.d.ts} +66 -44
  6. package/dist/decode.d.ts.map +1 -0
  7. package/dist/decode.js +1132 -0
  8. package/dist/decode.js.map +1 -0
  9. package/dist/{commonjs/encode.d.ts → encode.d.ts} +4 -0
  10. package/dist/encode.d.ts.map +1 -0
  11. package/dist/encode.js +295 -0
  12. package/dist/encode.js.map +1 -0
  13. package/dist/{esm/escape.d.ts → escape.d.ts} +23 -9
  14. package/dist/escape.d.ts.map +1 -0
  15. package/dist/escape.js +172 -0
  16. package/dist/escape.js.map +1 -0
  17. package/dist/generated/decode-data-html.d.ts +3 -0
  18. package/dist/generated/decode-data-html.d.ts.map +1 -0
  19. package/dist/generated/decode-data-html.js +5 -0
  20. package/dist/generated/decode-data-html.js.map +1 -0
  21. package/dist/generated/decode-data-xml.d.ts +3 -0
  22. package/dist/generated/decode-data-xml.d.ts.map +1 -0
  23. package/dist/generated/decode-data-xml.js +7 -0
  24. package/dist/generated/decode-data-xml.js.map +1 -0
  25. package/dist/generated/encode-html.d.ts +3 -0
  26. package/dist/generated/encode-html.d.ts.map +1 -0
  27. package/dist/generated/encode-html.js +3 -0
  28. package/dist/generated/encode-html.js.map +1 -0
  29. package/dist/{commonjs/index.d.ts → index.d.ts} +11 -18
  30. package/dist/index.d.ts.map +1 -0
  31. package/dist/{esm/index.js → index.js} +9 -29
  32. package/dist/index.js.map +1 -0
  33. package/dist/internal/bin-trie-flags.d.ts +48 -0
  34. package/dist/internal/bin-trie-flags.d.ts.map +1 -0
  35. package/dist/internal/bin-trie-flags.js +49 -0
  36. package/dist/internal/bin-trie-flags.js.map +1 -0
  37. package/dist/internal/decode-shared.d.ts +38 -0
  38. package/dist/internal/decode-shared.d.ts.map +1 -0
  39. package/dist/internal/decode-shared.js +195 -0
  40. package/dist/internal/decode-shared.js.map +1 -0
  41. package/package.json +28 -65
  42. package/readme.md +4 -16
  43. package/src/decode-codepoint.ts +51 -63
  44. package/src/decode.ts +944 -261
  45. package/src/encode.ts +289 -45
  46. package/src/escape.ts +114 -88
  47. package/src/generated/decode-data-html.ts +9 -3
  48. package/src/generated/decode-data-xml.ts +5 -4
  49. package/src/generated/encode-html.ts +1 -15
  50. package/src/index.ts +14 -41
  51. package/src/internal/bin-trie-flags.ts +38 -7
  52. package/src/internal/decode-shared.ts +203 -24
  53. package/decode.d.ts +0 -3
  54. package/decode.js +0 -3
  55. package/dist/commonjs/decode-codepoint.d.ts +0 -19
  56. package/dist/commonjs/decode-codepoint.d.ts.map +0 -1
  57. package/dist/commonjs/decode-codepoint.js +0 -77
  58. package/dist/commonjs/decode-codepoint.js.map +0 -1
  59. package/dist/commonjs/decode.d.ts +0 -205
  60. package/dist/commonjs/decode.d.ts.map +0 -1
  61. package/dist/commonjs/decode.js +0 -568
  62. package/dist/commonjs/decode.js.map +0 -1
  63. package/dist/commonjs/encode.d.ts.map +0 -1
  64. package/dist/commonjs/encode.js +0 -92
  65. package/dist/commonjs/encode.js.map +0 -1
  66. package/dist/commonjs/escape.d.ts +0 -46
  67. package/dist/commonjs/escape.d.ts.map +0 -1
  68. package/dist/commonjs/escape.js +0 -138
  69. package/dist/commonjs/escape.js.map +0 -1
  70. package/dist/commonjs/generated/decode-data-html.d.ts +0 -2
  71. package/dist/commonjs/generated/decode-data-html.d.ts.map +0 -1
  72. package/dist/commonjs/generated/decode-data-html.js +0 -7
  73. package/dist/commonjs/generated/decode-data-html.js.map +0 -1
  74. package/dist/commonjs/generated/decode-data-xml.d.ts +0 -2
  75. package/dist/commonjs/generated/decode-data-xml.d.ts.map +0 -1
  76. package/dist/commonjs/generated/decode-data-xml.js +0 -7
  77. package/dist/commonjs/generated/decode-data-xml.js.map +0 -1
  78. package/dist/commonjs/generated/encode-html.d.ts +0 -3
  79. package/dist/commonjs/generated/encode-html.d.ts.map +0 -1
  80. package/dist/commonjs/generated/encode-html.js +0 -14
  81. package/dist/commonjs/generated/encode-html.js.map +0 -1
  82. package/dist/commonjs/index.d.ts.map +0 -1
  83. package/dist/commonjs/index.js +0 -131
  84. package/dist/commonjs/index.js.map +0 -1
  85. package/dist/commonjs/internal/bin-trie-flags.d.ts +0 -17
  86. package/dist/commonjs/internal/bin-trie-flags.d.ts.map +0 -1
  87. package/dist/commonjs/internal/bin-trie-flags.js +0 -21
  88. package/dist/commonjs/internal/bin-trie-flags.js.map +0 -1
  89. package/dist/commonjs/internal/decode-shared.d.ts +0 -2
  90. package/dist/commonjs/internal/decode-shared.d.ts.map +0 -1
  91. package/dist/commonjs/internal/decode-shared.js +0 -31
  92. package/dist/commonjs/internal/decode-shared.js.map +0 -1
  93. package/dist/commonjs/internal/encode-shared.d.ts +0 -32
  94. package/dist/commonjs/internal/encode-shared.d.ts.map +0 -1
  95. package/dist/commonjs/internal/encode-shared.js +0 -94
  96. package/dist/commonjs/internal/encode-shared.js.map +0 -1
  97. package/dist/commonjs/package.json +0 -3
  98. package/dist/esm/decode-codepoint.d.ts +0 -19
  99. package/dist/esm/decode-codepoint.d.ts.map +0 -1
  100. package/dist/esm/decode-codepoint.js +0 -72
  101. package/dist/esm/decode-codepoint.js.map +0 -1
  102. package/dist/esm/decode.d.ts.map +0 -1
  103. package/dist/esm/decode.js +0 -554
  104. package/dist/esm/decode.js.map +0 -1
  105. package/dist/esm/encode.d.ts +0 -22
  106. package/dist/esm/encode.d.ts.map +0 -1
  107. package/dist/esm/encode.js +0 -88
  108. package/dist/esm/encode.js.map +0 -1
  109. package/dist/esm/escape.d.ts.map +0 -1
  110. package/dist/esm/escape.js +0 -134
  111. package/dist/esm/escape.js.map +0 -1
  112. package/dist/esm/generated/decode-data-html.d.ts +0 -2
  113. package/dist/esm/generated/decode-data-html.d.ts.map +0 -1
  114. package/dist/esm/generated/decode-data-html.js +0 -4
  115. package/dist/esm/generated/decode-data-html.js.map +0 -1
  116. package/dist/esm/generated/decode-data-xml.d.ts +0 -2
  117. package/dist/esm/generated/decode-data-xml.d.ts.map +0 -1
  118. package/dist/esm/generated/decode-data-xml.js +0 -4
  119. package/dist/esm/generated/decode-data-xml.js.map +0 -1
  120. package/dist/esm/generated/encode-html.d.ts +0 -3
  121. package/dist/esm/generated/encode-html.d.ts.map +0 -1
  122. package/dist/esm/generated/encode-html.js +0 -11
  123. package/dist/esm/generated/encode-html.js.map +0 -1
  124. package/dist/esm/index.d.ts +0 -96
  125. package/dist/esm/index.d.ts.map +0 -1
  126. package/dist/esm/index.js.map +0 -1
  127. package/dist/esm/internal/bin-trie-flags.d.ts +0 -17
  128. package/dist/esm/internal/bin-trie-flags.d.ts.map +0 -1
  129. package/dist/esm/internal/bin-trie-flags.js +0 -18
  130. package/dist/esm/internal/bin-trie-flags.js.map +0 -1
  131. package/dist/esm/internal/decode-shared.d.ts +0 -2
  132. package/dist/esm/internal/decode-shared.d.ts.map +0 -1
  133. package/dist/esm/internal/decode-shared.js +0 -28
  134. package/dist/esm/internal/decode-shared.js.map +0 -1
  135. package/dist/esm/internal/encode-shared.d.ts +0 -32
  136. package/dist/esm/internal/encode-shared.d.ts.map +0 -1
  137. package/dist/esm/internal/encode-shared.js +0 -91
  138. package/dist/esm/internal/encode-shared.js.map +0 -1
  139. package/dist/esm/package.json +0 -3
  140. package/escape.d.ts +0 -3
  141. package/escape.js +0 -3
  142. package/src/generated/.eslintrc.json +0 -10
  143. package/src/internal/encode-shared.ts +0 -121
@@ -0,0 +1,195 @@
1
+ /*
2
+ * Inverse of the encoder's SAFE alphabet (0x21..0x7E minus 0x22, 0x24, 0x5C),
3
+ * precomputed once at module load. Entries for excluded chars stay 0 but
4
+ * are never read.
5
+ */
6
+ const BASE91_INVERSE = /* #__PURE__ */ (() => {
7
+ const table = new Uint8Array(127);
8
+ let code = 0;
9
+ for (let char = 0x21; char <= 0x7e; char++) {
10
+ if (char !== 0x22 && char !== 0x24 && char !== 0x5c) {
11
+ table[char] = code++;
12
+ }
13
+ }
14
+ return table;
15
+ })();
16
+ /**
17
+ * Decode a dictionary-encoded trie string back into its Uint16Array.
18
+ *
19
+ * Stream layout (consumed in this order):
20
+ * 1. dict1 atoms — `dict1AtomCount` uint16 values, delta+RLE encoded.
21
+ * 2. dict2 atoms — `atomCount - dict1AtomCount` values, delta+RLE.
22
+ * 3. dict2 ngrams — `ngramCount - (dictSize - dict1AtomCount)` entries,
23
+ * each a pair of slot codes that resolve to earlier slots.
24
+ * 4. dict1 ngrams — `dictSize - dict1AtomCount` entries, same shape.
25
+ * 5. data — slot codes, each expanding to one or more uint16 values.
26
+ *
27
+ * Codes use a 91-char base (printable ASCII minus `"`, `$`, `\`):
28
+ * - char1 < dictSize → 1-char code, slot = char1
29
+ * - char1 ≥ dictSize → 2-char code, slot = dictSize + (char1 - dictSize)*91 + char2
30
+ *
31
+ * Slot index → token kind:
32
+ * [0, A) dict1 atoms (1-char codes)
33
+ * [A, dictSize) dict1 ngrams (1-char codes)
34
+ * [dictSize, dictSize+D) dict2 atoms (2-char codes)
35
+ * [dictSize+D, end) dict2 ngrams (2-char codes)
36
+ *
37
+ * Both atom dicts decode before any ngram, and dict2 ngrams decode before
38
+ * dict1 ngrams. So every ngram entry references slots whose contents are
39
+ * already filled — no forward references to handle.
40
+ *
41
+ * This runs on library import. Flat typed arrays store each slot as either
42
+ * a plain value (`single`, covering every atom) or a range in a shared
43
+ * `pool` (ngrams).
44
+ * @param input Packed trie string.
45
+ * @param resultLength Expected number of uint16 values in the output.
46
+ * @param atomCount Total number of distinct uint16 values in the trie.
47
+ * @param dict1AtomCount Atoms in the 1-char range (`A` above).
48
+ * @param ngramCount Total number of ngram entries (dict1 + dict2).
49
+ * @param dictSize Number of 1-char code slots; the rest of `BASE - dictSize`
50
+ * first-byte values are 2-char codes.
51
+ */
52
+ export function decodeTrieDict(input, resultLength, atomCount, dict1AtomCount, ngramCount, dictSize) {
53
+ const base = 91;
54
+ const inputLength = input.length;
55
+ // For 2-char codes, slot = char1 * base - twoCharBias + char2.
56
+ const twoCharBias = dictSize * (base - 1);
57
+ let pos = 0;
58
+ /** Read one slot code at `pos` and return its slot index, advancing pos. */
59
+ const readSlotCode = () => {
60
+ const c1 = BASE91_INVERSE[input.charCodeAt(pos++)];
61
+ return c1 < dictSize
62
+ ? c1
63
+ : c1 * base - twoCharBias + BASE91_INVERSE[input.charCodeAt(pos++)];
64
+ };
65
+ const dict2AtomCount = atomCount - dict1AtomCount;
66
+ const slotCount = atomCount + ngramCount;
67
+ /*
68
+ * Per-slot contents: atoms (always a single value) live directly in
69
+ * `single`; ngram slots hold -1 there and expand to
70
+ * `pool[start[slot] .. start[slot] + length[slot])`.
71
+ */
72
+ const single = new Int32Array(slotCount);
73
+ single.fill(-1, dict1AtomCount, dictSize);
74
+ single.fill(-1, dictSize + dict2AtomCount, slotCount);
75
+ const start = new Int32Array(slotCount);
76
+ const length = new Int32Array(slotCount);
77
+ /**
78
+ * Decode `count` ascending uint16 values from a delta+RLE stream into
79
+ * `single[off..off+count)`.
80
+ *
81
+ * code < 89 → delta = code
82
+ * code == 89 → run-length: next char encodes runLength-2; emit `runLength` consecutive +1 values
83
+ * code == 90, next < 90 → escape: delta = 89 + next * BASE + after-next
84
+ * code == 90, next == 90 → double-escape: extra char for very large deltas
85
+ * @param count
86
+ * @param off
87
+ */
88
+ function decodeDelta(count, off) {
89
+ let previous = 0;
90
+ let slot = off;
91
+ const end = off + count;
92
+ while (slot < end) {
93
+ const code = BASE91_INVERSE[input.charCodeAt(pos++)];
94
+ if (code < 89) {
95
+ previous += code;
96
+ single[slot++] = previous;
97
+ }
98
+ else if (code === 89) {
99
+ let runLength = BASE91_INVERSE[input.charCodeAt(pos++)] + 2;
100
+ while (runLength--)
101
+ single[slot++] = ++previous;
102
+ }
103
+ else {
104
+ const next = BASE91_INVERSE[input.charCodeAt(pos++)];
105
+ previous +=
106
+ 89 +
107
+ // eslint-disable-next-line unicorn/prefer-minimal-ternary -- branches read a different number of side-effecting input bytes
108
+ (next < 90
109
+ ? next * base + BASE91_INVERSE[input.charCodeAt(pos++)]
110
+ : BASE91_INVERSE[input.charCodeAt(pos++)] * 8281 +
111
+ BASE91_INVERSE[input.charCodeAt(pos++)] * base +
112
+ BASE91_INVERSE[input.charCodeAt(pos++)]);
113
+ single[slot++] = previous;
114
+ }
115
+ }
116
+ }
117
+ // Streams 1 & 2: atoms decoded into their slot ranges.
118
+ decodeDelta(dict1AtomCount, 0);
119
+ decodeDelta(dict2AtomCount, dictSize);
120
+ /*
121
+ * Streams 3 & 4 are read in two passes: first collect every ngram's two
122
+ * references and derive its expanded length (each ref resolves to an earlier
123
+ * slot, so lengths are already known), which sizes the shared pool.
124
+ * Pool ranges are handed out in decode order, so the second pass fills
125
+ * the pool contiguously with a single write cursor.
126
+ */
127
+ const references = new Int32Array(ngramCount * 2);
128
+ let poolSize = 0;
129
+ let ngramIndex = 0;
130
+ /**
131
+ * Read `count` ngram entries (each = 2 slot-code references) for the slots
132
+ * starting at `startSlot`, recording references and assigning pool ranges.
133
+ * @param count
134
+ * @param startSlot
135
+ */
136
+ function readNgramReferences(count, startSlot) {
137
+ for (let index = 0; index < count; index++) {
138
+ const slot = startSlot + index;
139
+ const a = readSlotCode();
140
+ const b = readSlotCode();
141
+ references[ngramIndex * 2] = a;
142
+ references[ngramIndex * 2 + 1] = b;
143
+ ngramIndex += 1;
144
+ start[slot] = poolSize;
145
+ const entryLength = (single[a] < 0 ? length[a] : 1) +
146
+ (single[b] < 0 ? length[b] : 1);
147
+ length[slot] = entryLength;
148
+ poolSize += entryLength;
149
+ }
150
+ }
151
+ readNgramReferences(ngramCount - dictSize + dict1AtomCount, dictSize + dict2AtomCount);
152
+ readNgramReferences(dictSize - dict1AtomCount, dict1AtomCount);
153
+ // Second pass: concatenate each ngram's two halves into the pool.
154
+ const pool = new Uint16Array(poolSize);
155
+ let write = 0;
156
+ for (let index = 0; index < ngramIndex; index++) {
157
+ for (let half = 0; half < 2; half++) {
158
+ const source = references[index * 2 + half];
159
+ const value = single[source];
160
+ if (value < 0) {
161
+ let read = start[source];
162
+ const readEnd = read + length[source];
163
+ while (read < readEnd)
164
+ pool[write++] = pool[read++];
165
+ }
166
+ else {
167
+ pool[write++] = value;
168
+ }
169
+ }
170
+ }
171
+ // Stream 5: data. Each code expands to its slot's stored values.
172
+ const out = new Uint16Array(resultLength);
173
+ let outIndex = 0;
174
+ while (pos < inputLength) {
175
+ let slot = BASE91_INVERSE[input.charCodeAt(pos++)];
176
+ if (slot >= dictSize) {
177
+ slot =
178
+ slot * base -
179
+ twoCharBias +
180
+ BASE91_INVERSE[input.charCodeAt(pos++)];
181
+ }
182
+ const value = single[slot];
183
+ if (value < 0) {
184
+ let read = start[slot];
185
+ const readEnd = read + length[slot];
186
+ while (read < readEnd)
187
+ out[outIndex++] = pool[read++];
188
+ }
189
+ else {
190
+ out[outIndex++] = value;
191
+ }
192
+ }
193
+ return out;
194
+ }
195
+ //# sourceMappingURL=decode-shared.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"decode-shared.js","sourceRoot":"","sources":["../../src/internal/decode-shared.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "entities",
3
- "version": "7.0.1",
3
+ "version": "8.1.0",
4
4
  "description": "Encode & decode XML and HTML entities with ease & speed",
5
5
  "keywords": [
6
6
  "html entities",
@@ -22,99 +22,62 @@
22
22
  "type": "module",
23
23
  "exports": {
24
24
  ".": {
25
- "import": {
26
- "types": "./dist/esm/index.d.ts",
27
- "default": "./dist/esm/index.js"
28
- },
29
- "require": {
30
- "types": "./dist/commonjs/index.d.ts",
31
- "default": "./dist/commonjs/index.js"
32
- }
25
+ "types": "./dist/index.d.ts",
26
+ "default": "./dist/index.js"
33
27
  },
34
28
  "./decode": {
35
- "import": {
36
- "types": "./dist/esm/decode.d.ts",
37
- "default": "./dist/esm/decode.js"
38
- },
39
- "require": {
40
- "types": "./dist/commonjs/decode.d.ts",
41
- "default": "./dist/commonjs/decode.js"
42
- }
29
+ "types": "./dist/decode.d.ts",
30
+ "default": "./dist/decode.js"
43
31
  },
44
32
  "./escape": {
45
- "import": {
46
- "types": "./dist/esm/escape.d.ts",
47
- "default": "./dist/esm/escape.js"
48
- },
49
- "require": {
50
- "types": "./dist/commonjs/escape.d.ts",
51
- "default": "./dist/commonjs/escape.js"
52
- }
33
+ "types": "./dist/escape.d.ts",
34
+ "default": "./dist/escape.js"
53
35
  }
54
36
  },
55
- "main": "./dist/commonjs/index.js",
56
- "module": "./dist/esm/index.js",
57
- "types": "./dist/commonjs/index.d.ts",
37
+ "main": "./dist/index.js",
38
+ "types": "./dist/index.d.ts",
58
39
  "files": [
59
- "decode.js",
60
- "decode.d.ts",
61
- "escape.js",
62
- "escape.d.ts",
63
40
  "dist",
64
41
  "src",
65
42
  "!**/*.spec.ts"
66
43
  ],
67
44
  "scripts": {
45
+ "benchmark": "node --import=tsx scripts/benchmark.ts",
46
+ "build": "tsc",
68
47
  "build:docs": "typedoc --hideGenerator src/index.ts",
69
48
  "build:encode-trie": "node --import=tsx scripts/write-encode-map.ts",
70
49
  "build:trie": "node --import=tsx scripts/write-decode-map.ts",
71
- "benchmark": "node --import=tsx scripts/benchmark.ts",
72
50
  "format": "npm run format:es && npm run format:biome",
73
- "format:es": "npm run lint:es -- --fix",
74
51
  "format:biome": "biome check --fix .",
52
+ "format:es": "npm run lint:es -- --fix",
75
53
  "lint": "npm run lint:es && npm run lint:ts && npm run lint:biome",
76
- "lint:es": "eslint . --ignore-path .gitignore",
77
54
  "lint:biome": "biome check .",
78
- "lint:ts": "tsc --noEmit",
79
- "prepublishOnly": "tshy",
55
+ "lint:es": "eslint .",
56
+ "lint:ts": "tsc --noEmit -p tsconfig.eslint.json",
57
+ "prepublishOnly": "npm run build",
80
58
  "test": "npm run test:vi && npm run lint",
81
59
  "test:vi": "vitest run"
82
60
  },
83
61
  "devDependencies": {
84
- "@biomejs/biome": "^2.3.11",
85
- "@types/node": "^25.0.9",
86
- "@typescript-eslint/eslint-plugin": "^8.53.1",
87
- "@typescript-eslint/parser": "^8.53.1",
88
- "@vitest/coverage-v8": "^3.2.4",
62
+ "@biomejs/biome": "^2.5.12",
63
+ "@eslint/compat": "^2.1.1",
64
+ "@feedic/eslint-config": "^0.5.0",
89
65
  "@types/he": "^1.2.3",
90
- "eslint": "^8.57.1",
66
+ "@types/node": "^26.4.1",
67
+ "eslint": "^10.10.0",
91
68
  "eslint-config-biome": "^2.1.3",
92
- "eslint-plugin-n": "^17.23.2",
93
- "eslint-plugin-unicorn": "^56.0.1",
69
+ "globals": "^17.12.0",
94
70
  "he": "^1.2.0",
95
71
  "html-entities": "^2.6.0",
96
72
  "parse-entities": "^4.0.2",
97
- "tinybench": "^5.1.0",
98
- "tshy": "^3.1.0",
99
- "tsx": "^4.21.0",
100
- "typedoc": "^0.28.16",
101
- "typescript": "^5.9.3",
102
- "vitest": "^3.2.4"
73
+ "tinybench": "^6.1.5",
74
+ "tsx": "^4.23.13",
75
+ "typedoc": "^0.28.20",
76
+ "typescript": "^6.0.3",
77
+ "typescript-eslint": "^8.69.0",
78
+ "vitest": "^5.0.0"
103
79
  },
104
80
  "engines": {
105
- "node": ">=0.12"
106
- },
107
- "tshy": {
108
- "exclude": [
109
- "**/*.spec.ts",
110
- "**/__fixtures__/*",
111
- "**/__tests__/*",
112
- "**/__snapshots__/*"
113
- ],
114
- "exports": {
115
- ".": "./src/index.ts",
116
- "./decode": "./src/decode.ts",
117
- "./escape": "./src/escape.ts"
118
- }
81
+ "node": ">=20.19.0"
119
82
  }
120
83
  }
package/readme.md CHANGED
@@ -24,7 +24,7 @@ Encode & decode HTML & XML entities with ease & speed.
24
24
  ### …use `entities`
25
25
 
26
26
  ```javascript
27
- const entities = require("entities");
27
+ import * as entities from "entities";
28
28
 
29
29
  // Encoding
30
30
  entities.escapeUTF8("&#38; ü"); // "&amp;#38; ü"
@@ -99,10 +99,9 @@ libraries, so have a look through your `node_modules` directory!
99
99
 
100
100
  > Does `entities` support tree shaking?
101
101
 
102
- Yes! `entities` ships as both a CommonJS and a ES module. Note that for best
103
- results, you should not use the `encode` and `decode` functions, as they wrap
104
- around a number of other functions, all of which will remain in the bundle.
105
- Instead, use the functions that you need directly.
102
+ Yes! Note that for best results, you should not use the `encode` and `decode`
103
+ functions, as they wrap around a number of other functions, all of which will
104
+ remain in the bundle. Instead, use the functions that you need directly.
106
105
 
107
106
  ---
108
107
 
@@ -130,14 +129,3 @@ License: BSD-2-Clause
130
129
  To report a security vulnerability, please use the
131
130
  [Tidelift security contact](https://tidelift.com/security). Tidelift will
132
131
  coordinate the fix and disclosure.
133
-
134
- ## `entities` for enterprise
135
-
136
- Available as part of the Tidelift Subscription
137
-
138
- The maintainers of `entities` and thousands of other packages are working with
139
- Tidelift to deliver commercial support and maintenance for the open source
140
- dependencies you use to build your applications. Save time, reduce risk, and
141
- improve code health, while paying the maintainers of the exact dependencies you
142
- use.
143
- [Learn more.](https://tidelift.com/subscription/pkg/npm-entities?utm_source=npm-entities&utm_medium=referral&utm_campaign=enterprise&utm_term=repo)
@@ -1,81 +1,69 @@
1
1
  // Adapted from https://github.com/mathiasbynens/he/blob/36afe179392226cf1b6ccdb16ebbb7a5a844d93a/src/he.js#L106-L134
2
2
 
3
- const decodeMap = new Map([
4
- [0, 65_533],
5
- // C1 Unicode control character reference replacements
6
- [128, 8364],
7
- [130, 8218],
8
- [131, 402],
9
- [132, 8222],
10
- [133, 8230],
11
- [134, 8224],
12
- [135, 8225],
13
- [136, 710],
14
- [137, 8240],
15
- [138, 352],
16
- [139, 8249],
17
- [140, 338],
18
- [142, 381],
19
- [145, 8216],
20
- [146, 8217],
21
- [147, 8220],
22
- [148, 8221],
23
- [149, 8226],
24
- [150, 8211],
25
- [151, 8212],
26
- [152, 732],
27
- [153, 8482],
28
- [154, 353],
29
- [155, 8250],
30
- [156, 339],
31
- [158, 382],
32
- [159, 376],
33
- ]);
34
-
35
3
  /**
36
- * Polyfill for `String.fromCodePoint`. It is used to create a string from a Unicode code point.
4
+ * C1 Unicode control character reference replacements (code points 128–159).
5
+ * Index i gives the replacement for code point 128+i; 0 means "no replacement".
37
6
  */
38
- export const fromCodePoint: (...codePoints: number[]) => string =
39
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition, n/no-unsupported-features/es-builtins
40
- String.fromCodePoint ??
41
- ((codePoint: number): string => {
42
- let output = "";
43
-
44
- if (codePoint > 0xff_ff) {
45
- codePoint -= 0x1_00_00;
46
- output += String.fromCharCode(
47
- ((codePoint >>> 10) & 0x3_ff) | 0xd8_00,
48
- );
49
- codePoint = 0xdc_00 | (codePoint & 0x3_ff);
50
- }
51
-
52
- output += String.fromCharCode(codePoint);
53
- return output;
54
- });
7
+ const c1: number[] = [
8
+ 8364, 0, 8218, 402, 8222, 8230, 8224, 8225, 710, 8240, 352, 8249, 338, 0,
9
+ 381, 0, 0, 8216, 8217, 8220, 8221, 8226, 8211, 8212, 732, 8482, 353, 8250,
10
+ 339, 0, 382, 376,
11
+ ];
55
12
 
56
13
  /**
57
- * Replace the given code point with a replacement character if it is a
58
- * surrogate or is outside the valid range. Otherwise return the code
59
- * point unchanged.
14
+ * True for NUL, UTF-16 surrogates, and values past U+10FFFF.
15
+ * @param codePoint Unicode code point to check.
60
16
  */
61
- export function replaceCodePoint(codePoint: number): number {
62
- if (
17
+ function isInvalidCodePoint(codePoint: number): boolean {
18
+ return (
19
+ codePoint === 0 ||
63
20
  (codePoint >= 0xd8_00 && codePoint <= 0xdf_ff) ||
64
21
  codePoint > 0x10_ff_ff
65
- ) {
22
+ );
23
+ }
24
+
25
+ /**
26
+ * Replace the given code point with U+FFFD if it is NUL (0), a surrogate, or
27
+ * outside the valid Unicode range. Code points in the C1 controls range
28
+ * (128–159) are remapped to their Windows-1252 equivalents, following the
29
+ * HTML spec. All other code points are returned unchanged.
30
+ * @param codePoint Unicode code point to convert.
31
+ */
32
+ export function replaceCodePoint(codePoint: number): number {
33
+ if (isInvalidCodePoint(codePoint)) {
66
34
  return 0xff_fd;
67
35
  }
68
36
 
69
- return decodeMap.get(codePoint) ?? codePoint;
37
+ if (codePoint >= 128 && codePoint <= 159) {
38
+ return c1[codePoint - 128] || codePoint;
39
+ }
40
+
41
+ return codePoint;
42
+ }
43
+
44
+ /**
45
+ * XML numeric character references are the referenced Unicode code point.
46
+ * Invalid values still become U+FFFD; the HTML Windows-1252 C1 remap is not
47
+ * applied.
48
+ * @see https://www.w3.org/TR/xml/#NT-CharRef
49
+ * @param codePoint Unicode code point to convert.
50
+ */
51
+ export function replaceCodePointXML(codePoint: number): number {
52
+ return isInvalidCodePoint(codePoint) ? 0xff_fd : codePoint;
70
53
  }
71
54
 
72
55
  /**
73
- * Replace the code point if relevant, then convert it to a string.
56
+ * Convert the code point of a decoded numeric entity to a string, replacing
57
+ * invalid values.
74
58
  *
75
- * @deprecated Use `fromCodePoint(replaceCodePoint(codePoint))` instead.
76
- * @param codePoint The code point to decode.
77
- * @returns The decoded code point.
59
+ * Fast path for plain BMP code points: [1..0x7F] and [0xA0..0xD7FF] pass
60
+ * `replaceCodePoint` unchanged (no NUL, C1 remap, surrogate, or out-of-range
61
+ * handling) and fit a single charCode. 0xd760 = 0xD800 (the first surrogate)
62
+ * - 0xA0.
63
+ * @param codePoint Unicode code point to convert.
78
64
  */
79
- export function decodeCodePoint(codePoint: number): string {
80
- return fromCodePoint(replaceCodePoint(codePoint));
65
+ export function codePointToString(codePoint: number): string {
66
+ return (codePoint - 1) >>> 0 < 0x7f || (codePoint - 0xa0) >>> 0 < 0xd7_60
67
+ ? String.fromCharCode(codePoint)
68
+ : String.fromCodePoint(replaceCodePoint(codePoint));
81
69
  }