{"version":3,"file":"parse5.mjs","names":[],"sources":["../../src/main/parse5.ts"],"sourcesContent":["/**\n * Optional parse adapter backed by parse5 (the reference WHATWG parser).\n * parse5 is an optional peer dependency, imported only when you import this module.\n *\n *   import { Sanitizer } from 'neosanitize';\n *   import { parse5Adapter } from 'neosanitize/parse5';\n *   const s = Sanitizer.builder(ugc).parser(parse5Adapter).build();\n */\nimport { parse } from 'parse5';\nimport type { ParseAdapter, ParentNode, ElementNode, TreeNode, NS } from './core';\n\nconst SVG_NS = 'http://www.w3.org/2000/svg';\nconst MATHML_NS = 'http://www.w3.org/1998/Math/MathML';\n\ninterface P5Node {\n  nodeName: string;\n  tagName?: string;\n  value?: string;\n  data?: string;\n  name?: string;\n  publicId?: string;\n  systemId?: string;\n  namespaceURI?: string;\n  attrs?: Array<{ name: string; value: string; prefix?: string }>;\n  childNodes?: P5Node[];\n  content?: { childNodes: P5Node[] };\n}\n\nexport const parse5Adapter: ParseAdapter = (html) => {\n  const doc = parse(html) as unknown as P5Node;\n  const root: ParentNode = { type: 'document', children: [] };\n  for (const child of doc.childNodes ?? []) root.children.push(to_node(child));\n  return root;\n};\n\nfunction ns_of(uri: string | undefined): NS {\n  if (uri === SVG_NS) return 'svg';\n  if (uri === MATHML_NS) return 'mathml';\n  return 'html';\n}\n\nfunction to_node(p: P5Node): TreeNode {\n  switch (p.nodeName) {\n    case '#text':\n      return { type: 'text', value: p.value ?? '', parent: null };\n    case '#comment':\n      return { type: 'comment', value: p.data ?? '', parent: null };\n    case '#documentType':\n      return { type: 'doctype', name: p.name ?? '', publicId: p.publicId ?? '', systemId: p.systemId ?? '', parent: null };\n    default:\n      return to_element(p);\n  }\n}\n\nfunction to_element(p: P5Node): ElementNode {\n  const ns = ns_of(p.namespaceURI);\n  const attrs: Array<[string, string]> = [];\n  // foreign namespaced attrs (xlink:href, xml:lang) use the \"prefix localname\"\n  // space form so URL and allow-list checks match the bundled parser.\n  for (const a of p.attrs ?? []) attrs.push([a.prefix ? a.prefix + ' ' + a.name : a.name, a.value]);\n  const kids = (ns === 'html' && p.tagName === 'template' && p.content ? p.content.childNodes : p.childNodes) ?? [];\n  const children: TreeNode[] = [];\n  for (const c of kids) children.push(to_node(c));\n  return { type: 'element', name: p.tagName ?? p.nodeName, namespace: ns, attrs, children, parent: null };\n}\n"],"mappings":";;;;;;;;;;AAWA,MAAM,SAAS;AACf,MAAM,YAAY;AAgBlB,MAAa,iBAA+B,SAAS;CACnD,MAAM,MAAM,MAAM,IAAI;CACtB,MAAM,OAAmB;EAAE,MAAM;EAAY,UAAU,CAAC;CAAE;CAC1D,KAAK,MAAM,SAAS,IAAI,cAAc,CAAC,GAAG,KAAK,SAAS,KAAK,QAAQ,KAAK,CAAC;CAC3E,OAAO;AACT;AAEA,SAAS,MAAM,KAA6B;CAC1C,IAAI,QAAQ,QAAQ,OAAO;CAC3B,IAAI,QAAQ,WAAW,OAAO;CAC9B,OAAO;AACT;AAEA,SAAS,QAAQ,GAAqB;CACpC,QAAQ,EAAE,UAAV;EACE,KAAK,SACH,OAAO;GAAE,MAAM;GAAQ,OAAO,EAAE,SAAS;GAAI,QAAQ;EAAK;EAC5D,KAAK,YACH,OAAO;GAAE,MAAM;GAAW,OAAO,EAAE,QAAQ;GAAI,QAAQ;EAAK;EAC9D,KAAK,iBACH,OAAO;GAAE,MAAM;GAAW,MAAM,EAAE,QAAQ;GAAI,UAAU,EAAE,YAAY;GAAI,UAAU,EAAE,YAAY;GAAI,QAAQ;EAAK;EACrH,SACE,OAAO,WAAW,CAAC;CACvB;AACF;AAEA,SAAS,WAAW,GAAwB;CAC1C,MAAM,KAAK,MAAM,EAAE,YAAY;CAC/B,MAAM,QAAiC,CAAC;CAGxC,KAAK,MAAM,KAAK,EAAE,SAAS,CAAC,GAAG,MAAM,KAAK,CAAC,EAAE,SAAS,EAAE,SAAS,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC;CAChG,MAAM,QAAQ,OAAO,UAAU,EAAE,YAAY,cAAc,EAAE,UAAU,EAAE,QAAQ,aAAa,EAAE,eAAe,CAAC;CAChH,MAAM,WAAuB,CAAC;CAC9B,KAAK,MAAM,KAAK,MAAM,SAAS,KAAK,QAAQ,CAAC,CAAC;CAC9C,OAAO;EAAE,MAAM;EAAW,MAAM,EAAE,WAAW,EAAE;EAAU,WAAW;EAAI;EAAO;EAAU,QAAQ;CAAK;AACxG"}