@particle-academy/react-fancy 5.48.0 → 5.48.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.
Files changed (52) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/dist/button.cjs +4 -4
  3. package/dist/button.js +2 -2
  4. package/dist/{chunk-ICQJ6475.cjs → chunk-3XJKJQSY.cjs} +4 -4
  5. package/dist/{chunk-ICQJ6475.cjs.map → chunk-3XJKJQSY.cjs.map} +1 -1
  6. package/dist/{chunk-JVGJHIIQ.js → chunk-62WPAKFS.js} +3 -3
  7. package/dist/{chunk-JVGJHIIQ.js.map → chunk-62WPAKFS.js.map} +1 -1
  8. package/dist/{chunk-MQ4ULIOU.cjs → chunk-EEKXWXYO.cjs} +4 -4
  9. package/dist/{chunk-MQ4ULIOU.cjs.map → chunk-EEKXWXYO.cjs.map} +1 -1
  10. package/dist/{chunk-ND5D7GJB.cjs → chunk-FNYUUVOK.cjs} +5 -5
  11. package/dist/{chunk-ND5D7GJB.cjs.map → chunk-FNYUUVOK.cjs.map} +1 -1
  12. package/dist/{chunk-25ZOOUFG.js → chunk-GMNMJLZO.js} +3 -3
  13. package/dist/{chunk-25ZOOUFG.js.map → chunk-GMNMJLZO.js.map} +1 -1
  14. package/dist/{chunk-MRARASNZ.cjs → chunk-I6XHZ3S2.cjs} +4 -4
  15. package/dist/{chunk-MRARASNZ.cjs.map → chunk-I6XHZ3S2.cjs.map} +1 -1
  16. package/dist/{chunk-P7WMYJ5I.js → chunk-JHDO6CRT.js} +3 -3
  17. package/dist/{chunk-P7WMYJ5I.js.map → chunk-JHDO6CRT.js.map} +1 -1
  18. package/dist/{chunk-TX6VUYBC.js → chunk-K74R6IEB.js} +4 -4
  19. package/dist/{chunk-TX6VUYBC.js.map → chunk-K74R6IEB.js.map} +1 -1
  20. package/dist/{chunk-BFKCVSNK.cjs → chunk-LRNWD26Z.cjs} +5 -3
  21. package/dist/chunk-LRNWD26Z.cjs.map +1 -0
  22. package/dist/{chunk-WWUKTXPX.cjs → chunk-ODAPI4QJ.cjs} +11 -11
  23. package/dist/{chunk-WWUKTXPX.cjs.map → chunk-ODAPI4QJ.cjs.map} +1 -1
  24. package/dist/{chunk-XJXQG34J.js → chunk-QXYO76NZ.js} +5 -3
  25. package/dist/chunk-QXYO76NZ.js.map +1 -0
  26. package/dist/{chunk-S5ZYG5MG.cjs → chunk-RLC2BE3D.cjs} +15 -15
  27. package/dist/{chunk-S5ZYG5MG.cjs.map → chunk-RLC2BE3D.cjs.map} +1 -1
  28. package/dist/{chunk-QSAYIYEB.js → chunk-SK4AEUO4.js} +3 -3
  29. package/dist/{chunk-QSAYIYEB.js.map → chunk-SK4AEUO4.js.map} +1 -1
  30. package/dist/{chunk-RBEQLBKI.cjs → chunk-TKDUT7ZA.cjs} +6 -6
  31. package/dist/{chunk-RBEQLBKI.cjs.map → chunk-TKDUT7ZA.cjs.map} +1 -1
  32. package/dist/{chunk-DMFJJ73P.js → chunk-VM5BNL4L.js} +3 -3
  33. package/dist/{chunk-DMFJJ73P.js.map → chunk-VM5BNL4L.js.map} +1 -1
  34. package/dist/{chunk-JJRD3WX3.js → chunk-ZLYOMQ2J.js} +3 -3
  35. package/dist/{chunk-JJRD3WX3.js.map → chunk-ZLYOMQ2J.js.map} +1 -1
  36. package/dist/content-renderer.cjs +5 -5
  37. package/dist/content-renderer.js +2 -2
  38. package/dist/editor.cjs +5 -5
  39. package/dist/editor.js +3 -3
  40. package/dist/index.cjs +35 -35
  41. package/dist/index.js +8 -8
  42. package/dist/json-editor.cjs +14 -14
  43. package/dist/json-editor.js +3 -3
  44. package/dist/magic-wand.cjs +4 -4
  45. package/dist/magic-wand.js +3 -3
  46. package/dist/prompt-input.cjs +4 -4
  47. package/dist/prompt-input.js +3 -3
  48. package/dist/reason-tag.cjs +4 -4
  49. package/dist/reason-tag.js +3 -3
  50. package/package.json +1 -1
  51. package/dist/chunk-BFKCVSNK.cjs.map +0 -1
  52. package/dist/chunk-XJXQG34J.js.map +0 -1
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var chunkS5ZYG5MG_cjs = require('./chunk-S5ZYG5MG.cjs');
3
+ var chunkRLC2BE3D_cjs = require('./chunk-RLC2BE3D.cjs');
4
4
  require('./chunk-2QIGXSSZ.cjs');
5
5
  require('./chunk-AR3JOPGT.cjs');
6
6
  require('./chunk-Y52NXM73.cjs');
@@ -14,8 +14,8 @@ require('./chunk-BVRPDMB7.cjs');
14
14
  require('./chunk-MSRYJETY.cjs');
15
15
  require('./chunk-X7H75WVP.cjs');
16
16
  require('./chunk-MOU6O324.cjs');
17
- require('./chunk-ICQJ6475.cjs');
18
- require('./chunk-BFKCVSNK.cjs');
17
+ require('./chunk-3XJKJQSY.cjs');
18
+ require('./chunk-LRNWD26Z.cjs');
19
19
  require('./chunk-XCZZVRBY.cjs');
20
20
  require('./chunk-QKFOJKVE.cjs');
21
21
  require('./chunk-LCNHEYIM.cjs');
@@ -33,47 +33,47 @@ require('./chunk-ZU5Q77OT.cjs');
33
33
 
34
34
  Object.defineProperty(exports, "JsonEditor", {
35
35
  enumerable: true,
36
- get: function () { return chunkS5ZYG5MG_cjs.JsonEditor; }
36
+ get: function () { return chunkRLC2BE3D_cjs.JsonEditor; }
37
37
  });
38
38
  Object.defineProperty(exports, "applyJsonEdit", {
39
39
  enumerable: true,
40
- get: function () { return chunkS5ZYG5MG_cjs.applyJsonEdit; }
40
+ get: function () { return chunkRLC2BE3D_cjs.applyJsonEdit; }
41
41
  });
42
42
  Object.defineProperty(exports, "describeEdit", {
43
43
  enumerable: true,
44
- get: function () { return chunkS5ZYG5MG_cjs.describeEdit; }
44
+ get: function () { return chunkRLC2BE3D_cjs.describeEdit; }
45
45
  });
46
46
  Object.defineProperty(exports, "findJsonConflicts", {
47
47
  enumerable: true,
48
- get: function () { return chunkS5ZYG5MG_cjs.findJsonConflicts; }
48
+ get: function () { return chunkRLC2BE3D_cjs.findJsonConflicts; }
49
49
  });
50
50
  Object.defineProperty(exports, "getAtPath", {
51
51
  enumerable: true,
52
- get: function () { return chunkS5ZYG5MG_cjs.getAtPath; }
52
+ get: function () { return chunkRLC2BE3D_cjs.getAtPath; }
53
53
  });
54
54
  Object.defineProperty(exports, "inferType", {
55
55
  enumerable: true,
56
- get: function () { return chunkS5ZYG5MG_cjs.inferType; }
56
+ get: function () { return chunkRLC2BE3D_cjs.inferType; }
57
57
  });
58
58
  Object.defineProperty(exports, "parseKeyMap", {
59
59
  enumerable: true,
60
- get: function () { return chunkS5ZYG5MG_cjs.parseKeyMap; }
60
+ get: function () { return chunkRLC2BE3D_cjs.parseKeyMap; }
61
61
  });
62
62
  Object.defineProperty(exports, "parsePath", {
63
63
  enumerable: true,
64
- get: function () { return chunkS5ZYG5MG_cjs.parsePath; }
64
+ get: function () { return chunkRLC2BE3D_cjs.parsePath; }
65
65
  });
66
66
  Object.defineProperty(exports, "pathToString", {
67
67
  enumerable: true,
68
- get: function () { return chunkS5ZYG5MG_cjs.pathToString; }
68
+ get: function () { return chunkRLC2BE3D_cjs.pathToString; }
69
69
  });
70
70
  Object.defineProperty(exports, "resolveKeyRule", {
71
71
  enumerable: true,
72
- get: function () { return chunkS5ZYG5MG_cjs.resolveKeyRule; }
72
+ get: function () { return chunkRLC2BE3D_cjs.resolveKeyRule; }
73
73
  });
74
74
  Object.defineProperty(exports, "typeMatches", {
75
75
  enumerable: true,
76
- get: function () { return chunkS5ZYG5MG_cjs.typeMatches; }
76
+ get: function () { return chunkRLC2BE3D_cjs.typeMatches; }
77
77
  });
78
78
  //# sourceMappingURL=json-editor.cjs.map
79
79
  //# sourceMappingURL=json-editor.cjs.map
@@ -1,4 +1,4 @@
1
- export { JsonEditor, applyJsonEdit, describeEdit, findJsonConflicts, getAtPath, inferType, parseKeyMap, parsePath, pathToString, resolveKeyRule, typeMatches } from './chunk-DMFJJ73P.js';
1
+ export { JsonEditor, applyJsonEdit, describeEdit, findJsonConflicts, getAtPath, inferType, parseKeyMap, parsePath, pathToString, resolveKeyRule, typeMatches } from './chunk-VM5BNL4L.js';
2
2
  import './chunk-EEWRLFTI.js';
3
3
  import './chunk-IECPLOSZ.js';
4
4
  import './chunk-NBAHXZHJ.js';
@@ -12,8 +12,8 @@ import './chunk-F2GAZZVS.js';
12
12
  import './chunk-KYZNCVRD.js';
13
13
  import './chunk-CF5KRDN4.js';
14
14
  import './chunk-6FCQD2KQ.js';
15
- import './chunk-JJRD3WX3.js';
16
- import './chunk-XJXQG34J.js';
15
+ import './chunk-ZLYOMQ2J.js';
16
+ import './chunk-QXYO76NZ.js';
17
17
  import './chunk-45BBNJQD.js';
18
18
  import './chunk-IVRYSSM7.js';
19
19
  import './chunk-ZXZJYVWP.js';
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var chunkMRARASNZ_cjs = require('./chunk-MRARASNZ.cjs');
3
+ var chunkI6XHZ3S2_cjs = require('./chunk-I6XHZ3S2.cjs');
4
4
  require('./chunk-V6VFSX6V.cjs');
5
5
  require('./chunk-7EZBMGEE.cjs');
6
6
  require('./chunk-XKDW6B7X.cjs');
@@ -9,8 +9,8 @@ require('./chunk-YLGTDBB2.cjs');
9
9
  require('./chunk-VBWRH4UW.cjs');
10
10
  require('./chunk-MOU6O324.cjs');
11
11
  require('./chunk-M5MUGSON.cjs');
12
- require('./chunk-ICQJ6475.cjs');
13
- require('./chunk-BFKCVSNK.cjs');
12
+ require('./chunk-3XJKJQSY.cjs');
13
+ require('./chunk-LRNWD26Z.cjs');
14
14
  require('./chunk-XCZZVRBY.cjs');
15
15
  require('./chunk-QKFOJKVE.cjs');
16
16
  require('./chunk-KJ22KE56.cjs');
@@ -21,7 +21,7 @@ require('./chunk-ZU5Q77OT.cjs');
21
21
 
22
22
  Object.defineProperty(exports, "MagicWand", {
23
23
  enumerable: true,
24
- get: function () { return chunkMRARASNZ_cjs.MagicWand; }
24
+ get: function () { return chunkI6XHZ3S2_cjs.MagicWand; }
25
25
  });
26
26
  //# sourceMappingURL=magic-wand.cjs.map
27
27
  //# sourceMappingURL=magic-wand.cjs.map
@@ -1,4 +1,4 @@
1
- export { MagicWand } from './chunk-P7WMYJ5I.js';
1
+ export { MagicWand } from './chunk-JHDO6CRT.js';
2
2
  import './chunk-DEFGT75G.js';
3
3
  import './chunk-PWEZCMIY.js';
4
4
  import './chunk-KKWNKBKR.js';
@@ -7,8 +7,8 @@ import './chunk-GFYSELJF.js';
7
7
  import './chunk-IQ4KQJAO.js';
8
8
  import './chunk-6FCQD2KQ.js';
9
9
  import './chunk-LQ4ICCN2.js';
10
- import './chunk-JJRD3WX3.js';
11
- import './chunk-XJXQG34J.js';
10
+ import './chunk-ZLYOMQ2J.js';
11
+ import './chunk-QXYO76NZ.js';
12
12
  import './chunk-45BBNJQD.js';
13
13
  import './chunk-IVRYSSM7.js';
14
14
  import './chunk-OL53XYHF.js';
@@ -1,12 +1,12 @@
1
1
  'use strict';
2
2
 
3
- var chunkRBEQLBKI_cjs = require('./chunk-RBEQLBKI.cjs');
3
+ var chunkTKDUT7ZA_cjs = require('./chunk-TKDUT7ZA.cjs');
4
4
  require('./chunk-AIA5UNQ5.cjs');
5
5
  require('./chunk-MSRYJETY.cjs');
6
6
  require('./chunk-X7H75WVP.cjs');
7
7
  require('./chunk-M5MUGSON.cjs');
8
- require('./chunk-ICQJ6475.cjs');
9
- require('./chunk-BFKCVSNK.cjs');
8
+ require('./chunk-3XJKJQSY.cjs');
9
+ require('./chunk-LRNWD26Z.cjs');
10
10
  require('./chunk-XCZZVRBY.cjs');
11
11
  require('./chunk-QKFOJKVE.cjs');
12
12
  require('./chunk-J2DI6RMR.cjs');
@@ -18,7 +18,7 @@ require('./chunk-ZU5Q77OT.cjs');
18
18
 
19
19
  Object.defineProperty(exports, "PromptInput", {
20
20
  enumerable: true,
21
- get: function () { return chunkRBEQLBKI_cjs.PromptInput; }
21
+ get: function () { return chunkTKDUT7ZA_cjs.PromptInput; }
22
22
  });
23
23
  //# sourceMappingURL=prompt-input.cjs.map
24
24
  //# sourceMappingURL=prompt-input.cjs.map
@@ -1,10 +1,10 @@
1
- export { PromptInput } from './chunk-QSAYIYEB.js';
1
+ export { PromptInput } from './chunk-SK4AEUO4.js';
2
2
  import './chunk-TJ66S5K6.js';
3
3
  import './chunk-KYZNCVRD.js';
4
4
  import './chunk-CF5KRDN4.js';
5
5
  import './chunk-LQ4ICCN2.js';
6
- import './chunk-JJRD3WX3.js';
7
- import './chunk-XJXQG34J.js';
6
+ import './chunk-ZLYOMQ2J.js';
7
+ import './chunk-QXYO76NZ.js';
8
8
  import './chunk-45BBNJQD.js';
9
9
  import './chunk-IVRYSSM7.js';
10
10
  import './chunk-MQ6VGG62.js';
@@ -1,10 +1,10 @@
1
1
  'use strict';
2
2
 
3
- var chunkMQ4ULIOU_cjs = require('./chunk-MQ4ULIOU.cjs');
3
+ var chunkEEKXWXYO_cjs = require('./chunk-EEKXWXYO.cjs');
4
4
  require('./chunk-WKNVZUWZ.cjs');
5
5
  require('./chunk-M5MUGSON.cjs');
6
- require('./chunk-ICQJ6475.cjs');
7
- require('./chunk-BFKCVSNK.cjs');
6
+ require('./chunk-3XJKJQSY.cjs');
7
+ require('./chunk-LRNWD26Z.cjs');
8
8
  require('./chunk-XCZZVRBY.cjs');
9
9
  require('./chunk-QKFOJKVE.cjs');
10
10
  require('./chunk-J2DI6RMR.cjs');
@@ -17,7 +17,7 @@ require('./chunk-ZU5Q77OT.cjs');
17
17
 
18
18
  Object.defineProperty(exports, "ReasonTag", {
19
19
  enumerable: true,
20
- get: function () { return chunkMQ4ULIOU_cjs.ReasonTag; }
20
+ get: function () { return chunkEEKXWXYO_cjs.ReasonTag; }
21
21
  });
22
22
  //# sourceMappingURL=reason-tag.cjs.map
23
23
  //# sourceMappingURL=reason-tag.cjs.map
@@ -1,8 +1,8 @@
1
- export { ReasonTag } from './chunk-JVGJHIIQ.js';
1
+ export { ReasonTag } from './chunk-62WPAKFS.js';
2
2
  import './chunk-6KXAFP2T.js';
3
3
  import './chunk-LQ4ICCN2.js';
4
- import './chunk-JJRD3WX3.js';
5
- import './chunk-XJXQG34J.js';
4
+ import './chunk-ZLYOMQ2J.js';
5
+ import './chunk-QXYO76NZ.js';
6
6
  import './chunk-45BBNJQD.js';
7
7
  import './chunk-IVRYSSM7.js';
8
8
  import './chunk-MQ6VGG62.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@particle-academy/react-fancy",
3
- "version": "5.48.0",
3
+ "version": "5.48.1",
4
4
  "description": "React UI component library for Human+ UX — controlled, agent-bridgeable primitives",
5
5
  "repository": {
6
6
  "type": "git",
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/utils/sanitize.ts"],"names":[],"mappings":"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","file":"chunk-BFKCVSNK.cjs","sourcesContent":["/**\n * HTML and URL sanitization utilities.\n *\n * Hand-rolled (no third-party deps) using browser-native `DOMParser`. Designed\n * for the trust model \"consumer passes user-generated markdown/HTML to a\n * react-fancy component\" — strips script tags, event handlers, and dangerous\n * URI schemes from `href`/`src` attributes.\n *\n * For server-side rendering (no `window`), `sanitizeHtml` returns the input\n * unchanged. Consumers SSR-rendering untrusted content should sanitize on the\n * server with their own pipeline.\n */\n\nconst DANGEROUS_TAGS = new Set([\n \"script\",\n \"style\",\n \"iframe\",\n \"object\",\n \"embed\",\n \"link\",\n \"meta\",\n \"base\",\n \"form\",\n]);\n\nconst URL_ATTRS = new Set([\"href\", \"src\", \"action\", \"formaction\", \"xlink:href\"]);\n\nconst SAFE_PROTOCOL = /^(?:https?:|mailto:|tel:|sms:|ftp:|#|\\/|\\.\\/|\\.\\.\\/|[^:]*$)/i;\n\n/**\n * Validate a URL/href against an allow-list of safe protocols. Returns the\n * input if safe, or `undefined` if it begins with a dangerous scheme like\n * `javascript:`, `data:`, or `vbscript:`. Relative URLs and fragment links\n * are allowed.\n */\nexport function sanitizeHref(href: string | undefined | null): string | undefined {\n if (href == null) return undefined;\n const trimmed = href.trim();\n if (!trimmed) return undefined;\n return SAFE_PROTOCOL.test(trimmed) ? trimmed : undefined;\n}\n\nfunction stripDangerousAttrs(el: Element): void {\n // Collect names first; mutating during iteration is awkward with NamedNodeMap.\n const names: string[] = [];\n for (let i = 0; i < el.attributes.length; i++) {\n names.push(el.attributes[i].name);\n }\n\n for (const name of names) {\n const lower = name.toLowerCase();\n\n // All on* event handlers\n if (lower.startsWith(\"on\")) {\n el.removeAttribute(name);\n continue;\n }\n\n // URL attributes — protocol-filter\n if (URL_ATTRS.has(lower)) {\n const sanitized = sanitizeHref(el.getAttribute(name));\n if (sanitized === undefined) {\n el.removeAttribute(name);\n } else {\n el.setAttribute(name, sanitized);\n }\n continue;\n }\n\n // srcdoc executes JS in the iframe — drop wholesale\n if (lower === \"srcdoc\") {\n el.removeAttribute(name);\n }\n }\n}\n\nfunction walk(el: Element, removeQueue: Element[]): void {\n const tag = el.tagName.toLowerCase();\n\n if (DANGEROUS_TAGS.has(tag)) {\n removeQueue.push(el);\n return;\n }\n\n stripDangerousAttrs(el);\n\n const children = Array.from(el.children);\n for (const child of children) {\n walk(child, removeQueue);\n }\n}\n\n/**\n * Sanitize an HTML string by removing dangerous tags (script, iframe, etc.),\n * event-handler attributes (`onclick`, `onerror`, ...), and dangerous URI\n * schemes in `href`/`src` attributes.\n *\n * Uses the browser's `DOMParser`. In non-browser environments returns the\n * input unchanged — sanitize on the server in those cases.\n */\nexport function sanitizeHtml(html: string): string {\n if (typeof window === \"undefined\" || typeof DOMParser === \"undefined\") {\n return html;\n }\n\n const doc = new DOMParser().parseFromString(`<body>${html}</body>`, \"text/html\");\n const body = doc.body;\n if (!body) return html;\n\n const removeQueue: Element[] = [];\n for (const child of Array.from(body.children)) {\n walk(child, removeQueue);\n }\n\n for (const el of removeQueue) {\n el.parentNode?.removeChild(el);\n }\n\n return body.innerHTML;\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/utils/sanitize.ts"],"names":[],"mappings":";AAaA,IAAM,cAAA,uBAAqB,GAAA,CAAI;AAAA,EAC7B,QAAA;AAAA,EACA,OAAA;AAAA,EACA,QAAA;AAAA,EACA,QAAA;AAAA,EACA,OAAA;AAAA,EACA,MAAA;AAAA,EACA,MAAA;AAAA,EACA,MAAA;AAAA,EACA;AACF,CAAC,CAAA;AAED,IAAM,SAAA,uBAAgB,GAAA,CAAI,CAAC,QAAQ,KAAA,EAAO,QAAA,EAAU,YAAA,EAAc,YAAY,CAAC,CAAA;AAE/E,IAAM,aAAA,GAAgB,8DAAA;AAQf,SAAS,aAAa,IAAA,EAAqD;AAChF,EAAA,IAAI,IAAA,IAAQ,MAAM,OAAO,MAAA;AACzB,EAAA,MAAM,OAAA,GAAU,KAAK,IAAA,EAAK;AAC1B,EAAA,IAAI,CAAC,SAAS,OAAO,MAAA;AACrB,EAAA,OAAO,aAAA,CAAc,IAAA,CAAK,OAAO,CAAA,GAAI,OAAA,GAAU,MAAA;AACjD;AAEA,SAAS,oBAAoB,EAAA,EAAmB;AAE9C,EAAA,MAAM,QAAkB,EAAC;AACzB,EAAA,KAAA,IAAS,IAAI,CAAA,EAAG,CAAA,GAAI,EAAA,CAAG,UAAA,CAAW,QAAQ,CAAA,EAAA,EAAK;AAC7C,IAAA,KAAA,CAAM,IAAA,CAAK,EAAA,CAAG,UAAA,CAAW,CAAC,EAAE,IAAI,CAAA;AAAA,EAClC;AAEA,EAAA,KAAA,MAAW,QAAQ,KAAA,EAAO;AACxB,IAAA,MAAM,KAAA,GAAQ,KAAK,WAAA,EAAY;AAG/B,IAAA,IAAI,KAAA,CAAM,UAAA,CAAW,IAAI,CAAA,EAAG;AAC1B,MAAA,EAAA,CAAG,gBAAgB,IAAI,CAAA;AACvB,MAAA;AAAA,IACF;AAGA,IAAA,IAAI,SAAA,CAAU,GAAA,CAAI,KAAK,CAAA,EAAG;AACxB,MAAA,MAAM,SAAA,GAAY,YAAA,CAAa,EAAA,CAAG,YAAA,CAAa,IAAI,CAAC,CAAA;AACpD,MAAA,IAAI,cAAc,MAAA,EAAW;AAC3B,QAAA,EAAA,CAAG,gBAAgB,IAAI,CAAA;AAAA,MACzB,CAAA,MAAO;AACL,QAAA,EAAA,CAAG,YAAA,CAAa,MAAM,SAAS,CAAA;AAAA,MACjC;AACA,MAAA;AAAA,IACF;AAGA,IAAA,IAAI,UAAU,QAAA,EAAU;AACtB,MAAA,EAAA,CAAG,gBAAgB,IAAI,CAAA;AAAA,IACzB;AAAA,EACF;AACF;AAEA,SAAS,IAAA,CAAK,IAAa,WAAA,EAA8B;AACvD,EAAA,MAAM,GAAA,GAAM,EAAA,CAAG,OAAA,CAAQ,WAAA,EAAY;AAEnC,EAAA,IAAI,cAAA,CAAe,GAAA,CAAI,GAAG,CAAA,EAAG;AAC3B,IAAA,WAAA,CAAY,KAAK,EAAE,CAAA;AACnB,IAAA;AAAA,EACF;AAEA,EAAA,mBAAA,CAAoB,EAAE,CAAA;AAEtB,EAAA,MAAM,QAAA,GAAW,KAAA,CAAM,IAAA,CAAK,EAAA,CAAG,QAAQ,CAAA;AACvC,EAAA,KAAA,MAAW,SAAS,QAAA,EAAU;AAC5B,IAAA,IAAA,CAAK,OAAO,WAAW,CAAA;AAAA,EACzB;AACF;AAUO,SAAS,aAAa,IAAA,EAAsB;AACjD,EAAA,IAAI,OAAO,MAAA,KAAW,WAAA,IAAe,OAAO,cAAc,WAAA,EAAa;AACrE,IAAA,OAAO,IAAA;AAAA,EACT;AAEA,EAAA,MAAM,GAAA,GAAM,IAAI,SAAA,EAAU,CAAE,gBAAgB,CAAA,MAAA,EAAS,IAAI,WAAW,WAAW,CAAA;AAC/E,EAAA,MAAM,OAAO,GAAA,CAAI,IAAA;AACjB,EAAA,IAAI,CAAC,MAAM,OAAO,IAAA;AAElB,EAAA,MAAM,cAAyB,EAAC;AAChC,EAAA,KAAA,MAAW,KAAA,IAAS,KAAA,CAAM,IAAA,CAAK,IAAA,CAAK,QAAQ,CAAA,EAAG;AAC7C,IAAA,IAAA,CAAK,OAAO,WAAW,CAAA;AAAA,EACzB;AAEA,EAAA,KAAA,MAAW,MAAM,WAAA,EAAa;AAC5B,IAAA,EAAA,CAAG,UAAA,EAAY,YAAY,EAAE,CAAA;AAAA,EAC/B;AAEA,EAAA,OAAO,IAAA,CAAK,SAAA;AACd","file":"chunk-XJXQG34J.js","sourcesContent":["/**\n * HTML and URL sanitization utilities.\n *\n * Hand-rolled (no third-party deps) using browser-native `DOMParser`. Designed\n * for the trust model \"consumer passes user-generated markdown/HTML to a\n * react-fancy component\" — strips script tags, event handlers, and dangerous\n * URI schemes from `href`/`src` attributes.\n *\n * For server-side rendering (no `window`), `sanitizeHtml` returns the input\n * unchanged. Consumers SSR-rendering untrusted content should sanitize on the\n * server with their own pipeline.\n */\n\nconst DANGEROUS_TAGS = new Set([\n \"script\",\n \"style\",\n \"iframe\",\n \"object\",\n \"embed\",\n \"link\",\n \"meta\",\n \"base\",\n \"form\",\n]);\n\nconst URL_ATTRS = new Set([\"href\", \"src\", \"action\", \"formaction\", \"xlink:href\"]);\n\nconst SAFE_PROTOCOL = /^(?:https?:|mailto:|tel:|sms:|ftp:|#|\\/|\\.\\/|\\.\\.\\/|[^:]*$)/i;\n\n/**\n * Validate a URL/href against an allow-list of safe protocols. Returns the\n * input if safe, or `undefined` if it begins with a dangerous scheme like\n * `javascript:`, `data:`, or `vbscript:`. Relative URLs and fragment links\n * are allowed.\n */\nexport function sanitizeHref(href: string | undefined | null): string | undefined {\n if (href == null) return undefined;\n const trimmed = href.trim();\n if (!trimmed) return undefined;\n return SAFE_PROTOCOL.test(trimmed) ? trimmed : undefined;\n}\n\nfunction stripDangerousAttrs(el: Element): void {\n // Collect names first; mutating during iteration is awkward with NamedNodeMap.\n const names: string[] = [];\n for (let i = 0; i < el.attributes.length; i++) {\n names.push(el.attributes[i].name);\n }\n\n for (const name of names) {\n const lower = name.toLowerCase();\n\n // All on* event handlers\n if (lower.startsWith(\"on\")) {\n el.removeAttribute(name);\n continue;\n }\n\n // URL attributes — protocol-filter\n if (URL_ATTRS.has(lower)) {\n const sanitized = sanitizeHref(el.getAttribute(name));\n if (sanitized === undefined) {\n el.removeAttribute(name);\n } else {\n el.setAttribute(name, sanitized);\n }\n continue;\n }\n\n // srcdoc executes JS in the iframe — drop wholesale\n if (lower === \"srcdoc\") {\n el.removeAttribute(name);\n }\n }\n}\n\nfunction walk(el: Element, removeQueue: Element[]): void {\n const tag = el.tagName.toLowerCase();\n\n if (DANGEROUS_TAGS.has(tag)) {\n removeQueue.push(el);\n return;\n }\n\n stripDangerousAttrs(el);\n\n const children = Array.from(el.children);\n for (const child of children) {\n walk(child, removeQueue);\n }\n}\n\n/**\n * Sanitize an HTML string by removing dangerous tags (script, iframe, etc.),\n * event-handler attributes (`onclick`, `onerror`, ...), and dangerous URI\n * schemes in `href`/`src` attributes.\n *\n * Uses the browser's `DOMParser`. In non-browser environments returns the\n * input unchanged — sanitize on the server in those cases.\n */\nexport function sanitizeHtml(html: string): string {\n if (typeof window === \"undefined\" || typeof DOMParser === \"undefined\") {\n return html;\n }\n\n const doc = new DOMParser().parseFromString(`<body>${html}</body>`, \"text/html\");\n const body = doc.body;\n if (!body) return html;\n\n const removeQueue: Element[] = [];\n for (const child of Array.from(body.children)) {\n walk(child, removeQueue);\n }\n\n for (const el of removeQueue) {\n el.parentNode?.removeChild(el);\n }\n\n return body.innerHTML;\n}\n"]}