entities 8.0.0 → 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.
- package/dist/decode-codepoint.d.ts +23 -3
- package/dist/decode-codepoint.d.ts.map +1 -1
- package/dist/decode-codepoint.js +52 -37
- package/dist/decode-codepoint.js.map +1 -1
- package/dist/decode.d.ts +61 -28
- package/dist/decode.d.ts.map +1 -1
- package/dist/decode.js +789 -201
- package/dist/decode.js.map +1 -1
- package/dist/encode.d.ts +4 -2
- package/dist/encode.d.ts.map +1 -1
- package/dist/encode.js +249 -44
- package/dist/encode.js.map +1 -1
- package/dist/escape.d.ts +19 -7
- package/dist/escape.d.ts.map +1 -1
- package/dist/escape.js +104 -64
- package/dist/escape.js.map +1 -1
- package/dist/generated/decode-data-html.d.ts.map +1 -1
- package/dist/generated/decode-data-html.js +2 -2
- package/dist/generated/decode-data-html.js.map +1 -1
- package/dist/generated/decode-data-xml.d.ts.map +1 -1
- package/dist/generated/decode-data-xml.js +4 -2
- package/dist/generated/decode-data-xml.js.map +1 -1
- package/dist/generated/encode-html.d.ts +2 -4
- package/dist/generated/encode-html.d.ts.map +1 -1
- package/dist/generated/encode-html.js +1 -10
- package/dist/generated/encode-html.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -6
- package/dist/index.js.map +1 -1
- package/dist/internal/bin-trie-flags.d.ts +39 -8
- package/dist/internal/bin-trie-flags.d.ts.map +1 -1
- package/dist/internal/bin-trie-flags.js +37 -6
- package/dist/internal/bin-trie-flags.js.map +1 -1
- package/dist/internal/decode-shared.d.ts +35 -4
- package/dist/internal/decode-shared.d.ts.map +1 -1
- package/dist/internal/decode-shared.js +189 -11
- package/dist/internal/decode-shared.js.map +1 -1
- package/package.json +14 -14
- package/src/decode-codepoint.ts +58 -39
- package/src/decode.ts +942 -245
- package/src/encode.ts +289 -47
- package/src/escape.ts +110 -83
- package/src/generated/decode-data-html.ts +8 -3
- package/src/generated/decode-data-xml.ts +4 -4
- package/src/generated/encode-html.ts +1 -16
- package/src/index.ts +6 -8
- package/src/internal/bin-trie-flags.ts +38 -7
- package/src/internal/decode-shared.ts +203 -12
- package/dist/internal/encode-shared.d.ts +0 -33
- package/dist/internal/encode-shared.d.ts.map +0 -1
- package/dist/internal/encode-shared.js +0 -93
- package/dist/internal/encode-shared.js.map +0 -1
- package/src/internal/encode-shared.ts +0 -123
|
@@ -1,17 +1,48 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Bit flags & masks for the binary trie encoding used for entity decoding.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
4
|
+
* The trie is a flat `Uint16Array`. Every node starts with one header word:
|
|
5
|
+
*
|
|
6
|
+
* 15..14 VALUE_LENGTH Number of words the value occupies, +1.
|
|
7
|
+
* 0 = no value; 1 = value inline in bits 12..0;
|
|
8
|
+
* 2/3 = value in the 1/2 words after the header.
|
|
9
|
+
* 13 FLAG13 If VALUE_LENGTH > 0: semicolon required ("strict"
|
|
10
|
+
* entity; `;` is never stored as a branch).
|
|
11
|
+
* If VALUE_LENGTH == 0: this node is a compact run.
|
|
12
|
+
* 12..7 BRANCH_LENGTH Number of branches (or run length for runs).
|
|
13
|
+
* 6..0 JUMP_TABLE Jump-table offset / single-branch char / first
|
|
14
|
+
* run char (see below).
|
|
15
|
+
*
|
|
16
|
+
* Branch data follows the header and any value words. Its shape is selected
|
|
17
|
+
* by (JUMP_TABLE, BRANCH_LENGTH) in the header:
|
|
18
|
+
*
|
|
19
|
+
* Single branch JUMP_TABLE = the only child's char, BRANCH_LENGTH = 0.
|
|
20
|
+
* No branch words; the child node follows immediately.
|
|
21
|
+
* Jump table JUMP_TABLE = first covered char (> 0), BRANCH_LENGTH =
|
|
22
|
+
* table length. One word per covered char: 0 = no branch,
|
|
23
|
+
* otherwise the child's offset from the END of the table,
|
|
24
|
+
* +1 (so 0 stays the no-branch sentinel).
|
|
25
|
+
* Dictionary JUMP_TABLE = 0, BRANCH_LENGTH = number of branches.
|
|
26
|
+
* ceil(n/2) words of sorted keys packed two per word
|
|
27
|
+
* (low byte first), then n pointer words storing the
|
|
28
|
+
* child's offset from the END of the branch data.
|
|
29
|
+
* Compact run VALUE_LENGTH = 0, FLAG13 set. BRANCH_LENGTH = run
|
|
30
|
+
* length (3..63), JUMP_TABLE = first char; remaining run
|
|
31
|
+
* chars packed two per word after the header. The target
|
|
32
|
+
* node follows the packed words immediately.
|
|
33
|
+
*
|
|
34
|
+
* Pointers are end-relative (rather than relative to the pointer's own
|
|
35
|
+
* position) because that makes the common "child encoded right after the
|
|
36
|
+
* branch data" case a small constant, which compresses far better. Offsets
|
|
37
|
+
* to already-encoded (shared) nodes wrap via uint16 modulo arithmetic; the
|
|
38
|
+
* decoder masks navigation results with `& 0xff_ff` to match.
|
|
10
39
|
*/
|
|
11
|
-
export declare enum BinTrieFlags {
|
|
40
|
+
export declare const enum BinTrieFlags {
|
|
12
41
|
VALUE_LENGTH = 49152,
|
|
13
42
|
FLAG13 = 8192,
|
|
14
43
|
BRANCH_LENGTH = 8064,
|
|
15
|
-
JUMP_TABLE = 127
|
|
44
|
+
JUMP_TABLE = 127,
|
|
45
|
+
/** Bits 12..0: the inline value of a VALUE_LENGTH = 1 header word. */
|
|
46
|
+
VALUE_MASK = 8191
|
|
16
47
|
}
|
|
17
48
|
//# sourceMappingURL=bin-trie-flags.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bin-trie-flags.d.ts","sourceRoot":"","sources":["../../src/internal/bin-trie-flags.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"bin-trie-flags.d.ts","sourceRoot":"","sources":["../../src/internal/bin-trie-flags.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH,0BAAkB,YAAY;IAC1B,YAAY,QAAwB;IACpC,MAAM,OAAwB;IAC9B,aAAa,OAAwB;IACrC,UAAU,MAAwB;IAClC,sEAAsE;IACtE,UAAU,OAAwB;CACrC"}
|
|
@@ -1,12 +1,41 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Bit flags & masks for the binary trie encoding used for entity decoding.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
4
|
+
* The trie is a flat `Uint16Array`. Every node starts with one header word:
|
|
5
|
+
*
|
|
6
|
+
* 15..14 VALUE_LENGTH Number of words the value occupies, +1.
|
|
7
|
+
* 0 = no value; 1 = value inline in bits 12..0;
|
|
8
|
+
* 2/3 = value in the 1/2 words after the header.
|
|
9
|
+
* 13 FLAG13 If VALUE_LENGTH > 0: semicolon required ("strict"
|
|
10
|
+
* entity; `;` is never stored as a branch).
|
|
11
|
+
* If VALUE_LENGTH == 0: this node is a compact run.
|
|
12
|
+
* 12..7 BRANCH_LENGTH Number of branches (or run length for runs).
|
|
13
|
+
* 6..0 JUMP_TABLE Jump-table offset / single-branch char / first
|
|
14
|
+
* run char (see below).
|
|
15
|
+
*
|
|
16
|
+
* Branch data follows the header and any value words. Its shape is selected
|
|
17
|
+
* by (JUMP_TABLE, BRANCH_LENGTH) in the header:
|
|
18
|
+
*
|
|
19
|
+
* Single branch JUMP_TABLE = the only child's char, BRANCH_LENGTH = 0.
|
|
20
|
+
* No branch words; the child node follows immediately.
|
|
21
|
+
* Jump table JUMP_TABLE = first covered char (> 0), BRANCH_LENGTH =
|
|
22
|
+
* table length. One word per covered char: 0 = no branch,
|
|
23
|
+
* otherwise the child's offset from the END of the table,
|
|
24
|
+
* +1 (so 0 stays the no-branch sentinel).
|
|
25
|
+
* Dictionary JUMP_TABLE = 0, BRANCH_LENGTH = number of branches.
|
|
26
|
+
* ceil(n/2) words of sorted keys packed two per word
|
|
27
|
+
* (low byte first), then n pointer words storing the
|
|
28
|
+
* child's offset from the END of the branch data.
|
|
29
|
+
* Compact run VALUE_LENGTH = 0, FLAG13 set. BRANCH_LENGTH = run
|
|
30
|
+
* length (3..63), JUMP_TABLE = first char; remaining run
|
|
31
|
+
* chars packed two per word after the header. The target
|
|
32
|
+
* node follows the packed words immediately.
|
|
33
|
+
*
|
|
34
|
+
* Pointers are end-relative (rather than relative to the pointer's own
|
|
35
|
+
* position) because that makes the common "child encoded right after the
|
|
36
|
+
* branch data" case a small constant, which compresses far better. Offsets
|
|
37
|
+
* to already-encoded (shared) nodes wrap via uint16 modulo arithmetic; the
|
|
38
|
+
* decoder masks navigation results with `& 0xff_ff` to match.
|
|
10
39
|
*/
|
|
11
40
|
export var BinTrieFlags;
|
|
12
41
|
(function (BinTrieFlags) {
|
|
@@ -14,5 +43,7 @@ export var BinTrieFlags;
|
|
|
14
43
|
BinTrieFlags[BinTrieFlags["FLAG13"] = 8192] = "FLAG13";
|
|
15
44
|
BinTrieFlags[BinTrieFlags["BRANCH_LENGTH"] = 8064] = "BRANCH_LENGTH";
|
|
16
45
|
BinTrieFlags[BinTrieFlags["JUMP_TABLE"] = 127] = "JUMP_TABLE";
|
|
46
|
+
/** Bits 12..0: the inline value of a VALUE_LENGTH = 1 header word. */
|
|
47
|
+
BinTrieFlags[BinTrieFlags["VALUE_MASK"] = 8191] = "VALUE_MASK";
|
|
17
48
|
})(BinTrieFlags || (BinTrieFlags = {}));
|
|
18
49
|
//# sourceMappingURL=bin-trie-flags.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bin-trie-flags.js","sourceRoot":"","sources":["../../src/internal/bin-trie-flags.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"bin-trie-flags.js","sourceRoot":"","sources":["../../src/internal/bin-trie-flags.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH,MAAM,CAAN,IAAkB,YAOjB;AAPD,WAAkB,YAAY;IAC1B,mEAAoC,CAAA;IACpC,sDAA8B,CAAA;IAC9B,oEAAqC,CAAA;IACrC,6DAAkC,CAAA;IAClC,sEAAsE;IACtE,8DAAkC,CAAA;AACtC,CAAC,EAPiB,YAAY,KAAZ,YAAY,QAO7B"}
|
|
@@ -1,7 +1,38 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
2
|
+
* Decode a dictionary-encoded trie string back into its Uint16Array.
|
|
3
|
+
*
|
|
4
|
+
* Stream layout (consumed in this order):
|
|
5
|
+
* 1. dict1 atoms — `dict1AtomCount` uint16 values, delta+RLE encoded.
|
|
6
|
+
* 2. dict2 atoms — `atomCount - dict1AtomCount` values, delta+RLE.
|
|
7
|
+
* 3. dict2 ngrams — `ngramCount - (dictSize - dict1AtomCount)` entries,
|
|
8
|
+
* each a pair of slot codes that resolve to earlier slots.
|
|
9
|
+
* 4. dict1 ngrams — `dictSize - dict1AtomCount` entries, same shape.
|
|
10
|
+
* 5. data — slot codes, each expanding to one or more uint16 values.
|
|
11
|
+
*
|
|
12
|
+
* Codes use a 91-char base (printable ASCII minus `"`, `$`, `\`):
|
|
13
|
+
* - char1 < dictSize → 1-char code, slot = char1
|
|
14
|
+
* - char1 ≥ dictSize → 2-char code, slot = dictSize + (char1 - dictSize)*91 + char2
|
|
15
|
+
*
|
|
16
|
+
* Slot index → token kind:
|
|
17
|
+
* [0, A) dict1 atoms (1-char codes)
|
|
18
|
+
* [A, dictSize) dict1 ngrams (1-char codes)
|
|
19
|
+
* [dictSize, dictSize+D) dict2 atoms (2-char codes)
|
|
20
|
+
* [dictSize+D, end) dict2 ngrams (2-char codes)
|
|
21
|
+
*
|
|
22
|
+
* Both atom dicts decode before any ngram, and dict2 ngrams decode before
|
|
23
|
+
* dict1 ngrams. So every ngram entry references slots whose contents are
|
|
24
|
+
* already filled — no forward references to handle.
|
|
25
|
+
*
|
|
26
|
+
* This runs on library import. Flat typed arrays store each slot as either
|
|
27
|
+
* a plain value (`single`, covering every atom) or a range in a shared
|
|
28
|
+
* `pool` (ngrams).
|
|
29
|
+
* @param input Packed trie string.
|
|
30
|
+
* @param resultLength Expected number of uint16 values in the output.
|
|
31
|
+
* @param atomCount Total number of distinct uint16 values in the trie.
|
|
32
|
+
* @param dict1AtomCount Atoms in the 1-char range (`A` above).
|
|
33
|
+
* @param ngramCount Total number of ngram entries (dict1 + dict2).
|
|
34
|
+
* @param dictSize Number of 1-char code slots; the rest of `BASE - dictSize`
|
|
35
|
+
* first-byte values are 2-char codes.
|
|
5
36
|
*/
|
|
6
|
-
export declare function
|
|
37
|
+
export declare function decodeTrieDict(input: string, resultLength: number, atomCount: number, dict1AtomCount: number, ngramCount: number, dictSize: number): Uint16Array;
|
|
7
38
|
//# sourceMappingURL=decode-shared.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"decode-shared.d.ts","sourceRoot":"","sources":["../../src/internal/decode-shared.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"decode-shared.d.ts","sourceRoot":"","sources":["../../src/internal/decode-shared.ts"],"names":[],"mappings":"AAgBA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,wBAAgB,cAAc,CAC1B,KAAK,EAAE,MAAM,EACb,YAAY,EAAE,MAAM,EACpB,SAAS,EAAE,MAAM,EACjB,cAAc,EAAE,MAAM,EACtB,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,GACjB,WAAW,CAqJb"}
|
|
@@ -1,16 +1,194 @@
|
|
|
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
|
+
})();
|
|
1
16
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
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.
|
|
5
51
|
*/
|
|
6
|
-
export function
|
|
7
|
-
const
|
|
8
|
-
const
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
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
|
+
}
|
|
14
192
|
}
|
|
15
193
|
return out;
|
|
16
194
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"decode-shared.js","sourceRoot":"","sources":["../../src/internal/decode-shared.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,UAAU,
|
|
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": "8.
|
|
3
|
+
"version": "8.1.0",
|
|
4
4
|
"description": "Encode & decode XML and HTML entities with ease & speed",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"html entities",
|
|
@@ -53,29 +53,29 @@
|
|
|
53
53
|
"lint": "npm run lint:es && npm run lint:ts && npm run lint:biome",
|
|
54
54
|
"lint:biome": "biome check .",
|
|
55
55
|
"lint:es": "eslint .",
|
|
56
|
-
"lint:ts": "tsc --noEmit",
|
|
56
|
+
"lint:ts": "tsc --noEmit -p tsconfig.eslint.json",
|
|
57
57
|
"prepublishOnly": "npm run build",
|
|
58
58
|
"test": "npm run test:vi && npm run lint",
|
|
59
59
|
"test:vi": "vitest run"
|
|
60
60
|
},
|
|
61
61
|
"devDependencies": {
|
|
62
|
-
"@biomejs/biome": "^2.
|
|
63
|
-
"@eslint/compat": "^2.
|
|
64
|
-
"@feedic/eslint-config": "^0.
|
|
62
|
+
"@biomejs/biome": "^2.5.12",
|
|
63
|
+
"@eslint/compat": "^2.1.1",
|
|
64
|
+
"@feedic/eslint-config": "^0.5.0",
|
|
65
65
|
"@types/he": "^1.2.3",
|
|
66
|
-
"@types/node": "^
|
|
67
|
-
"eslint": "^10.0
|
|
66
|
+
"@types/node": "^26.4.1",
|
|
67
|
+
"eslint": "^10.10.0",
|
|
68
68
|
"eslint-config-biome": "^2.1.3",
|
|
69
|
-
"globals": "^17.
|
|
69
|
+
"globals": "^17.12.0",
|
|
70
70
|
"he": "^1.2.0",
|
|
71
71
|
"html-entities": "^2.6.0",
|
|
72
72
|
"parse-entities": "^4.0.2",
|
|
73
|
-
"tinybench": "^6.
|
|
74
|
-
"tsx": "^4.
|
|
75
|
-
"typedoc": "^0.28.
|
|
76
|
-
"typescript": "^
|
|
77
|
-
"typescript-eslint": "^8.
|
|
78
|
-
"vitest": "^
|
|
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"
|
|
79
79
|
},
|
|
80
80
|
"engines": {
|
|
81
81
|
"node": ">=20.19.0"
|
package/src/decode-codepoint.ts
CHANGED
|
@@ -1,50 +1,69 @@
|
|
|
1
1
|
// Adapted from https://github.com/mathiasbynens/he/blob/36afe179392226cf1b6ccdb16ebbb7a5a844d93a/src/he.js#L106-L134
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
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
|
-
]);
|
|
3
|
+
/**
|
|
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".
|
|
6
|
+
*/
|
|
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
|
+
];
|
|
34
12
|
|
|
35
13
|
/**
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
* point unchanged.
|
|
39
|
-
* @param codePoint Unicode code point to convert.
|
|
14
|
+
* True for NUL, UTF-16 surrogates, and values past U+10FFFF.
|
|
15
|
+
* @param codePoint Unicode code point to check.
|
|
40
16
|
*/
|
|
41
|
-
|
|
42
|
-
|
|
17
|
+
function isInvalidCodePoint(codePoint: number): boolean {
|
|
18
|
+
return (
|
|
19
|
+
codePoint === 0 ||
|
|
43
20
|
(codePoint >= 0xd8_00 && codePoint <= 0xdf_ff) ||
|
|
44
21
|
codePoint > 0x10_ff_ff
|
|
45
|
-
)
|
|
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)) {
|
|
46
34
|
return 0xff_fd;
|
|
47
35
|
}
|
|
48
36
|
|
|
49
|
-
|
|
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;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Convert the code point of a decoded numeric entity to a string, replacing
|
|
57
|
+
* invalid values.
|
|
58
|
+
*
|
|
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.
|
|
64
|
+
*/
|
|
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));
|
|
50
69
|
}
|