{"version":3,"sources":["../../src/common/transformers/flat-list-grouper.ts","../../src/common/utils/attribute-sanitizer.ts","../../src/common/utils/mention-sanitizer.ts","../../src/common/utils/url-sanitizer.ts"],"names":["groupConsecutiveElementsWhile"],"mappings":";;;;;;;AAyBO,IAAM,eAAA,GAA+B,CAAC,QAAA,KAA+B;AAC1E,EAAA,OAAO,eAAe,QAAQ,CAAA;AAChC;AAEA,SAAS,WAAW,IAAA,EAAsB;AACxC,EAAA,OAAO,KAAK,IAAA,KAAS,WAAA;AACvB;AAEA,SAAS,eAAe,QAAA,EAA4B;AAClD,EAAA,MAAM,OAAA,GAAUA,+CAAA,CAA8B,QAAA,EAAU,CAAC,MAAM,IAAA,KAAS;AACtE,IAAA,OAAO,UAAA,CAAW,IAAI,CAAA,IAAK,UAAA,CAAW,IAAI,CAAA;AAAA,EAC5C,CAAC,CAAA;AAED,EAAA,OAAO,OAAA,CAAQ,GAAA,CAAI,CAAC,IAAA,KAAgB;AAClC,IAAA,IAAI,CAAC,KAAA,CAAM,OAAA,CAAQ,IAAI,CAAA,EAAG;AACxB,MAAA,IAAI,UAAA,CAAW,IAAI,CAAA,EAAG;AACpB,QAAA,OAAO,UAAA,CAAW,CAAC,IAAI,CAAC,CAAA;AAAA,MAC1B;AACA,MAAA,OAAO,IAAA;AAAA,IACT;AACA,IAAA,OAAO,WAAW,IAAI,CAAA;AAAA,EACxB,CAAC,CAAA;AACH;AAEA,SAAS,WAAW,KAAA,EAAuB;AACzC,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,MAAA;AAAA,IACN,YAAY,EAAC;AAAA,IACb,QAAA,EAAU,KAAA;AAAA,IACV,QAAA,EAAU;AAAA,GACZ;AACF;;;AClDO,SAAS,aAAa,KAAA,EAAyB;AACpD,EAAA,IAAI,OAAO,KAAA,KAAU,QAAA,EAAU,OAAO,KAAA;AACtC,EAAA,MAAM,CAAA,GAAI,MAAM,IAAA,EAAK;AACrB,EAAA,IAAI,CAAC,GAAG,OAAO,KAAA;AAGf,EAAA,IAAI,mDAAA,CAAoD,IAAA,CAAK,CAAC,CAAA,EAAG,OAAO,IAAA;AAGxE,EAAA,IAAI,aAAA,CAAc,IAAA,CAAK,CAAC,CAAA,EAAG,OAAO,IAAA;AAGlC,EAAA,IAAI,qCAAA,CAAsC,IAAA,CAAK,CAAC,CAAA,EAAG,OAAO,IAAA;AAE1D,EAAA,OAAO,KAAA;AACT;AAOO,SAAS,oBAAoB,KAAA,EAAyB;AAC3D,EAAA,IAAI,OAAO,KAAA,KAAU,QAAA,EAAU,OAAO,KAAA;AACtC,EAAA,OAAO,aAAA,CAAc,IAAA,CAAK,KAAA,CAAM,IAAA,EAAM,CAAA;AACxC;AAMO,SAAS,kBAAkB,KAAA,EAAyB;AACzD,EAAA,IAAI,OAAO,KAAA,KAAU,QAAA,EAAU,OAAO,KAAA;AACtC,EAAA,OAAO,kBAAA,CAAmB,IAAA,CAAK,KAAA,CAAM,IAAA,EAAM,CAAA;AAC7C;AAOO,SAAS,YAAY,KAAA,EAAyB;AACnD,EAAA,IAAI,OAAO,KAAA,KAAU,QAAA,EAAU,OAAO,KAAA;AACtC,EAAA,MAAM,CAAA,GAAI,MAAM,IAAA,EAAK;AAGrB,EAAA,IACE,CAAC,OAAA,EAAS,OAAA,EAAS,MAAA,EAAQ,QAAA,EAAU,SAAA,EAAW,SAAA,EAAW,UAAA,EAAY,UAAU,CAAA,CAAE,QAAA,CAAS,CAAC,CAAA,EAC7F;AACA,IAAA,OAAO,IAAA;AAAA,EACT;AAGA,EAAA,IAAI,qDAAA,CAAsD,IAAA,CAAK,CAAC,CAAA,EAAG,OAAO,IAAA;AAE1E,EAAA,OAAO,KAAA;AACT;AAMO,SAAS,aAAa,KAAA,EAAyB;AACpD,EAAA,IAAI,OAAO,KAAA,KAAU,QAAA,EAAU,OAAO,KAAA;AACtC,EAAA,MAAM,CAAA,GAAI,MAAM,IAAA,EAAK;AAErB,EAAA,IAAI,CAAA,KAAM,QAAQ,OAAO,IAAA;AACzB,EAAA,IAAI,gCAAA,CAAiC,IAAA,CAAK,CAAC,CAAA,EAAG,OAAO,IAAA;AAErD,EAAA,OAAO,KAAA;AACT;;;AClDO,SAAS,gBAAgB,IAAA,EAAwC;AACtE,EAAA,IAAI,CAAC,IAAA,IAAQ,OAAO,IAAA,KAAS,UAAU,OAAO,IAAA;AAE9C,EAAA,MAAM,GAAA,GAAM,IAAA;AACZ,EAAA,MAAM,OAAO,OAAO,GAAA,CAAI,IAAA,KAAS,QAAA,GAAW,IAAI,IAAA,GAAO,EAAA;AAEvD,EAAA,IAAI,CAAC,MAAM,OAAO,IAAA;AAElB,EAAA,MAAM,MAAA,GAA2B,EAAE,IAAA,EAAK;AAExC,EAAA,IAAI,OAAO,GAAA,CAAI,MAAA,KAAW,QAAA,IAAY,IAAI,MAAA,EAAQ;AAChD,IAAA,MAAA,CAAO,SAAS,GAAA,CAAI,MAAA;AAAA,EACtB;AACA,EAAA,IAAI,OAAO,GAAA,CAAI,IAAA,KAAS,QAAA,IAAY,IAAI,IAAA,EAAM;AAC5C,IAAA,MAAA,CAAO,OAAO,GAAA,CAAI,IAAA;AAAA,EACpB;AACA,EAAA,IAAI,OAAO,GAAA,CAAI,KAAA,KAAU,QAAA,IAAY,IAAI,KAAA,EAAO;AAC9C,IAAA,MAAA,CAAO,QAAQ,GAAA,CAAI,KAAA;AAAA,EACrB;AACA,EAAA,IAAI,OAAO,GAAA,CAAI,WAAW,MAAM,QAAA,IAAY,GAAA,CAAI,WAAW,CAAA,EAAG;AAC5D,IAAA,MAAA,CAAO,WAAW,CAAA,GAAI,GAAA,CAAI,WAAW,CAAA;AAAA,EACvC;AAEA,EAAA,OAAO,MAAA;AACT;;;AC/CA,IAAM,sBAAA,GAAyB;AAAA,EAC7B,OAAA;AAAA,EACA,QAAA;AAAA,EACA,SAAA;AAAA,EACA,MAAA;AAAA,EACA,MAAA;AAAA,EACA,OAAA;AAAA,EACA;AACF,CAAA;AAoCO,SAAS,mBACd,MAAA,EACqC;AACrC,EAAA,MAAM,SAAA,GAAY,QAAQ,SAAA,IAAa;AAAA,IACrC,GAAG,sBAAA;AAAA,IACH,GAAI,MAAA,EAAQ,cAAA,IAAkB;AAAC,GACjC;AAEA,EAAA,OAAO,CAAC,GAAA,KAAoC;AAC1C,IAAA,MAAM,OAAA,GAAU,IAAI,IAAA,EAAK;AAGzB,IAAA,IAAI,OAAA,CAAQ,UAAA,CAAW,GAAG,CAAA,IAAK,OAAA,CAAQ,UAAA,CAAW,GAAG,CAAA,IAAK,OAAA,CAAQ,UAAA,CAAW,GAAG,CAAA,EAAG;AACjF,MAAA,OAAO,GAAA;AAAA,IACT;AAGA,IAAA,MAAM,UAAA,GAAa,OAAA,CAAQ,OAAA,CAAQ,GAAG,CAAA;AACtC,IAAA,IAAI,eAAe,EAAA,EAAI;AAErB,MAAA,OAAO,GAAA;AAAA,IACT;AAGA,IAAA,MAAM,KAAA,GAAQ,QAAQ,WAAA,EAAY;AAClC,IAAA,KAAA,MAAW,YAAY,SAAA,EAAW;AAChC,MAAA,IAAI,KAAA,CAAM,UAAA,CAAW,QAAQ,CAAA,EAAG;AAC9B,QAAA,OAAO,GAAA;AAAA,MACT;AAAA,IACF;AAGA,IAAA,OAAO,MAAA;AAAA,EACT,CAAA;AACF","file":"index.cjs","sourcesContent":["import type { TNode, Transformer } from '../../core/ast-types';\nimport { groupConsecutiveElementsWhile } from '../utils/group-consecutive';\n\n/**\n * Groups adjacent `list-item` nodes into a flat `list` container,\n * matching Quill's editor DOM structure.\n *\n * Unlike `listGrouper`, this transformer does NOT nest sub-lists.\n * All consecutive list items (regardless of type or indent) are placed\n * as flat siblings inside a single `<ol>`. Visual nesting is handled\n * by `ql-indent-*` CSS classes.\n *\n * This matches Quill's actual `root.innerHTML` structure:\n * ```html\n * <ol>\n *   <li data-list=\"bullet\">Parent</li>\n *   <li class=\"ql-indent-1\" data-list=\"bullet\">Child</li>\n * </ol>\n * ```\n *\n * @example\n * ```ts\n * const ast = new DeltaParser(delta).use(flatListGrouper).toAST();\n * ```\n */\nexport const flatListGrouper: Transformer = (children: TNode[]): TNode[] => {\n  return groupFlatLists(children);\n};\n\nfunction isListItem(node: TNode): boolean {\n  return node.type === 'list-item';\n}\n\nfunction groupFlatLists(children: TNode[]): TNode[] {\n  const grouped = groupConsecutiveElementsWhile(children, (curr, prev) => {\n    return isListItem(curr) && isListItem(prev);\n  });\n\n  return grouped.map((item): TNode => {\n    if (!Array.isArray(item)) {\n      if (isListItem(item)) {\n        return createList([item]);\n      }\n      return item;\n    }\n    return createList(item);\n  });\n}\n\nfunction createList(items: TNode[]): TNode {\n  return {\n    type: 'list',\n    attributes: {},\n    children: items,\n    isInline: false,\n  };\n}\n","/**\n * Validates a CSS color value.\n *\n * Accepts hex colors (`#fff`, `#ffffff`), named colors (`red`, `transparent`),\n * and CSS color functions (`rgb(...)`, `rgba(...)`, `hsl(...)`, `hsla(...)`).\n */\nexport function isValidColor(value: unknown): boolean {\n  if (typeof value !== 'string') return false;\n  const v = value.trim();\n  if (!v) return false;\n\n  // Hex color\n  if (/^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$/.test(v)) return true;\n\n  // Named colors (common subset + transparent + inherit)\n  if (/^[a-zA-Z]+$/.test(v)) return true;\n\n  // rgb/rgba/hsl/hsla functions\n  if (/^(rgb|rgba|hsl|hsla)\\([\\d\\s,%.]+\\)$/.test(v)) return true;\n\n  return false;\n}\n\n/**\n * Validates a CSS color literal (named color only, no hex or functions).\n * Used specifically for `allowBackgroundClasses` — only named colors\n * should be used as CSS class names.\n */\nexport function isValidColorLiteral(value: unknown): boolean {\n  if (typeof value !== 'string') return false;\n  return /^[a-zA-Z]+$/.test(value.trim());\n}\n\n/**\n * Validates a CSS font-family value.\n * Allows letters, spaces, hyphens, and commas.\n */\nexport function isValidFontFamily(value: unknown): boolean {\n  if (typeof value !== 'string') return false;\n  return /^[a-zA-Z\\s,'-]+$/.test(value.trim());\n}\n\n/**\n * Validates a CSS size value.\n * Accepts common size keywords (small, large, huge, etc.)\n * and numeric values with units (px, em, rem, %, pt).\n */\nexport function isValidSize(value: unknown): boolean {\n  if (typeof value !== 'string') return false;\n  const v = value.trim();\n\n  // Size keywords\n  if (\n    ['small', 'large', 'huge', 'normal', 'x-small', 'x-large', 'xx-small', 'xx-large'].includes(v)\n  ) {\n    return true;\n  }\n\n  // Numeric with unit\n  if (/^\\d+(\\.\\d+)?(px|em|rem|%|pt|ex|ch|vw|vh|vmin|vmax)$/.test(v)) return true;\n\n  return false;\n}\n\n/**\n * Validates a CSS width value.\n * Accepts numeric values with units (px, em, rem, %, auto).\n */\nexport function isValidWidth(value: unknown): boolean {\n  if (typeof value !== 'string') return false;\n  const v = value.trim();\n\n  if (v === 'auto') return true;\n  if (/^\\d+(\\.\\d+)?(px|em|rem|%|pt)?$/.test(v)) return true;\n\n  return false;\n}\n","/**\n * Sanitized mention data structure.\n */\nexport interface SanitizedMention {\n  name: string;\n  target?: string;\n  slug?: string;\n  class?: string;\n  'end-point'?: string;\n}\n\n/**\n * Sanitizes mention data from a Quill delta.\n *\n * Ensures all fields are strings and strips unexpected properties.\n * This is opt-in — call it before passing mention data to the renderer\n * if you want strict validation.\n *\n * @example\n * ```ts\n * const safe = sanitizeMention(rawMentionData);\n * if (safe) {\n *   // use safe.name, safe.slug, etc.\n * }\n * ```\n */\nexport function sanitizeMention(data: unknown): SanitizedMention | null {\n  if (!data || typeof data !== 'object') return null;\n\n  const obj = data as Record<string, unknown>;\n  const name = typeof obj.name === 'string' ? obj.name : '';\n\n  if (!name) return null;\n\n  const result: SanitizedMention = { name };\n\n  if (typeof obj.target === 'string' && obj.target) {\n    result.target = obj.target;\n  }\n  if (typeof obj.slug === 'string' && obj.slug) {\n    result.slug = obj.slug;\n  }\n  if (typeof obj.class === 'string' && obj.class) {\n    result.class = obj.class;\n  }\n  if (typeof obj['end-point'] === 'string' && obj['end-point']) {\n    result['end-point'] = obj['end-point'];\n  }\n\n  return result;\n}\n","/**\n * Default-safe protocols for URL sanitization.\n */\nconst DEFAULT_SAFE_PROTOCOLS = [\n  'http:',\n  'https:',\n  'mailto:',\n  'tel:',\n  'ftp:',\n  'ftps:',\n  'data:image/',\n];\n\n/**\n * URL sanitizer config.\n */\nexport interface UrlSanitizerConfig {\n  /** Additional protocols to allow beyond the defaults. */\n  extraProtocols?: string[];\n  /** Replace the default protocol whitelist entirely. */\n  protocols?: string[];\n}\n\n/**\n * Creates a URL sanitizer function.\n *\n * The sanitizer checks the URL against a protocol whitelist.\n * Relative URLs (starting with `/`, `#`, or no protocol) are always allowed.\n * Returns `undefined` for unsafe URLs, or the original URL if safe.\n *\n * This is opt-in — not required by any renderer, but can be passed\n * as the `urlSanitizer` config option to `SemanticHtmlRenderer`.\n *\n * @example\n * ```ts\n * const sanitize = createUrlSanitizer();\n * sanitize('https://example.com'); // 'https://example.com'\n * sanitize('javascript:alert(1)'); // undefined\n * ```\n *\n * @example\n * ```ts\n * const renderer = new SemanticHtmlRenderer({\n *   urlSanitizer: createUrlSanitizer(),\n * });\n * ```\n */\nexport function createUrlSanitizer(\n  config?: UrlSanitizerConfig,\n): (url: string) => string | undefined {\n  const protocols = config?.protocols ?? [\n    ...DEFAULT_SAFE_PROTOCOLS,\n    ...(config?.extraProtocols ?? []),\n  ];\n\n  return (url: string): string | undefined => {\n    const trimmed = url.trim();\n\n    // Relative URLs are always safe\n    if (trimmed.startsWith('/') || trimmed.startsWith('#') || trimmed.startsWith('?')) {\n      return url;\n    }\n\n    // Check for protocol\n    const colonIndex = trimmed.indexOf(':');\n    if (colonIndex === -1) {\n      // No protocol means it's relative (e.g. \"page.html\")\n      return url;\n    }\n\n    // Check against whitelist\n    const lower = trimmed.toLowerCase();\n    for (const protocol of protocols) {\n      if (lower.startsWith(protocol)) {\n        return url;\n      }\n    }\n\n    // Unsafe URL\n    return undefined;\n  };\n}\n"]}