entities 6.0.1 → 7.0.1
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/decode.d.ts +2 -0
- package/dist/commonjs/decode-codepoint.d.ts.map +1 -1
- package/dist/commonjs/decode-codepoint.js +2 -2
- package/dist/commonjs/decode-codepoint.js.map +1 -1
- package/dist/commonjs/decode.d.ts +3 -7
- package/dist/commonjs/decode.d.ts.map +1 -1
- package/dist/commonjs/decode.js +105 -48
- package/dist/commonjs/decode.js.map +1 -1
- package/dist/commonjs/encode.d.ts.map +1 -1
- package/dist/commonjs/encode.js +49 -30
- package/dist/commonjs/encode.js.map +1 -1
- package/dist/commonjs/escape.d.ts +7 -4
- package/dist/commonjs/escape.d.ts.map +1 -1
- package/dist/commonjs/escape.js +36 -19
- package/dist/commonjs/escape.js.map +1 -1
- package/dist/commonjs/generated/decode-data-html.d.ts.map +1 -1
- package/dist/commonjs/generated/decode-data-html.js +2 -5
- package/dist/commonjs/generated/decode-data-html.js.map +1 -1
- package/dist/commonjs/generated/decode-data-xml.d.ts.map +1 -1
- package/dist/commonjs/generated/decode-data-xml.js +2 -5
- package/dist/commonjs/generated/decode-data-xml.js.map +1 -1
- package/dist/commonjs/generated/encode-html.d.ts +1 -6
- package/dist/commonjs/generated/encode-html.d.ts.map +1 -1
- package/dist/commonjs/generated/encode-html.js +9 -8
- package/dist/commonjs/generated/encode-html.js.map +1 -1
- package/dist/commonjs/index.d.ts +3 -3
- package/dist/commonjs/index.d.ts.map +1 -1
- package/dist/commonjs/index.js +19 -19
- package/dist/commonjs/index.js.map +1 -1
- package/dist/commonjs/internal/bin-trie-flags.d.ts +17 -0
- package/dist/commonjs/internal/bin-trie-flags.d.ts.map +1 -0
- package/dist/commonjs/internal/bin-trie-flags.js +21 -0
- package/dist/commonjs/internal/bin-trie-flags.js.map +1 -0
- package/dist/commonjs/internal/decode-shared.d.ts +2 -0
- package/dist/commonjs/internal/decode-shared.d.ts.map +1 -0
- package/dist/commonjs/internal/decode-shared.js +31 -0
- package/dist/commonjs/internal/decode-shared.js.map +1 -0
- package/dist/commonjs/internal/encode-shared.d.ts +32 -0
- package/dist/commonjs/internal/encode-shared.d.ts.map +1 -0
- package/dist/commonjs/internal/encode-shared.js +94 -0
- package/dist/commonjs/internal/encode-shared.js.map +1 -0
- package/dist/esm/decode-codepoint.d.ts.map +1 -1
- package/dist/esm/decode-codepoint.js +2 -2
- package/dist/esm/decode-codepoint.js.map +1 -1
- package/dist/esm/decode.d.ts +3 -7
- package/dist/esm/decode.d.ts.map +1 -1
- package/dist/esm/decode.js +96 -39
- package/dist/esm/decode.js.map +1 -1
- package/dist/esm/encode.d.ts.map +1 -1
- package/dist/esm/encode.js +49 -30
- package/dist/esm/encode.js.map +1 -1
- package/dist/esm/escape.d.ts +7 -4
- package/dist/esm/escape.d.ts.map +1 -1
- package/dist/esm/escape.js +35 -18
- package/dist/esm/escape.js.map +1 -1
- package/dist/esm/generated/decode-data-html.d.ts.map +1 -1
- package/dist/esm/generated/decode-data-html.js +2 -5
- package/dist/esm/generated/decode-data-html.js.map +1 -1
- package/dist/esm/generated/decode-data-xml.d.ts.map +1 -1
- package/dist/esm/generated/decode-data-xml.js +2 -5
- package/dist/esm/generated/decode-data-xml.js.map +1 -1
- package/dist/esm/generated/encode-html.d.ts +1 -6
- package/dist/esm/generated/encode-html.d.ts.map +1 -1
- package/dist/esm/generated/encode-html.js +9 -8
- package/dist/esm/generated/encode-html.js.map +1 -1
- package/dist/esm/index.d.ts +3 -3
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +9 -9
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/internal/bin-trie-flags.d.ts +17 -0
- package/dist/esm/internal/bin-trie-flags.d.ts.map +1 -0
- package/dist/esm/internal/bin-trie-flags.js +18 -0
- package/dist/esm/internal/bin-trie-flags.js.map +1 -0
- package/dist/esm/internal/decode-shared.d.ts +2 -0
- package/dist/esm/internal/decode-shared.d.ts.map +1 -0
- package/dist/esm/internal/decode-shared.js +28 -0
- package/dist/esm/internal/decode-shared.js.map +1 -0
- package/dist/esm/internal/encode-shared.d.ts +32 -0
- package/dist/esm/internal/encode-shared.d.ts.map +1 -0
- package/dist/esm/internal/encode-shared.js +91 -0
- package/dist/esm/internal/encode-shared.js.map +1 -0
- package/escape.d.ts +2 -0
- package/package.json +26 -24
- package/readme.md +32 -11
- package/src/decode-codepoint.ts +2 -2
- package/src/decode.ts +120 -55
- package/src/encode.ts +47 -31
- package/src/escape.ts +39 -26
- package/src/generated/decode-data-html.ts +3 -5
- package/src/generated/decode-data-xml.ts +3 -5
- package/src/generated/encode-html.ts +14 -14
- package/src/index.ts +23 -24
- package/src/internal/bin-trie-flags.ts +16 -0
- package/src/internal/decode-shared.ts +30 -0
- package/src/internal/encode-shared.ts +121 -0
- package/src/decode.spec.ts +0 -320
- package/src/encode.spec.ts +0 -78
- package/src/escape.spec.ts +0 -14
- package/src/index.spec.ts +0 -125
package/src/decode.spec.ts
DELETED
|
@@ -1,320 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, vitest } from "vitest";
|
|
2
|
-
import * as entities from "./decode.js";
|
|
3
|
-
|
|
4
|
-
describe("Decode test", () => {
|
|
5
|
-
const testcases = [
|
|
6
|
-
{ input: "&", output: "&" },
|
|
7
|
-
{ input: "&", output: "&" },
|
|
8
|
-
{ input: "&", output: "&" },
|
|
9
|
-
{ input: "&", output: "&" },
|
|
10
|
-
{ input: "&", output: "&" },
|
|
11
|
-
{ input: "&", output: "&" },
|
|
12
|
-
{ input: "&", output: "&" },
|
|
13
|
-
{ input: ":", output: ":" },
|
|
14
|
-
{ input: ":", output: ":" },
|
|
15
|
-
{ input: ":", output: ":" },
|
|
16
|
-
{ input: ":", output: ":" },
|
|
17
|
-
{ input: "&#", output: "&#" },
|
|
18
|
-
{ input: "&>", output: "&>" },
|
|
19
|
-
{ input: "id=770&#anchor", output: "id=770&#anchor" },
|
|
20
|
-
];
|
|
21
|
-
|
|
22
|
-
for (const { input, output } of testcases) {
|
|
23
|
-
it(`should XML decode ${input}`, () =>
|
|
24
|
-
expect(entities.decodeXML(input)).toBe(output));
|
|
25
|
-
it(`should HTML decode ${input}`, () =>
|
|
26
|
-
expect(entities.decodeHTML(input)).toBe(output));
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
it("should HTML decode partial legacy entity", () => {
|
|
30
|
-
expect(entities.decodeHTMLStrict("×bar")).toBe("×bar");
|
|
31
|
-
expect(entities.decodeHTML("×bar")).toBe("×bar");
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
it("should HTML decode legacy entities according to spec", () =>
|
|
35
|
-
expect(entities.decodeHTML("?&image_uri=1&ℑ=2&image=3")).toBe(
|
|
36
|
-
"?&image_uri=1&ℑ=2&image=3",
|
|
37
|
-
));
|
|
38
|
-
|
|
39
|
-
it("should back out of legacy entities", () =>
|
|
40
|
-
expect(entities.decodeHTML("&a")).toBe("&a"));
|
|
41
|
-
|
|
42
|
-
it("should not parse numeric entities in strict mode", () =>
|
|
43
|
-
expect(entities.decodeHTMLStrict("7")).toBe("7"));
|
|
44
|
-
|
|
45
|
-
it("should parse   followed by < (#852)", () =>
|
|
46
|
-
expect(entities.decodeHTML(" <")).toBe("\u00A0<"));
|
|
47
|
-
|
|
48
|
-
it("should decode trailing legacy entities", () => {
|
|
49
|
-
expect(entities.decodeHTML("⨱×bar")).toBe("⨱×bar");
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
it("should decode multi-byte entities", () => {
|
|
53
|
-
expect(entities.decodeHTML("≧̸")).toBe("≧̸");
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
it("should not decode legacy entities followed by text in attribute mode", () => {
|
|
57
|
-
expect(
|
|
58
|
-
entities.decodeHTML("¬", entities.DecodingMode.Attribute),
|
|
59
|
-
).toBe("¬");
|
|
60
|
-
|
|
61
|
-
expect(
|
|
62
|
-
entities.decodeHTML("¬i", entities.DecodingMode.Attribute),
|
|
63
|
-
).toBe("¬i");
|
|
64
|
-
|
|
65
|
-
expect(
|
|
66
|
-
entities.decodeHTML("¬=", entities.DecodingMode.Attribute),
|
|
67
|
-
).toBe("¬=");
|
|
68
|
-
|
|
69
|
-
expect(entities.decodeHTMLAttribute("¬p")).toBe("¬p");
|
|
70
|
-
expect(entities.decodeHTMLAttribute("¬P")).toBe("¬P");
|
|
71
|
-
expect(entities.decodeHTMLAttribute("¬3")).toBe("¬3");
|
|
72
|
-
});
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
describe("EntityDecoder", () => {
|
|
76
|
-
it("should decode decimal entities", () => {
|
|
77
|
-
const callback = vitest.fn();
|
|
78
|
-
const decoder = new entities.EntityDecoder(
|
|
79
|
-
entities.htmlDecodeTree,
|
|
80
|
-
callback,
|
|
81
|
-
);
|
|
82
|
-
|
|
83
|
-
expect(decoder.write("", 1)).toBe(-1);
|
|
84
|
-
expect(decoder.write("8;", 0)).toBe(5);
|
|
85
|
-
|
|
86
|
-
expect(callback).toHaveBeenCalledTimes(1);
|
|
87
|
-
expect(callback).toHaveBeenCalledWith(":".charCodeAt(0), 5);
|
|
88
|
-
});
|
|
89
|
-
|
|
90
|
-
it("should decode hex entities", () => {
|
|
91
|
-
const callback = vitest.fn();
|
|
92
|
-
const decoder = new entities.EntityDecoder(
|
|
93
|
-
entities.htmlDecodeTree,
|
|
94
|
-
callback,
|
|
95
|
-
);
|
|
96
|
-
|
|
97
|
-
expect(decoder.write(":", 1)).toBe(6);
|
|
98
|
-
|
|
99
|
-
expect(callback).toHaveBeenCalledTimes(1);
|
|
100
|
-
expect(callback).toHaveBeenCalledWith(":".charCodeAt(0), 6);
|
|
101
|
-
});
|
|
102
|
-
|
|
103
|
-
it("should decode named entities", () => {
|
|
104
|
-
const callback = vitest.fn();
|
|
105
|
-
const decoder = new entities.EntityDecoder(
|
|
106
|
-
entities.htmlDecodeTree,
|
|
107
|
-
callback,
|
|
108
|
-
);
|
|
109
|
-
|
|
110
|
-
expect(decoder.write("&", 1)).toBe(5);
|
|
111
|
-
|
|
112
|
-
expect(callback).toHaveBeenCalledTimes(1);
|
|
113
|
-
expect(callback).toHaveBeenCalledWith("&".charCodeAt(0), 5);
|
|
114
|
-
});
|
|
115
|
-
|
|
116
|
-
it("should decode legacy entities", () => {
|
|
117
|
-
const callback = vitest.fn();
|
|
118
|
-
const decoder = new entities.EntityDecoder(
|
|
119
|
-
entities.htmlDecodeTree,
|
|
120
|
-
callback,
|
|
121
|
-
);
|
|
122
|
-
decoder.startEntity(entities.DecodingMode.Legacy);
|
|
123
|
-
|
|
124
|
-
expect(decoder.write("&", 1)).toBe(-1);
|
|
125
|
-
|
|
126
|
-
expect(callback).toHaveBeenCalledTimes(0);
|
|
127
|
-
|
|
128
|
-
expect(decoder.end()).toBe(4);
|
|
129
|
-
|
|
130
|
-
expect(callback).toHaveBeenCalledTimes(1);
|
|
131
|
-
expect(callback).toHaveBeenCalledWith("&".charCodeAt(0), 4);
|
|
132
|
-
});
|
|
133
|
-
|
|
134
|
-
it("should decode named entity written character by character", () => {
|
|
135
|
-
const callback = vitest.fn();
|
|
136
|
-
const decoder = new entities.EntityDecoder(
|
|
137
|
-
entities.htmlDecodeTree,
|
|
138
|
-
callback,
|
|
139
|
-
);
|
|
140
|
-
|
|
141
|
-
for (const c of "amp") {
|
|
142
|
-
expect(decoder.write(c, 0)).toBe(-1);
|
|
143
|
-
}
|
|
144
|
-
expect(decoder.write(";", 0)).toBe(5);
|
|
145
|
-
|
|
146
|
-
expect(callback).toHaveBeenCalledTimes(1);
|
|
147
|
-
expect(callback).toHaveBeenCalledWith("&".charCodeAt(0), 5);
|
|
148
|
-
});
|
|
149
|
-
|
|
150
|
-
it("should decode numeric entity written character by character", () => {
|
|
151
|
-
const callback = vitest.fn();
|
|
152
|
-
const decoder = new entities.EntityDecoder(
|
|
153
|
-
entities.htmlDecodeTree,
|
|
154
|
-
callback,
|
|
155
|
-
);
|
|
156
|
-
|
|
157
|
-
for (const c of "#x3a") {
|
|
158
|
-
expect(decoder.write(c, 0)).toBe(-1);
|
|
159
|
-
}
|
|
160
|
-
expect(decoder.write(";", 0)).toBe(6);
|
|
161
|
-
|
|
162
|
-
expect(callback).toHaveBeenCalledTimes(1);
|
|
163
|
-
expect(callback).toHaveBeenCalledWith(":".charCodeAt(0), 6);
|
|
164
|
-
});
|
|
165
|
-
|
|
166
|
-
it("should decode hex entities across several chunks", () => {
|
|
167
|
-
const callback = vitest.fn();
|
|
168
|
-
const decoder = new entities.EntityDecoder(
|
|
169
|
-
entities.htmlDecodeTree,
|
|
170
|
-
callback,
|
|
171
|
-
);
|
|
172
|
-
|
|
173
|
-
for (const chunk of ["#x", "cf", "ff", "d"]) {
|
|
174
|
-
expect(decoder.write(chunk, 0)).toBe(-1);
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
expect(decoder.write(";", 0)).toBe(9);
|
|
178
|
-
expect(callback).toHaveBeenCalledTimes(1);
|
|
179
|
-
expect(callback).toHaveBeenCalledWith(0xc_ff_fd, 9);
|
|
180
|
-
});
|
|
181
|
-
|
|
182
|
-
it("should not fail if nothing is written", () => {
|
|
183
|
-
const callback = vitest.fn();
|
|
184
|
-
const decoder = new entities.EntityDecoder(
|
|
185
|
-
entities.htmlDecodeTree,
|
|
186
|
-
callback,
|
|
187
|
-
);
|
|
188
|
-
|
|
189
|
-
expect(decoder.end()).toBe(0);
|
|
190
|
-
expect(callback).toHaveBeenCalledTimes(0);
|
|
191
|
-
});
|
|
192
|
-
|
|
193
|
-
describe("errors", () => {
|
|
194
|
-
it("should produce an error for a named entity without a semicolon", () => {
|
|
195
|
-
const errorHandlers = {
|
|
196
|
-
missingSemicolonAfterCharacterReference: vitest.fn(),
|
|
197
|
-
absenceOfDigitsInNumericCharacterReference: vitest.fn(),
|
|
198
|
-
validateNumericCharacterReference: vitest.fn(),
|
|
199
|
-
};
|
|
200
|
-
const callback = vitest.fn();
|
|
201
|
-
const decoder = new entities.EntityDecoder(
|
|
202
|
-
entities.htmlDecodeTree,
|
|
203
|
-
callback,
|
|
204
|
-
errorHandlers,
|
|
205
|
-
);
|
|
206
|
-
|
|
207
|
-
decoder.startEntity(entities.DecodingMode.Legacy);
|
|
208
|
-
expect(decoder.write("&", 1)).toBe(5);
|
|
209
|
-
expect(callback).toHaveBeenCalledTimes(1);
|
|
210
|
-
expect(callback).toHaveBeenCalledWith("&".charCodeAt(0), 5);
|
|
211
|
-
expect(
|
|
212
|
-
errorHandlers.missingSemicolonAfterCharacterReference,
|
|
213
|
-
).toHaveBeenCalledTimes(0);
|
|
214
|
-
|
|
215
|
-
decoder.startEntity(entities.DecodingMode.Legacy);
|
|
216
|
-
expect(decoder.write("&", 1)).toBe(-1);
|
|
217
|
-
expect(decoder.end()).toBe(4);
|
|
218
|
-
|
|
219
|
-
expect(callback).toHaveBeenCalledTimes(2);
|
|
220
|
-
expect(callback).toHaveBeenLastCalledWith("&".charCodeAt(0), 4);
|
|
221
|
-
expect(
|
|
222
|
-
errorHandlers.missingSemicolonAfterCharacterReference,
|
|
223
|
-
).toHaveBeenCalledTimes(1);
|
|
224
|
-
});
|
|
225
|
-
|
|
226
|
-
it("should produce an error for a numeric entity without a semicolon", () => {
|
|
227
|
-
const errorHandlers = {
|
|
228
|
-
missingSemicolonAfterCharacterReference: vitest.fn(),
|
|
229
|
-
absenceOfDigitsInNumericCharacterReference: vitest.fn(),
|
|
230
|
-
validateNumericCharacterReference: vitest.fn(),
|
|
231
|
-
};
|
|
232
|
-
const callback = vitest.fn();
|
|
233
|
-
const decoder = new entities.EntityDecoder(
|
|
234
|
-
entities.htmlDecodeTree,
|
|
235
|
-
callback,
|
|
236
|
-
errorHandlers,
|
|
237
|
-
);
|
|
238
|
-
|
|
239
|
-
decoder.startEntity(entities.DecodingMode.Legacy);
|
|
240
|
-
expect(decoder.write(":", 1)).toBe(-1);
|
|
241
|
-
expect(decoder.end()).toBe(5);
|
|
242
|
-
|
|
243
|
-
expect(callback).toHaveBeenCalledTimes(1);
|
|
244
|
-
expect(callback).toHaveBeenCalledWith(0x3a, 5);
|
|
245
|
-
expect(
|
|
246
|
-
errorHandlers.missingSemicolonAfterCharacterReference,
|
|
247
|
-
).toHaveBeenCalledTimes(1);
|
|
248
|
-
expect(
|
|
249
|
-
errorHandlers.absenceOfDigitsInNumericCharacterReference,
|
|
250
|
-
).toHaveBeenCalledTimes(0);
|
|
251
|
-
expect(
|
|
252
|
-
errorHandlers.validateNumericCharacterReference,
|
|
253
|
-
).toHaveBeenCalledTimes(1);
|
|
254
|
-
expect(
|
|
255
|
-
errorHandlers.validateNumericCharacterReference,
|
|
256
|
-
).toHaveBeenCalledWith(0x3a);
|
|
257
|
-
});
|
|
258
|
-
|
|
259
|
-
it("should produce an error for numeric entities without digits", () => {
|
|
260
|
-
const errorHandlers = {
|
|
261
|
-
missingSemicolonAfterCharacterReference: vitest.fn(),
|
|
262
|
-
absenceOfDigitsInNumericCharacterReference: vitest.fn(),
|
|
263
|
-
validateNumericCharacterReference: vitest.fn(),
|
|
264
|
-
};
|
|
265
|
-
const callback = vitest.fn();
|
|
266
|
-
const decoder = new entities.EntityDecoder(
|
|
267
|
-
entities.htmlDecodeTree,
|
|
268
|
-
callback,
|
|
269
|
-
errorHandlers,
|
|
270
|
-
);
|
|
271
|
-
|
|
272
|
-
decoder.startEntity(entities.DecodingMode.Legacy);
|
|
273
|
-
expect(decoder.write("&#", 1)).toBe(-1);
|
|
274
|
-
expect(decoder.end()).toBe(0);
|
|
275
|
-
|
|
276
|
-
expect(callback).toHaveBeenCalledTimes(0);
|
|
277
|
-
expect(
|
|
278
|
-
errorHandlers.missingSemicolonAfterCharacterReference,
|
|
279
|
-
).toHaveBeenCalledTimes(0);
|
|
280
|
-
expect(
|
|
281
|
-
errorHandlers.absenceOfDigitsInNumericCharacterReference,
|
|
282
|
-
).toHaveBeenCalledTimes(1);
|
|
283
|
-
expect(
|
|
284
|
-
errorHandlers.absenceOfDigitsInNumericCharacterReference,
|
|
285
|
-
).toHaveBeenCalledWith(2);
|
|
286
|
-
expect(
|
|
287
|
-
errorHandlers.validateNumericCharacterReference,
|
|
288
|
-
).toHaveBeenCalledTimes(0);
|
|
289
|
-
});
|
|
290
|
-
|
|
291
|
-
it("should produce an error for hex entities without digits", () => {
|
|
292
|
-
const errorHandlers = {
|
|
293
|
-
missingSemicolonAfterCharacterReference: vitest.fn(),
|
|
294
|
-
absenceOfDigitsInNumericCharacterReference: vitest.fn(),
|
|
295
|
-
validateNumericCharacterReference: vitest.fn(),
|
|
296
|
-
};
|
|
297
|
-
const callback = vitest.fn();
|
|
298
|
-
const decoder = new entities.EntityDecoder(
|
|
299
|
-
entities.htmlDecodeTree,
|
|
300
|
-
callback,
|
|
301
|
-
errorHandlers,
|
|
302
|
-
);
|
|
303
|
-
|
|
304
|
-
decoder.startEntity(entities.DecodingMode.Legacy);
|
|
305
|
-
expect(decoder.write("&#x", 1)).toBe(-1);
|
|
306
|
-
expect(decoder.end()).toBe(0);
|
|
307
|
-
|
|
308
|
-
expect(callback).toHaveBeenCalledTimes(0);
|
|
309
|
-
expect(
|
|
310
|
-
errorHandlers.missingSemicolonAfterCharacterReference,
|
|
311
|
-
).toHaveBeenCalledTimes(0);
|
|
312
|
-
expect(
|
|
313
|
-
errorHandlers.absenceOfDigitsInNumericCharacterReference,
|
|
314
|
-
).toHaveBeenCalledTimes(1);
|
|
315
|
-
expect(
|
|
316
|
-
errorHandlers.validateNumericCharacterReference,
|
|
317
|
-
).toHaveBeenCalledTimes(0);
|
|
318
|
-
});
|
|
319
|
-
});
|
|
320
|
-
});
|
package/src/encode.spec.ts
DELETED
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect } from "vitest";
|
|
2
|
-
import * as entities from "./index.js";
|
|
3
|
-
|
|
4
|
-
describe("Encode->decode test", () => {
|
|
5
|
-
const testcases = [
|
|
6
|
-
{
|
|
7
|
-
input: "asdf & ÿ ü '",
|
|
8
|
-
xml: "asdf & ÿ ü '",
|
|
9
|
-
html: "asdf & ÿ ü '",
|
|
10
|
-
},
|
|
11
|
-
{
|
|
12
|
-
input: "&",
|
|
13
|
-
xml: "&#38;",
|
|
14
|
-
html: "&#38;",
|
|
15
|
-
},
|
|
16
|
-
];
|
|
17
|
-
|
|
18
|
-
for (const { input, xml, html } of testcases) {
|
|
19
|
-
const encodedXML = entities.encodeXML(input);
|
|
20
|
-
it(`should XML encode ${input}`, () => expect(encodedXML).toBe(xml));
|
|
21
|
-
it(`should default to XML encode ${input}`, () =>
|
|
22
|
-
expect(entities.encode(input)).toBe(xml));
|
|
23
|
-
it(`should XML decode ${encodedXML}`, () =>
|
|
24
|
-
expect(entities.decodeXML(encodedXML)).toBe(input));
|
|
25
|
-
it(`should default to XML encode ${encodedXML}`, () =>
|
|
26
|
-
expect(entities.decode(encodedXML)).toBe(input));
|
|
27
|
-
it(`should default strict to XML encode ${encodedXML}`, () =>
|
|
28
|
-
expect(entities.decodeStrict(encodedXML)).toBe(input));
|
|
29
|
-
|
|
30
|
-
const encodedHTML5 = entities.encodeHTML5(input);
|
|
31
|
-
it(`should HTML5 encode ${input}`, () =>
|
|
32
|
-
expect(encodedHTML5).toBe(html));
|
|
33
|
-
it(`should HTML5 decode ${encodedHTML5}`, () =>
|
|
34
|
-
expect(entities.decodeHTML(encodedHTML5)).toBe(input));
|
|
35
|
-
it("should encode emojis", () =>
|
|
36
|
-
expect(entities.encodeHTML5("😄🍾🥳💥😇")).toBe(
|
|
37
|
-
"😄🍾🥳💥😇",
|
|
38
|
-
));
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
it("should encode data URIs (issue #16)", () => {
|
|
42
|
-
const data =
|
|
43
|
-
"data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAALAAABAAEAAAIBRAA7";
|
|
44
|
-
expect(entities.decode(entities.encode(data))).toBe(data);
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
it("should HTML encode all ASCII characters", () => {
|
|
48
|
-
for (let index = 0; index < 128; index++) {
|
|
49
|
-
const char = String.fromCharCode(index);
|
|
50
|
-
const encoded = entities.encodeHTML(char);
|
|
51
|
-
const decoded = entities.decodeHTML(encoded);
|
|
52
|
-
expect(decoded).toBe(char);
|
|
53
|
-
}
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
it("should encode trailing parts of entities", () =>
|
|
57
|
-
expect(entities.encodeHTML("\uD835")).toBe("�"));
|
|
58
|
-
|
|
59
|
-
it("should encode surrogate pair with first surrogate equivalent of entity, without corresponding entity", () =>
|
|
60
|
-
expect(entities.encodeHTML("\u{1D4A4}")).toBe("𝒤"));
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
describe("encodeNonAsciiHTML", () => {
|
|
64
|
-
it("should encode all non-ASCII characters", () =>
|
|
65
|
-
expect(entities.encodeNonAsciiHTML("<test> #123! übermaßen")).toBe(
|
|
66
|
-
"<test> #123! übermaßen",
|
|
67
|
-
));
|
|
68
|
-
|
|
69
|
-
it("should encode emojis", () =>
|
|
70
|
-
expect(entities.encodeNonAsciiHTML("😄🍾🥳💥😇")).toBe(
|
|
71
|
-
"😄🍾🥳💥😇",
|
|
72
|
-
));
|
|
73
|
-
|
|
74
|
-
it("should encode chars above surrogates", () =>
|
|
75
|
-
expect(entities.encodeNonAsciiHTML("♒️♓️♈️♉️♊️♋️♌️♍️♎️♏️♐️♑️")).toBe(
|
|
76
|
-
"♒️♓️♈️♉️♊️♋️♌️♍️♎️♏️♐️♑️",
|
|
77
|
-
));
|
|
78
|
-
});
|
package/src/escape.spec.ts
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect } from "vitest";
|
|
2
|
-
import * as entities from "./index.js";
|
|
3
|
-
|
|
4
|
-
describe("escape HTML", () => {
|
|
5
|
-
it("should escape HTML attribute values", () =>
|
|
6
|
-
expect(entities.escapeAttribute('<a " attr > & value \u00A0!')).toBe(
|
|
7
|
-
"<a " attr > & value !",
|
|
8
|
-
));
|
|
9
|
-
|
|
10
|
-
it("should escape HTML text", () =>
|
|
11
|
-
expect(entities.escapeText('<a " text > & value \u00A0!')).toBe(
|
|
12
|
-
'<a " text > & value !',
|
|
13
|
-
));
|
|
14
|
-
});
|
package/src/index.spec.ts
DELETED
|
@@ -1,125 +0,0 @@
|
|
|
1
|
-
import { readFileSync } from "node:fs";
|
|
2
|
-
import { describe, it, expect } from "vitest";
|
|
3
|
-
import * as entities from "./index.js";
|
|
4
|
-
import legacy from "../maps/legacy.json" with { type: "json" };
|
|
5
|
-
|
|
6
|
-
const levels = ["xml", "entities"];
|
|
7
|
-
|
|
8
|
-
describe("Documents", () => {
|
|
9
|
-
const levelDocuments = levels
|
|
10
|
-
.map((name) => new URL(`../maps/${name}.json`, import.meta.url))
|
|
11
|
-
.map((url) => JSON.parse(readFileSync(url, "utf8")))
|
|
12
|
-
.map((document, index) => [index, document]);
|
|
13
|
-
|
|
14
|
-
for (const [level, document] of levelDocuments) {
|
|
15
|
-
describe("Decode", () => {
|
|
16
|
-
it(levels[level], () => {
|
|
17
|
-
for (const entity of Object.keys(document)) {
|
|
18
|
-
for (let l = level; l < levels.length; l++) {
|
|
19
|
-
expect(entities.decode(`&${entity};`, l)).toBe(
|
|
20
|
-
document[entity],
|
|
21
|
-
);
|
|
22
|
-
expect(
|
|
23
|
-
entities.decode(`&${entity};`, { level: l }),
|
|
24
|
-
).toBe(document[entity]);
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
});
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
describe("Decode strict", () => {
|
|
31
|
-
it(levels[level], () => {
|
|
32
|
-
for (const entity of Object.keys(document)) {
|
|
33
|
-
for (let l = level; l < levels.length; l++) {
|
|
34
|
-
expect(entities.decodeStrict(`&${entity};`, l)).toBe(
|
|
35
|
-
document[entity],
|
|
36
|
-
);
|
|
37
|
-
expect(
|
|
38
|
-
entities.decode(`&${entity};`, {
|
|
39
|
-
level: l,
|
|
40
|
-
mode: entities.DecodingMode.Strict,
|
|
41
|
-
}),
|
|
42
|
-
).toBe(document[entity]);
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
});
|
|
46
|
-
});
|
|
47
|
-
|
|
48
|
-
describe("Encode", () => {
|
|
49
|
-
it(levels[level], () => {
|
|
50
|
-
for (const entity of Object.keys(document)) {
|
|
51
|
-
for (let l = level; l < levels.length; l++) {
|
|
52
|
-
const encoded = entities.encode(document[entity], l);
|
|
53
|
-
const decoded = entities.decode(encoded, l);
|
|
54
|
-
expect(decoded).toBe(document[entity]);
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
it("should only encode non-ASCII values if asked", () =>
|
|
60
|
-
expect(
|
|
61
|
-
entities.encode("Great #'s of 🎁", {
|
|
62
|
-
level,
|
|
63
|
-
mode: entities.EncodingMode.ASCII,
|
|
64
|
-
}),
|
|
65
|
-
).toBe("Great #'s of 🎁"));
|
|
66
|
-
});
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
describe("Legacy", () => {
|
|
70
|
-
const legacyMap: Record<string, string> = legacy;
|
|
71
|
-
it("should decode", () => {
|
|
72
|
-
for (const entity of Object.keys(legacyMap)) {
|
|
73
|
-
expect(entities.decodeHTML(`&${entity}`)).toBe(
|
|
74
|
-
legacyMap[entity],
|
|
75
|
-
);
|
|
76
|
-
expect(
|
|
77
|
-
entities.decodeStrict(`&${entity}`, {
|
|
78
|
-
level: entities.EntityLevel.HTML,
|
|
79
|
-
mode: entities.DecodingMode.Legacy,
|
|
80
|
-
}),
|
|
81
|
-
).toBe(legacyMap[entity]);
|
|
82
|
-
}
|
|
83
|
-
});
|
|
84
|
-
});
|
|
85
|
-
});
|
|
86
|
-
|
|
87
|
-
const astral = [
|
|
88
|
-
["1d306", "\uD834\uDF06"],
|
|
89
|
-
["1d11e", "\uD834\uDD1E"],
|
|
90
|
-
];
|
|
91
|
-
|
|
92
|
-
const astralSpecial = [
|
|
93
|
-
["80", "\u20AC"],
|
|
94
|
-
["110000", "\uFFFD"],
|
|
95
|
-
];
|
|
96
|
-
|
|
97
|
-
describe("Astral entities", () => {
|
|
98
|
-
for (const [c, value] of astral) {
|
|
99
|
-
it(`should decode ${value}`, () =>
|
|
100
|
-
expect(entities.decode(`&#x${c};`)).toBe(value));
|
|
101
|
-
|
|
102
|
-
it(`should encode ${value}`, () =>
|
|
103
|
-
expect(entities.encode(value)).toBe(`&#x${c};`));
|
|
104
|
-
|
|
105
|
-
it(`should escape ${value}`, () =>
|
|
106
|
-
expect(entities.escape(value)).toBe(`&#x${c};`));
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
for (const [c, value] of astralSpecial) {
|
|
110
|
-
it(`should decode special \\u${c}`, () =>
|
|
111
|
-
expect(entities.decode(`&#x${c};`)).toBe(value));
|
|
112
|
-
}
|
|
113
|
-
});
|
|
114
|
-
|
|
115
|
-
describe("Escape", () => {
|
|
116
|
-
it("should always decode ASCII chars", () => {
|
|
117
|
-
for (let index = 0; index < 0x7f; index++) {
|
|
118
|
-
const c = String.fromCharCode(index);
|
|
119
|
-
expect(entities.decodeXML(entities.escape(c))).toBe(c);
|
|
120
|
-
}
|
|
121
|
-
});
|
|
122
|
-
|
|
123
|
-
it("should keep UTF8 characters", () =>
|
|
124
|
-
expect(entities.escapeUTF8('ß < "ü"')).toBe(`ß < "ü"`));
|
|
125
|
-
});
|