@levischuck/tiny-html 0.0.4 → 0.1.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/dist/index.d.ts +15 -3
- package/dist/index.js +484 -288
- package/dist/parser.d.ts +2 -2
- package/dist/safe-html.d.ts +15 -0
- package/dist/types.d.ts +76 -0
- package/dist/utils.d.ts +9 -0
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
import { ParseResult, HtmlNode, WriterOptions } from './types.ts';
|
|
1
|
+
import { ParseResult, HtmlNode, WriterOptions, SafeHtmlOptions, ParserOptions } from './types.ts';
|
|
2
2
|
/**
|
|
3
3
|
* Parses HTML string into a ParseResult containing HtmlNode
|
|
4
|
+
* @param html - The HTML string to parse
|
|
5
|
+
* @param options - Parser options including attributeNaming ('reactName' or 'exactName')
|
|
4
6
|
*/
|
|
5
|
-
export declare function readHtml(html: string): ParseResult;
|
|
7
|
+
export declare function readHtml(html: string, options?: ParserOptions): ParseResult;
|
|
6
8
|
/**
|
|
7
9
|
* Renders HtmlNode or ParseResult to HTML string
|
|
8
10
|
*/
|
|
@@ -12,8 +14,18 @@ export declare function writeHtml(input: HtmlNode | ParseResult, options?: Write
|
|
|
12
14
|
* Returns a new HtmlNode with all promises resolved
|
|
13
15
|
*/
|
|
14
16
|
export declare function awaitHtmlNode(node: HtmlNode | Promise<HtmlNode>): Promise<HtmlNode>;
|
|
17
|
+
/**
|
|
18
|
+
* Sanitizes an HtmlNode tree by removing disallowed tags, attributes, and URLs.
|
|
19
|
+
* - Tags not in allowedTags have their content retained (folded into parent)
|
|
20
|
+
* - Images replaced with their alt text when removed
|
|
21
|
+
* - Attributes not in the tag's allowed list are dropped
|
|
22
|
+
* - Classes are filtered by allowedClasses patterns (supports wildcards)
|
|
23
|
+
* - URLs not matching allowedLinkProtocols cause the element to be removed
|
|
24
|
+
*/
|
|
25
|
+
export declare function safeHtml(node: HtmlNode, options?: SafeHtmlOptions): HtmlNode;
|
|
15
26
|
export { htmlNodeTo } from './convert.ts';
|
|
16
27
|
export { decodeHtmlEntities, encodeHtmlEntities } from './entities.ts';
|
|
17
28
|
export type { CreateElementFn, CreateElementProps } from './convert.ts';
|
|
18
29
|
export { getTextContent } from './writer.ts';
|
|
19
|
-
export
|
|
30
|
+
export { htmlNodeToHtmlElement } from './utils.ts';
|
|
31
|
+
export type { WriterOptions, ParseResult, HtmlNode, HtmlElement, HtmlProps, HtmlStyle, SafeHtmlOptions, AllowedTag, ParserOptions, ParserAttributeNaming, WriterAttributeNaming, } from './types.ts';
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const
|
|
1
|
+
const $ = /* @__PURE__ */ new Set([
|
|
2
2
|
"area",
|
|
3
3
|
"base",
|
|
4
4
|
"br",
|
|
@@ -13,7 +13,7 @@ const F = /* @__PURE__ */ new Set([
|
|
|
13
13
|
"source",
|
|
14
14
|
"track",
|
|
15
15
|
"wbr"
|
|
16
|
-
]),
|
|
16
|
+
]), J = /* @__PURE__ */ new Set([
|
|
17
17
|
// Containers
|
|
18
18
|
"div",
|
|
19
19
|
"span",
|
|
@@ -110,7 +110,7 @@ const F = /* @__PURE__ */ new Set([
|
|
|
110
110
|
"body",
|
|
111
111
|
"title",
|
|
112
112
|
"meta"
|
|
113
|
-
]),
|
|
113
|
+
]), z = /* @__PURE__ */ new Map([
|
|
114
114
|
["p", /* @__PURE__ */ new Set(["p"])],
|
|
115
115
|
["li", /* @__PURE__ */ new Set(["li"])],
|
|
116
116
|
["dt", /* @__PURE__ */ new Set(["dt", "dd"])],
|
|
@@ -123,7 +123,7 @@ const F = /* @__PURE__ */ new Set([
|
|
|
123
123
|
["tr", /* @__PURE__ */ new Set(["tr"])],
|
|
124
124
|
["td", /* @__PURE__ */ new Set(["td", "th"])],
|
|
125
125
|
["th", /* @__PURE__ */ new Set(["td", "th"])]
|
|
126
|
-
]),
|
|
126
|
+
]), B = /* @__PURE__ */ new Map([
|
|
127
127
|
["altglyph", "altGlyph"],
|
|
128
128
|
["altglyphdef", "altGlyphDef"],
|
|
129
129
|
["altglyphitem", "altGlyphItem"],
|
|
@@ -161,7 +161,7 @@ const F = /* @__PURE__ */ new Set([
|
|
|
161
161
|
["lineargradient", "linearGradient"],
|
|
162
162
|
["radialgradient", "radialGradient"],
|
|
163
163
|
["textpath", "textPath"]
|
|
164
|
-
]),
|
|
164
|
+
]), V = /* @__PURE__ */ new Map([
|
|
165
165
|
["attributename", "attributeName"],
|
|
166
166
|
["attributetype", "attributeType"],
|
|
167
167
|
["basefrequency", "baseFrequency"],
|
|
@@ -220,7 +220,7 @@ const F = /* @__PURE__ */ new Set([
|
|
|
220
220
|
["xchannelselector", "xChannelSelector"],
|
|
221
221
|
["ychannelselector", "yChannelSelector"],
|
|
222
222
|
["zoomandpan", "zoomAndPan"]
|
|
223
|
-
]),
|
|
223
|
+
]), P = {
|
|
224
224
|
lt: "<",
|
|
225
225
|
gt: ">",
|
|
226
226
|
amp: "&",
|
|
@@ -291,44 +291,44 @@ const F = /* @__PURE__ */ new Set([
|
|
|
291
291
|
rArr: "⇒",
|
|
292
292
|
dArr: "⇓",
|
|
293
293
|
hArr: "⇔"
|
|
294
|
-
},
|
|
295
|
-
for (const [e,
|
|
296
|
-
|
|
297
|
-
function
|
|
298
|
-
return !e || typeof e != "string" || !e.includes("&") ? e : e.replace(/&(?:#[xX]([0-9a-fA-F]+)|#(\d+)|([a-zA-Z][a-zA-Z0-9]*));/g, (
|
|
299
|
-
if (
|
|
300
|
-
const
|
|
301
|
-
return String.fromCodePoint(
|
|
294
|
+
}, W = {};
|
|
295
|
+
for (const [e, t] of Object.entries(P))
|
|
296
|
+
W[t] || (W[t] = e);
|
|
297
|
+
function O(e) {
|
|
298
|
+
return !e || typeof e != "string" || !e.includes("&") ? e : e.replace(/&(?:#[xX]([0-9a-fA-F]+)|#(\d+)|([a-zA-Z][a-zA-Z0-9]*));/g, (t, i, l, s) => {
|
|
299
|
+
if (i) {
|
|
300
|
+
const a = parseInt(i, 16);
|
|
301
|
+
return String.fromCodePoint(a);
|
|
302
302
|
} else if (l) {
|
|
303
|
-
const
|
|
304
|
-
return String.fromCodePoint(
|
|
305
|
-
} else if (
|
|
306
|
-
return
|
|
307
|
-
return
|
|
303
|
+
const a = parseInt(l, 10);
|
|
304
|
+
return String.fromCodePoint(a);
|
|
305
|
+
} else if (s && P[s])
|
|
306
|
+
return P[s];
|
|
307
|
+
return t;
|
|
308
308
|
});
|
|
309
309
|
}
|
|
310
|
-
function
|
|
310
|
+
function G(e, t = !1) {
|
|
311
311
|
if (!e || typeof e != "string")
|
|
312
312
|
return e;
|
|
313
|
-
let
|
|
314
|
-
return
|
|
313
|
+
let i = e;
|
|
314
|
+
return i = i.replace(/&/g, "&"), i = i.replace(/</g, "<"), i = i.replace(/>/g, ">"), t && (i = i.replace(/"/g, """)), i;
|
|
315
315
|
}
|
|
316
|
-
function
|
|
316
|
+
function ee(e) {
|
|
317
317
|
return e.replace(/\]\]>/g, "]]]]></g, (
|
|
319
|
+
function Z(e) {
|
|
320
|
+
return e.replace(/[-_]([a-z])/g, (t, i) => i.toUpperCase());
|
|
321
321
|
}
|
|
322
|
-
function
|
|
323
|
-
return e.replace(/[A-Z]/g, (
|
|
322
|
+
function te(e) {
|
|
323
|
+
return e.replace(/[A-Z]/g, (t) => `-${t.toLowerCase()}`);
|
|
324
324
|
}
|
|
325
|
-
function
|
|
326
|
-
return new TextDecoder("utf-8").decode(e.slice(
|
|
325
|
+
function b(e, t, i) {
|
|
326
|
+
return new TextDecoder("utf-8").decode(e.slice(t, i));
|
|
327
327
|
}
|
|
328
|
-
function
|
|
328
|
+
function C(e) {
|
|
329
329
|
return e === 32 || e === 9 || e === 10 || e === 13;
|
|
330
330
|
}
|
|
331
|
-
function
|
|
331
|
+
function S(e) {
|
|
332
332
|
return e >= 97 && e <= 122 || // a-z
|
|
333
333
|
e >= 65 && e <= 90 || // A-Z
|
|
334
334
|
e >= 48 && e <= 57 || // 0-9
|
|
@@ -336,419 +336,615 @@ function N(e) {
|
|
|
336
336
|
e === 95 || // _
|
|
337
337
|
e === 58;
|
|
338
338
|
}
|
|
339
|
-
function
|
|
340
|
-
|
|
339
|
+
function Ae(e) {
|
|
340
|
+
if (typeof e == "string" && e.trim().startsWith("<") && (e = Q(e).node), typeof e == "object" && e && "type" in e)
|
|
341
|
+
return e;
|
|
342
|
+
if (Array.isArray(e)) {
|
|
343
|
+
for (const t of e)
|
|
344
|
+
if (typeof t == "object" && t && "type" in t)
|
|
345
|
+
return t;
|
|
346
|
+
}
|
|
347
|
+
throw new Error("Could not find HtmlElement in decoded Html");
|
|
348
|
+
}
|
|
349
|
+
function Q(e, t = {}) {
|
|
350
|
+
const i = t.attributeNaming ?? "reactName", s = new TextEncoder().encode(e), a = {
|
|
341
351
|
node: []
|
|
342
|
-
},
|
|
343
|
-
let
|
|
344
|
-
function
|
|
345
|
-
return o.length > 0 ? o[o.length - 1].children :
|
|
352
|
+
}, p = [], o = [];
|
|
353
|
+
let T = "HTML", n = "TEXT", r = 0, h = 0, g = 0, E = 0, N = 0, A = "", q = 0, d = null;
|
|
354
|
+
function x() {
|
|
355
|
+
return o.length > 0 ? o[o.length - 1].children : p;
|
|
346
356
|
}
|
|
347
|
-
function
|
|
348
|
-
if (
|
|
349
|
-
const
|
|
350
|
-
|
|
357
|
+
function D(f, c) {
|
|
358
|
+
if (f >= c) return;
|
|
359
|
+
const u = b(s, f, c), m = O(u);
|
|
360
|
+
m.length > 0 && x().push(m);
|
|
351
361
|
}
|
|
352
|
-
function
|
|
353
|
-
if (
|
|
354
|
-
const
|
|
355
|
-
|
|
362
|
+
function M(f, c) {
|
|
363
|
+
if (f >= c) return;
|
|
364
|
+
const u = b(s, f, c);
|
|
365
|
+
u.length > 0 && x().push(u);
|
|
356
366
|
}
|
|
357
|
-
function
|
|
358
|
-
const
|
|
359
|
-
return
|
|
367
|
+
function v(f, c) {
|
|
368
|
+
const u = f.toLowerCase();
|
|
369
|
+
return c === "SVG" && B.has(u) ? B.get(u) : u;
|
|
360
370
|
}
|
|
361
|
-
function
|
|
362
|
-
const
|
|
363
|
-
|
|
364
|
-
if (p === "for") return "htmlFor";
|
|
365
|
-
if (f === "SVG")
|
|
366
|
-
return z.has(p) ? z.get(p) : s;
|
|
367
|
-
if (f === "HTML") {
|
|
368
|
-
const T = k(p);
|
|
369
|
-
return p === "class" || p === "for" ? p === "class" ? "className" : "htmlFor" : T;
|
|
370
|
-
}
|
|
371
|
-
return p;
|
|
371
|
+
function L(f, c) {
|
|
372
|
+
const u = f.toLowerCase();
|
|
373
|
+
return u === "class" ? i === "exactName" ? "class" : "className" : u === "for" ? i === "exactName" ? "for" : "htmlFor" : c === "SVG" ? V.has(u) ? V.get(u) : f : c === "HTML" ? Z(u) : u;
|
|
372
374
|
}
|
|
373
|
-
function
|
|
374
|
-
const
|
|
375
|
-
for (let
|
|
376
|
-
if (o[
|
|
377
|
-
for (let
|
|
378
|
-
const
|
|
379
|
-
type:
|
|
375
|
+
function I(f) {
|
|
376
|
+
const c = v(f, T);
|
|
377
|
+
for (let u = o.length - 1; u >= 0; u--)
|
|
378
|
+
if (o[u].type === c) {
|
|
379
|
+
for (let m = o.length - 1; m >= u; m--) {
|
|
380
|
+
const y = o.pop(), w = {
|
|
381
|
+
type: y.type,
|
|
380
382
|
props: {
|
|
381
|
-
...
|
|
382
|
-
children:
|
|
383
|
+
...y.props,
|
|
384
|
+
children: y.children.length === 1 ? y.children[0] : y.children
|
|
383
385
|
}
|
|
384
386
|
};
|
|
385
|
-
o.length > 0 ? o[o.length - 1].children.push(
|
|
387
|
+
o.length > 0 ? o[o.length - 1].children.push(w) : p.push(w), (y.type === "svg" || y.type === "math") && (T = "HTML");
|
|
386
388
|
}
|
|
387
389
|
return;
|
|
388
390
|
}
|
|
389
391
|
}
|
|
390
|
-
function
|
|
391
|
-
const
|
|
392
|
-
if (o.length > 0 &&
|
|
393
|
-
const
|
|
394
|
-
|
|
392
|
+
function _(f, c, u) {
|
|
393
|
+
const m = v(f, T);
|
|
394
|
+
if (o.length > 0 && z.has(m)) {
|
|
395
|
+
const w = z.get(m), H = o[o.length - 1].type;
|
|
396
|
+
w.has(H) && I(H);
|
|
395
397
|
}
|
|
396
|
-
let
|
|
397
|
-
if (
|
|
398
|
-
const
|
|
399
|
-
type:
|
|
400
|
-
props:
|
|
398
|
+
let y = T;
|
|
399
|
+
if (m === "svg" ? y = "SVG" : m === "math" && (y = "MATHML"), $.has(m) || u) {
|
|
400
|
+
const w = {
|
|
401
|
+
type: m,
|
|
402
|
+
props: c
|
|
401
403
|
};
|
|
402
|
-
|
|
404
|
+
x().push(w);
|
|
403
405
|
} else {
|
|
404
|
-
const
|
|
405
|
-
type:
|
|
406
|
-
props:
|
|
406
|
+
const w = {
|
|
407
|
+
type: m,
|
|
408
|
+
props: c,
|
|
407
409
|
children: [],
|
|
408
|
-
namespace:
|
|
410
|
+
namespace: y
|
|
409
411
|
};
|
|
410
|
-
o.push(
|
|
412
|
+
o.push(w), T = y;
|
|
411
413
|
}
|
|
412
414
|
}
|
|
413
|
-
for (;
|
|
414
|
-
const
|
|
415
|
-
switch (
|
|
415
|
+
for (; r < s.length; ) {
|
|
416
|
+
const f = s[r];
|
|
417
|
+
switch (n) {
|
|
416
418
|
case "TEXT":
|
|
417
|
-
|
|
419
|
+
f === 60 && (D(h, r), n = "TAG_OPEN"), r++;
|
|
418
420
|
break;
|
|
419
421
|
case "TAG_OPEN":
|
|
420
|
-
|
|
422
|
+
f === 33 ? s[r + 1] === 45 && s[r + 2] === 45 ? (n = "COMMENT", r += 3) : s[r + 1] === 68 || s[r + 1] === 100 ? b(s, r, Math.min(r + 20, s.length)).toLowerCase().startsWith("!doctype") ? (n = "DOCTYPE", g = r, r++) : (h = r - 1, n = "TEXT") : s[r + 1] === 91 && s[r + 2] === 67 && b(s, r, Math.min(r + 9, s.length)).startsWith("![CDATA[") ? (n = "CDATA", h = r + 8, r += 8) : (h = r - 1, n = "TEXT") : f === 63 ? (n = "PROCESSING_INSTRUCTION", g = r - 1, r++) : f === 47 ? (n = "TAG_CLOSE_START", r++) : S(f) ? (g = r, n = "TAG_NAME", d = null, r++) : (h = r - 1, n = "TEXT");
|
|
421
423
|
break;
|
|
422
424
|
case "TAG_NAME":
|
|
423
|
-
if (
|
|
424
|
-
const
|
|
425
|
-
|
|
426
|
-
type:
|
|
425
|
+
if (C(f)) {
|
|
426
|
+
const c = b(s, g, r), u = c.toLowerCase();
|
|
427
|
+
d = {
|
|
428
|
+
type: c,
|
|
427
429
|
props: {},
|
|
428
430
|
children: [],
|
|
429
|
-
namespace:
|
|
430
|
-
},
|
|
431
|
-
} else if (
|
|
432
|
-
const
|
|
433
|
-
|
|
434
|
-
const
|
|
435
|
-
|
|
436
|
-
} else
|
|
431
|
+
namespace: u === "svg" ? "SVG" : u === "math" ? "MATHML" : T
|
|
432
|
+
}, n = "ATTRIBUTES", r++;
|
|
433
|
+
} else if (f === 62) {
|
|
434
|
+
const c = b(s, g, r);
|
|
435
|
+
_(c, {}, !1);
|
|
436
|
+
const u = v(c, T);
|
|
437
|
+
u === "script" ? (n = "SCRIPT_CONTENT", h = r + 1) : u === "style" ? (n = "STYLE_CONTENT", h = r + 1) : (n = "TEXT", h = r + 1), r++;
|
|
438
|
+
} else f === 47 ? (n = "TAG_CLOSE_SELF", r++) : S(f) ? r++ : (h = g - 1, n = "TEXT");
|
|
437
439
|
break;
|
|
438
440
|
case "ATTRIBUTES":
|
|
439
|
-
if (
|
|
440
|
-
|
|
441
|
-
else if (
|
|
442
|
-
const
|
|
443
|
-
|
|
444
|
-
const
|
|
445
|
-
|
|
446
|
-
} else
|
|
441
|
+
if (C(f))
|
|
442
|
+
r++;
|
|
443
|
+
else if (f === 62) {
|
|
444
|
+
const c = d.type;
|
|
445
|
+
_(c, d.props, !1);
|
|
446
|
+
const u = v(c, T);
|
|
447
|
+
u === "script" ? (n = "SCRIPT_CONTENT", h = r + 1) : u === "style" ? (n = "STYLE_CONTENT", h = r + 1) : (n = "TEXT", h = r + 1), r++;
|
|
448
|
+
} else f === 47 ? (n = "TAG_CLOSE_SELF", r++) : S(f) ? (E = r, n = "ATTRIBUTE_NAME", r++) : (h = g - 1, n = "TEXT");
|
|
447
449
|
break;
|
|
448
450
|
case "ATTRIBUTE_NAME":
|
|
449
|
-
if (
|
|
450
|
-
|
|
451
|
-
const
|
|
452
|
-
|
|
453
|
-
} else if (
|
|
454
|
-
|
|
455
|
-
else if (
|
|
456
|
-
|
|
457
|
-
const
|
|
458
|
-
|
|
459
|
-
const
|
|
460
|
-
|
|
461
|
-
const
|
|
462
|
-
|
|
463
|
-
} else if (
|
|
464
|
-
|
|
465
|
-
const
|
|
466
|
-
|
|
467
|
-
} else
|
|
451
|
+
if (C(f)) {
|
|
452
|
+
A = b(s, E, r);
|
|
453
|
+
const c = L(A, d.namespace);
|
|
454
|
+
d.props[c] = !0, A = "", n = "ATTRIBUTES", r++;
|
|
455
|
+
} else if (f === 61)
|
|
456
|
+
A = b(s, E, r), n = "ATTRIBUTE_VALUE_START", r++;
|
|
457
|
+
else if (f === 62) {
|
|
458
|
+
A = b(s, E, r);
|
|
459
|
+
const c = L(A, d.namespace);
|
|
460
|
+
d.props[c] = !0, A = "";
|
|
461
|
+
const u = d.type;
|
|
462
|
+
_(u, d.props, !1);
|
|
463
|
+
const m = v(u, T);
|
|
464
|
+
m === "script" ? (n = "SCRIPT_CONTENT", h = r + 1) : m === "style" ? (n = "STYLE_CONTENT", h = r + 1) : (n = "TEXT", h = r + 1), r++;
|
|
465
|
+
} else if (f === 47) {
|
|
466
|
+
A = b(s, E, r);
|
|
467
|
+
const c = L(A, d.namespace);
|
|
468
|
+
d.props[c] = !0, A = "", n = "TAG_CLOSE_SELF", r++;
|
|
469
|
+
} else S(f) ? r++ : (h = g - 1, n = "TEXT");
|
|
468
470
|
break;
|
|
469
471
|
case "ATTRIBUTE_VALUE_START":
|
|
470
|
-
|
|
472
|
+
C(f) ? r++ : f === 34 || f === 39 ? (q = f, N = r + 1, n = "ATTRIBUTE_VALUE_QUOTED", r++) : (N = r, n = "ATTRIBUTE_VALUE_UNQUOTED");
|
|
471
473
|
break;
|
|
472
474
|
case "ATTRIBUTE_VALUE_QUOTED":
|
|
473
|
-
if (
|
|
474
|
-
const
|
|
475
|
-
|
|
475
|
+
if (f === q) {
|
|
476
|
+
const c = b(s, N, r), u = O(c), m = L(A, d.namespace);
|
|
477
|
+
m === "style" ? d.props[m] = F(u) : d.props[m] = u, A = "", n = "ATTRIBUTES", r++;
|
|
476
478
|
} else
|
|
477
|
-
|
|
479
|
+
r++;
|
|
478
480
|
break;
|
|
479
481
|
case "ATTRIBUTE_VALUE_UNQUOTED":
|
|
480
|
-
if (
|
|
481
|
-
const
|
|
482
|
-
|
|
482
|
+
if (C(f) || f === 62 || f === 47) {
|
|
483
|
+
const c = b(s, N, r), u = O(c), m = L(A, d.namespace);
|
|
484
|
+
m === "style" ? d.props[m] = F(u) : d.props[m] = u, A = "", n = "ATTRIBUTES";
|
|
483
485
|
} else
|
|
484
|
-
|
|
486
|
+
r++;
|
|
485
487
|
break;
|
|
486
488
|
case "TAG_CLOSE_SELF":
|
|
487
|
-
if (
|
|
488
|
-
const
|
|
489
|
-
|
|
489
|
+
if (f === 62) {
|
|
490
|
+
const c = d.type;
|
|
491
|
+
_(c, d.props, !0), n = "TEXT", h = r + 1, r++;
|
|
490
492
|
} else
|
|
491
|
-
|
|
493
|
+
h = g - 1, n = "TEXT";
|
|
492
494
|
break;
|
|
493
495
|
case "TAG_CLOSE_START":
|
|
494
|
-
|
|
496
|
+
S(f) ? (g = r, n = "TAG_CLOSE_NAME", r++) : (h = r - 2, n = "TEXT");
|
|
495
497
|
break;
|
|
496
498
|
case "TAG_CLOSE_NAME":
|
|
497
|
-
if (
|
|
498
|
-
const
|
|
499
|
-
|
|
500
|
-
} else
|
|
499
|
+
if (f === 62) {
|
|
500
|
+
const c = b(s, g, r);
|
|
501
|
+
I(c), n = "TEXT", h = r + 1, r++;
|
|
502
|
+
} else C(f) || S(f) ? r++ : (h = g - 2, n = "TEXT");
|
|
501
503
|
break;
|
|
502
504
|
case "COMMENT":
|
|
503
|
-
|
|
505
|
+
f === 45 && s[r + 1] === 45 && s[r + 2] === 62 ? (n = "TEXT", h = r + 3, r += 3) : r++;
|
|
504
506
|
break;
|
|
505
507
|
case "DOCTYPE":
|
|
506
|
-
if (
|
|
507
|
-
const
|
|
508
|
-
|
|
508
|
+
if (f === 62) {
|
|
509
|
+
const c = b(s, g, r + 1);
|
|
510
|
+
a.doctype = "<" + c, n = "TEXT", h = r + 1, r++;
|
|
509
511
|
} else
|
|
510
|
-
|
|
512
|
+
r++;
|
|
511
513
|
break;
|
|
512
514
|
case "CDATA":
|
|
513
|
-
|
|
515
|
+
f === 93 && s[r + 1] === 93 && s[r + 2] === 62 ? (M(h, r), n = "TEXT", h = r + 3, r += 3) : r++;
|
|
514
516
|
break;
|
|
515
517
|
case "PROCESSING_INSTRUCTION":
|
|
516
|
-
if (
|
|
517
|
-
const
|
|
518
|
-
|
|
518
|
+
if (f === 63 && s[r + 1] === 62) {
|
|
519
|
+
const c = b(s, g, r + 2);
|
|
520
|
+
a.xml = c, n = "TEXT", h = r + 2, r += 2;
|
|
519
521
|
} else
|
|
520
|
-
|
|
522
|
+
r++;
|
|
521
523
|
break;
|
|
522
524
|
case "SCRIPT_CONTENT":
|
|
523
525
|
case "STYLE_CONTENT":
|
|
524
|
-
if (
|
|
525
|
-
const
|
|
526
|
-
if (
|
|
527
|
-
|
|
528
|
-
let
|
|
529
|
-
for (;
|
|
530
|
-
|
|
526
|
+
if (f === 60 && s[r + 1] === 47) {
|
|
527
|
+
const c = n === "SCRIPT_CONTENT" ? "script" : "style", u = "</" + c, m = b(s, r, Math.min(r + u.length + 1, s.length)).toLowerCase();
|
|
528
|
+
if (m.startsWith(u) && (m[u.length] === ">" || C(m.charCodeAt(u.length)))) {
|
|
529
|
+
M(h, r);
|
|
530
|
+
let y = r + u.length;
|
|
531
|
+
for (; y < s.length && s[y] !== 62; ) y++;
|
|
532
|
+
I(c), n = "TEXT", h = y + 1, r = y + 1;
|
|
531
533
|
} else
|
|
532
|
-
|
|
534
|
+
r++;
|
|
533
535
|
} else
|
|
534
|
-
|
|
536
|
+
r++;
|
|
535
537
|
break;
|
|
536
538
|
default:
|
|
537
|
-
|
|
539
|
+
r++;
|
|
538
540
|
}
|
|
539
541
|
}
|
|
540
|
-
for (
|
|
541
|
-
const
|
|
542
|
-
type:
|
|
542
|
+
for (n === "TEXT" ? D(h, r) : (n === "SCRIPT_CONTENT" || n === "STYLE_CONTENT") && M(h, r); o.length > 0; ) {
|
|
543
|
+
const f = o.pop(), c = {
|
|
544
|
+
type: f.type,
|
|
543
545
|
props: {
|
|
544
|
-
...
|
|
545
|
-
children:
|
|
546
|
+
...f.props,
|
|
547
|
+
children: f.children.length === 1 ? f.children[0] : f.children
|
|
546
548
|
}
|
|
547
549
|
};
|
|
548
|
-
o.length > 0 ? o[o.length - 1].children.push(
|
|
550
|
+
o.length > 0 ? o[o.length - 1].children.push(c) : p.push(c);
|
|
549
551
|
}
|
|
550
|
-
return
|
|
551
|
-
}
|
|
552
|
-
function
|
|
553
|
-
const
|
|
554
|
-
for (const
|
|
555
|
-
const
|
|
556
|
-
if (
|
|
557
|
-
const
|
|
558
|
-
|
|
552
|
+
return p.length === 0 ? a.node = null : p.length === 1 ? a.node = p[0] : a.node = p, a;
|
|
553
|
+
}
|
|
554
|
+
function F(e) {
|
|
555
|
+
const t = {}, l = O(e).split(/;(?![^(]*\))/);
|
|
556
|
+
for (const s of l) {
|
|
557
|
+
const a = s.indexOf(":");
|
|
558
|
+
if (a === -1) continue;
|
|
559
|
+
const p = s.substring(0, a).trim(), o = s.substring(a + 1).trim();
|
|
560
|
+
p && o && (t[Z(p)] = o);
|
|
559
561
|
}
|
|
560
|
-
return
|
|
562
|
+
return t;
|
|
561
563
|
}
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
564
|
+
const re = {
|
|
565
|
+
className: "class",
|
|
566
|
+
htmlFor: "for"
|
|
567
|
+
};
|
|
568
|
+
function se(e, t) {
|
|
569
|
+
return t === "reactName" ? e : t === "exactName" || t === "eitherName" ? re[e] ?? e : e;
|
|
570
|
+
}
|
|
571
|
+
function k(e, t = {}) {
|
|
572
|
+
const i = [];
|
|
573
|
+
let l, s, a;
|
|
565
574
|
if (e && typeof e == "object" && "node" in e) {
|
|
566
|
-
const
|
|
567
|
-
l =
|
|
575
|
+
const r = e;
|
|
576
|
+
l = r.node, s = r.xml ?? t.xml, a = r.doctype ?? t.doctype;
|
|
568
577
|
} else
|
|
569
|
-
l = e,
|
|
570
|
-
|
|
571
|
-
`) ||
|
|
572
|
-
`)),
|
|
573
|
-
`) ||
|
|
578
|
+
l = e, s = t.xml, a = t.doctype;
|
|
579
|
+
s && (i.push(s), s.endsWith(`
|
|
580
|
+
`) || i.push(`
|
|
581
|
+
`)), a && (i.push(a), a.endsWith(`
|
|
582
|
+
`) || i.push(`
|
|
574
583
|
`));
|
|
575
|
-
const
|
|
576
|
-
return
|
|
584
|
+
const p = t.useCDataForScripts ?? !1, o = t.useCDataForStyles ?? !1, T = t.voidTrailingSlash ?? !0, n = t.attributeNaming ?? "eitherName";
|
|
585
|
+
return R(l, i, "HTML", p, o, T, n), i.join("");
|
|
577
586
|
}
|
|
578
|
-
function
|
|
587
|
+
function R(e, t, i, l, s, a, p) {
|
|
579
588
|
if (e != null) {
|
|
580
589
|
if (typeof e == "string") {
|
|
581
|
-
|
|
590
|
+
t.push(G(e, !1));
|
|
582
591
|
return;
|
|
583
592
|
}
|
|
584
593
|
if (typeof e == "number" || typeof e == "bigint") {
|
|
585
|
-
|
|
594
|
+
t.push(String(e));
|
|
586
595
|
return;
|
|
587
596
|
}
|
|
588
597
|
if (typeof e == "boolean") {
|
|
589
|
-
|
|
598
|
+
t.push(String(e));
|
|
590
599
|
return;
|
|
591
600
|
}
|
|
592
601
|
if (Array.isArray(e)) {
|
|
593
|
-
for (const
|
|
594
|
-
|
|
602
|
+
for (const o of e)
|
|
603
|
+
R(o, t, i, l, s, a, p);
|
|
595
604
|
return;
|
|
596
605
|
}
|
|
597
606
|
if (typeof e != "function" && typeof e != "symbol" && !(e && typeof e == "object" && "then" in e && typeof e.then == "function") && e && typeof e == "object" && "type" in e && "props" in e) {
|
|
598
|
-
|
|
607
|
+
ie(e, t, i, l, s, a, p);
|
|
599
608
|
return;
|
|
600
609
|
}
|
|
601
610
|
}
|
|
602
611
|
}
|
|
603
|
-
function
|
|
604
|
-
var
|
|
605
|
-
const
|
|
606
|
-
let
|
|
607
|
-
if (
|
|
608
|
-
for (const [
|
|
609
|
-
if (
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
612
|
+
function ie(e, t, i, l, s, a, p) {
|
|
613
|
+
var h;
|
|
614
|
+
const o = e.type;
|
|
615
|
+
let T = i;
|
|
616
|
+
if (o === "svg" ? T = "SVG" : o === "math" && (T = "MATHML"), t.push("<"), t.push(o), e.props)
|
|
617
|
+
for (const [g, E] of Object.entries(e.props)) {
|
|
618
|
+
if (g === "children" || E === !1 || E === null || E === void 0)
|
|
619
|
+
continue;
|
|
620
|
+
const N = se(g, p);
|
|
621
|
+
if (E === !0)
|
|
622
|
+
t.push(" "), t.push(N);
|
|
623
|
+
else if (g === "style" && typeof E == "object") {
|
|
624
|
+
const A = ne(E);
|
|
625
|
+
A && (t.push(' style="'), t.push(G(A, !0)), t.push('"'));
|
|
626
|
+
} else
|
|
627
|
+
t.push(" "), t.push(N), t.push('="'), t.push(G(String(E), !0)), t.push('"');
|
|
628
|
+
}
|
|
629
|
+
const n = (h = e.props) == null ? void 0 : h.children;
|
|
630
|
+
let r;
|
|
631
|
+
if (n && typeof n == "object" && "then" in n && typeof n.then == "function" ? r = !1 : r = n != null && (Array.isArray(n) && n.length > 0 || !Array.isArray(n) && n !== !1), $.has(o))
|
|
632
|
+
a ? t.push(" />") : t.push(">");
|
|
633
|
+
else if (r) {
|
|
634
|
+
t.push(">");
|
|
635
|
+
const g = n;
|
|
636
|
+
o === "script" && l || o === "style" && s ? (t.push("<![CDATA["), j(g, t, T, l, s, a, p), t.push("]]>")) : o === "script" || o === "style" ? K(g, t) : R(g, t, T, l, s, a, p), t.push("</"), t.push(o), t.push(">");
|
|
637
|
+
} else J.has(o), t.push("></"), t.push(o), t.push(">");
|
|
638
|
+
}
|
|
639
|
+
function j(e, t, i, l, s, a, p, o) {
|
|
629
640
|
if (e != null) {
|
|
630
641
|
if (typeof e == "string") {
|
|
631
|
-
|
|
642
|
+
t.push(ee(e));
|
|
632
643
|
return;
|
|
633
644
|
}
|
|
634
645
|
if (typeof e == "number" || typeof e == "bigint" || typeof e == "boolean") {
|
|
635
|
-
|
|
646
|
+
t.push(String(e));
|
|
636
647
|
return;
|
|
637
648
|
}
|
|
638
649
|
if (Array.isArray(e)) {
|
|
639
|
-
for (const
|
|
640
|
-
|
|
650
|
+
for (const T of e)
|
|
651
|
+
j(T, t, i, l, s, a, p);
|
|
641
652
|
return;
|
|
642
653
|
}
|
|
643
|
-
|
|
654
|
+
R(e, t, i, l, s, a, p);
|
|
644
655
|
}
|
|
645
656
|
}
|
|
646
|
-
function
|
|
657
|
+
function K(e, t) {
|
|
647
658
|
if (e != null) {
|
|
648
659
|
if (typeof e == "string") {
|
|
649
|
-
|
|
660
|
+
t.push(e);
|
|
650
661
|
return;
|
|
651
662
|
}
|
|
652
663
|
if (typeof e == "number" || typeof e == "bigint" || typeof e == "boolean") {
|
|
653
|
-
|
|
664
|
+
t.push(String(e));
|
|
654
665
|
return;
|
|
655
666
|
}
|
|
656
667
|
if (Array.isArray(e)) {
|
|
657
|
-
for (const
|
|
658
|
-
|
|
668
|
+
for (const i of e)
|
|
669
|
+
K(i, t);
|
|
659
670
|
return;
|
|
660
671
|
}
|
|
661
672
|
}
|
|
662
673
|
}
|
|
663
|
-
function
|
|
664
|
-
const
|
|
665
|
-
for (const [
|
|
674
|
+
function ne(e) {
|
|
675
|
+
const t = [];
|
|
676
|
+
for (const [i, l] of Object.entries(e))
|
|
666
677
|
if (l) {
|
|
667
|
-
const
|
|
668
|
-
|
|
678
|
+
const s = te(i);
|
|
679
|
+
t.push(`${s}: ${l}`);
|
|
669
680
|
}
|
|
670
|
-
return
|
|
681
|
+
return t.join("; ");
|
|
671
682
|
}
|
|
672
|
-
function
|
|
673
|
-
const
|
|
674
|
-
function
|
|
675
|
-
if (typeof l == "string" &&
|
|
676
|
-
const
|
|
677
|
-
if (l.type === "script" || l.type === "style" || l.type === "template" ||
|
|
683
|
+
function be(e) {
|
|
684
|
+
const t = [];
|
|
685
|
+
function i(l) {
|
|
686
|
+
if (typeof l == "string" && t.push(l), (typeof l == "number" || typeof l == "bigint" || typeof l == "boolean") && t.push(`${l}`), typeof l == "object" && l !== null && "type" in l && l.props && "children" in l.props) {
|
|
687
|
+
const s = l.props.children;
|
|
688
|
+
if (l.type === "script" || l.type === "style" || l.type === "template" || s && typeof s == "object" && "then" in s && typeof s.then == "function")
|
|
678
689
|
return;
|
|
679
|
-
if (Array.isArray(
|
|
680
|
-
for (const
|
|
681
|
-
|
|
682
|
-
else
|
|
690
|
+
if (Array.isArray(s))
|
|
691
|
+
for (const a of s)
|
|
692
|
+
i(a);
|
|
693
|
+
else s != null && i(s);
|
|
683
694
|
}
|
|
684
695
|
if (Array.isArray(l))
|
|
685
|
-
for (const
|
|
686
|
-
|
|
696
|
+
for (const s of l)
|
|
697
|
+
i(s);
|
|
687
698
|
}
|
|
688
|
-
return
|
|
699
|
+
return i(e), t.join("");
|
|
689
700
|
}
|
|
690
|
-
async function
|
|
701
|
+
async function U(e) {
|
|
691
702
|
if (e == null)
|
|
692
703
|
return e;
|
|
693
704
|
if (e && typeof e == "object" && "then" in e && typeof e.then == "function") {
|
|
694
|
-
const
|
|
695
|
-
return
|
|
705
|
+
const t = await e;
|
|
706
|
+
return U(t);
|
|
696
707
|
}
|
|
697
708
|
if (typeof e == "string" || typeof e == "number" || typeof e == "boolean" || typeof e == "bigint")
|
|
698
709
|
return e;
|
|
699
710
|
if (typeof e != "function" && typeof e != "symbol") {
|
|
700
711
|
if (Array.isArray(e))
|
|
701
712
|
return await Promise.all(
|
|
702
|
-
e.filter((
|
|
713
|
+
e.filter((i) => !(i == null || typeof i == "function" || typeof i == "symbol")).map((i) => U(i))
|
|
703
714
|
);
|
|
704
715
|
if (e && typeof e == "object" && "type" in e && "props" in e) {
|
|
705
|
-
const
|
|
706
|
-
for (const [l,
|
|
716
|
+
const t = e, i = {};
|
|
717
|
+
for (const [l, s] of Object.entries(t.props))
|
|
707
718
|
if (l === "children") {
|
|
708
|
-
const
|
|
709
|
-
|
|
719
|
+
const a = await U(s);
|
|
720
|
+
a != null && (i.children = a);
|
|
710
721
|
} else {
|
|
711
|
-
if (typeof
|
|
722
|
+
if (typeof s == "function" || typeof s == "symbol")
|
|
712
723
|
continue;
|
|
713
|
-
|
|
724
|
+
s != null && (i[l] = s);
|
|
714
725
|
}
|
|
715
726
|
return {
|
|
716
|
-
type:
|
|
717
|
-
props:
|
|
727
|
+
type: t.type,
|
|
728
|
+
props: i
|
|
718
729
|
};
|
|
719
730
|
}
|
|
720
731
|
}
|
|
721
732
|
}
|
|
722
|
-
|
|
733
|
+
const le = [
|
|
734
|
+
"br",
|
|
735
|
+
["span", "class"],
|
|
736
|
+
"p",
|
|
737
|
+
["a", "href", "rel", "class"],
|
|
738
|
+
"pre",
|
|
739
|
+
"del",
|
|
740
|
+
"code",
|
|
741
|
+
"em",
|
|
742
|
+
"strong",
|
|
743
|
+
"i",
|
|
744
|
+
"u",
|
|
745
|
+
"ul",
|
|
746
|
+
["ol", "start", "reversed"],
|
|
747
|
+
["li", "value"],
|
|
748
|
+
"blockquote"
|
|
749
|
+
], ae = [
|
|
750
|
+
"h-*",
|
|
751
|
+
"p-*",
|
|
752
|
+
"u-*",
|
|
753
|
+
"dt-*",
|
|
754
|
+
"e-*",
|
|
755
|
+
"mention",
|
|
756
|
+
"hashtag",
|
|
757
|
+
"ellipsis",
|
|
758
|
+
"invisible"
|
|
759
|
+
], oe = ["http", "https"], fe = {
|
|
760
|
+
a: ["href"],
|
|
761
|
+
area: ["href"],
|
|
762
|
+
audio: ["src"],
|
|
763
|
+
base: ["href"],
|
|
764
|
+
blockquote: ["cite"],
|
|
765
|
+
button: ["formaction"],
|
|
766
|
+
del: ["cite"],
|
|
767
|
+
embed: ["src"],
|
|
768
|
+
form: ["action"],
|
|
769
|
+
iframe: ["src"],
|
|
770
|
+
img: ["src", "longdesc"],
|
|
771
|
+
input: ["src", "formaction"],
|
|
772
|
+
ins: ["cite"],
|
|
773
|
+
link: ["href"],
|
|
774
|
+
object: ["data"],
|
|
775
|
+
q: ["cite"],
|
|
776
|
+
script: ["src"],
|
|
777
|
+
source: ["src"],
|
|
778
|
+
track: ["src"],
|
|
779
|
+
video: ["src", "poster"]
|
|
780
|
+
};
|
|
781
|
+
function ce(e) {
|
|
782
|
+
const t = /* @__PURE__ */ new Map();
|
|
783
|
+
let i = !1, l = /* @__PURE__ */ new Set(), s = !1;
|
|
784
|
+
for (const a of e)
|
|
785
|
+
if (typeof a == "string")
|
|
786
|
+
a === "*" ? i = !0 : t.set(a.toLowerCase(), {
|
|
787
|
+
allowed: !0,
|
|
788
|
+
allowedAttributes: /* @__PURE__ */ new Set(),
|
|
789
|
+
allowAllAttributes: !1
|
|
790
|
+
});
|
|
791
|
+
else {
|
|
792
|
+
const [p, ...o] = a, T = o.includes("*");
|
|
793
|
+
p === "*" ? (i = !0, T ? s = !0 : l = new Set(o.map((n) => n.toLowerCase()))) : t.set(p.toLowerCase(), {
|
|
794
|
+
allowed: !0,
|
|
795
|
+
allowedAttributes: T ? /* @__PURE__ */ new Set() : new Set(o.map((n) => n.toLowerCase())),
|
|
796
|
+
allowAllAttributes: T
|
|
797
|
+
});
|
|
798
|
+
}
|
|
799
|
+
return { configs: t, allowAll: i, universalAttrs: l, universalAllowAllAttrs: s };
|
|
800
|
+
}
|
|
801
|
+
function ue(e) {
|
|
802
|
+
return e.includes("*") ? { patterns: [], allowAll: !0 } : { patterns: e.map((i) => {
|
|
803
|
+
const s = "^" + i.replace(/[.+?^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*") + "$";
|
|
804
|
+
return new RegExp(s);
|
|
805
|
+
}), allowAll: !1 };
|
|
806
|
+
}
|
|
807
|
+
function pe(e = {}) {
|
|
808
|
+
const t = e.allowedTags ?? le, i = e.allowedClasses ?? ae, l = e.allowedLinkProtocols ?? oe, s = e.attributeNaming ?? "reactName", a = ce(t), p = ue(i);
|
|
809
|
+
return {
|
|
810
|
+
tagConfigs: a.configs,
|
|
811
|
+
classPatterns: p.patterns,
|
|
812
|
+
protocols: new Set(l.map((o) => o.toLowerCase())),
|
|
813
|
+
attributeNaming: s,
|
|
814
|
+
allowAllClasses: p.allowAll,
|
|
815
|
+
allowAllTags: a.allowAll,
|
|
816
|
+
universalAttributes: a.universalAttrs,
|
|
817
|
+
universalAllowAllAttributes: a.universalAllowAllAttrs
|
|
818
|
+
};
|
|
819
|
+
}
|
|
820
|
+
function he(e, t, i) {
|
|
821
|
+
return i ? !0 : t.some((l) => l.test(e));
|
|
822
|
+
}
|
|
823
|
+
function me(e, t, i) {
|
|
824
|
+
return i ? e : e.split(/\s+/).filter((a) => a.length > 0).filter((a) => he(a, t, i)).join(" ");
|
|
825
|
+
}
|
|
826
|
+
function Te(e, t) {
|
|
827
|
+
const i = e.trim();
|
|
828
|
+
if (t.has(".")) {
|
|
829
|
+
if (i.startsWith("/") || i.startsWith("./") || i.startsWith("../") || i.startsWith("#") || i.startsWith("?"))
|
|
830
|
+
return !0;
|
|
831
|
+
const a = i.indexOf(":"), p = i.indexOf("/");
|
|
832
|
+
if (a === -1 || p !== -1 && p < a)
|
|
833
|
+
return !0;
|
|
834
|
+
}
|
|
835
|
+
const l = i.match(/^([a-zA-Z][a-zA-Z0-9+.-]*):/);
|
|
836
|
+
if (!l || !l[1])
|
|
837
|
+
return t.has(".");
|
|
838
|
+
const s = l[1].toLowerCase();
|
|
839
|
+
return t.has(s);
|
|
840
|
+
}
|
|
841
|
+
function ge(e) {
|
|
842
|
+
return fe[e.toLowerCase()] ?? [];
|
|
843
|
+
}
|
|
844
|
+
function de(e, t, i, l) {
|
|
845
|
+
const s = {}, a = ge(e), p = i.allowAllAttributes || l.universalAllowAllAttributes, o = l.attributeNaming === "exactName" ? "class" : "className", T = l.attributeNaming === "exactName" ? "for" : "htmlFor";
|
|
846
|
+
for (const [n, r] of Object.entries(t)) {
|
|
847
|
+
if (n === "children")
|
|
848
|
+
continue;
|
|
849
|
+
const h = n.toLowerCase();
|
|
850
|
+
if (a.includes(h) && typeof r == "string" && !Te(r, l.protocols))
|
|
851
|
+
return null;
|
|
852
|
+
if ((n === "className" || n === "class") && typeof r == "string") {
|
|
853
|
+
if (p)
|
|
854
|
+
s[o] = r;
|
|
855
|
+
else if (i.allowedAttributes.has("class") || l.universalAttributes.has("class")) {
|
|
856
|
+
const g = me(r, l.classPatterns, l.allowAllClasses);
|
|
857
|
+
g && (s[o] = g);
|
|
858
|
+
}
|
|
859
|
+
continue;
|
|
860
|
+
}
|
|
861
|
+
if ((n === "htmlFor" || n === "for") && typeof r == "string") {
|
|
862
|
+
(p || i.allowedAttributes.has("for") || l.universalAttributes.has("for")) && (s[T] = r);
|
|
863
|
+
continue;
|
|
864
|
+
}
|
|
865
|
+
(p || i.allowedAttributes.has(h) || i.allowedAttributes.has(n) || l.universalAttributes.has(h) || l.universalAttributes.has(n)) && (s[n] = r);
|
|
866
|
+
}
|
|
867
|
+
return s;
|
|
868
|
+
}
|
|
869
|
+
function X(e, t) {
|
|
870
|
+
if (e == null || typeof e == "string" || typeof e == "number" || typeof e == "boolean" || typeof e == "bigint")
|
|
871
|
+
return e;
|
|
872
|
+
if (Array.isArray(e)) {
|
|
873
|
+
const o = [];
|
|
874
|
+
for (const T of e) {
|
|
875
|
+
const n = X(T, t);
|
|
876
|
+
Array.isArray(n) ? o.push(...n) : n != null && o.push(n);
|
|
877
|
+
}
|
|
878
|
+
return o.length === 0 ? [] : o.length === 1 ? o[0] : o;
|
|
879
|
+
}
|
|
880
|
+
const i = e, l = i.type.toLowerCase();
|
|
881
|
+
let s = t.tagConfigs.get(l);
|
|
882
|
+
!s && t.allowAllTags && (s = {
|
|
883
|
+
allowed: !0,
|
|
884
|
+
allowedAttributes: t.universalAttributes,
|
|
885
|
+
allowAllAttributes: t.universalAllowAllAttributes
|
|
886
|
+
});
|
|
887
|
+
const a = i.props.children !== void 0 ? X(i.props.children, t) : void 0;
|
|
888
|
+
if (!s) {
|
|
889
|
+
if (l === "img") {
|
|
890
|
+
const o = i.props.alt;
|
|
891
|
+
return typeof o == "string" && o.length > 0 ? o : void 0;
|
|
892
|
+
}
|
|
893
|
+
return a !== void 0 ? a : void 0;
|
|
894
|
+
}
|
|
895
|
+
const p = de(l, i.props, s, t);
|
|
896
|
+
if (p === null) {
|
|
897
|
+
if (l === "img") {
|
|
898
|
+
const o = i.props.alt;
|
|
899
|
+
if (typeof o == "string" && o.length > 0)
|
|
900
|
+
return o;
|
|
901
|
+
}
|
|
902
|
+
return a !== void 0 ? a : void 0;
|
|
903
|
+
}
|
|
904
|
+
return a !== void 0 && (p.children = a), {
|
|
905
|
+
type: i.type,
|
|
906
|
+
props: p
|
|
907
|
+
};
|
|
908
|
+
}
|
|
909
|
+
function ye(e, t = {}) {
|
|
910
|
+
const i = pe(t);
|
|
911
|
+
return X(e, i);
|
|
912
|
+
}
|
|
913
|
+
function Y(e, t) {
|
|
723
914
|
if (e == null || typeof e == "string" || typeof e == "number" || typeof e == "boolean" || typeof e == "bigint")
|
|
724
915
|
return e;
|
|
725
916
|
if (Array.isArray(e))
|
|
726
|
-
return e.map((
|
|
917
|
+
return e.map((i) => Y(i, t));
|
|
727
918
|
if (typeof e == "object" && "type" in e && "props" in e) {
|
|
728
|
-
const { type:
|
|
729
|
-
if (
|
|
730
|
-
const
|
|
731
|
-
return
|
|
919
|
+
const { type: i, props: l } = e, { children: s, ...a } = l;
|
|
920
|
+
if (s !== void 0) {
|
|
921
|
+
const p = Y(s, t);
|
|
922
|
+
return p === null ? t(i, a) : Array.isArray(p) ? t(i, a, ...p) : t(i, a, p);
|
|
732
923
|
}
|
|
733
|
-
return
|
|
924
|
+
return t(i, a);
|
|
734
925
|
}
|
|
735
926
|
return null;
|
|
736
927
|
}
|
|
737
|
-
function
|
|
738
|
-
return
|
|
928
|
+
function Ee(e, t = {}) {
|
|
929
|
+
return Q(e, t);
|
|
930
|
+
}
|
|
931
|
+
function we(e, t = {}) {
|
|
932
|
+
return e && typeof e == "object" && "node" in e ? k(e, t) : e === void 0 ? "" : k(e, t);
|
|
739
933
|
}
|
|
740
|
-
function
|
|
741
|
-
return
|
|
934
|
+
async function Ne(e) {
|
|
935
|
+
return await U(e);
|
|
742
936
|
}
|
|
743
|
-
|
|
744
|
-
return
|
|
937
|
+
function Ce(e, t = {}) {
|
|
938
|
+
return ye(e, t);
|
|
745
939
|
}
|
|
746
940
|
export {
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
941
|
+
Ne as awaitHtmlNode,
|
|
942
|
+
O as decodeHtmlEntities,
|
|
943
|
+
G as encodeHtmlEntities,
|
|
944
|
+
be as getTextContent,
|
|
751
945
|
Y as htmlNodeTo,
|
|
752
|
-
|
|
753
|
-
|
|
946
|
+
Ae as htmlNodeToHtmlElement,
|
|
947
|
+
Ee as readHtml,
|
|
948
|
+
Ce as safeHtml,
|
|
949
|
+
we as writeHtml
|
|
754
950
|
};
|
package/dist/parser.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { ParseResult } from './types.ts';
|
|
2
|
-
export declare function parseHtml(html: string): ParseResult;
|
|
1
|
+
import { ParseResult, ParserOptions } from './types.ts';
|
|
2
|
+
export declare function parseHtml(html: string, options?: ParserOptions): ParseResult;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { HtmlNode, SafeHtmlOptions } from './types.ts';
|
|
2
|
+
/**
|
|
3
|
+
* Sanitizes an HtmlNode tree by removing disallowed tags, attributes, and URLs.
|
|
4
|
+
*
|
|
5
|
+
* - Tags not in allowedTags have their content retained (folded into parent)
|
|
6
|
+
* - Images replaced with their alt text when removed
|
|
7
|
+
* - Attributes not in the tag's allowed list are dropped
|
|
8
|
+
* - Classes are filtered by allowedClasses patterns (supports wildcards like 'h-*')
|
|
9
|
+
* - URLs not matching allowedLinkProtocols cause the element to be removed
|
|
10
|
+
* - Use '.' as a protocol to allow relative URLs
|
|
11
|
+
* @param node - The HtmlNode to sanitize
|
|
12
|
+
* @param options - The SafeHtmlOptions to use
|
|
13
|
+
* @returns The sanitized HtmlNode
|
|
14
|
+
*/
|
|
15
|
+
export declare function safeHtml(node: HtmlNode, options?: SafeHtmlOptions): HtmlNode;
|
package/dist/types.d.ts
CHANGED
|
@@ -1,14 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Style attribute as a structured record.
|
|
3
|
+
*/
|
|
1
4
|
export interface HtmlStyle {
|
|
2
5
|
[key: string]: string;
|
|
3
6
|
}
|
|
7
|
+
/**
|
|
8
|
+
* Properties of an HtmlElement.
|
|
9
|
+
*/
|
|
4
10
|
export interface HtmlElement {
|
|
5
11
|
type: string;
|
|
6
12
|
props: HtmlProps;
|
|
7
13
|
}
|
|
14
|
+
/**
|
|
15
|
+
* HtmlElement properties
|
|
16
|
+
*/
|
|
8
17
|
export interface HtmlProps {
|
|
9
18
|
[key: string]: string | number | boolean | HtmlStyle | HtmlNode | Promise<HtmlNode>;
|
|
10
19
|
children?: HtmlNode | Promise<HtmlNode>;
|
|
11
20
|
}
|
|
21
|
+
/**
|
|
22
|
+
* Nodes will be parsed into one of these types.
|
|
23
|
+
*/
|
|
12
24
|
export type HtmlNode = HtmlElement | string | number | bigint | boolean | null | undefined | HtmlNode[];
|
|
13
25
|
export declare enum ParserState {
|
|
14
26
|
TEXT = "TEXT",
|
|
@@ -29,6 +41,9 @@ export declare enum ParserState {
|
|
|
29
41
|
SCRIPT_CONTENT = "SCRIPT_CONTENT",
|
|
30
42
|
STYLE_CONTENT = "STYLE_CONTENT"
|
|
31
43
|
}
|
|
44
|
+
/**
|
|
45
|
+
* Namespace of an element.
|
|
46
|
+
*/
|
|
32
47
|
export declare enum Namespace {
|
|
33
48
|
HTML = "HTML",
|
|
34
49
|
SVG = "SVG",
|
|
@@ -45,10 +60,71 @@ export interface ParseResult {
|
|
|
45
60
|
doctype?: string;
|
|
46
61
|
node: HtmlNode | HtmlNode[];
|
|
47
62
|
}
|
|
63
|
+
/**
|
|
64
|
+
* Controls how special attributes like 'class' and 'for' are named:
|
|
65
|
+
* - 'reactName': Use React-style names (className, htmlFor) - default for parsing
|
|
66
|
+
* - 'exactName': Use exact HTML names (class, for)
|
|
67
|
+
*/
|
|
68
|
+
export type ParserAttributeNaming = 'reactName' | 'exactName';
|
|
69
|
+
/**
|
|
70
|
+
* Controls how special attributes are written:
|
|
71
|
+
* - 'reactName': Write as React-style (className, htmlFor)
|
|
72
|
+
* - 'exactName': Write as exact HTML (class, for)
|
|
73
|
+
* - 'eitherName': Normalize className->class, htmlFor->for (default)
|
|
74
|
+
*/
|
|
75
|
+
export type WriterAttributeNaming = 'reactName' | 'exactName' | 'eitherName';
|
|
76
|
+
export interface ParserOptions {
|
|
77
|
+
/**
|
|
78
|
+
* How to name special attributes like 'class' and 'for'.
|
|
79
|
+
* - 'reactName' (default): Convert to React-style (className, htmlFor)
|
|
80
|
+
* - 'exactName': Keep exact HTML names (class, for)
|
|
81
|
+
*/
|
|
82
|
+
attributeNaming?: ParserAttributeNaming;
|
|
83
|
+
}
|
|
48
84
|
export interface WriterOptions {
|
|
49
85
|
useCDataForScripts?: boolean;
|
|
50
86
|
useCDataForStyles?: boolean;
|
|
51
87
|
xml?: string;
|
|
52
88
|
doctype?: string;
|
|
53
89
|
voidTrailingSlash?: boolean;
|
|
90
|
+
/**
|
|
91
|
+
* How to write special attributes like 'class' and 'for'.
|
|
92
|
+
* - 'eitherName' (default): Normalize className->class, htmlFor->for
|
|
93
|
+
* - 'reactName': Write as-is (className, htmlFor)
|
|
94
|
+
* - 'exactName': Write as exact HTML (class, for)
|
|
95
|
+
*/
|
|
96
|
+
attributeNaming?: WriterAttributeNaming;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Allowed tag specification:
|
|
100
|
+
* - string: tag name with no custom attributes allowed (only global attrs like 'class' if classes are allowed)
|
|
101
|
+
* - [tagName, ...attrs]: tag name with specific allowed attributes
|
|
102
|
+
*/
|
|
103
|
+
export type AllowedTag = string | [string, ...string[]];
|
|
104
|
+
/**
|
|
105
|
+
* Options for the safeHtml function.
|
|
106
|
+
*/
|
|
107
|
+
export interface SafeHtmlOptions {
|
|
108
|
+
/**
|
|
109
|
+
* List of allowed tags. Can be strings (tag name only) or tuples [tagName, ...allowedAttributes].
|
|
110
|
+
* If not provided, uses default safe tags.
|
|
111
|
+
*/
|
|
112
|
+
allowedTags?: AllowedTag[];
|
|
113
|
+
/**
|
|
114
|
+
* List of allowed CSS class patterns. Supports wildcards like 'h-*', 'p-*'.
|
|
115
|
+
* If not provided, uses default allowed classes.
|
|
116
|
+
*/
|
|
117
|
+
allowedClasses?: string[];
|
|
118
|
+
/**
|
|
119
|
+
* List of allowed URL protocols for links/media. Use '.' for relative URLs.
|
|
120
|
+
* If not provided, uses default ['http', 'https'].
|
|
121
|
+
*/
|
|
122
|
+
allowedLinkProtocols?: string[];
|
|
123
|
+
/**
|
|
124
|
+
* The attribute naming convention used in the input.
|
|
125
|
+
* - 'reactName' (default): Input uses React-style names (className, htmlFor)
|
|
126
|
+
* - 'exactName': Input uses exact HTML names (class, for)
|
|
127
|
+
* When set, also affects how the output is named.
|
|
128
|
+
*/
|
|
129
|
+
attributeNaming?: ParserAttributeNaming;
|
|
54
130
|
}
|
package/dist/utils.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { HtmlElement, HtmlNode } from './types.ts';
|
|
1
2
|
/**
|
|
2
3
|
* Converts a kebab-case or snake_case string to camelCase
|
|
3
4
|
* @example toCamelCase("foo-bar") => "fooBar"
|
|
@@ -32,3 +33,11 @@ export declare function isWhitespace(code: number): boolean;
|
|
|
32
33
|
* Checks if a character code is valid for tag/attribute names
|
|
33
34
|
*/
|
|
34
35
|
export declare function isNameChar(code: number): boolean;
|
|
36
|
+
/**
|
|
37
|
+
* Find the first HtmlElement in the HtmlNode, may be an html string.
|
|
38
|
+
*
|
|
39
|
+
* @param node - the result of readHtml or a string of HTML
|
|
40
|
+
* @returns the first HtmlElement in the HtmlNode
|
|
41
|
+
* @throws an error if no HtmlElement is found
|
|
42
|
+
*/
|
|
43
|
+
export declare function htmlNodeToHtmlElement(node: HtmlNode): HtmlElement;
|