{"version":3,"file":"unsafe-html.cjs","names":[],"sources":["../../src/directives/unsafe-html.ts"],"sourcesContent":["import { computed, isReactive, type Readable, effect as rawEffect, type Signal } from '@vielzeug/ripple';\n\nimport { invariant } from '../errors';\nimport { createDirectiveResult, type DirectiveResult } from '../template/result';\nimport { createReplaceableSlot } from '../utils/dom';\n\nconst parseHtml = (html: string, parent: ParentNode, insertBefore: Node): Node[] => {\n  const tpl = document.createElement('template');\n\n  tpl.innerHTML = html;\n\n  const nodes = Array.from(tpl.content.cloneNode(true).childNodes);\n\n  for (const node of nodes) parent.insertBefore(node, insertBefore);\n\n  return nodes;\n};\n\n/**\n * Renders HTML without escaping as a DirectiveResult.\n *\n * This is intentionally named `unsafeHtml`: sanitization is an application\n * boundary, not mutable process-wide framework configuration. Sanitize\n * untrusted content before passing it here.\n *\n * Supports static strings, signals, and getter functions `() => string`.\n * When reactive, the DOM is updated in-place whenever the value changes.\n */\nexport function unsafeHtml(value: (() => string) | string | Signal<string> | Readable<string>): DirectiveResult {\n  if (typeof value === 'function') {\n    const c = computed(value);\n\n    return createDirectiveResult((anchor, registerCleanup) => {\n      unsafeHtml(c).mount(anchor, registerCleanup);\n    });\n  }\n\n  return createDirectiveResult((anchor, registerCleanup) => {\n    const parent = anchor.parentNode;\n\n    invariant(parent, 'unsafeHtml() anchor comment has no parent node');\n\n    const endMarker = document.createComment('unsafe-html/end');\n\n    parent.insertBefore(endMarker, anchor.nextSibling);\n\n    if (isReactive(value)) {\n      const slot = createReplaceableSlot();\n      const src = value as Readable<string>;\n\n      const stop = rawEffect(() => {\n        slot.clear();\n        slot.setNodes(parseHtml(src.value, parent, endMarker));\n      });\n\n      registerCleanup(() => stop.dispose());\n      registerCleanup(() => {\n        slot.clear();\n        endMarker.remove();\n      });\n    } else {\n      parseHtml(value, parent, endMarker);\n\n      registerCleanup(() => endMarker.remove());\n    }\n  });\n}\n"],"mappings":"qIAMA,IAAM,GAAa,EAAc,EAAoB,IAA+B,CAClF,IAAM,EAAM,SAAS,cAAc,UAAU,EAE7C,EAAI,UAAY,EAEhB,IAAM,EAAQ,MAAM,KAAK,EAAI,QAAQ,UAAU,EAAI,CAAC,CAAC,UAAU,EAE/D,IAAK,IAAM,KAAQ,EAAO,EAAO,aAAa,EAAM,CAAY,EAEhE,OAAO,CACT,EAYA,SAAgB,EAAW,EAAqF,CAC9G,GAAI,OAAO,GAAU,WAAY,CAC/B,IAAM,GAAA,EAAI,EAAA,SAAA,CAAS,CAAK,EAExB,OAAO,EAAA,uBAAuB,EAAQ,IAAoB,CACxD,EAAW,CAAC,CAAC,CAAC,MAAM,EAAQ,CAAe,CAC7C,CAAC,CACH,CAEA,OAAO,EAAA,uBAAuB,EAAQ,IAAoB,CACxD,IAAM,EAAS,EAAO,WAEtB,EAAA,UAAU,EAAQ,gDAAgD,EAElE,IAAM,EAAY,SAAS,cAAc,iBAAiB,EAI1D,GAFA,EAAO,aAAa,EAAW,EAAO,WAAW,GAEjD,EAAI,EAAA,WAAA,CAAW,CAAK,EAAG,CACrB,IAAM,EAAO,EAAA,sBAAsB,EAC7B,EAAM,EAEN,GAAA,EAAO,EAAA,OAAA,KAAgB,CAC3B,EAAK,MAAM,EACX,EAAK,SAAS,EAAU,EAAI,MAAO,EAAQ,CAAS,CAAC,CACvD,CAAC,EAED,MAAsB,EAAK,QAAQ,CAAC,EACpC,MAAsB,CACpB,EAAK,MAAM,EACX,EAAU,OAAO,CACnB,CAAC,CACH,MACE,EAAU,EAAO,EAAQ,CAAS,EAElC,MAAsB,EAAU,OAAO,CAAC,CAE5C,CAAC,CACH"}