-
-
Notifications
You must be signed in to change notification settings - Fork 59
/
index.ts
178 lines (161 loc) · 4.57 KB
/
index.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
import { decodeXML, decodeHTML, DecodingMode } from "./decode.js";
import { encodeHTML, encodeNonAsciiHTML } from "./encode.js";
import {
encodeXML,
escapeUTF8,
escapeAttribute,
escapeText,
} from "./escape.js";
/** The level of entities to support. */
export enum EntityLevel {
/** Support only XML entities. */
XML = 0,
/** Support HTML entities, which are a superset of XML entities. */
HTML = 1,
}
export enum EncodingMode {
/**
* The output is UTF-8 encoded. Only characters that need escaping within
* XML will be escaped.
*/
UTF8,
/**
* The output consists only of ASCII characters. Characters that need
* escaping within HTML, and characters that aren't ASCII characters will
* be escaped.
*/
ASCII,
/**
* Encode all characters that have an equivalent entity, as well as all
* characters that are not ASCII characters.
*/
Extensive,
/**
* Encode all characters that have to be escaped in HTML attributes,
* following {@link https://html.spec.whatwg.org/multipage/parsing.html#escapingString}.
*/
Attribute,
/**
* Encode all characters that have to be escaped in HTML text,
* following {@link https://html.spec.whatwg.org/multipage/parsing.html#escapingString}.
*/
Text,
}
export interface DecodingOptions {
/**
* The level of entities to support.
* @default {@link EntityLevel.XML}
*/
level?: EntityLevel;
/**
* Decoding mode. If `Legacy`, will support legacy entities not terminated
* with a semicolon (`;`).
*
* Always `Strict` for XML. For HTML, set this to `true` if you are parsing
* an attribute value.
*
* The deprecated `decodeStrict` function defaults this to `Strict`.
*
* @default {@link DecodingMode.Legacy}
*/
mode?: DecodingMode | undefined;
}
/**
* Decodes a string with entities.
*
* @param data String to decode.
* @param options Decoding options.
*/
export function decode(
data: string,
options: DecodingOptions | EntityLevel = EntityLevel.XML,
): string {
const level = typeof options === "number" ? options : options.level;
if (level === EntityLevel.HTML) {
const mode = typeof options === "object" ? options.mode : undefined;
return decodeHTML(data, mode);
}
return decodeXML(data);
}
/**
* Decodes a string with entities. Does not allow missing trailing semicolons for entities.
*
* @param data String to decode.
* @param options Decoding options.
* @deprecated Use `decode` with the `mode` set to `Strict`.
*/
export function decodeStrict(
data: string,
options: DecodingOptions | EntityLevel = EntityLevel.XML,
): string {
const opts = typeof options === "number" ? { level: options } : options;
opts.mode ??= DecodingMode.Strict;
return decode(data, opts);
}
/**
* Options for `encode`.
*/
export interface EncodingOptions {
/**
* The level of entities to support.
* @default {@link EntityLevel.XML}
*/
level?: EntityLevel;
/**
* Output format.
* @default {@link EncodingMode.Extensive}
*/
mode?: EncodingMode;
}
/**
* Encodes a string with entities.
*
* @param data String to encode.
* @param options Encoding options.
*/
export function encode(
data: string,
options: EncodingOptions | EntityLevel = EntityLevel.XML,
): string {
const opts = typeof options === "number" ? { level: options } : options;
// Mode `UTF8` just escapes XML entities
if (opts.mode === EncodingMode.UTF8) return escapeUTF8(data);
if (opts.mode === EncodingMode.Attribute) return escapeAttribute(data);
if (opts.mode === EncodingMode.Text) return escapeText(data);
if (opts.level === EntityLevel.HTML) {
if (opts.mode === EncodingMode.ASCII) {
return encodeNonAsciiHTML(data);
}
return encodeHTML(data);
}
// ASCII and Extensive are equivalent
return encodeXML(data);
}
export {
encodeXML,
escape,
escapeUTF8,
escapeAttribute,
escapeText,
} from "./escape.js";
export {
encodeHTML,
encodeNonAsciiHTML,
// Legacy aliases (deprecated)
encodeHTML as encodeHTML4,
encodeHTML as encodeHTML5,
} from "./encode.js";
export {
EntityDecoder,
DecodingMode,
decodeXML,
decodeHTML,
decodeHTMLStrict,
decodeHTMLAttribute,
// Legacy aliases (deprecated)
decodeHTML as decodeHTML4,
decodeHTML as decodeHTML5,
decodeHTMLStrict as decodeHTML4Strict,
decodeHTMLStrict as decodeHTML5Strict,
decodeXML as decodeXMLStrict,
} from "./decode.js";