@pixldocs/canvas-renderer 0.5.116 → 0.5.118

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 (33) hide show
  1. package/dist/index-Gf5_pgK7.cjs +18489 -0
  2. package/dist/index-Gf5_pgK7.cjs.map +1 -0
  3. package/dist/index-LbVR8GZp.js +18474 -0
  4. package/dist/index-LbVR8GZp.js.map +1 -0
  5. package/dist/index.cjs +36 -18056
  6. package/dist/index.cjs.map +1 -1
  7. package/dist/index.d.ts +19 -1
  8. package/dist/index.js +36 -18039
  9. package/dist/index.js.map +1 -1
  10. package/dist/pdfFonts-BSytIe1x.cjs +995 -0
  11. package/dist/pdfFonts-BSytIe1x.cjs.map +1 -0
  12. package/dist/{svgTextToPath-CQ2Tp03U.js → pdfFonts-ts7v2Fja.js} +281 -639
  13. package/dist/pdfFonts-ts7v2Fja.js.map +1 -0
  14. package/dist/pdfWatermark-CewmS9qQ.js +36 -0
  15. package/dist/pdfWatermark-CewmS9qQ.js.map +1 -0
  16. package/dist/pdfWatermark-DdBUt6s5.cjs +36 -0
  17. package/dist/pdfWatermark-DdBUt6s5.cjs.map +1 -0
  18. package/dist/{svgColorUtils-BkKZ8cyd.js → svgColorUtils-CIehRL4U.js} +262 -1
  19. package/dist/{svgColorUtils-BkKZ8cyd.js.map → svgColorUtils-CIehRL4U.js.map} +1 -1
  20. package/dist/{svgColorUtils-DQN6fbIM.cjs → svgColorUtils-DKcCq1sO.cjs} +262 -1
  21. package/dist/{svgColorUtils-DQN6fbIM.cjs.map → svgColorUtils-DKcCq1sO.cjs.map} +1 -1
  22. package/dist/svgTextToPath-ByZSG1vO.cjs +665 -0
  23. package/dist/svgTextToPath-ByZSG1vO.cjs.map +1 -0
  24. package/dist/svgTextToPath-FrpfjI8G.js +626 -0
  25. package/dist/svgTextToPath-FrpfjI8G.js.map +1 -0
  26. package/dist/vectorPdfExport-CJd8RINw.js +4749 -0
  27. package/dist/vectorPdfExport-CJd8RINw.js.map +1 -0
  28. package/dist/vectorPdfExport-DMv7QYM5.cjs +4766 -0
  29. package/dist/vectorPdfExport-DMv7QYM5.cjs.map +1 -0
  30. package/package.json +1 -1
  31. package/dist/svgTextToPath-4Y_THSBg.cjs +0 -1393
  32. package/dist/svgTextToPath-4Y_THSBg.cjs.map +0 -1
  33. package/dist/svgTextToPath-CQ2Tp03U.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"svgColorUtils-BkKZ8cyd.js","sources":["../../../src/lib/svgColorUtils.ts"],"sourcesContent":["/**\n * SVG Color Extraction & Replacement Utilities\n */\n\nconst NON_RECOLORABLE = new Set([\n 'none',\n 'transparent',\n 'currentcolor',\n 'inherit',\n 'initial',\n 'unset',\n]);\n\nlet colorCtx: CanvasRenderingContext2D | null | undefined;\n\nfunction getColorContext(): CanvasRenderingContext2D | null {\n if (colorCtx !== undefined) return colorCtx;\n if (typeof document === 'undefined') {\n colorCtx = null;\n return colorCtx;\n }\n colorCtx = document.createElement('canvas').getContext('2d');\n return colorCtx;\n}\n\n/** Normalize supported CSS color values to #rrggbb. Returns null for non-recolorable values. */\nexport function normalizeSvgColor(value: string): string | null {\n if (!value) return null;\n const raw = value.trim().toLowerCase();\n if (!raw || NON_RECOLORABLE.has(raw) || raw.startsWith('url(') || raw.startsWith('var(')) return null;\n\n if (/^#[0-9a-f]{3}$/.test(raw)) {\n return `#${raw[1]}${raw[1]}${raw[2]}${raw[2]}${raw[3]}${raw[3]}`;\n }\n if (/^#[0-9a-f]{6}$/.test(raw)) return raw;\n if (/^#[0-9a-f]{8}$/.test(raw)) return raw.slice(0, 7);\n\n const rgb = raw.match(/^rgba?\\(([^)]+)\\)$/);\n if (rgb) {\n const body = rgb[1].trim();\n const colorPortion = body.includes('/') ? body.split('/')[0].trim() : body;\n\n const commaParts = colorPortion.split(',').map((p) => p.trim()).filter(Boolean);\n const parts = commaParts.length >= 3 ? commaParts : colorPortion.split(/\\s+/).map((p) => p.trim()).filter(Boolean);\n\n if (parts.length >= 3) {\n const parseRgbComponent = (token: string): number | null => {\n const t = token.trim();\n if (!t) return null;\n if (t.endsWith('%')) {\n const pct = Number.parseFloat(t.slice(0, -1));\n if (!Number.isFinite(pct)) return null;\n return Math.max(0, Math.min(255, Math.round((pct / 100) * 255)));\n }\n const num = Number.parseFloat(t);\n if (!Number.isFinite(num)) return null;\n return Math.max(0, Math.min(255, Math.round(num)));\n };\n\n const rgbNums = parts.slice(0, 3).map(parseRgbComponent);\n if (rgbNums.every((n): n is number => n != null)) {\n const [r, g, b] = rgbNums;\n return `#${r.toString(16).padStart(2, '0')}${g.toString(16).padStart(2, '0')}${b.toString(16).padStart(2, '0')}`;\n }\n }\n }\n\n // Browser-normalized fallback for named/hsl/etc CSS colors\n const ctx = getColorContext();\n if (ctx) {\n try {\n ctx.fillStyle = '#000000';\n ctx.fillStyle = raw;\n const parsed = String(ctx.fillStyle).toLowerCase();\n if (/^#[0-9a-f]{6}$/.test(parsed)) return parsed;\n const parsedRgb = parsed.match(/^rgba?\\(([^)]+)\\)$/);\n if (parsedRgb) {\n const parts = parsedRgb[1].split(',').map((p) => p.trim());\n const nums = parts.slice(0, 3).map((p) => Number.parseFloat(p));\n if (nums.every((n) => Number.isFinite(n))) {\n const [r, g, b] = nums.map((n) => Math.max(0, Math.min(255, Math.round(n))));\n return `#${r.toString(16).padStart(2, '0')}${g.toString(16).padStart(2, '0')}${b.toString(16).padStart(2, '0')}`;\n }\n }\n } catch {\n // ignore invalid css colors\n }\n }\n\n return null;\n}\n\nfunction parseAlphaToken(token: string): number | null {\n const trimmed = token.trim();\n if (!trimmed) return null;\n\n if (trimmed.endsWith('%')) {\n const pct = Number.parseFloat(trimmed.slice(0, -1));\n if (!Number.isFinite(pct)) return null;\n return Math.max(0, Math.min(1, pct / 100));\n }\n\n const num = Number.parseFloat(trimmed);\n if (!Number.isFinite(num)) return null;\n const normalized = num > 1 ? num / 100 : num;\n return Math.max(0, Math.min(1, normalized));\n}\n\n/** Extract alpha channel from a CSS color literal, if present. */\nfunction extractColorAlpha(value: string): number | null {\n const raw = value.trim().toLowerCase();\n if (!raw) return null;\n\n const hex8 = raw.match(/^#[0-9a-f]{8}$/);\n if (hex8) {\n const alpha = Number.parseInt(raw.slice(7, 9), 16) / 255;\n return Math.max(0, Math.min(1, alpha));\n }\n\n // rgba(255,0,0,0.5) and hsla(0,100%,50%,0.5)\n const legacyFunc = raw.match(/^(?:rgba|hsla)\\(([^)]+)\\)$/);\n if (legacyFunc) {\n const parts = legacyFunc[1].split(',').map((p) => p.trim());\n if (parts.length >= 4) {\n return parseAlphaToken(parts[3]);\n }\n }\n\n // rgb(255 0 0 / 50%) modern syntax\n const modernSlash = raw.match(/^(?:rgb|rgba|hsl|hsla)\\((.+)\\)$/);\n if (modernSlash && modernSlash[1].includes('/')) {\n const alphaPart = modernSlash[1].split('/')[1];\n if (alphaPart) return parseAlphaToken(alphaPart);\n }\n\n return null;\n}\n\nfunction hexToRgb(hex: string): { r: number; g: number; b: number } {\n const cleaned = hex.replace('#', '');\n return {\n r: Number.parseInt(cleaned.slice(0, 2), 16),\n g: Number.parseInt(cleaned.slice(2, 4), 16),\n b: Number.parseInt(cleaned.slice(4, 6), 16),\n };\n}\n\n/** Keep source alpha (if any) while swapping hue to mapped color. */\nfunction applyMappedColorPreservingAlpha(originalValue: string, mappedHex: string): string {\n // Transparent / none → use SVG-standard 'none' for proper rendering in svg2pdf and browsers.\n if (mappedHex === 'transparent' || mappedHex === 'none') return 'none';\n const alpha = extractColorAlpha(originalValue);\n if (alpha == null || alpha >= 0.999) return mappedHex;\n const { r, g, b } = hexToRgb(mappedHex);\n const alphaText = Number(alpha.toFixed(4)).toString();\n return `rgba(${r}, ${g}, ${b}, ${alphaText})`;\n}\n\nfunction parseStyleDeclarations(styleText: string): Array<{ key: string; value: string }> {\n return styleText\n .split(';')\n .map((decl) => decl.trim())\n .filter(Boolean)\n .map((decl) => {\n const idx = decl.indexOf(':');\n if (idx === -1) return null;\n return {\n key: decl.slice(0, idx).trim().toLowerCase(),\n value: decl.slice(idx + 1).trim(),\n };\n })\n .filter((x): x is { key: string; value: string } => !!x);\n}\n\nconst SHAPE_TAGS = new Set([\n 'path', 'rect', 'circle', 'ellipse', 'line', 'polyline', 'polygon', 'text', 'tspan', 'g', 'use',\n]);\n\nconst NON_DRAWABLE_TAGS = new Set(['defs', 'metadata', 'style', 'title', 'desc', 'script']);\n\ninterface BoundsRect {\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\n/** Check if an element has an implicit black fill (no fill attribute and not set to none). */\nfunction hasImplicitBlackFill(el: Element, styleBlocks: string): boolean {\n const tag = el.tagName.toLowerCase();\n if (!SHAPE_TAGS.has(tag)) return false;\n const fill = el.getAttribute('fill');\n if (fill) return false;\n const style = el.getAttribute('style');\n if (style) {\n const decls = parseStyleDeclarations(style);\n const fillDecl = decls.find((d) => d.key === 'fill');\n if (fillDecl) return false;\n }\n const cls = el.getAttribute('class');\n if (cls && styleBlocks) {\n const classNames = cls.split(/\\s+/);\n for (const cn of classNames) {\n if (styleBlocks.includes(`.${cn}`) && /fill\\s*:/i.test(styleBlocks)) return false;\n }\n }\n return true;\n}\n\n/**\n * SVG stop-color defaults to black when omitted.\n * Treat such stops as implicit black so gradient path colors are editable.\n */\nfunction hasImplicitBlackStopColor(el: Element, styleBlocks: string): boolean {\n const tag = el.tagName.toLowerCase();\n if (!(tag === 'stop' || tag.endsWith(':stop'))) return false;\n\n const hasAttrStopColor = !!(el.getAttribute('stop-color') || el.getAttribute('svg:stop-color'));\n if (hasAttrStopColor) return false;\n\n const style = el.getAttribute('style');\n if (style) {\n const hasInlineStopColor = parseStyleDeclarations(style).some(({ key }) => key === 'stop-color' || key.endsWith(':stop-color'));\n if (hasInlineStopColor) return false;\n }\n\n let hasClassStopColor = false;\n collectFromClassRules(el, styleBlocks, (ruleBody) => {\n if (hasClassStopColor) return;\n hasClassStopColor = parseStyleDeclarations(ruleBody).some(({ key }) => key === 'stop-color' || key.endsWith(':stop-color'));\n });\n\n return !hasClassStopColor;\n}\n\nfunction parseSvgLengthNumber(value: string | null): number | null {\n if (!value) return null;\n const parsed = Number.parseFloat(value.replace(/px$/i, '').trim());\n return Number.isFinite(parsed) ? parsed : null;\n}\n\nfunction parseViewBox(svgRoot: SVGSVGElement): BoundsRect | null {\n const viewBox = svgRoot.getAttribute('viewBox');\n if (viewBox) {\n const values = viewBox.split(/[\\s,]+/).map((n) => Number.parseFloat(n)).filter((n) => Number.isFinite(n));\n if (values.length === 4 && values[2] > 0 && values[3] > 0) {\n return { x: values[0], y: values[1], width: values[2], height: values[3] };\n }\n }\n\n const width = parseSvgLengthNumber(svgRoot.getAttribute('width'));\n const height = parseSvgLengthNumber(svgRoot.getAttribute('height'));\n if (width && height) {\n return { x: 0, y: 0, width, height };\n }\n\n return null;\n}\n\nfunction collectReferencedIdsFromString(value: string | null, ids: Set<string>) {\n if (!value) return;\n const normalizedValue = value.replace(/&quot;/gi, '\"').replace(/&apos;/gi, \"'\");\n // Support url(#id), url(\"#id\"), url('#id') and optional whitespace.\n const urlRegex = /url\\(\\s*['\"]?#([^)\"'\\s]+)['\"]?\\s*\\)/gi;\n let match: RegExpExecArray | null;\n while ((match = urlRegex.exec(normalizedValue)) !== null) {\n if (match[1]) ids.add(match[1]);\n }\n}\n\nfunction escapeRegexToken(value: string): string {\n return value.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n\nfunction collectFromClassRules(el: Element, styleBlockText: string, onRuleBody: (ruleBody: string) => void) {\n if (!styleBlockText) return;\n const classAttr = el.getAttribute('class');\n if (!classAttr) return;\n\n const classNames = classAttr.split(/\\s+/).map((c) => c.trim()).filter(Boolean);\n if (classNames.length === 0) return;\n\n for (const className of classNames) {\n const classRegex = new RegExp(`\\\\.${escapeRegexToken(className)}[^\\\\{]*\\\\{([^}]*)\\\\}`, 'gi');\n let match: RegExpExecArray | null;\n while ((match = classRegex.exec(styleBlockText)) !== null) {\n onRuleBody(match[1] || '');\n }\n }\n}\n\nfunction collectReferencedDefIds(el: Element, ids: Set<string>, styleBlockText: string = '') {\n const attrs = ['fill', 'stroke', 'clip-path', 'mask', 'filter', 'style', 'marker-start', 'marker-mid', 'marker-end'];\n for (const attr of attrs) {\n collectReferencedIdsFromString(el.getAttribute(attr), ids);\n }\n\n collectFromClassRules(el, styleBlockText, (ruleBody) => {\n collectReferencedIdsFromString(ruleBody, ids);\n });\n\n const href = el.getAttribute('href') || el.getAttribute('xlink:href');\n if (href?.startsWith('#')) ids.add(href.slice(1));\n\n try {\n if (typeof window !== 'undefined') {\n const computed = window.getComputedStyle(el);\n collectReferencedIdsFromString(computed.fill, ids);\n collectReferencedIdsFromString(computed.stroke, ids);\n collectReferencedIdsFromString(computed.clipPath, ids);\n collectReferencedIdsFromString(computed.mask, ids);\n collectReferencedIdsFromString(computed.filter, ids);\n }\n } catch {\n // Ignore computed style errors\n }\n}\n\nfunction getScreenBounds(el: SVGGraphicsElement): BoundsRect | null {\n try {\n const bbox = el.getBBox();\n if (bbox.width <= 0 && bbox.height <= 0) return null;\n\n const matrix = el.getScreenCTM();\n if (!matrix) {\n return { x: bbox.x, y: bbox.y, width: bbox.width, height: bbox.height };\n }\n\n const p1 = new DOMPoint(bbox.x, bbox.y).matrixTransform(matrix);\n const p2 = new DOMPoint(bbox.x + bbox.width, bbox.y).matrixTransform(matrix);\n const p3 = new DOMPoint(bbox.x, bbox.y + bbox.height).matrixTransform(matrix);\n const p4 = new DOMPoint(bbox.x + bbox.width, bbox.y + bbox.height).matrixTransform(matrix);\n\n const minX = Math.min(p1.x, p2.x, p3.x, p4.x);\n const minY = Math.min(p1.y, p2.y, p3.y, p4.y);\n const maxX = Math.max(p1.x, p2.x, p3.x, p4.x);\n const maxY = Math.max(p1.y, p2.y, p3.y, p4.y);\n\n return { x: minX, y: minY, width: maxX - minX, height: maxY - minY };\n } catch {\n return null;\n }\n}\n\nfunction getViewBoxScreenBounds(svgRoot: SVGSVGElement, viewBox: BoundsRect): BoundsRect | null {\n const matrix = svgRoot.getScreenCTM();\n if (!matrix || typeof DOMPoint === 'undefined') return null;\n\n const p1 = new DOMPoint(viewBox.x, viewBox.y).matrixTransform(matrix);\n const p2 = new DOMPoint(viewBox.x + viewBox.width, viewBox.y + viewBox.height).matrixTransform(matrix);\n\n const minX = Math.min(p1.x, p2.x);\n const minY = Math.min(p1.y, p2.y);\n const maxX = Math.max(p1.x, p2.x);\n const maxY = Math.max(p1.y, p2.y);\n\n return { x: minX, y: minY, width: maxX - minX, height: maxY - minY };\n}\n\nfunction intersects(a: BoundsRect, b: BoundsRect): boolean {\n return !(a.x > b.x + b.width || a.x + a.width < b.x || a.y > b.y + b.height || a.y + a.height < b.y);\n}\n\nfunction addRecolorableColor(value: string | null, colors: Set<string>) {\n if (!value) return;\n const normalized = normalizeSvgColor(value);\n if (normalized) colors.add(normalized);\n}\n\nfunction isPaintStyleKey(key: string): boolean {\n return key === 'fill' || key === 'stroke' || key === 'stop-color' || key.endsWith(':fill') || key.endsWith(':stroke') || key.endsWith(':stop-color');\n}\n\nfunction isStopColorStyleKey(key: string): boolean {\n return key === 'stop-color' || key.endsWith(':stop-color');\n}\n\nfunction collectPaintColorsFromClassRules(el: Element, styleBlockText: string, colors: Set<string>) {\n collectFromClassRules(el, styleBlockText, (ruleBody) => {\n parseStyleDeclarations(ruleBody).forEach(({ key, value }) => {\n if (isPaintStyleKey(key)) {\n addRecolorableColor(value, colors);\n }\n });\n });\n}\n\nfunction extractElementPaintColors(el: Element, colors: Set<string>, styleBlockText = '') {\n addRecolorableColor(el.getAttribute('fill'), colors);\n addRecolorableColor(el.getAttribute('stroke'), colors);\n addRecolorableColor(el.getAttribute('stop-color'), colors);\n\n const style = el.getAttribute('style');\n if (style) {\n parseStyleDeclarations(style).forEach(({ key, value }) => {\n if (isPaintStyleKey(key)) {\n addRecolorableColor(value, colors);\n }\n });\n }\n\n try {\n if (typeof window !== 'undefined') {\n const computed = window.getComputedStyle(el);\n addRecolorableColor(computed.fill, colors);\n addRecolorableColor(computed.stroke, colors);\n addRecolorableColor(computed.stopColor, colors);\n }\n } catch {\n // Ignore computed style errors\n }\n\n if (hasImplicitBlackStopColor(el, styleBlockText)) {\n colors.add('#000000');\n }\n}\n\nfunction normalizeSvgMarkupForColorExtraction(svgText: string): string {\n if (!svgText) return svgText;\n return svgText\n .trim()\n .replace(/^\\uFEFF/, '')\n .replace(/<(\\/?)\\s*svg:svg\\b/gi, '<$1svg')\n .replace(/<(\\/?)\\s*svg:/gi, '<$1')\n .replace(/(\\s)svg:([a-zA-Z_][\\w:.-]*)(\\s*=)/gi, '$1$2$3')\n .replace(/\\s+xmlns:svg\\s*=\\s*\"[^\"]*\"/gi, '')\n .replace(/\\s+xmlns:svg\\s*=\\s*'[^']*'/gi, '');\n}\n\nfunction collectColorLiteralsFromMarkup(svgText: string, colors: Set<string>) {\n if (!svgText) return;\n const literalRegex = /#[0-9a-fA-F]{3,8}\\b|(?:rgba?|hsla?)\\([^)]*\\)/g;\n let match: RegExpExecArray | null;\n while ((match = literalRegex.exec(svgText)) !== null) {\n const normalized = normalizeSvgColor(match[0]);\n if (normalized) colors.add(normalized);\n }\n}\n\nfunction collectStopColorsFromMarkup(svgText: string, colors: Set<string>) {\n if (!svgText) return;\n\n const attrRegex = /(?:svg:)?stop-color\\s*=\\s*[\"']([^\"']+)[\"']/gi;\n let match: RegExpExecArray | null;\n while ((match = attrRegex.exec(svgText)) !== null) {\n addRecolorableColor((match[1] || '').trim(), colors);\n }\n\n const styleRegex = /(?:^|[;\\s{])(?:svg:)?stop-color\\s*:\\s*([^;{}]+)/gi;\n while ((match = styleRegex.exec(svgText)) !== null) {\n addRecolorableColor((match[1] || '').trim(), colors);\n }\n}\n\n/** Extract all unique recolorable fill/stroke colors from SVG. */\nexport function extractSvgColors(svgText: string): string[] {\n if (!svgText) return [];\n\n const normalizedSvgText = normalizeSvgMarkupForColorExtraction(svgText);\n const colors = new Set<string>();\n let hasImplicitBlack = false;\n\n try {\n if (typeof DOMParser !== 'undefined' && typeof document !== 'undefined') {\n const doc = new DOMParser().parseFromString(normalizedSvgText, 'image/svg+xml');\n const parserError = doc.querySelector('parsererror');\n if (!parserError) {\n const sourceRoot = doc.documentElement;\n if (!sourceRoot || sourceRoot.tagName.toLowerCase() !== 'svg') return [];\n\n const importedRoot = document.importNode(sourceRoot, true);\n if (!(importedRoot instanceof SVGSVGElement)) return [];\n const svgRoot = importedRoot;\n\n let styleBlockText = '';\n svgRoot.querySelectorAll('style').forEach((s) => {\n styleBlockText += s.textContent || '';\n });\n\n svgRoot.style.position = 'absolute';\n svgRoot.style.left = '-99999px';\n svgRoot.style.top = '-99999px';\n svgRoot.style.visibility = 'hidden';\n svgRoot.style.pointerEvents = 'none';\n\n document.body.appendChild(svgRoot);\n\n try {\n const viewBox = parseViewBox(svgRoot);\n const viewBounds = viewBox ? getViewBoxScreenBounds(svgRoot, viewBox) : null;\n\n const usedDefIds = new Set<string>();\n const allElements = Array.from(svgRoot.querySelectorAll('*'));\n\n for (const el of allElements) {\n const tag = el.tagName.toLowerCase();\n // First pass should only inspect visible scene content, not defs.\n if (NON_DRAWABLE_TAGS.has(tag) || tag === 'stop' || !!el.closest('defs')) continue;\n\n let intersectsView = true;\n if (viewBounds && el instanceof SVGGraphicsElement) {\n const elBounds = getScreenBounds(el);\n if (elBounds) intersectsView = intersects(elBounds, viewBounds);\n }\n if (!intersectsView) continue;\n\n extractElementPaintColors(el, colors, styleBlockText);\n collectPaintColorsFromClassRules(el, styleBlockText, colors);\n collectReferencedDefIds(el, usedDefIds, styleBlockText);\n\n if (!hasImplicitBlack && hasImplicitBlackFill(el, styleBlockText)) {\n hasImplicitBlack = true;\n }\n }\n\n const idMap = new Map<string, Element>();\n svgRoot.querySelectorAll('[id]').forEach((node) => {\n const id = node.getAttribute('id');\n if (id) idMap.set(id, node);\n });\n\n const resolvedDefIds = new Set<string>();\n const queue = Array.from(usedDefIds);\n\n while (queue.length > 0) {\n const id = queue.pop()!;\n if (resolvedDefIds.has(id)) continue;\n resolvedDefIds.add(id);\n\n const defNode = idMap.get(id);\n if (!defNode) continue;\n\n collectReferencedDefIds(defNode, usedDefIds, styleBlockText);\n for (const nestedId of usedDefIds) {\n if (!resolvedDefIds.has(nestedId)) queue.push(nestedId);\n }\n }\n\n for (const id of resolvedDefIds) {\n const defNode = idMap.get(id);\n if (!defNode) continue;\n\n extractElementPaintColors(defNode, colors, styleBlockText);\n collectPaintColorsFromClassRules(defNode, styleBlockText, colors);\n defNode.querySelectorAll('*').forEach((node) => {\n extractElementPaintColors(node, colors, styleBlockText);\n collectPaintColorsFromClassRules(node, styleBlockText, colors);\n });\n }\n\n // Keep extraction strict: visible shapes + defs they actually reference.\n // Only broaden to literal scanning if strict extraction found nothing.\n if (colors.size === 0) {\n collectStopColorsFromMarkup(styleBlockText, colors);\n collectColorLiteralsFromMarkup(normalizedSvgText, colors);\n collectStopColorsFromMarkup(normalizedSvgText, colors);\n }\n } finally {\n document.body.removeChild(svgRoot);\n }\n\n if (hasImplicitBlack) {\n colors.add('#000000');\n }\n\n return Array.from(colors);\n }\n }\n } catch {\n // If strict extraction partially succeeded, prefer that over broad literal fallback.\n if (colors.size > 0) return Array.from(colors);\n // fallback below\n }\n\n // Regex fallback\n const attrRegex = /(?:(?:svg:)?fill|(?:svg:)?stroke|(?:svg:)?stop-color)\\s*=\\s*[\"']([^\"']+)[\"']/gi;\n let match: RegExpExecArray | null;\n while ((match = attrRegex.exec(normalizedSvgText))) {\n const norm = normalizeSvgColor(match[1]);\n if (norm) colors.add(norm);\n }\n\n const styleRegex = /(?:(?:svg:)?fill|(?:svg:)?stroke|(?:svg:)?stop-color)\\s*:\\s*([^;{}]+)/gi;\n while ((match = styleRegex.exec(normalizedSvgText))) {\n const norm = normalizeSvgColor(match[1]);\n if (norm) colors.add(norm);\n }\n\n collectColorLiteralsFromMarkup(normalizedSvgText, colors);\n collectStopColorsFromMarkup(normalizedSvgText, colors);\n\n if (colors.size === 0 && /<(?:path|rect|circle|ellipse|polygon|polyline|line|text)\\b/i.test(normalizedSvgText)) {\n colors.add('#000000');\n }\n\n return Array.from(colors);\n}\n\n/** Apply a color replacement map to SVG fill/stroke attrs + inline/style-block declarations.\n * Handles implicit black: if colorMap maps #000000 → X, elements with no fill get fill=\"X\". */\nexport function applySvgColorMap(svgText: string, colorMap: Record<string, string>): string {\n if (!svgText || !colorMap || Object.keys(colorMap).length === 0) return svgText;\n\n const normalizedMap = new Map<string, string>();\n const transparentTargets = new Set<string>(); // keys whose target is transparent/none\n for (const [from, to] of Object.entries(colorMap)) {\n const key = normalizeSvgColor(from);\n if (!key) continue;\n const isTransparentTarget = to === 'transparent' || to === 'none' || to === '';\n if (isTransparentTarget) {\n normalizedMap.set(key, 'transparent');\n transparentTargets.add(key);\n } else if (/^#[0-9a-f]{6}$/i.test(to)) {\n normalizedMap.set(key, to.toLowerCase());\n }\n }\n if (normalizedMap.size === 0) return svgText;\n\n // Build a fuzzy lookup: for any color value, find the closest mapping key within threshold\n // Only build fuzzy entries for non-transparent targets (transparent is exact-match only)\n const mapEntries = Array.from(normalizedMap.entries())\n .filter(([k]) => !transparentTargets.has(k))\n .map(([k, v]) => ({ hex: k, rgb: hexToRgb(k), target: v }));\n const fuzzyThresholdSq = 30 * 30;\n\n function fuzzyLookup(value: string): string | null {\n const norm = normalizeSvgColor(value);\n if (!norm) return null;\n // Exact match first\n const exact = normalizedMap.get(norm);\n if (exact) return exact;\n // Fuzzy match\n const rgb = hexToRgb(norm);\n let bestDist = Infinity;\n let bestTarget: string | null = null;\n for (const entry of mapEntries) {\n const dr = rgb.r - entry.rgb.r;\n const dg = rgb.g - entry.rgb.g;\n const db = rgb.b - entry.rgb.b;\n const distSq = dr * dr + dg * dg + db * db;\n if (distSq < bestDist && distSq <= fuzzyThresholdSq) {\n bestDist = distSq;\n bestTarget = entry.target;\n }\n }\n return bestTarget;\n }\n\n const implicitBlackTarget = normalizedMap.get('#000000');\n\n const isTransparentMapTarget = (mapped: string): boolean =>\n mapped === 'transparent' || mapped === 'none';\n\n const isStopColorProperty = (property: string): boolean =>\n property === 'stop-color' || property === 'svg:stop-color' || property.endsWith(':stop-color');\n\n const TRANSPARENT_STOP_FALLBACK_COLOR = '#000000';\n\n const toMappedPaint = (originalValue: string, mapped: string, property: string): string => {\n if (isTransparentMapTarget(mapped) && isStopColorProperty(property)) return TRANSPARENT_STOP_FALLBACK_COLOR;\n return applyMappedColorPreservingAlpha(originalValue, mapped);\n };\n\n try {\n if (typeof DOMParser !== 'undefined' && typeof XMLSerializer !== 'undefined') {\n const doc = new DOMParser().parseFromString(svgText, 'image/svg+xml');\n const parserError = doc.querySelector('parsererror');\n if (!parserError) {\n // Collect style block text for class-based detection\n let styleBlockText = '';\n doc.querySelectorAll('style').forEach((s) => { styleBlockText += s.textContent || ''; });\n\n const elements = doc.querySelectorAll('*');\n elements.forEach((el) => {\n (['fill', 'stroke', 'stop-color', 'svg:fill', 'svg:stroke', 'svg:stop-color'] as const).forEach((attr) => {\n const val = el.getAttribute(attr);\n if (!val) return;\n const mapped = fuzzyLookup(val);\n if (!mapped) return;\n\n const mappedValue = toMappedPaint(val, mapped, attr);\n el.setAttribute(attr, mappedValue);\n\n if (isStopColorProperty(attr) && isTransparentMapTarget(mapped)) {\n el.setAttribute('stop-opacity', '0');\n }\n });\n\n // Handle implicit black: add explicit paint to elements that rely on SVG defaults.\n if (implicitBlackTarget && hasImplicitBlackFill(el, styleBlockText)) {\n el.setAttribute('fill', applyMappedColorPreservingAlpha('#000000', implicitBlackTarget));\n }\n if (implicitBlackTarget && hasImplicitBlackStopColor(el, styleBlockText)) {\n const isTransparentStop = isTransparentMapTarget(implicitBlackTarget);\n el.setAttribute(\n 'stop-color',\n isTransparentStop\n ? TRANSPARENT_STOP_FALLBACK_COLOR\n : applyMappedColorPreservingAlpha('#000000', implicitBlackTarget)\n );\n if (isTransparentStop) {\n el.setAttribute('stop-opacity', '0');\n }\n }\n\n const style = el.getAttribute('style');\n if (style) {\n let forceStopOpacityZero = false;\n const declarations = parseStyleDeclarations(style).map(({ key, value }) => {\n if (isPaintStyleKey(key)) {\n const mapped = fuzzyLookup(value);\n if (mapped) {\n const mappedValue = toMappedPaint(value, mapped, key);\n if (isStopColorStyleKey(key) && isTransparentMapTarget(mapped)) {\n forceStopOpacityZero = true;\n }\n return `${key}: ${mappedValue}`;\n }\n }\n return `${key}: ${value}`;\n });\n\n const nextDeclarations = forceStopOpacityZero\n ? declarations.filter((decl) => !/^stop-opacity\\s*:/i.test(decl))\n : declarations;\n\n if (forceStopOpacityZero) {\n nextDeclarations.push('stop-opacity: 0');\n }\n\n el.setAttribute('style', nextDeclarations.join('; '));\n }\n });\n\n doc.querySelectorAll('style').forEach((styleNode) => {\n const css = styleNode.textContent || '';\n styleNode.textContent = css.replace(/(((?:svg:)?fill|(?:svg:)?stroke|(?:svg:)?stop-color)\\s*:\\s*)([^;{}]+)/gi, (_all, prefix, prop, value) => {\n const valueText = String(value);\n const mapped = fuzzyLookup(valueText);\n if (!mapped) return `${prefix}${valueText}`;\n const mappedValue = toMappedPaint(valueText, mapped, String(prop).toLowerCase());\n if (isStopColorProperty(String(prop).toLowerCase()) && isTransparentMapTarget(mapped)) {\n return `${prefix}${mappedValue}; stop-opacity: 0`;\n }\n return `${prefix}${mappedValue}`;\n });\n });\n\n return new XMLSerializer().serializeToString(doc);\n }\n }\n } catch {\n // fallback below\n }\n\n // Regex fallback\n let result = svgText;\n result = result.replace(\n /(((?:svg:)?fill|(?:svg:)?stroke|(?:svg:)?stop-color)\\s*=\\s*[\"'])([^\"']+)([\"'])/gi,\n (full, prefix, prop, value, suffix) => {\n const valueText = String(value);\n const mapped = fuzzyLookup(valueText);\n if (!mapped) return full;\n const propText = String(prop).toLowerCase();\n const mappedValue = toMappedPaint(valueText, mapped, propText);\n return `${prefix}${mappedValue}${suffix}`;\n }\n );\n\n result = result.replace(\n /(((?:svg:)?fill|(?:svg:)?stroke|(?:svg:)?stop-color)\\s*:\\s*)([^;{}]+)/gi,\n (full, prefix, prop, value) => {\n const valueText = String(value);\n const mapped = fuzzyLookup(valueText);\n if (!mapped) return full;\n const propText = String(prop).toLowerCase();\n const mappedValue = toMappedPaint(valueText, mapped, propText);\n if (isStopColorProperty(propText) && isTransparentMapTarget(mapped)) {\n return `${prefix}${mappedValue}; stop-opacity: 0`;\n }\n return `${prefix}${mappedValue}`;\n }\n );\n\n // Regex fallback for implicit black defaults.\n if (implicitBlackTarget) {\n const implicitFillValue = applyMappedColorPreservingAlpha('#000000', implicitBlackTarget);\n result = result.replace(\n /(<(?:path|rect|circle|ellipse|polygon|polyline|line|text)\\b)(?![^>]*\\bfill\\b)([^>]*>)/gi,\n `$1 fill=\"${implicitFillValue}\"$2`\n );\n\n result = result.replace(/<((?:svg:)?stop)\\b([^>]*)>/gi, (full, tag, attrs) => {\n const attrsText = String(attrs || '');\n if (/\\b(?:svg:)?stop-color\\s*=\\s*[\"'][^\"']*[\"']/i.test(attrsText)) return full;\n if (/\\bstyle\\s*=\\s*[\"'][^\"']*(?:svg:)?stop-color\\s*:[^\"']*[\"']/i.test(attrsText)) return full;\n const isTransparentStop = isTransparentMapTarget(implicitBlackTarget);\n const stopColorValue = isTransparentStop\n ? TRANSPARENT_STOP_FALLBACK_COLOR\n : applyMappedColorPreservingAlpha('#000000', implicitBlackTarget);\n const stopOpacityAttr = isTransparentStop ? ' stop-opacity=\"0\"' : '';\n return `<${tag}${attrsText} stop-color=\"${stopColorValue}\"${stopOpacityAttr}>`;\n });\n }\n\n return result;\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"svgColorUtils-CIehRL4U.js","sources":["../../../src/lib/svgColorUtils.ts"],"sourcesContent":["/**\n * SVG Color Extraction & Replacement Utilities\n */\n\nconst NON_RECOLORABLE = new Set([\n 'none',\n 'transparent',\n 'currentcolor',\n 'inherit',\n 'initial',\n 'unset',\n]);\n\nlet colorCtx: CanvasRenderingContext2D | null | undefined;\n\nfunction getColorContext(): CanvasRenderingContext2D | null {\n if (colorCtx !== undefined) return colorCtx;\n if (typeof document === 'undefined') {\n colorCtx = null;\n return colorCtx;\n }\n colorCtx = document.createElement('canvas').getContext('2d');\n return colorCtx;\n}\n\n/** Normalize supported CSS color values to #rrggbb. Returns null for non-recolorable values. */\nexport function normalizeSvgColor(value: string): string | null {\n if (!value) return null;\n const raw = value.trim().toLowerCase();\n if (!raw || NON_RECOLORABLE.has(raw) || raw.startsWith('url(') || raw.startsWith('var(')) return null;\n\n if (/^#[0-9a-f]{3}$/.test(raw)) {\n return `#${raw[1]}${raw[1]}${raw[2]}${raw[2]}${raw[3]}${raw[3]}`;\n }\n if (/^#[0-9a-f]{6}$/.test(raw)) return raw;\n if (/^#[0-9a-f]{8}$/.test(raw)) return raw.slice(0, 7);\n\n const rgb = raw.match(/^rgba?\\(([^)]+)\\)$/);\n if (rgb) {\n const body = rgb[1].trim();\n const colorPortion = body.includes('/') ? body.split('/')[0].trim() : body;\n\n const commaParts = colorPortion.split(',').map((p) => p.trim()).filter(Boolean);\n const parts = commaParts.length >= 3 ? commaParts : colorPortion.split(/\\s+/).map((p) => p.trim()).filter(Boolean);\n\n if (parts.length >= 3) {\n const parseRgbComponent = (token: string): number | null => {\n const t = token.trim();\n if (!t) return null;\n if (t.endsWith('%')) {\n const pct = Number.parseFloat(t.slice(0, -1));\n if (!Number.isFinite(pct)) return null;\n return Math.max(0, Math.min(255, Math.round((pct / 100) * 255)));\n }\n const num = Number.parseFloat(t);\n if (!Number.isFinite(num)) return null;\n return Math.max(0, Math.min(255, Math.round(num)));\n };\n\n const rgbNums = parts.slice(0, 3).map(parseRgbComponent);\n if (rgbNums.every((n): n is number => n != null)) {\n const [r, g, b] = rgbNums;\n return `#${r.toString(16).padStart(2, '0')}${g.toString(16).padStart(2, '0')}${b.toString(16).padStart(2, '0')}`;\n }\n }\n }\n\n // Browser-normalized fallback for named/hsl/etc CSS colors\n const ctx = getColorContext();\n if (ctx) {\n try {\n ctx.fillStyle = '#000000';\n ctx.fillStyle = raw;\n const parsed = String(ctx.fillStyle).toLowerCase();\n if (/^#[0-9a-f]{6}$/.test(parsed)) return parsed;\n const parsedRgb = parsed.match(/^rgba?\\(([^)]+)\\)$/);\n if (parsedRgb) {\n const parts = parsedRgb[1].split(',').map((p) => p.trim());\n const nums = parts.slice(0, 3).map((p) => Number.parseFloat(p));\n if (nums.every((n) => Number.isFinite(n))) {\n const [r, g, b] = nums.map((n) => Math.max(0, Math.min(255, Math.round(n))));\n return `#${r.toString(16).padStart(2, '0')}${g.toString(16).padStart(2, '0')}${b.toString(16).padStart(2, '0')}`;\n }\n }\n } catch {\n // ignore invalid css colors\n }\n }\n\n return null;\n}\n\nfunction parseAlphaToken(token: string): number | null {\n const trimmed = token.trim();\n if (!trimmed) return null;\n\n if (trimmed.endsWith('%')) {\n const pct = Number.parseFloat(trimmed.slice(0, -1));\n if (!Number.isFinite(pct)) return null;\n return Math.max(0, Math.min(1, pct / 100));\n }\n\n const num = Number.parseFloat(trimmed);\n if (!Number.isFinite(num)) return null;\n const normalized = num > 1 ? num / 100 : num;\n return Math.max(0, Math.min(1, normalized));\n}\n\n/** Extract alpha channel from a CSS color literal, if present. */\nfunction extractColorAlpha(value: string): number | null {\n const raw = value.trim().toLowerCase();\n if (!raw) return null;\n\n const hex8 = raw.match(/^#[0-9a-f]{8}$/);\n if (hex8) {\n const alpha = Number.parseInt(raw.slice(7, 9), 16) / 255;\n return Math.max(0, Math.min(1, alpha));\n }\n\n // rgba(255,0,0,0.5) and hsla(0,100%,50%,0.5)\n const legacyFunc = raw.match(/^(?:rgba|hsla)\\(([^)]+)\\)$/);\n if (legacyFunc) {\n const parts = legacyFunc[1].split(',').map((p) => p.trim());\n if (parts.length >= 4) {\n return parseAlphaToken(parts[3]);\n }\n }\n\n // rgb(255 0 0 / 50%) modern syntax\n const modernSlash = raw.match(/^(?:rgb|rgba|hsl|hsla)\\((.+)\\)$/);\n if (modernSlash && modernSlash[1].includes('/')) {\n const alphaPart = modernSlash[1].split('/')[1];\n if (alphaPart) return parseAlphaToken(alphaPart);\n }\n\n return null;\n}\n\nfunction hexToRgb(hex: string): { r: number; g: number; b: number } {\n const cleaned = hex.replace('#', '');\n return {\n r: Number.parseInt(cleaned.slice(0, 2), 16),\n g: Number.parseInt(cleaned.slice(2, 4), 16),\n b: Number.parseInt(cleaned.slice(4, 6), 16),\n };\n}\n\n/** Keep source alpha (if any) while swapping hue to mapped color. */\nfunction applyMappedColorPreservingAlpha(originalValue: string, mappedHex: string): string {\n // Transparent / none → use SVG-standard 'none' for proper rendering in svg2pdf and browsers.\n if (mappedHex === 'transparent' || mappedHex === 'none') return 'none';\n const alpha = extractColorAlpha(originalValue);\n if (alpha == null || alpha >= 0.999) return mappedHex;\n const { r, g, b } = hexToRgb(mappedHex);\n const alphaText = Number(alpha.toFixed(4)).toString();\n return `rgba(${r}, ${g}, ${b}, ${alphaText})`;\n}\n\nfunction parseStyleDeclarations(styleText: string): Array<{ key: string; value: string }> {\n return styleText\n .split(';')\n .map((decl) => decl.trim())\n .filter(Boolean)\n .map((decl) => {\n const idx = decl.indexOf(':');\n if (idx === -1) return null;\n return {\n key: decl.slice(0, idx).trim().toLowerCase(),\n value: decl.slice(idx + 1).trim(),\n };\n })\n .filter((x): x is { key: string; value: string } => !!x);\n}\n\nconst SHAPE_TAGS = new Set([\n 'path', 'rect', 'circle', 'ellipse', 'line', 'polyline', 'polygon', 'text', 'tspan', 'g', 'use',\n]);\n\nconst NON_DRAWABLE_TAGS = new Set(['defs', 'metadata', 'style', 'title', 'desc', 'script']);\n\ninterface BoundsRect {\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\n/** Check if an element has an implicit black fill (no fill attribute and not set to none). */\nfunction hasImplicitBlackFill(el: Element, styleBlocks: string): boolean {\n const tag = el.tagName.toLowerCase();\n if (!SHAPE_TAGS.has(tag)) return false;\n const fill = el.getAttribute('fill');\n if (fill) return false;\n const style = el.getAttribute('style');\n if (style) {\n const decls = parseStyleDeclarations(style);\n const fillDecl = decls.find((d) => d.key === 'fill');\n if (fillDecl) return false;\n }\n const cls = el.getAttribute('class');\n if (cls && styleBlocks) {\n const classNames = cls.split(/\\s+/);\n for (const cn of classNames) {\n if (styleBlocks.includes(`.${cn}`) && /fill\\s*:/i.test(styleBlocks)) return false;\n }\n }\n return true;\n}\n\n/**\n * SVG stop-color defaults to black when omitted.\n * Treat such stops as implicit black so gradient path colors are editable.\n */\nfunction hasImplicitBlackStopColor(el: Element, styleBlocks: string): boolean {\n const tag = el.tagName.toLowerCase();\n if (!(tag === 'stop' || tag.endsWith(':stop'))) return false;\n\n const hasAttrStopColor = !!(el.getAttribute('stop-color') || el.getAttribute('svg:stop-color'));\n if (hasAttrStopColor) return false;\n\n const style = el.getAttribute('style');\n if (style) {\n const hasInlineStopColor = parseStyleDeclarations(style).some(({ key }) => key === 'stop-color' || key.endsWith(':stop-color'));\n if (hasInlineStopColor) return false;\n }\n\n let hasClassStopColor = false;\n collectFromClassRules(el, styleBlocks, (ruleBody) => {\n if (hasClassStopColor) return;\n hasClassStopColor = parseStyleDeclarations(ruleBody).some(({ key }) => key === 'stop-color' || key.endsWith(':stop-color'));\n });\n\n return !hasClassStopColor;\n}\n\nfunction parseSvgLengthNumber(value: string | null): number | null {\n if (!value) return null;\n const parsed = Number.parseFloat(value.replace(/px$/i, '').trim());\n return Number.isFinite(parsed) ? parsed : null;\n}\n\nfunction parseViewBox(svgRoot: SVGSVGElement): BoundsRect | null {\n const viewBox = svgRoot.getAttribute('viewBox');\n if (viewBox) {\n const values = viewBox.split(/[\\s,]+/).map((n) => Number.parseFloat(n)).filter((n) => Number.isFinite(n));\n if (values.length === 4 && values[2] > 0 && values[3] > 0) {\n return { x: values[0], y: values[1], width: values[2], height: values[3] };\n }\n }\n\n const width = parseSvgLengthNumber(svgRoot.getAttribute('width'));\n const height = parseSvgLengthNumber(svgRoot.getAttribute('height'));\n if (width && height) {\n return { x: 0, y: 0, width, height };\n }\n\n return null;\n}\n\nfunction collectReferencedIdsFromString(value: string | null, ids: Set<string>) {\n if (!value) return;\n const normalizedValue = value.replace(/&quot;/gi, '\"').replace(/&apos;/gi, \"'\");\n // Support url(#id), url(\"#id\"), url('#id') and optional whitespace.\n const urlRegex = /url\\(\\s*['\"]?#([^)\"'\\s]+)['\"]?\\s*\\)/gi;\n let match: RegExpExecArray | null;\n while ((match = urlRegex.exec(normalizedValue)) !== null) {\n if (match[1]) ids.add(match[1]);\n }\n}\n\nfunction escapeRegexToken(value: string): string {\n return value.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n\nfunction collectFromClassRules(el: Element, styleBlockText: string, onRuleBody: (ruleBody: string) => void) {\n if (!styleBlockText) return;\n const classAttr = el.getAttribute('class');\n if (!classAttr) return;\n\n const classNames = classAttr.split(/\\s+/).map((c) => c.trim()).filter(Boolean);\n if (classNames.length === 0) return;\n\n for (const className of classNames) {\n const classRegex = new RegExp(`\\\\.${escapeRegexToken(className)}[^\\\\{]*\\\\{([^}]*)\\\\}`, 'gi');\n let match: RegExpExecArray | null;\n while ((match = classRegex.exec(styleBlockText)) !== null) {\n onRuleBody(match[1] || '');\n }\n }\n}\n\nfunction collectReferencedDefIds(el: Element, ids: Set<string>, styleBlockText: string = '') {\n const attrs = ['fill', 'stroke', 'clip-path', 'mask', 'filter', 'style', 'marker-start', 'marker-mid', 'marker-end'];\n for (const attr of attrs) {\n collectReferencedIdsFromString(el.getAttribute(attr), ids);\n }\n\n collectFromClassRules(el, styleBlockText, (ruleBody) => {\n collectReferencedIdsFromString(ruleBody, ids);\n });\n\n const href = el.getAttribute('href') || el.getAttribute('xlink:href');\n if (href?.startsWith('#')) ids.add(href.slice(1));\n\n try {\n if (typeof window !== 'undefined') {\n const computed = window.getComputedStyle(el);\n collectReferencedIdsFromString(computed.fill, ids);\n collectReferencedIdsFromString(computed.stroke, ids);\n collectReferencedIdsFromString(computed.clipPath, ids);\n collectReferencedIdsFromString(computed.mask, ids);\n collectReferencedIdsFromString(computed.filter, ids);\n }\n } catch {\n // Ignore computed style errors\n }\n}\n\nfunction getScreenBounds(el: SVGGraphicsElement): BoundsRect | null {\n try {\n const bbox = el.getBBox();\n if (bbox.width <= 0 && bbox.height <= 0) return null;\n\n const matrix = el.getScreenCTM();\n if (!matrix) {\n return { x: bbox.x, y: bbox.y, width: bbox.width, height: bbox.height };\n }\n\n const p1 = new DOMPoint(bbox.x, bbox.y).matrixTransform(matrix);\n const p2 = new DOMPoint(bbox.x + bbox.width, bbox.y).matrixTransform(matrix);\n const p3 = new DOMPoint(bbox.x, bbox.y + bbox.height).matrixTransform(matrix);\n const p4 = new DOMPoint(bbox.x + bbox.width, bbox.y + bbox.height).matrixTransform(matrix);\n\n const minX = Math.min(p1.x, p2.x, p3.x, p4.x);\n const minY = Math.min(p1.y, p2.y, p3.y, p4.y);\n const maxX = Math.max(p1.x, p2.x, p3.x, p4.x);\n const maxY = Math.max(p1.y, p2.y, p3.y, p4.y);\n\n return { x: minX, y: minY, width: maxX - minX, height: maxY - minY };\n } catch {\n return null;\n }\n}\n\nfunction getViewBoxScreenBounds(svgRoot: SVGSVGElement, viewBox: BoundsRect): BoundsRect | null {\n const matrix = svgRoot.getScreenCTM();\n if (!matrix || typeof DOMPoint === 'undefined') return null;\n\n const p1 = new DOMPoint(viewBox.x, viewBox.y).matrixTransform(matrix);\n const p2 = new DOMPoint(viewBox.x + viewBox.width, viewBox.y + viewBox.height).matrixTransform(matrix);\n\n const minX = Math.min(p1.x, p2.x);\n const minY = Math.min(p1.y, p2.y);\n const maxX = Math.max(p1.x, p2.x);\n const maxY = Math.max(p1.y, p2.y);\n\n return { x: minX, y: minY, width: maxX - minX, height: maxY - minY };\n}\n\nfunction intersects(a: BoundsRect, b: BoundsRect): boolean {\n return !(a.x > b.x + b.width || a.x + a.width < b.x || a.y > b.y + b.height || a.y + a.height < b.y);\n}\n\nfunction addRecolorableColor(value: string | null, colors: Set<string>) {\n if (!value) return;\n const normalized = normalizeSvgColor(value);\n if (normalized) colors.add(normalized);\n}\n\nfunction isPaintStyleKey(key: string): boolean {\n return key === 'fill' || key === 'stroke' || key === 'stop-color' || key.endsWith(':fill') || key.endsWith(':stroke') || key.endsWith(':stop-color');\n}\n\nfunction isStopColorStyleKey(key: string): boolean {\n return key === 'stop-color' || key.endsWith(':stop-color');\n}\n\nfunction collectPaintColorsFromClassRules(el: Element, styleBlockText: string, colors: Set<string>) {\n collectFromClassRules(el, styleBlockText, (ruleBody) => {\n parseStyleDeclarations(ruleBody).forEach(({ key, value }) => {\n if (isPaintStyleKey(key)) {\n addRecolorableColor(value, colors);\n }\n });\n });\n}\n\nfunction extractElementPaintColors(el: Element, colors: Set<string>, styleBlockText = '') {\n addRecolorableColor(el.getAttribute('fill'), colors);\n addRecolorableColor(el.getAttribute('stroke'), colors);\n addRecolorableColor(el.getAttribute('stop-color'), colors);\n\n const style = el.getAttribute('style');\n if (style) {\n parseStyleDeclarations(style).forEach(({ key, value }) => {\n if (isPaintStyleKey(key)) {\n addRecolorableColor(value, colors);\n }\n });\n }\n\n try {\n if (typeof window !== 'undefined') {\n const computed = window.getComputedStyle(el);\n addRecolorableColor(computed.fill, colors);\n addRecolorableColor(computed.stroke, colors);\n addRecolorableColor(computed.stopColor, colors);\n }\n } catch {\n // Ignore computed style errors\n }\n\n if (hasImplicitBlackStopColor(el, styleBlockText)) {\n colors.add('#000000');\n }\n}\n\nfunction normalizeSvgMarkupForColorExtraction(svgText: string): string {\n if (!svgText) return svgText;\n return svgText\n .trim()\n .replace(/^\\uFEFF/, '')\n .replace(/<(\\/?)\\s*svg:svg\\b/gi, '<$1svg')\n .replace(/<(\\/?)\\s*svg:/gi, '<$1')\n .replace(/(\\s)svg:([a-zA-Z_][\\w:.-]*)(\\s*=)/gi, '$1$2$3')\n .replace(/\\s+xmlns:svg\\s*=\\s*\"[^\"]*\"/gi, '')\n .replace(/\\s+xmlns:svg\\s*=\\s*'[^']*'/gi, '');\n}\n\nfunction collectColorLiteralsFromMarkup(svgText: string, colors: Set<string>) {\n if (!svgText) return;\n const literalRegex = /#[0-9a-fA-F]{3,8}\\b|(?:rgba?|hsla?)\\([^)]*\\)/g;\n let match: RegExpExecArray | null;\n while ((match = literalRegex.exec(svgText)) !== null) {\n const normalized = normalizeSvgColor(match[0]);\n if (normalized) colors.add(normalized);\n }\n}\n\nfunction collectStopColorsFromMarkup(svgText: string, colors: Set<string>) {\n if (!svgText) return;\n\n const attrRegex = /(?:svg:)?stop-color\\s*=\\s*[\"']([^\"']+)[\"']/gi;\n let match: RegExpExecArray | null;\n while ((match = attrRegex.exec(svgText)) !== null) {\n addRecolorableColor((match[1] || '').trim(), colors);\n }\n\n const styleRegex = /(?:^|[;\\s{])(?:svg:)?stop-color\\s*:\\s*([^;{}]+)/gi;\n while ((match = styleRegex.exec(svgText)) !== null) {\n addRecolorableColor((match[1] || '').trim(), colors);\n }\n}\n\n/** Extract all unique recolorable fill/stroke colors from SVG. */\nexport function extractSvgColors(svgText: string): string[] {\n if (!svgText) return [];\n\n const normalizedSvgText = normalizeSvgMarkupForColorExtraction(svgText);\n const colors = new Set<string>();\n let hasImplicitBlack = false;\n\n try {\n if (typeof DOMParser !== 'undefined' && typeof document !== 'undefined') {\n const doc = new DOMParser().parseFromString(normalizedSvgText, 'image/svg+xml');\n const parserError = doc.querySelector('parsererror');\n if (!parserError) {\n const sourceRoot = doc.documentElement;\n if (!sourceRoot || sourceRoot.tagName.toLowerCase() !== 'svg') return [];\n\n const importedRoot = document.importNode(sourceRoot, true);\n if (!(importedRoot instanceof SVGSVGElement)) return [];\n const svgRoot = importedRoot;\n\n let styleBlockText = '';\n svgRoot.querySelectorAll('style').forEach((s) => {\n styleBlockText += s.textContent || '';\n });\n\n svgRoot.style.position = 'absolute';\n svgRoot.style.left = '-99999px';\n svgRoot.style.top = '-99999px';\n svgRoot.style.visibility = 'hidden';\n svgRoot.style.pointerEvents = 'none';\n\n document.body.appendChild(svgRoot);\n\n try {\n const viewBox = parseViewBox(svgRoot);\n const viewBounds = viewBox ? getViewBoxScreenBounds(svgRoot, viewBox) : null;\n\n const usedDefIds = new Set<string>();\n const allElements = Array.from(svgRoot.querySelectorAll('*'));\n\n for (const el of allElements) {\n const tag = el.tagName.toLowerCase();\n // First pass should only inspect visible scene content, not defs.\n if (NON_DRAWABLE_TAGS.has(tag) || tag === 'stop' || !!el.closest('defs')) continue;\n\n let intersectsView = true;\n if (viewBounds && el instanceof SVGGraphicsElement) {\n const elBounds = getScreenBounds(el);\n if (elBounds) intersectsView = intersects(elBounds, viewBounds);\n }\n if (!intersectsView) continue;\n\n extractElementPaintColors(el, colors, styleBlockText);\n collectPaintColorsFromClassRules(el, styleBlockText, colors);\n collectReferencedDefIds(el, usedDefIds, styleBlockText);\n\n if (!hasImplicitBlack && hasImplicitBlackFill(el, styleBlockText)) {\n hasImplicitBlack = true;\n }\n }\n\n const idMap = new Map<string, Element>();\n svgRoot.querySelectorAll('[id]').forEach((node) => {\n const id = node.getAttribute('id');\n if (id) idMap.set(id, node);\n });\n\n const resolvedDefIds = new Set<string>();\n const queue = Array.from(usedDefIds);\n\n while (queue.length > 0) {\n const id = queue.pop()!;\n if (resolvedDefIds.has(id)) continue;\n resolvedDefIds.add(id);\n\n const defNode = idMap.get(id);\n if (!defNode) continue;\n\n collectReferencedDefIds(defNode, usedDefIds, styleBlockText);\n for (const nestedId of usedDefIds) {\n if (!resolvedDefIds.has(nestedId)) queue.push(nestedId);\n }\n }\n\n for (const id of resolvedDefIds) {\n const defNode = idMap.get(id);\n if (!defNode) continue;\n\n extractElementPaintColors(defNode, colors, styleBlockText);\n collectPaintColorsFromClassRules(defNode, styleBlockText, colors);\n defNode.querySelectorAll('*').forEach((node) => {\n extractElementPaintColors(node, colors, styleBlockText);\n collectPaintColorsFromClassRules(node, styleBlockText, colors);\n });\n }\n\n // Keep extraction strict: visible shapes + defs they actually reference.\n // Only broaden to literal scanning if strict extraction found nothing.\n if (colors.size === 0) {\n collectStopColorsFromMarkup(styleBlockText, colors);\n collectColorLiteralsFromMarkup(normalizedSvgText, colors);\n collectStopColorsFromMarkup(normalizedSvgText, colors);\n }\n } finally {\n document.body.removeChild(svgRoot);\n }\n\n if (hasImplicitBlack) {\n colors.add('#000000');\n }\n\n return Array.from(colors);\n }\n }\n } catch {\n // If strict extraction partially succeeded, prefer that over broad literal fallback.\n if (colors.size > 0) return Array.from(colors);\n // fallback below\n }\n\n // Regex fallback\n const attrRegex = /(?:(?:svg:)?fill|(?:svg:)?stroke|(?:svg:)?stop-color)\\s*=\\s*[\"']([^\"']+)[\"']/gi;\n let match: RegExpExecArray | null;\n while ((match = attrRegex.exec(normalizedSvgText))) {\n const norm = normalizeSvgColor(match[1]);\n if (norm) colors.add(norm);\n }\n\n const styleRegex = /(?:(?:svg:)?fill|(?:svg:)?stroke|(?:svg:)?stop-color)\\s*:\\s*([^;{}]+)/gi;\n while ((match = styleRegex.exec(normalizedSvgText))) {\n const norm = normalizeSvgColor(match[1]);\n if (norm) colors.add(norm);\n }\n\n collectColorLiteralsFromMarkup(normalizedSvgText, colors);\n collectStopColorsFromMarkup(normalizedSvgText, colors);\n\n if (colors.size === 0 && /<(?:path|rect|circle|ellipse|polygon|polyline|line|text)\\b/i.test(normalizedSvgText)) {\n colors.add('#000000');\n }\n\n return Array.from(colors);\n}\n\n/** Apply a color replacement map to SVG fill/stroke attrs + inline/style-block declarations.\n * Handles implicit black: if colorMap maps #000000 → X, elements with no fill get fill=\"X\". */\nexport function applySvgColorMap(svgText: string, colorMap: Record<string, string>): string {\n if (!svgText || !colorMap || Object.keys(colorMap).length === 0) return svgText;\n\n const normalizedMap = new Map<string, string>();\n const transparentTargets = new Set<string>(); // keys whose target is transparent/none\n for (const [from, to] of Object.entries(colorMap)) {\n const key = normalizeSvgColor(from);\n if (!key) continue;\n const isTransparentTarget = to === 'transparent' || to === 'none' || to === '';\n if (isTransparentTarget) {\n normalizedMap.set(key, 'transparent');\n transparentTargets.add(key);\n } else if (/^#[0-9a-f]{6}$/i.test(to)) {\n normalizedMap.set(key, to.toLowerCase());\n }\n }\n if (normalizedMap.size === 0) return svgText;\n\n // Build a fuzzy lookup: for any color value, find the closest mapping key within threshold\n // Only build fuzzy entries for non-transparent targets (transparent is exact-match only)\n const mapEntries = Array.from(normalizedMap.entries())\n .filter(([k]) => !transparentTargets.has(k))\n .map(([k, v]) => ({ hex: k, rgb: hexToRgb(k), target: v }));\n const fuzzyThresholdSq = 30 * 30;\n\n function fuzzyLookup(value: string): string | null {\n const norm = normalizeSvgColor(value);\n if (!norm) return null;\n // Exact match first\n const exact = normalizedMap.get(norm);\n if (exact) return exact;\n // Fuzzy match\n const rgb = hexToRgb(norm);\n let bestDist = Infinity;\n let bestTarget: string | null = null;\n for (const entry of mapEntries) {\n const dr = rgb.r - entry.rgb.r;\n const dg = rgb.g - entry.rgb.g;\n const db = rgb.b - entry.rgb.b;\n const distSq = dr * dr + dg * dg + db * db;\n if (distSq < bestDist && distSq <= fuzzyThresholdSq) {\n bestDist = distSq;\n bestTarget = entry.target;\n }\n }\n return bestTarget;\n }\n\n const implicitBlackTarget = normalizedMap.get('#000000');\n\n const isTransparentMapTarget = (mapped: string): boolean =>\n mapped === 'transparent' || mapped === 'none';\n\n const isStopColorProperty = (property: string): boolean =>\n property === 'stop-color' || property === 'svg:stop-color' || property.endsWith(':stop-color');\n\n const TRANSPARENT_STOP_FALLBACK_COLOR = '#000000';\n\n const toMappedPaint = (originalValue: string, mapped: string, property: string): string => {\n if (isTransparentMapTarget(mapped) && isStopColorProperty(property)) return TRANSPARENT_STOP_FALLBACK_COLOR;\n return applyMappedColorPreservingAlpha(originalValue, mapped);\n };\n\n try {\n if (typeof DOMParser !== 'undefined' && typeof XMLSerializer !== 'undefined') {\n const doc = new DOMParser().parseFromString(svgText, 'image/svg+xml');\n const parserError = doc.querySelector('parsererror');\n if (!parserError) {\n // Collect style block text for class-based detection\n let styleBlockText = '';\n doc.querySelectorAll('style').forEach((s) => { styleBlockText += s.textContent || ''; });\n\n const elements = doc.querySelectorAll('*');\n elements.forEach((el) => {\n (['fill', 'stroke', 'stop-color', 'svg:fill', 'svg:stroke', 'svg:stop-color'] as const).forEach((attr) => {\n const val = el.getAttribute(attr);\n if (!val) return;\n const mapped = fuzzyLookup(val);\n if (!mapped) return;\n\n const mappedValue = toMappedPaint(val, mapped, attr);\n el.setAttribute(attr, mappedValue);\n\n if (isStopColorProperty(attr) && isTransparentMapTarget(mapped)) {\n el.setAttribute('stop-opacity', '0');\n }\n });\n\n // Handle implicit black: add explicit paint to elements that rely on SVG defaults.\n if (implicitBlackTarget && hasImplicitBlackFill(el, styleBlockText)) {\n el.setAttribute('fill', applyMappedColorPreservingAlpha('#000000', implicitBlackTarget));\n }\n if (implicitBlackTarget && hasImplicitBlackStopColor(el, styleBlockText)) {\n const isTransparentStop = isTransparentMapTarget(implicitBlackTarget);\n el.setAttribute(\n 'stop-color',\n isTransparentStop\n ? TRANSPARENT_STOP_FALLBACK_COLOR\n : applyMappedColorPreservingAlpha('#000000', implicitBlackTarget)\n );\n if (isTransparentStop) {\n el.setAttribute('stop-opacity', '0');\n }\n }\n\n const style = el.getAttribute('style');\n if (style) {\n let forceStopOpacityZero = false;\n const declarations = parseStyleDeclarations(style).map(({ key, value }) => {\n if (isPaintStyleKey(key)) {\n const mapped = fuzzyLookup(value);\n if (mapped) {\n const mappedValue = toMappedPaint(value, mapped, key);\n if (isStopColorStyleKey(key) && isTransparentMapTarget(mapped)) {\n forceStopOpacityZero = true;\n }\n return `${key}: ${mappedValue}`;\n }\n }\n return `${key}: ${value}`;\n });\n\n const nextDeclarations = forceStopOpacityZero\n ? declarations.filter((decl) => !/^stop-opacity\\s*:/i.test(decl))\n : declarations;\n\n if (forceStopOpacityZero) {\n nextDeclarations.push('stop-opacity: 0');\n }\n\n el.setAttribute('style', nextDeclarations.join('; '));\n }\n });\n\n doc.querySelectorAll('style').forEach((styleNode) => {\n const css = styleNode.textContent || '';\n styleNode.textContent = css.replace(/(((?:svg:)?fill|(?:svg:)?stroke|(?:svg:)?stop-color)\\s*:\\s*)([^;{}]+)/gi, (_all, prefix, prop, value) => {\n const valueText = String(value);\n const mapped = fuzzyLookup(valueText);\n if (!mapped) return `${prefix}${valueText}`;\n const mappedValue = toMappedPaint(valueText, mapped, String(prop).toLowerCase());\n if (isStopColorProperty(String(prop).toLowerCase()) && isTransparentMapTarget(mapped)) {\n return `${prefix}${mappedValue}; stop-opacity: 0`;\n }\n return `${prefix}${mappedValue}`;\n });\n });\n\n return new XMLSerializer().serializeToString(doc);\n }\n }\n } catch {\n // fallback below\n }\n\n // Regex fallback\n let result = svgText;\n result = result.replace(\n /(((?:svg:)?fill|(?:svg:)?stroke|(?:svg:)?stop-color)\\s*=\\s*[\"'])([^\"']+)([\"'])/gi,\n (full, prefix, prop, value, suffix) => {\n const valueText = String(value);\n const mapped = fuzzyLookup(valueText);\n if (!mapped) return full;\n const propText = String(prop).toLowerCase();\n const mappedValue = toMappedPaint(valueText, mapped, propText);\n return `${prefix}${mappedValue}${suffix}`;\n }\n );\n\n result = result.replace(\n /(((?:svg:)?fill|(?:svg:)?stroke|(?:svg:)?stop-color)\\s*:\\s*)([^;{}]+)/gi,\n (full, prefix, prop, value) => {\n const valueText = String(value);\n const mapped = fuzzyLookup(valueText);\n if (!mapped) return full;\n const propText = String(prop).toLowerCase();\n const mappedValue = toMappedPaint(valueText, mapped, propText);\n if (isStopColorProperty(propText) && isTransparentMapTarget(mapped)) {\n return `${prefix}${mappedValue}; stop-opacity: 0`;\n }\n return `${prefix}${mappedValue}`;\n }\n );\n\n // Regex fallback for implicit black defaults.\n if (implicitBlackTarget) {\n const implicitFillValue = applyMappedColorPreservingAlpha('#000000', implicitBlackTarget);\n result = result.replace(\n /(<(?:path|rect|circle|ellipse|polygon|polyline|line|text)\\b)(?![^>]*\\bfill\\b)([^>]*>)/gi,\n `$1 fill=\"${implicitFillValue}\"$2`\n );\n\n result = result.replace(/<((?:svg:)?stop)\\b([^>]*)>/gi, (full, tag, attrs) => {\n const attrsText = String(attrs || '');\n if (/\\b(?:svg:)?stop-color\\s*=\\s*[\"'][^\"']*[\"']/i.test(attrsText)) return full;\n if (/\\bstyle\\s*=\\s*[\"'][^\"']*(?:svg:)?stop-color\\s*:[^\"']*[\"']/i.test(attrsText)) return full;\n const isTransparentStop = isTransparentMapTarget(implicitBlackTarget);\n const stopColorValue = isTransparentStop\n ? TRANSPARENT_STOP_FALLBACK_COLOR\n : applyMappedColorPreservingAlpha('#000000', implicitBlackTarget);\n const stopOpacityAttr = isTransparentStop ? ' stop-opacity=\"0\"' : '';\n return `<${tag}${attrsText} stop-color=\"${stopColorValue}\"${stopOpacityAttr}>`;\n });\n }\n\n return result;\n}\n"],"names":[],"mappings":"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"}
@@ -148,6 +148,7 @@ const SHAPE_TAGS = /* @__PURE__ */ new Set([
148
148
  "g",
149
149
  "use"
150
150
  ]);
151
+ const NON_DRAWABLE_TAGS = /* @__PURE__ */ new Set(["defs", "metadata", "style", "title", "desc", "script"]);
151
152
  function hasImplicitBlackFill(el, styleBlocks) {
152
153
  const tag = el.tagName.toLowerCase();
153
154
  if (!SHAPE_TAGS.has(tag)) return false;
@@ -185,6 +186,35 @@ function hasImplicitBlackStopColor(el, styleBlocks) {
185
186
  });
186
187
  return !hasClassStopColor;
187
188
  }
189
+ function parseSvgLengthNumber(value) {
190
+ if (!value) return null;
191
+ const parsed = Number.parseFloat(value.replace(/px$/i, "").trim());
192
+ return Number.isFinite(parsed) ? parsed : null;
193
+ }
194
+ function parseViewBox(svgRoot) {
195
+ const viewBox = svgRoot.getAttribute("viewBox");
196
+ if (viewBox) {
197
+ const values = viewBox.split(/[\s,]+/).map((n) => Number.parseFloat(n)).filter((n) => Number.isFinite(n));
198
+ if (values.length === 4 && values[2] > 0 && values[3] > 0) {
199
+ return { x: values[0], y: values[1], width: values[2], height: values[3] };
200
+ }
201
+ }
202
+ const width = parseSvgLengthNumber(svgRoot.getAttribute("width"));
203
+ const height = parseSvgLengthNumber(svgRoot.getAttribute("height"));
204
+ if (width && height) {
205
+ return { x: 0, y: 0, width, height };
206
+ }
207
+ return null;
208
+ }
209
+ function collectReferencedIdsFromString(value, ids) {
210
+ if (!value) return;
211
+ const normalizedValue = value.replace(/&quot;/gi, '"').replace(/&apos;/gi, "'");
212
+ const urlRegex = /url\(\s*['"]?#([^)"'\s]+)['"]?\s*\)/gi;
213
+ let match;
214
+ while ((match = urlRegex.exec(normalizedValue)) !== null) {
215
+ if (match[1]) ids.add(match[1]);
216
+ }
217
+ }
188
218
  function escapeRegexToken(value) {
189
219
  return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
190
220
  }
@@ -202,12 +232,242 @@ function collectFromClassRules(el, styleBlockText, onRuleBody) {
202
232
  }
203
233
  }
204
234
  }
235
+ function collectReferencedDefIds(el, ids, styleBlockText = "") {
236
+ const attrs = ["fill", "stroke", "clip-path", "mask", "filter", "style", "marker-start", "marker-mid", "marker-end"];
237
+ for (const attr of attrs) {
238
+ collectReferencedIdsFromString(el.getAttribute(attr), ids);
239
+ }
240
+ collectFromClassRules(el, styleBlockText, (ruleBody) => {
241
+ collectReferencedIdsFromString(ruleBody, ids);
242
+ });
243
+ const href = el.getAttribute("href") || el.getAttribute("xlink:href");
244
+ if (href == null ? void 0 : href.startsWith("#")) ids.add(href.slice(1));
245
+ try {
246
+ if (typeof window !== "undefined") {
247
+ const computed = window.getComputedStyle(el);
248
+ collectReferencedIdsFromString(computed.fill, ids);
249
+ collectReferencedIdsFromString(computed.stroke, ids);
250
+ collectReferencedIdsFromString(computed.clipPath, ids);
251
+ collectReferencedIdsFromString(computed.mask, ids);
252
+ collectReferencedIdsFromString(computed.filter, ids);
253
+ }
254
+ } catch {
255
+ }
256
+ }
257
+ function getScreenBounds(el) {
258
+ try {
259
+ const bbox = el.getBBox();
260
+ if (bbox.width <= 0 && bbox.height <= 0) return null;
261
+ const matrix = el.getScreenCTM();
262
+ if (!matrix) {
263
+ return { x: bbox.x, y: bbox.y, width: bbox.width, height: bbox.height };
264
+ }
265
+ const p1 = new DOMPoint(bbox.x, bbox.y).matrixTransform(matrix);
266
+ const p2 = new DOMPoint(bbox.x + bbox.width, bbox.y).matrixTransform(matrix);
267
+ const p3 = new DOMPoint(bbox.x, bbox.y + bbox.height).matrixTransform(matrix);
268
+ const p4 = new DOMPoint(bbox.x + bbox.width, bbox.y + bbox.height).matrixTransform(matrix);
269
+ const minX = Math.min(p1.x, p2.x, p3.x, p4.x);
270
+ const minY = Math.min(p1.y, p2.y, p3.y, p4.y);
271
+ const maxX = Math.max(p1.x, p2.x, p3.x, p4.x);
272
+ const maxY = Math.max(p1.y, p2.y, p3.y, p4.y);
273
+ return { x: minX, y: minY, width: maxX - minX, height: maxY - minY };
274
+ } catch {
275
+ return null;
276
+ }
277
+ }
278
+ function getViewBoxScreenBounds(svgRoot, viewBox) {
279
+ const matrix = svgRoot.getScreenCTM();
280
+ if (!matrix || typeof DOMPoint === "undefined") return null;
281
+ const p1 = new DOMPoint(viewBox.x, viewBox.y).matrixTransform(matrix);
282
+ const p2 = new DOMPoint(viewBox.x + viewBox.width, viewBox.y + viewBox.height).matrixTransform(matrix);
283
+ const minX = Math.min(p1.x, p2.x);
284
+ const minY = Math.min(p1.y, p2.y);
285
+ const maxX = Math.max(p1.x, p2.x);
286
+ const maxY = Math.max(p1.y, p2.y);
287
+ return { x: minX, y: minY, width: maxX - minX, height: maxY - minY };
288
+ }
289
+ function intersects(a, b) {
290
+ return !(a.x > b.x + b.width || a.x + a.width < b.x || a.y > b.y + b.height || a.y + a.height < b.y);
291
+ }
292
+ function addRecolorableColor(value, colors) {
293
+ if (!value) return;
294
+ const normalized = normalizeSvgColor(value);
295
+ if (normalized) colors.add(normalized);
296
+ }
205
297
  function isPaintStyleKey(key) {
206
298
  return key === "fill" || key === "stroke" || key === "stop-color" || key.endsWith(":fill") || key.endsWith(":stroke") || key.endsWith(":stop-color");
207
299
  }
208
300
  function isStopColorStyleKey(key) {
209
301
  return key === "stop-color" || key.endsWith(":stop-color");
210
302
  }
303
+ function collectPaintColorsFromClassRules(el, styleBlockText, colors) {
304
+ collectFromClassRules(el, styleBlockText, (ruleBody) => {
305
+ parseStyleDeclarations(ruleBody).forEach(({ key, value }) => {
306
+ if (isPaintStyleKey(key)) {
307
+ addRecolorableColor(value, colors);
308
+ }
309
+ });
310
+ });
311
+ }
312
+ function extractElementPaintColors(el, colors, styleBlockText = "") {
313
+ addRecolorableColor(el.getAttribute("fill"), colors);
314
+ addRecolorableColor(el.getAttribute("stroke"), colors);
315
+ addRecolorableColor(el.getAttribute("stop-color"), colors);
316
+ const style = el.getAttribute("style");
317
+ if (style) {
318
+ parseStyleDeclarations(style).forEach(({ key, value }) => {
319
+ if (isPaintStyleKey(key)) {
320
+ addRecolorableColor(value, colors);
321
+ }
322
+ });
323
+ }
324
+ try {
325
+ if (typeof window !== "undefined") {
326
+ const computed = window.getComputedStyle(el);
327
+ addRecolorableColor(computed.fill, colors);
328
+ addRecolorableColor(computed.stroke, colors);
329
+ addRecolorableColor(computed.stopColor, colors);
330
+ }
331
+ } catch {
332
+ }
333
+ if (hasImplicitBlackStopColor(el, styleBlockText)) {
334
+ colors.add("#000000");
335
+ }
336
+ }
337
+ function normalizeSvgMarkupForColorExtraction(svgText) {
338
+ if (!svgText) return svgText;
339
+ return svgText.trim().replace(/^\uFEFF/, "").replace(/<(\/?)\s*svg:svg\b/gi, "<$1svg").replace(/<(\/?)\s*svg:/gi, "<$1").replace(/(\s)svg:([a-zA-Z_][\w:.-]*)(\s*=)/gi, "$1$2$3").replace(/\s+xmlns:svg\s*=\s*"[^"]*"/gi, "").replace(/\s+xmlns:svg\s*=\s*'[^']*'/gi, "");
340
+ }
341
+ function collectColorLiteralsFromMarkup(svgText, colors) {
342
+ if (!svgText) return;
343
+ const literalRegex = /#[0-9a-fA-F]{3,8}\b|(?:rgba?|hsla?)\([^)]*\)/g;
344
+ let match;
345
+ while ((match = literalRegex.exec(svgText)) !== null) {
346
+ const normalized = normalizeSvgColor(match[0]);
347
+ if (normalized) colors.add(normalized);
348
+ }
349
+ }
350
+ function collectStopColorsFromMarkup(svgText, colors) {
351
+ if (!svgText) return;
352
+ const attrRegex = /(?:svg:)?stop-color\s*=\s*["']([^"']+)["']/gi;
353
+ let match;
354
+ while ((match = attrRegex.exec(svgText)) !== null) {
355
+ addRecolorableColor((match[1] || "").trim(), colors);
356
+ }
357
+ const styleRegex = /(?:^|[;\s{])(?:svg:)?stop-color\s*:\s*([^;{}]+)/gi;
358
+ while ((match = styleRegex.exec(svgText)) !== null) {
359
+ addRecolorableColor((match[1] || "").trim(), colors);
360
+ }
361
+ }
362
+ function extractSvgColors(svgText) {
363
+ if (!svgText) return [];
364
+ const normalizedSvgText = normalizeSvgMarkupForColorExtraction(svgText);
365
+ const colors = /* @__PURE__ */ new Set();
366
+ let hasImplicitBlack = false;
367
+ try {
368
+ if (typeof DOMParser !== "undefined" && typeof document !== "undefined") {
369
+ const doc = new DOMParser().parseFromString(normalizedSvgText, "image/svg+xml");
370
+ const parserError = doc.querySelector("parsererror");
371
+ if (!parserError) {
372
+ const sourceRoot = doc.documentElement;
373
+ if (!sourceRoot || sourceRoot.tagName.toLowerCase() !== "svg") return [];
374
+ const importedRoot = document.importNode(sourceRoot, true);
375
+ if (!(importedRoot instanceof SVGSVGElement)) return [];
376
+ const svgRoot = importedRoot;
377
+ let styleBlockText = "";
378
+ svgRoot.querySelectorAll("style").forEach((s) => {
379
+ styleBlockText += s.textContent || "";
380
+ });
381
+ svgRoot.style.position = "absolute";
382
+ svgRoot.style.left = "-99999px";
383
+ svgRoot.style.top = "-99999px";
384
+ svgRoot.style.visibility = "hidden";
385
+ svgRoot.style.pointerEvents = "none";
386
+ document.body.appendChild(svgRoot);
387
+ try {
388
+ const viewBox = parseViewBox(svgRoot);
389
+ const viewBounds = viewBox ? getViewBoxScreenBounds(svgRoot, viewBox) : null;
390
+ const usedDefIds = /* @__PURE__ */ new Set();
391
+ const allElements = Array.from(svgRoot.querySelectorAll("*"));
392
+ for (const el of allElements) {
393
+ const tag = el.tagName.toLowerCase();
394
+ if (NON_DRAWABLE_TAGS.has(tag) || tag === "stop" || !!el.closest("defs")) continue;
395
+ let intersectsView = true;
396
+ if (viewBounds && el instanceof SVGGraphicsElement) {
397
+ const elBounds = getScreenBounds(el);
398
+ if (elBounds) intersectsView = intersects(elBounds, viewBounds);
399
+ }
400
+ if (!intersectsView) continue;
401
+ extractElementPaintColors(el, colors, styleBlockText);
402
+ collectPaintColorsFromClassRules(el, styleBlockText, colors);
403
+ collectReferencedDefIds(el, usedDefIds, styleBlockText);
404
+ if (!hasImplicitBlack && hasImplicitBlackFill(el, styleBlockText)) {
405
+ hasImplicitBlack = true;
406
+ }
407
+ }
408
+ const idMap = /* @__PURE__ */ new Map();
409
+ svgRoot.querySelectorAll("[id]").forEach((node) => {
410
+ const id = node.getAttribute("id");
411
+ if (id) idMap.set(id, node);
412
+ });
413
+ const resolvedDefIds = /* @__PURE__ */ new Set();
414
+ const queue = Array.from(usedDefIds);
415
+ while (queue.length > 0) {
416
+ const id = queue.pop();
417
+ if (resolvedDefIds.has(id)) continue;
418
+ resolvedDefIds.add(id);
419
+ const defNode = idMap.get(id);
420
+ if (!defNode) continue;
421
+ collectReferencedDefIds(defNode, usedDefIds, styleBlockText);
422
+ for (const nestedId of usedDefIds) {
423
+ if (!resolvedDefIds.has(nestedId)) queue.push(nestedId);
424
+ }
425
+ }
426
+ for (const id of resolvedDefIds) {
427
+ const defNode = idMap.get(id);
428
+ if (!defNode) continue;
429
+ extractElementPaintColors(defNode, colors, styleBlockText);
430
+ collectPaintColorsFromClassRules(defNode, styleBlockText, colors);
431
+ defNode.querySelectorAll("*").forEach((node) => {
432
+ extractElementPaintColors(node, colors, styleBlockText);
433
+ collectPaintColorsFromClassRules(node, styleBlockText, colors);
434
+ });
435
+ }
436
+ if (colors.size === 0) {
437
+ collectStopColorsFromMarkup(styleBlockText, colors);
438
+ collectColorLiteralsFromMarkup(normalizedSvgText, colors);
439
+ collectStopColorsFromMarkup(normalizedSvgText, colors);
440
+ }
441
+ } finally {
442
+ document.body.removeChild(svgRoot);
443
+ }
444
+ if (hasImplicitBlack) {
445
+ colors.add("#000000");
446
+ }
447
+ return Array.from(colors);
448
+ }
449
+ }
450
+ } catch {
451
+ if (colors.size > 0) return Array.from(colors);
452
+ }
453
+ const attrRegex = /(?:(?:svg:)?fill|(?:svg:)?stroke|(?:svg:)?stop-color)\s*=\s*["']([^"']+)["']/gi;
454
+ let match;
455
+ while (match = attrRegex.exec(normalizedSvgText)) {
456
+ const norm = normalizeSvgColor(match[1]);
457
+ if (norm) colors.add(norm);
458
+ }
459
+ const styleRegex = /(?:(?:svg:)?fill|(?:svg:)?stroke|(?:svg:)?stop-color)\s*:\s*([^;{}]+)/gi;
460
+ while (match = styleRegex.exec(normalizedSvgText)) {
461
+ const norm = normalizeSvgColor(match[1]);
462
+ if (norm) colors.add(norm);
463
+ }
464
+ collectColorLiteralsFromMarkup(normalizedSvgText, colors);
465
+ collectStopColorsFromMarkup(normalizedSvgText, colors);
466
+ if (colors.size === 0 && /<(?:path|rect|circle|ellipse|polygon|polyline|line|text)\b/i.test(normalizedSvgText)) {
467
+ colors.add("#000000");
468
+ }
469
+ return Array.from(colors);
470
+ }
211
471
  function applySvgColorMap(svgText, colorMap) {
212
472
  if (!svgText || !colorMap || Object.keys(colorMap).length === 0) return svgText;
213
473
  const normalizedMap = /* @__PURE__ */ new Map();
@@ -375,5 +635,6 @@ function applySvgColorMap(svgText, colorMap) {
375
635
  return result;
376
636
  }
377
637
  exports.applySvgColorMap = applySvgColorMap;
638
+ exports.extractSvgColors = extractSvgColors;
378
639
  exports.normalizeSvgColor = normalizeSvgColor;
379
- //# sourceMappingURL=svgColorUtils-DQN6fbIM.cjs.map
640
+ //# sourceMappingURL=svgColorUtils-DKcCq1sO.cjs.map