{"version":3,"file":"index.modern.mjs","sources":["../src/core/constants.ts","../src/core/utils.ts","../src/core/attributes.ts","../src/core/render.ts","../src/index.ts"],"sourcesContent":["export const STYLE_COMMENTS_REGEX = /\\/\\*[^*]*\\*+([^/*][^*]*\\*+)*\\//g;\nexport const STYLE_RULES_REGEX =\n  /\\s*([a-z\\-]+)\\s*:\\s*((?:[^;]*url\\(.*?\\)[^;]*|[^;]*)*)\\s*(?:;|$)/gi;\n\nexport const BOOL_HTML_ATTRIBUTES =\n  \"allowFullScreen async autoFocus autoPlay checked controls default defer disabled download formNoValidate inert itemScope hidden loop multiple muted noModule noValidate open playsInline readOnly required reversed selected\";\nexport const HTML_ATTRIBUTES =\n  \"accept-charset accessKey autoCapitalize autoComplete autoCorrect autoSave cellPadding cellSpacing charSet classID colSpan contentEditable contextMenu controlsList crossOrigin dateTime defaultChecked defaultValue disablePictureInPicture disableRemotePlayback encType enterKeyHint formMethod formAction formEncType formTarget frameBorder hrefLang http-equiv imageSizes imageSrcSet inputMode itemID itemProp itemRef itemType keyParams keyType marginWidth marginHeight maxLength mediaGroup minLength radioGroup referrerPolicy rowSpan spellCheck srcDoc srcLang srcSet tabIndex useMap\";\nexport const SVG_ATTRIBUTES =\n  \"accent-height alignment-baseline allowReorder arabic-form attributeName attributeType autoReverse baseFrequency baseline-shift baseProfile calcMode cap-height clip-path clipPathUnits clip-rule color-interpolation color-interpolation-filters color-profile color-rendering contentScriptType contentStyleType diffuseConstant dominant-baseline edgeMode enable-background externalResourcesRequired fill-opacity fill-rule filterRes filterUnits flood-opacity flood-color font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-name glyph-orientation-horizontal glyph-orientation-vertical glyphRef gradientTransform gradientUnits horiz-adv-x horiz-origin-x image-rendering kernelMatrix kernelUnitLength keyPoints keySplines keyTimes lengthAdjust letter-spacing lighting-color limitingConeAngle marker-end markerHeight marker-mid marker-start markerUnits markerWidth maskContentUnits maskUnits numOctaves overline-position overline-thickness paint-order panose-1 pathLength patternContentUnits patternTransform patternUnits pointer-events pointsAtX pointsAtY pointsAtZ preserveAlpha preserveAspectRatio primitiveUnits refX refY rendering-intent repeatCount repeatDur requiredExtensions requiredFeatures shape-rendering specularConstant specularExponent spreadMethod startOffset stdDeviation stitchTiles stop-color stop-opacity strikethrough-position strikethrough-thickness stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-width stroke-opacity suppressContentEditableWarning suppressHydrationWarning surfaceScale systemLanguage tableValues targetX targetY text-anchor text-decoration textLength text-rendering underline-position underline-thickness unicode-bidi unicode-range units-per-em v-alphabetic vector-effect vert-adv-y vert-origin-x vert-origin-y v-hanging v-ideographic viewBox viewTarget v-mathematical word-spacing writing-mode xChannelSelector x-height xlink:actuate xlink:arcrole xlink:href xlink:role xlink:show xlink:title xlink:type xml:base xml:lang xml:space xmlns:xlink yChannelSelector zoomAndPan\";\n","export function camelCase(value: string) {\n  return value.replace(/[-:](\\w)/g, (_, $1) => $1.toUpperCase());\n}\n\nexport function identity<T>(value: T): T {\n  return value;\n}\n\nexport function boolAttrValue(value: unknown, nodeName?: string) {\n  return !value || (nodeName == \"download\" ? value : !!value);\n}\n","import {\n  STYLE_COMMENTS_REGEX,\n  STYLE_RULES_REGEX,\n  HTML_ATTRIBUTES,\n  BOOL_HTML_ATTRIBUTES,\n} from \"./constants\";\nimport { camelCase, boolAttrValue } from \"./utils\";\nimport { AttributesMap, CSSProperties, Attributes } from \"./types\";\n\nexport const htmlAttrsMap = parseAttrs(HTML_ATTRIBUTES, {\n  class: \"className\",\n  for: \"htmlFor\",\n});\nexport const boolHtmlAttrsMap = parseAttrs(BOOL_HTML_ATTRIBUTES);\n\nexport function parseAttrs(\n  attrs: string,\n  initialValue?: AttributesMap\n): AttributesMap {\n  return attrs.split(\" \").reduce<AttributesMap>((acc, prop) => {\n    const value = camelCase(prop);\n\n    acc[prop.toLowerCase()] = value;\n\n    if (prop.match(/[-:]/)) {\n      acc[value.toLowerCase()] = value;\n    }\n\n    return acc;\n  }, initialValue || {});\n}\n\nexport function styleToObject(style: string): CSSProperties {\n  style = style.replace(STYLE_COMMENTS_REGEX, \"\");\n  const rules: Record<string, string | number> = {};\n  let arr: RegExpExecArray | null;\n\n  while ((arr = STYLE_RULES_REGEX.exec(style))) {\n    const key = arr[1];\n    const value = arr[2];\n    const rule = key[0] == \"-\" ? key : camelCase(key);\n\n    rules[rule] = value;\n  }\n\n  return rules;\n}\n\nexport function attrsToProps(\n  node: Element,\n  attrsMap: AttributesMap\n): Attributes {\n  return Array.from(node.attributes).reduce<Attributes>(\n    (acc, { nodeName, nodeValue }) => {\n      const defaultAttrValue = nodeValue || \"\";\n      const attrKey =\n        ![\"reset\", \"submit\"].includes(node.getAttribute(\"type\") || \"\") &&\n        [\"checked\", \"value\"].includes(nodeName)\n          ? camelCase(\"default-\" + nodeName)\n          : attrsMap[nodeName] || nodeName;\n\n      acc[attrKey] =\n        attrKey == \"style\"\n          ? defaultAttrValue\n            ? styleToObject(defaultAttrValue)\n            : {}\n          : boolHtmlAttrsMap[nodeName]\n          ? boolAttrValue(nodeValue, nodeName)\n          : defaultAttrValue;\n\n      return acc;\n    },\n    {}\n  );\n}\n","import { ReactNode, createElement, isValidElement } from \"react\";\nimport { identity } from \"./utils\";\nimport { attrsToProps, boolHtmlAttrsMap, htmlAttrsMap } from \"./attributes\";\nimport { RenderOptions, Key } from \"./types\";\n\nexport function getNodeList(html: string, _container?: HTMLElement) {\n  try {\n    _container = new DOMParser().parseFromString(html, \"text/html\").body;\n  } catch (_) {\n    _container = document.createElement(\"div\");\n    _container.innerHTML = html;\n  }\n\n  return _container.childNodes;\n}\n\nexport function renderNode(\n  node: Node,\n  key?: Key,\n  options: RenderOptions = {}\n): ReactNode {\n  const { mapNode, mapElement, components } = options;\n  const _mapNode = mapNode || identity;\n  const _node = _mapNode(node, key, options);\n\n  if (!(_node && _node instanceof Node)) {\n    return _node;\n  }\n\n  const nodeType = _node.nodeType;\n\n  if (nodeType === 3) {\n    return _node.nodeValue;\n  }\n\n  if (nodeType === 1) {\n    const { childNodes, nodeName } = _node as Element;\n    const _nodeName = nodeName.toLowerCase();\n    const children = childNodes.length\n      ? renderNodes(childNodes, options)\n      : null;\n    const props = Object.assign(\n      { key, children },\n      attrsToProps(\n        _node as Element,\n        Object.assign({}, htmlAttrsMap, boolHtmlAttrsMap, options.attrsMap)\n      )\n    );\n    const mapComponent = components?.[_nodeName];\n\n    const reactNode = mapComponent\n      ? mapComponent(props)\n      : createElement(_nodeName, props);\n\n    return mapElement && isValidElement(reactNode)\n      ? mapElement(reactNode)\n      : reactNode;\n  }\n}\n\nexport function renderNodes(\n  nodeList: NodeListOf<Node> | Node[],\n  options?: RenderOptions\n): ReactNode[] {\n  return Array.from(nodeList).reduce<ReactNode[]>(\n    (acc, node, key) => (acc.push(renderNode(node, key, options)), acc),\n    []\n  );\n}\n","import { createElement, Fragment, ReactNode } from \"react\";\nimport { SVG_ATTRIBUTES } from \"./core/constants\";\nimport { identity } from \"./core/utils\";\nimport { renderNode, renderNodes, getNodeList } from \"./core/render\";\nimport { parseAttrs } from \"./core/attributes\";\nimport { ParseOptions } from \"./core/types\";\n\nconst typeErrorMessage = \"HTML must be a string\";\nfunction checkTypeError(html: unknown, message: string) {\n  if (typeof html !== \"string\") {\n    throw new TypeError(message);\n  }\n}\n\nfunction parse(html: string, options: ParseOptions = {}) {\n  let node: ReactNode = null;\n\n  try {\n    checkTypeError(html, typeErrorMessage);\n\n    html = (options.sanitize || identity)(html);\n\n    checkTypeError(html, \"Sanitized \" + typeErrorMessage);\n\n    node = createElement(\n      Fragment,\n      {},\n      html && renderNodes(getNodeList(html), options)\n    );\n  } catch (error) {\n    const onError = options.onError;\n\n    if (onError?.call) {\n      onError(error, html);\n    }\n  }\n\n  return node;\n}\n\nexport * from \"./core/types\";\nexport { parse, parseAttrs, renderNodes, renderNode, SVG_ATTRIBUTES };\n"],"names":["STYLE_COMMENTS_REGEX","STYLE_RULES_REGEX","SVG_ATTRIBUTES","camelCase","value","replace","_","$1","toUpperCase","identity","htmlAttrsMap","parseAttrs","class","for","boolHtmlAttrsMap","attrs","initialValue","split","reduce","acc","prop","toLowerCase","match","node","key","options","mapNode","mapElement","components","_node","nodeType","nodeValue","childNodes","nodeName","_nodeName","length","renderNodes","props","Object","assign","children","attrsToProps","attrsMap","from","attributes","defaultAttrValue","attrKey","includes","getAttribute","styleToObject","style","rules","arr","exec","boolAttrValue","mapComponent","reactNode","createElement","isValidElement","nodeList","Array","push","renderNode","checkTypeError","html","message","TypeError","sanitize","Fragment","getNodeList","_container","DOMParser","parseFromString","body","document","innerHTML","error","onError","call"],"mappings":"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"}