@tenphi/tasty 3.11.2 → 3.13.0
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.
- package/README.md +6 -6
- package/dist/{babel-types-BKDTT4--.d.ts → babel-types-docs8f4c.d.ts} +2 -2
- package/dist/chunks/{build-config-DlxpZKk_.js → build-config-DmSCYjYl.js} +5 -5
- package/dist/chunks/{build-config-DlxpZKk_.js.map → build-config-DmSCYjYl.js.map} +1 -1
- package/dist/chunks/{collector-B4-yqFEs.js → collector-8w5r-xFl.js} +4 -4
- package/dist/chunks/{collector-B4-yqFEs.js.map → collector-8w5r-xFl.js.map} +1 -1
- package/dist/chunks/{config-engine-DJsb5WYu.js → config-engine-DjRv6Axa.js} +5 -5
- package/dist/chunks/config-engine-DjRv6Axa.js.map +1 -0
- package/dist/chunks/{css-definitions-DW1TGGiy.js → css-definitions-_UidGa56.js} +3 -3
- package/dist/chunks/{css-definitions-DW1TGGiy.js.map → css-definitions-_UidGa56.js.map} +1 -1
- package/dist/chunks/{debug-DMMwe1rY.js → debug-B6dZq3uH.js} +4 -4
- package/dist/chunks/{debug-DMMwe1rY.js.map → debug-B6dZq3uH.js.map} +1 -1
- package/dist/chunks/{dsl-DYSJc1-T.js → dsl-rgu6XQcD.js} +42 -39
- package/dist/chunks/dsl-rgu6XQcD.js.map +1 -0
- package/dist/chunks/{react-runtime-DhPtFlZs.js → react-runtime-DS1cEAMK.js} +5 -5
- package/dist/chunks/react-runtime-DS1cEAMK.js.map +1 -0
- package/dist/chunks/{runtime-engine-BlrVXv8l.js → runtime-engine-DFCZN1nF.js} +6 -6
- package/dist/chunks/runtime-engine-DFCZN1nF.js.map +1 -0
- package/dist/chunks/{runtime-state-BLyMRYFF.js → runtime-state-C8MzPjBR.js} +2 -2
- package/dist/chunks/{runtime-state-BLyMRYFF.js.map → runtime-state-C8MzPjBR.js.map} +1 -1
- package/dist/chunks/{style-engine-of5Xbc27.js → style-engine-DoGrZPBB.js} +17 -12
- package/dist/chunks/style-engine-DoGrZPBB.js.map +1 -0
- package/dist/chunks/{zero-engine-D2jPSpWA.js → zero-engine-CiVidroC.js} +5 -5
- package/dist/chunks/{zero-engine-D2jPSpWA.js.map → zero-engine-CiVidroC.js.map} +1 -1
- package/dist/{config-CcxqSZI2.d.ts → config-DDY7NlZ1.d.ts} +7 -8
- package/dist/core/index.d.ts +2 -2
- package/dist/core/index.js +7 -7
- package/dist/{index--GdqCPlp.d.ts → index-enN6b6o_.d.ts} +5 -5
- package/dist/index.d.ts +3 -3
- package/dist/index.js +8 -8
- package/dist/ssr/astro.js +2 -2
- package/dist/ssr/index.js +2 -2
- package/dist/ssr/next-config.d.ts +1 -1
- package/dist/ssr/next-config.js +3 -3
- package/dist/ssr/next.js +3 -3
- package/dist/zero/babel.d.ts +9 -3
- package/dist/zero/babel.js +8 -8
- package/dist/zero/babel.js.map +1 -1
- package/dist/zero/index.d.ts +3 -2
- package/dist/zero/index.js +5 -4
- package/dist/zero/index.js.map +1 -1
- package/dist/zero/next.d.ts +1 -1
- package/docs/ai-agents.md +1 -0
- package/docs/configuration.md +12 -10
- package/docs/dsl.md +56 -42
- package/docs/styles.md +4 -0
- package/docs/tasty-static.md +21 -7
- package/package.json +26 -27
- package/dist/chunks/config-engine-DJsb5WYu.js.map +0 -1
- package/dist/chunks/dsl-DYSJc1-T.js.map +0 -1
- package/dist/chunks/react-runtime-DhPtFlZs.js.map +0 -1
- package/dist/chunks/runtime-engine-BlrVXv8l.js.map +0 -1
- package/dist/chunks/style-engine-of5Xbc27.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"debug-DMMwe1rY.js","names":[],"sources":["../../src/debug.ts"],"sourcesContent":["/* eslint-disable no-console */\nimport { CHUNK_NAMES } from './chunks/definitions';\nimport { getNamePrefix } from './config';\nimport { flushStyles, getCSSTextForNode, injector } from './injector';\nimport type { CacheMetrics, RootRegistry } from './injector/types';\nimport { tastyClassRegex } from './utils/name-prefix';\n\ndeclare global {\n interface Window {\n tastyDebug?: typeof tastyDebug;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\ntype CSSTarget =\n 'all' | 'global' | 'active' | 'unused' | 'page' | string | string[] | Element;\n\nexport interface DebugOptions {\n root?: Document | ShadowRoot;\n /** Suppress console logging and return data only (default: false) */\n raw?: boolean;\n}\n\nexport interface CSSOptions extends DebugOptions {\n prettify?: boolean;\n /** Read from stored source CSS (dev-mode only) instead of live CSSOM */\n source?: boolean;\n}\n\nexport interface DebugChunkInfo {\n className: string;\n chunkName: string | null;\n}\n\nexport interface InspectResult {\n element?: Element | null;\n classes: string[];\n chunks: DebugChunkInfo[];\n css: string;\n size: number;\n rules: number;\n}\n\nexport interface CacheStatus {\n classes: {\n active: string[];\n unused: string[];\n all: string[];\n };\n metrics: CacheMetrics | null;\n}\n\nexport interface ChunkBreakdown {\n byChunk: Record<\n string,\n { classes: string[]; cssSize: number; ruleCount: number }\n >;\n totalChunkTypes: number;\n totalClasses: number;\n}\n\nexport interface Summary {\n activeClasses: string[];\n /** Classes `gc({ force: true })` would delete right now. */\n unusedClasses: string[];\n /**\n * Held but in neither list: nothing renders them, yet collection will not\n * take them — inside the grace window, or pinned by an `inject()` handle.\n */\n hotClasses: string[];\n totalStyledClasses: string[];\n\n activeCSSSize: number;\n unusedCSSSize: number;\n globalCSSSize: number;\n rawCSSSize: number;\n keyframesCSSSize: number;\n propertyCSSSize: number;\n totalCSSSize: number;\n\n activeRuleCount: number;\n unusedRuleCount: number;\n globalRuleCount: number;\n rawRuleCount: number;\n keyframesRuleCount: number;\n propertyRuleCount: number;\n totalRuleCount: number;\n\n metrics: CacheMetrics | null;\n definedProperties: string[];\n definedKeyframes: { name: string; refCount: number }[];\n chunkBreakdown: ChunkBreakdown;\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction fmtSize(bytes: number): string {\n return bytes > 1024 ? `${(bytes / 1024).toFixed(1)}KB` : `${bytes}B`;\n}\n\nfunction countRules(css: string): number {\n return (css.match(/\\{[^}]*\\}/g) || []).length;\n}\n\nfunction sortTastyClasses(classes: Iterable<string>): string[] {\n // Class names use a base36 hash format (e.g. `t3a5f`), so sort lexicographically.\n return Array.from(classes).sort((a, b) => a.localeCompare(b));\n}\n\n/** A DOM root to read, or `null` when the environment has no DOM at all. */\ntype DebugRoot = Document | ShadowRoot | null;\n\n/**\n * The root these helpers read, or `null` where there is no DOM.\n *\n * `document` used to be a default parameter value, and a default is evaluated\n * at the call site — so every read below threw a bare `ReferenceError` under\n * Node, taking out five of the eight public methods. A debug utility must not\n * be able to fail an SSR render because a call was left in, so the DOM-less\n * case reports an empty result and says why.\n */\nfunction defaultRoot(): DebugRoot {\n return typeof document === 'undefined' ? null : document;\n}\n\nlet warnedNoDom = false;\n\n/** Say once why the numbers are empty. Silent under `{ raw: true }`. */\nfunction warnNoDom(raw: boolean): void {\n if (raw || warnedNoDom) return;\n warnedNoDom = true;\n console.warn(\n '[Tasty] tastyDebug reads the DOM and this environment has none, so the ' +\n 'result is empty. During SSR, read the ServerStyleCollector instead.',\n );\n}\n\n/**\n * The registry for `root`, with every queued write landed first.\n *\n * Every injector read API is a flush point, and the reads below reach past\n * those APIs straight into the registry and the sheet manager. Without this\n * they would report a batch window's contents as absent — a rule that is\n * enqueued but not yet in a sheet is missing from `globalRules`, from the\n * sheets, and from anything counting either.\n */\nfunction getRegistry(\n root: DebugRoot = defaultRoot(),\n): RootRegistry | undefined {\n if (!root) return undefined;\n flushStyles();\n\n return injector.instance._sheetManager?.getRegistry(root);\n}\n\nfunction findDomTastyClasses(root: DebugRoot = defaultRoot()): string[] {\n if (!root) return [];\n const classes = new Set<string>();\n const elements = (root as Document).querySelectorAll?.('[class]') || [];\n const classRegex = tastyClassRegex(getNamePrefix());\n for (const element of elements) {\n const attribute = element.getAttribute('class');\n if (!attribute) continue;\n for (const className of attribute.split(/\\s+/)) {\n if (classRegex.test(className)) classes.add(className);\n }\n }\n return sortTastyClasses(classes);\n}\n\n/**\n * Everything this injector holds in `root`, in the order the engine applies it,\n * with the sources kept byte-for-byte — trimming would report a total smaller\n * than one of its own parts whenever raw CSS has edge whitespace.\n */\nfunction getAllCSS(root: DebugRoot = defaultRoot()): string {\n const registry = getRegistry(root);\n const sheetManager = injector.instance._sheetManager;\n // `getRegistry` already returns nothing for a null root; the `!root` is what\n // narrows the type for the call below.\n if (!root || !registry || !sheetManager) return '';\n\n return sheetManager.getOwnedCSSInOrder(registry, root).join('\\n');\n}\n\n/**\n * The injector's own readers fall back to `document` when `root` is omitted, so\n * they have to be reached with a real root or not at all.\n */\nfunction cssTextForClasses(classNames: string[], root: DebugRoot): string {\n if (!root) return '';\n\n return injector.instance.getCSSTextForClasses(classNames, { root });\n}\n\nfunction getInjectorMetrics(root: DebugRoot): CacheMetrics | null {\n if (!root) return null;\n\n return injector.instance.getMetrics({ root });\n}\n\n/**\n * Injected classes that no element carries and nobody pinned — the exact set\n * `gc({ force: true })` would delete.\n *\n * Deliberately borrowed from the injector rather than recomputed here: the two\n * drifted apart once before, when this file still read \"unused\" off the pin\n * counts the render path had stopped maintaining.\n */\nfunction getUnusedClasses(root: DebugRoot = defaultRoot()): string[] {\n if (!root) return [];\n\n return sortTastyClasses(injector.instance.getUnusedClasses({ root }));\n}\n\n/** Every class this injector holds CSS for in `root`. */\nfunction getOwnedClasses(root: DebugRoot = defaultRoot()): string[] {\n const registry = getRegistry(root);\n if (!registry) return [];\n\n const owned: string[] = [];\n for (const [className, info] of registry.rules) {\n // A negative sheet index marks a class whose CSS this injector does not\n // hold: server-rendered, pre-allocated, or queued.\n if (info.sheetIndex >= 0) owned.push(className);\n }\n\n return sortTastyClasses(owned);\n}\n\n// ---------------------------------------------------------------------------\n// prettifyCSS — readable output for nested rules\n// ---------------------------------------------------------------------------\n\nfunction prettifyCSS(css: string): string {\n if (!css || !css.trim()) return '';\n\n const out: string[] = [];\n let depth = 0;\n\n const lines = css\n .replace(/\\s+/g, ' ')\n .trim()\n .replaceAll(' {', '{')\n .replaceAll('{', ' {\\n')\n .replaceAll('}', '\\n}\\n')\n .replaceAll(';', ';\\n')\n .split('\\n');\n\n for (let line of lines) {\n line = line.trim();\n if (!line) continue;\n\n if (line === '}') {\n const last = out.at(-1);\n if (last && !/[;{}]$/.test(last)) {\n out[out.length - 1] += ';';\n }\n depth = Math.max(0, depth - 1);\n }\n out.push(`${' '.repeat(depth)}${line}`);\n if (line.endsWith('{')) depth++;\n }\n\n return out.join('\\n');\n}\n\n// ---------------------------------------------------------------------------\n// Chunk helpers\n// ---------------------------------------------------------------------------\n\nfunction extractChunkName(cacheKey: string): string | null {\n for (const part of cacheKey.split('\\0')) {\n if (part.startsWith('[states:')) continue;\n if (!part.includes(':') && part.length > 0) return part;\n }\n return null;\n}\n\nfunction getChunkForClass(\n className: string,\n root: DebugRoot = defaultRoot(),\n): string | null {\n const registry = getRegistry(root);\n if (!registry) return null;\n for (const [key, cn] of registry.cacheKeyToClassName) {\n if (cn === className) return extractChunkName(key);\n }\n return null;\n}\n\nfunction buildChunkBreakdown(root: DebugRoot = defaultRoot()): ChunkBreakdown {\n const registry = getRegistry(root);\n if (!root || !registry)\n return { byChunk: {}, totalChunkTypes: 0, totalClasses: 0 };\n\n const byChunk: ChunkBreakdown['byChunk'] = {};\n for (const [cacheKey, className] of registry.cacheKeyToClassName) {\n const chunk = extractChunkName(cacheKey) || 'unknown';\n const entry = (byChunk[chunk] ??= {\n classes: [],\n cssSize: 0,\n ruleCount: 0,\n });\n entry.classes.push(className);\n const css = cssTextForClasses([className], root);\n entry.cssSize += css.length;\n entry.ruleCount += countRules(css);\n }\n\n const entries = Object.values(byChunk);\n for (const entry of entries) {\n entry.classes = sortTastyClasses(entry.classes);\n }\n\n const totalClasses = entries.reduce((sum, entry) => {\n return sum + entry.classes.length;\n }, 0);\n return {\n byChunk,\n totalChunkTypes: Object.keys(byChunk).length,\n totalClasses,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Global-type CSS helper (internal only)\n// ---------------------------------------------------------------------------\n\n/**\n * Every prefix `registry.globalRules` is keyed by. Anything missing here is a\n * rule the summary would hold but never count, which is how the totals stopped\n * adding up the first time.\n */\nconst GLOBAL_RULE_PREFIXES = {\n global: 'global:',\n property: 'property:',\n fontFace: 'fontface:',\n counterStyle: 'counterstyle:',\n function: 'function:',\n} as const;\n\nfunction getGlobalTypeCSS(\n type: keyof typeof GLOBAL_RULE_PREFIXES | 'raw' | 'keyframes',\n root: DebugRoot = defaultRoot(),\n includeCSS = true,\n): { css: string; ruleCount: number; size: number } {\n const registry = getRegistry(root);\n if (!root || !registry) return { css: '', ruleCount: 0, size: 0 };\n\n const chunks: string[] = [];\n const sheetManager = injector.instance._sheetManager;\n let rc = 0;\n\n if (type === 'raw') {\n // Raw blocks are kept by the sheet manager, not in `globalRules`, so the\n // prefix scan below never sees them — and their rules are counted from the\n // parsed sheet, since one raw block is one string but any number of rules.\n const css = injector.instance.getRawCSSText({ root });\n\n return {\n css: includeCSS ? prettifyCSS(css) : '',\n ruleCount: sheetManager?.getRawRuleCount(root) ?? 0,\n size: css.length,\n };\n }\n\n if (type === 'keyframes') {\n for (const [, entry] of registry.keyframesCache) {\n const info = entry.info;\n const sheetInfo = registry.sheets[info.sheetIndex];\n const ss =\n sheetInfo && sheetManager ? sheetManager.getCSSSheet(sheetInfo) : null;\n if (ss && info.ruleIndex < ss.cssRules.length) {\n const rule = ss.cssRules[info.ruleIndex];\n if (rule) {\n chunks.push(rule.cssText);\n rc++;\n }\n } else if (info.cssText) {\n chunks.push(info.cssText);\n rc++;\n }\n }\n } else {\n const prefix = GLOBAL_RULE_PREFIXES[type];\n for (const [key, ri] of registry.globalRules) {\n if (!key.startsWith(prefix)) continue;\n const sheetInfo = registry.sheets[ri.sheetIndex];\n const ss =\n sheetInfo && sheetManager ? sheetManager.getCSSSheet(sheetInfo) : null;\n if (ss) {\n const start = Math.max(0, ri.ruleIndex);\n const end = Math.min(\n ss.cssRules.length - 1,\n (ri.endRuleIndex as number) ?? ri.ruleIndex,\n );\n if (start >= 0 && end >= start && start < ss.cssRules.length) {\n for (let i = start; i <= end; i++) {\n const rule = ss.cssRules[i];\n if (rule) {\n chunks.push(rule.cssText);\n rc++;\n }\n }\n }\n } else if (ri.cssText?.length) {\n chunks.push(...ri.cssText);\n rc += ri.cssText.length;\n }\n }\n }\n\n const raw = chunks.join('\\n');\n return {\n css: includeCSS ? prettifyCSS(raw) : '',\n ruleCount: rc,\n size: raw.length,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Source CSS (dev-mode RuleInfo.cssText)\n// ---------------------------------------------------------------------------\n\nfunction getSourceCssForClasses(\n classNames: string[],\n root: DebugRoot = defaultRoot(),\n): string | null {\n const registry = getRegistry(root);\n if (!registry) return null;\n\n const chunks: string[] = [];\n let found = false;\n for (const cls of classNames) {\n const info = registry.rules.get(cls);\n if (info?.cssText?.length) {\n chunks.push(...info.cssText);\n found = true;\n }\n }\n return found ? chunks.join('\\n') : null;\n}\n\n// ---------------------------------------------------------------------------\n// Definitions helper (internal)\n// ---------------------------------------------------------------------------\n\nfunction getDefs(root: DebugRoot = defaultRoot()) {\n const registry = getRegistry(root);\n let properties: string[] = [];\n if (registry?.injectedProperties) {\n properties = Array.from(\n (registry.injectedProperties as Map<string, string>).keys(),\n ).sort();\n }\n\n const keyframes: { name: string; refCount: number }[] = [];\n if (registry) {\n for (const entry of registry.keyframesCache.values()) {\n keyframes.push({ name: entry.name, refCount: entry.refCount });\n }\n keyframes.sort((a, b) => a.name.localeCompare(b.name));\n }\n\n return { properties, keyframes };\n}\n\n// ---------------------------------------------------------------------------\n// Chunk display order\n// ---------------------------------------------------------------------------\n\nconst CHUNK_ORDER = [\n CHUNK_NAMES.COMBINED,\n CHUNK_NAMES.APPEARANCE,\n CHUNK_NAMES.FONT,\n CHUNK_NAMES.DIMENSION,\n CHUNK_NAMES.DISPLAY,\n CHUNK_NAMES.LAYOUT,\n CHUNK_NAMES.POSITION,\n CHUNK_NAMES.MISC,\n CHUNK_NAMES.SUBCOMPONENTS,\n];\n\nfunction logChunkEntries(breakdown: ChunkBreakdown): void {\n for (const name of CHUNK_ORDER) {\n const data = breakdown.byChunk[name];\n if (data)\n console.log(\n ` ${name}: ${data.classes.length} cls, ${data.ruleCount} rules, ${fmtSize(data.cssSize)}`,\n );\n }\n for (const [name, data] of Object.entries(breakdown.byChunk)) {\n if (!CHUNK_ORDER.includes(name as (typeof CHUNK_ORDER)[number]))\n console.log(\n ` ${name}: ${data.classes.length} cls, ${data.ruleCount} rules, ${fmtSize(data.cssSize)}`,\n );\n }\n}\n\n// ---------------------------------------------------------------------------\n// tastyDebug API\n// ---------------------------------------------------------------------------\n\nexport const tastyDebug = {\n css(target: CSSTarget, opts?: CSSOptions): string {\n const {\n root = defaultRoot(),\n prettify = true,\n raw = false,\n source = false,\n } = opts || {};\n if (!root) {\n warnNoDom(raw);\n\n return '';\n }\n let css = '';\n\n const classRegex = tastyClassRegex(getNamePrefix());\n if (source && typeof target === 'string' && classRegex.test(target)) {\n const src = getSourceCssForClasses([target], root);\n if (src) {\n css = src;\n } else {\n if (!raw) {\n console.warn(\n '[Tasty] source CSS not available (requires dev mode or TASTY_DEBUG=true). Falling back to live CSSOM.',\n );\n }\n css = cssTextForClasses([target], root);\n }\n } else if (source && Array.isArray(target)) {\n const src = getSourceCssForClasses(target, root);\n if (src) {\n css = src;\n } else {\n if (!raw) {\n console.warn(\n '[Tasty] source CSS not available. Falling back to live CSSOM.',\n );\n }\n css = cssTextForClasses(target, root);\n }\n } else if (typeof target === 'string') {\n if (target === 'all') {\n // Documented as component + global + raw, and raw has its own sheet.\n css = getAllCSS(root);\n } else if (target === 'global') {\n css = getGlobalTypeCSS('global', root).css;\n return css; // already prettified\n } else if (target === 'active') {\n const active = findDomTastyClasses(root);\n css = cssTextForClasses(active, root);\n } else if (target === 'unused') {\n const unused = getUnusedClasses(root);\n css = cssTextForClasses(unused, root);\n } else if (target === 'page') {\n css = getPageCSS(root);\n } else if (classRegex.test(target)) {\n css = cssTextForClasses([target], root);\n } else {\n const el = (root as Document).querySelector?.(target);\n if (el) css = getCSSTextForNode(el, { root });\n }\n } else if (Array.isArray(target)) {\n css = cssTextForClasses(target, root);\n } else if (target instanceof Element) {\n css = getCSSTextForNode(target, { root });\n }\n\n const result = prettify ? prettifyCSS(css) : css;\n\n if (!raw) {\n const label = Array.isArray(target) ? `[${target.join(', ')}]` : target;\n const rc = countRules(css);\n console.group(`CSS for ${label} (${rc} rules, ${fmtSize(css.length)})`);\n console.log(result || '(empty)');\n console.groupEnd();\n }\n\n return result;\n },\n\n inspect(target: string | Element, opts?: DebugOptions): InspectResult {\n const { root = defaultRoot(), raw = false } = opts || {};\n const element = !root\n ? null\n : typeof target === 'string'\n ? (root as Document).querySelector?.(target)\n : target;\n if (!root) warnNoDom(raw);\n\n if (!element) {\n const empty: InspectResult = {\n element: null,\n classes: [],\n chunks: [],\n css: '',\n size: 0,\n rules: 0,\n };\n // With no DOM at all, `warnNoDom` above already said why; \"element not\n // found\" would only misdirect.\n if (!raw && root)\n console.warn('[Tasty] debug.inspect: element not found');\n return empty;\n }\n\n const classList = element.getAttribute('class') || '';\n const classRegex = tastyClassRegex(getNamePrefix());\n const tastyClasses = classList\n .split(/\\s+/)\n .filter((cls) => classRegex.test(cls));\n\n const chunks: DebugChunkInfo[] = tastyClasses.map((className) => ({\n className,\n chunkName: getChunkForClass(className, root),\n }));\n\n const css = getCSSTextForNode(element, { root: root ?? undefined });\n const rules = countRules(css);\n\n const result: InspectResult = {\n element,\n classes: tastyClasses,\n chunks,\n css: prettifyCSS(css),\n size: css.length,\n rules,\n };\n\n if (!raw) {\n const tag = element.tagName.toLowerCase();\n const id = element.id ? `#${element.id}` : '';\n console.group(\n `inspect ${tag}${id} — ${tastyClasses.length} classes, ${rules} rules, ${fmtSize(css.length)}`,\n );\n if (chunks.length) {\n console.log(\n 'Chunks:',\n chunks.map((c) => `${c.className}→${c.chunkName || '?'}`).join(', '),\n );\n }\n console.groupCollapsed('CSS');\n console.log(result.css || '(empty)');\n console.groupEnd();\n console.groupEnd();\n }\n\n return result;\n },\n\n summary(opts?: DebugOptions): Summary {\n const { root = defaultRoot(), raw = false } = opts || {};\n if (!root) warnNoDom(raw);\n\n const activeClasses = findDomTastyClasses(root);\n const unusedClasses = getUnusedClasses(root);\n // Everything, not just the two bands above: a class that went cold a\n // moment ago is in neither, and dropping it here is the accounting failure\n // this whole change started from.\n const ownedClasses = getOwnedClasses(root);\n const totalStyledClasses = sortTastyClasses(\n new Set([...activeClasses, ...ownedClasses]),\n );\n const unusedSet = new Set(unusedClasses);\n const activeSet = new Set(activeClasses);\n const hotClasses = ownedClasses.filter(\n (className) => !activeSet.has(className) && !unusedSet.has(className),\n );\n const hotCSS = cssTextForClasses(hotClasses, root);\n\n const activeCSS = cssTextForClasses(activeClasses, root);\n const unusedCSS = cssTextForClasses(unusedClasses, root);\n const allCSS = getAllCSS(root);\n\n const activeRuleCount = countRules(activeCSS);\n const unusedRuleCount = countRules(unusedCSS);\n\n const globalData = getGlobalTypeCSS('global', root, false);\n const rawData = getGlobalTypeCSS('raw', root, false);\n const kfData = getGlobalTypeCSS('keyframes', root, false);\n const propData = getGlobalTypeCSS('property', root, false);\n // Folded into the global line rather than given their own: they are all\n // at-rules injected once and kept forever, and leaving them out of the\n // total is what made it not a total.\n const atRuleData = (\n ['fontFace', 'counterStyle', 'function'] as const\n ).reduce(\n (total, type) => {\n const data = getGlobalTypeCSS(type, root, false);\n total.ruleCount += data.ruleCount;\n total.size += data.size;\n return total;\n },\n { ruleCount: 0, size: 0 },\n );\n\n const hotRuleCount = countRules(hotCSS);\n const globalRuleCount = globalData.ruleCount + atRuleData.ruleCount;\n const globalCSSSize = globalData.size + atRuleData.size;\n\n const totalRuleCount =\n activeRuleCount +\n unusedRuleCount +\n hotRuleCount +\n globalRuleCount +\n rawData.ruleCount +\n kfData.ruleCount +\n propData.ruleCount;\n\n const metrics = getInjectorMetrics(root);\n const defs = getDefs(root);\n const chunkBreakdown = buildChunkBreakdown(root);\n\n const summary: Summary = {\n activeClasses,\n unusedClasses,\n hotClasses,\n totalStyledClasses,\n activeCSSSize: activeCSS.length,\n unusedCSSSize: unusedCSS.length,\n globalCSSSize,\n rawCSSSize: rawData.size,\n keyframesCSSSize: kfData.size,\n propertyCSSSize: propData.size,\n totalCSSSize: allCSS.length,\n activeRuleCount,\n unusedRuleCount,\n globalRuleCount,\n rawRuleCount: rawData.ruleCount,\n keyframesRuleCount: kfData.ruleCount,\n propertyRuleCount: propData.ruleCount,\n totalRuleCount,\n metrics,\n definedProperties: defs.properties,\n definedKeyframes: defs.keyframes,\n chunkBreakdown,\n };\n\n if (!raw) {\n console.group('Tasty Summary');\n console.log(\n `Active: ${activeClasses.length} classes, ${activeRuleCount} rules, ${fmtSize(activeCSS.length)}`,\n );\n console.log(\n `Unused: ${unusedClasses.length} classes, ${unusedRuleCount} rules, ${fmtSize(unusedCSS.length)}`,\n );\n if (hotClasses.length)\n console.log(\n `Held: ${hotClasses.length} classes, ${hotRuleCount} rules, ${fmtSize(hotCSS.length)} (not rendered, not yet collectable)`,\n );\n console.log(\n `Global: ${globalRuleCount} rules, ${fmtSize(globalCSSSize)}`,\n );\n if (rawData.ruleCount)\n console.log(\n `Raw: ${rawData.ruleCount} rules, ${fmtSize(rawData.size)}`,\n );\n if (kfData.ruleCount)\n console.log(\n `Keyframes: ${kfData.ruleCount} rules, ${fmtSize(kfData.size)}`,\n );\n if (propData.ruleCount)\n console.log(\n `@property: ${propData.ruleCount} rules, ${fmtSize(propData.size)}`,\n );\n console.log(\n `Total: ${totalStyledClasses.length} classes, ${totalRuleCount} rules, ${fmtSize(allCSS.length)}`,\n );\n\n if (metrics) {\n const total = metrics.hits + metrics.misses;\n const rate = total > 0 ? ((metrics.hits / total) * 100).toFixed(1) : 0;\n console.log(`Cache: ${rate}% hit rate (${total} lookups)`);\n }\n\n if (chunkBreakdown.totalChunkTypes > 0) {\n console.groupCollapsed(\n `Chunks (${chunkBreakdown.totalChunkTypes} types, ${chunkBreakdown.totalClasses} classes)`,\n );\n logChunkEntries(chunkBreakdown);\n console.groupEnd();\n }\n\n if (defs.properties.length || defs.keyframes.length) {\n console.log(\n `Defs: ${defs.properties.length} @property, ${defs.keyframes.length} @keyframes`,\n );\n }\n\n console.groupEnd();\n }\n\n return summary;\n },\n\n chunks(opts?: DebugOptions): ChunkBreakdown {\n const { root = defaultRoot(), raw = false } = opts || {};\n if (!root) warnNoDom(raw);\n const breakdown = buildChunkBreakdown(root);\n\n if (!raw) {\n console.group(\n `Chunks (${breakdown.totalChunkTypes} types, ${breakdown.totalClasses} classes)`,\n );\n logChunkEntries(breakdown);\n console.groupEnd();\n }\n\n return breakdown;\n },\n\n cache(opts?: DebugOptions): CacheStatus {\n const { root = defaultRoot(), raw = false } = opts || {};\n if (!root) warnNoDom(raw);\n const active = findDomTastyClasses(root);\n const unused = getUnusedClasses(root);\n const metrics = getInjectorMetrics(root);\n\n // `all` is everything held, not the two bands above: a class that went cold\n // a moment ago is in neither, and it is still taking up a sheet.\n const all = sortTastyClasses(\n new Set([...active, ...getOwnedClasses(root)]),\n );\n\n const status: CacheStatus = {\n classes: { active, unused, all },\n metrics,\n };\n\n if (!raw) {\n console.group('Cache');\n console.log(`Active: ${active.length}, Unused: ${unused.length}`);\n if (metrics) {\n const total = metrics.hits + metrics.misses;\n const rate = total > 0 ? ((metrics.hits / total) * 100).toFixed(1) : 0;\n console.log(\n `Hits: ${metrics.hits}, Misses: ${metrics.misses}, Rate: ${rate}%`,\n );\n }\n console.groupEnd();\n }\n\n return status;\n },\n\n cleanup(opts?: { root?: Document | ShadowRoot }): void {\n const root = opts?.root ?? defaultRoot();\n if (!root) return;\n injector.instance.cleanup(root);\n },\n\n help(): void {\n console.log(`tastyDebug API:\n .summary() — overview (classes, rules, sizes)\n .css(\"active\") — CSS for classes in DOM\n .css(\"t3a5f\") — CSS for a specific class\n .css(\"t3a5f\",{source:true}) — original CSS before browser parsing (dev only)\n .css(\".selector\") — CSS for a DOM element\n .inspect(\".selector\") — element details (classes, chunks, rules)\n .chunks() — style chunk breakdown\n .cache() — cache status and metrics\n .cleanup() — force unused style cleanup\nOptions: { raw: true } suppresses logging, { root: shadowRoot } targets Shadow DOM`);\n },\n\n install(): void {\n if (typeof window !== 'undefined' && window.tastyDebug !== tastyDebug) {\n window.tastyDebug = tastyDebug;\n console.log('tastyDebug installed. Run tastyDebug.help() for commands.');\n }\n },\n};\n\n// ---------------------------------------------------------------------------\n// Page CSS (minimal, kept internal)\n// ---------------------------------------------------------------------------\n\nfunction getPageCSS(root: DebugRoot = defaultRoot()): string {\n if (!root) return '';\n const chunks: string[] = [];\n try {\n if ('styleSheets' in root) {\n for (const sheet of Array.from((root as Document).styleSheets)) {\n try {\n if (sheet.cssRules)\n chunks.push(\n Array.from(sheet.cssRules)\n .map((r) => r.cssText)\n .join('\\n'),\n );\n } catch {\n /* cross-origin */\n }\n }\n }\n } catch {\n /* ignore */\n }\n return chunks.join('\\n');\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"debug-B6dZq3uH.js","names":[],"sources":["../../src/debug.ts"],"sourcesContent":["/* eslint-disable no-console */\nimport { CHUNK_NAMES } from './chunks/definitions';\nimport { getNamePrefix } from './config';\nimport { flushStyles, getCSSTextForNode, injector } from './injector';\nimport type { CacheMetrics, RootRegistry } from './injector/types';\nimport { tastyClassRegex } from './utils/name-prefix';\n\ndeclare global {\n interface Window {\n tastyDebug?: typeof tastyDebug;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\ntype CSSTarget =\n 'all' | 'global' | 'active' | 'unused' | 'page' | string | string[] | Element;\n\nexport interface DebugOptions {\n root?: Document | ShadowRoot;\n /** Suppress console logging and return data only (default: false) */\n raw?: boolean;\n}\n\nexport interface CSSOptions extends DebugOptions {\n prettify?: boolean;\n /** Read from stored source CSS (dev-mode only) instead of live CSSOM */\n source?: boolean;\n}\n\nexport interface DebugChunkInfo {\n className: string;\n chunkName: string | null;\n}\n\nexport interface InspectResult {\n element?: Element | null;\n classes: string[];\n chunks: DebugChunkInfo[];\n css: string;\n size: number;\n rules: number;\n}\n\nexport interface CacheStatus {\n classes: {\n active: string[];\n unused: string[];\n all: string[];\n };\n metrics: CacheMetrics | null;\n}\n\nexport interface ChunkBreakdown {\n byChunk: Record<\n string,\n { classes: string[]; cssSize: number; ruleCount: number }\n >;\n totalChunkTypes: number;\n totalClasses: number;\n}\n\nexport interface Summary {\n activeClasses: string[];\n /** Classes `gc({ force: true })` would delete right now. */\n unusedClasses: string[];\n /**\n * Held but in neither list: nothing renders them, yet collection will not\n * take them — inside the grace window, or pinned by an `inject()` handle.\n */\n hotClasses: string[];\n totalStyledClasses: string[];\n\n activeCSSSize: number;\n unusedCSSSize: number;\n globalCSSSize: number;\n rawCSSSize: number;\n keyframesCSSSize: number;\n propertyCSSSize: number;\n totalCSSSize: number;\n\n activeRuleCount: number;\n unusedRuleCount: number;\n globalRuleCount: number;\n rawRuleCount: number;\n keyframesRuleCount: number;\n propertyRuleCount: number;\n totalRuleCount: number;\n\n metrics: CacheMetrics | null;\n definedProperties: string[];\n definedKeyframes: { name: string; refCount: number }[];\n chunkBreakdown: ChunkBreakdown;\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction fmtSize(bytes: number): string {\n return bytes > 1024 ? `${(bytes / 1024).toFixed(1)}KB` : `${bytes}B`;\n}\n\nfunction countRules(css: string): number {\n return (css.match(/\\{[^}]*\\}/g) || []).length;\n}\n\nfunction sortTastyClasses(classes: Iterable<string>): string[] {\n // Class names use a base36 hash format (e.g. `t3a5f`), so sort lexicographically.\n return Array.from(classes).sort((a, b) => a.localeCompare(b));\n}\n\n/** A DOM root to read, or `null` when the environment has no DOM at all. */\ntype DebugRoot = Document | ShadowRoot | null;\n\n/**\n * The root these helpers read, or `null` where there is no DOM.\n *\n * `document` used to be a default parameter value, and a default is evaluated\n * at the call site — so every read below threw a bare `ReferenceError` under\n * Node, taking out five of the eight public methods. A debug utility must not\n * be able to fail an SSR render because a call was left in, so the DOM-less\n * case reports an empty result and says why.\n */\nfunction defaultRoot(): DebugRoot {\n return typeof document === 'undefined' ? null : document;\n}\n\nlet warnedNoDom = false;\n\n/** Say once why the numbers are empty. Silent under `{ raw: true }`. */\nfunction warnNoDom(raw: boolean): void {\n if (raw || warnedNoDom) return;\n warnedNoDom = true;\n console.warn(\n '[Tasty] tastyDebug reads the DOM and this environment has none, so the ' +\n 'result is empty. During SSR, read the ServerStyleCollector instead.',\n );\n}\n\n/**\n * The registry for `root`, with every queued write landed first.\n *\n * Every injector read API is a flush point, and the reads below reach past\n * those APIs straight into the registry and the sheet manager. Without this\n * they would report a batch window's contents as absent — a rule that is\n * enqueued but not yet in a sheet is missing from `globalRules`, from the\n * sheets, and from anything counting either.\n */\nfunction getRegistry(\n root: DebugRoot = defaultRoot(),\n): RootRegistry | undefined {\n if (!root) return undefined;\n flushStyles();\n\n return injector.instance._sheetManager?.getRegistry(root);\n}\n\nfunction findDomTastyClasses(root: DebugRoot = defaultRoot()): string[] {\n if (!root) return [];\n const classes = new Set<string>();\n const elements = (root as Document).querySelectorAll?.('[class]') || [];\n const classRegex = tastyClassRegex(getNamePrefix());\n for (const element of elements) {\n const attribute = element.getAttribute('class');\n if (!attribute) continue;\n for (const className of attribute.split(/\\s+/)) {\n if (classRegex.test(className)) classes.add(className);\n }\n }\n return sortTastyClasses(classes);\n}\n\n/**\n * Everything this injector holds in `root`, in the order the engine applies it,\n * with the sources kept byte-for-byte — trimming would report a total smaller\n * than one of its own parts whenever raw CSS has edge whitespace.\n */\nfunction getAllCSS(root: DebugRoot = defaultRoot()): string {\n const registry = getRegistry(root);\n const sheetManager = injector.instance._sheetManager;\n // `getRegistry` already returns nothing for a null root; the `!root` is what\n // narrows the type for the call below.\n if (!root || !registry || !sheetManager) return '';\n\n return sheetManager.getOwnedCSSInOrder(registry, root).join('\\n');\n}\n\n/**\n * The injector's own readers fall back to `document` when `root` is omitted, so\n * they have to be reached with a real root or not at all.\n */\nfunction cssTextForClasses(classNames: string[], root: DebugRoot): string {\n if (!root) return '';\n\n return injector.instance.getCSSTextForClasses(classNames, { root });\n}\n\nfunction getInjectorMetrics(root: DebugRoot): CacheMetrics | null {\n if (!root) return null;\n\n return injector.instance.getMetrics({ root });\n}\n\n/**\n * Injected classes that no element carries and nobody pinned — the exact set\n * `gc({ force: true })` would delete.\n *\n * Deliberately borrowed from the injector rather than recomputed here: the two\n * drifted apart once before, when this file still read \"unused\" off the pin\n * counts the render path had stopped maintaining.\n */\nfunction getUnusedClasses(root: DebugRoot = defaultRoot()): string[] {\n if (!root) return [];\n\n return sortTastyClasses(injector.instance.getUnusedClasses({ root }));\n}\n\n/** Every class this injector holds CSS for in `root`. */\nfunction getOwnedClasses(root: DebugRoot = defaultRoot()): string[] {\n const registry = getRegistry(root);\n if (!registry) return [];\n\n const owned: string[] = [];\n for (const [className, info] of registry.rules) {\n // A negative sheet index marks a class whose CSS this injector does not\n // hold: server-rendered, pre-allocated, or queued.\n if (info.sheetIndex >= 0) owned.push(className);\n }\n\n return sortTastyClasses(owned);\n}\n\n// ---------------------------------------------------------------------------\n// prettifyCSS — readable output for nested rules\n// ---------------------------------------------------------------------------\n\nfunction prettifyCSS(css: string): string {\n if (!css || !css.trim()) return '';\n\n const out: string[] = [];\n let depth = 0;\n\n const lines = css\n .replace(/\\s+/g, ' ')\n .trim()\n .replaceAll(' {', '{')\n .replaceAll('{', ' {\\n')\n .replaceAll('}', '\\n}\\n')\n .replaceAll(';', ';\\n')\n .split('\\n');\n\n for (let line of lines) {\n line = line.trim();\n if (!line) continue;\n\n if (line === '}') {\n const last = out.at(-1);\n if (last && !/[;{}]$/.test(last)) {\n out[out.length - 1] += ';';\n }\n depth = Math.max(0, depth - 1);\n }\n out.push(`${' '.repeat(depth)}${line}`);\n if (line.endsWith('{')) depth++;\n }\n\n return out.join('\\n');\n}\n\n// ---------------------------------------------------------------------------\n// Chunk helpers\n// ---------------------------------------------------------------------------\n\nfunction extractChunkName(cacheKey: string): string | null {\n for (const part of cacheKey.split('\\0')) {\n if (part.startsWith('[states:')) continue;\n if (!part.includes(':') && part.length > 0) return part;\n }\n return null;\n}\n\nfunction getChunkForClass(\n className: string,\n root: DebugRoot = defaultRoot(),\n): string | null {\n const registry = getRegistry(root);\n if (!registry) return null;\n for (const [key, cn] of registry.cacheKeyToClassName) {\n if (cn === className) return extractChunkName(key);\n }\n return null;\n}\n\nfunction buildChunkBreakdown(root: DebugRoot = defaultRoot()): ChunkBreakdown {\n const registry = getRegistry(root);\n if (!root || !registry)\n return { byChunk: {}, totalChunkTypes: 0, totalClasses: 0 };\n\n const byChunk: ChunkBreakdown['byChunk'] = {};\n for (const [cacheKey, className] of registry.cacheKeyToClassName) {\n const chunk = extractChunkName(cacheKey) || 'unknown';\n const entry = (byChunk[chunk] ??= {\n classes: [],\n cssSize: 0,\n ruleCount: 0,\n });\n entry.classes.push(className);\n const css = cssTextForClasses([className], root);\n entry.cssSize += css.length;\n entry.ruleCount += countRules(css);\n }\n\n const entries = Object.values(byChunk);\n for (const entry of entries) {\n entry.classes = sortTastyClasses(entry.classes);\n }\n\n const totalClasses = entries.reduce((sum, entry) => {\n return sum + entry.classes.length;\n }, 0);\n return {\n byChunk,\n totalChunkTypes: Object.keys(byChunk).length,\n totalClasses,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Global-type CSS helper (internal only)\n// ---------------------------------------------------------------------------\n\n/**\n * Every prefix `registry.globalRules` is keyed by. Anything missing here is a\n * rule the summary would hold but never count, which is how the totals stopped\n * adding up the first time.\n */\nconst GLOBAL_RULE_PREFIXES = {\n global: 'global:',\n property: 'property:',\n fontFace: 'fontface:',\n counterStyle: 'counterstyle:',\n function: 'function:',\n} as const;\n\nfunction getGlobalTypeCSS(\n type: keyof typeof GLOBAL_RULE_PREFIXES | 'raw' | 'keyframes',\n root: DebugRoot = defaultRoot(),\n includeCSS = true,\n): { css: string; ruleCount: number; size: number } {\n const registry = getRegistry(root);\n if (!root || !registry) return { css: '', ruleCount: 0, size: 0 };\n\n const chunks: string[] = [];\n const sheetManager = injector.instance._sheetManager;\n let rc = 0;\n\n if (type === 'raw') {\n // Raw blocks are kept by the sheet manager, not in `globalRules`, so the\n // prefix scan below never sees them — and their rules are counted from the\n // parsed sheet, since one raw block is one string but any number of rules.\n const css = injector.instance.getRawCSSText({ root });\n\n return {\n css: includeCSS ? prettifyCSS(css) : '',\n ruleCount: sheetManager?.getRawRuleCount(root) ?? 0,\n size: css.length,\n };\n }\n\n if (type === 'keyframes') {\n for (const [, entry] of registry.keyframesCache) {\n const info = entry.info;\n const sheetInfo = registry.sheets[info.sheetIndex];\n const ss =\n sheetInfo && sheetManager ? sheetManager.getCSSSheet(sheetInfo) : null;\n if (ss && info.ruleIndex < ss.cssRules.length) {\n const rule = ss.cssRules[info.ruleIndex];\n if (rule) {\n chunks.push(rule.cssText);\n rc++;\n }\n } else if (info.cssText) {\n chunks.push(info.cssText);\n rc++;\n }\n }\n } else {\n const prefix = GLOBAL_RULE_PREFIXES[type];\n for (const [key, ri] of registry.globalRules) {\n if (!key.startsWith(prefix)) continue;\n const sheetInfo = registry.sheets[ri.sheetIndex];\n const ss =\n sheetInfo && sheetManager ? sheetManager.getCSSSheet(sheetInfo) : null;\n if (ss) {\n const start = Math.max(0, ri.ruleIndex);\n const end = Math.min(\n ss.cssRules.length - 1,\n (ri.endRuleIndex as number) ?? ri.ruleIndex,\n );\n if (start >= 0 && end >= start && start < ss.cssRules.length) {\n for (let i = start; i <= end; i++) {\n const rule = ss.cssRules[i];\n if (rule) {\n chunks.push(rule.cssText);\n rc++;\n }\n }\n }\n } else if (ri.cssText?.length) {\n chunks.push(...ri.cssText);\n rc += ri.cssText.length;\n }\n }\n }\n\n const raw = chunks.join('\\n');\n return {\n css: includeCSS ? prettifyCSS(raw) : '',\n ruleCount: rc,\n size: raw.length,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Source CSS (dev-mode RuleInfo.cssText)\n// ---------------------------------------------------------------------------\n\nfunction getSourceCssForClasses(\n classNames: string[],\n root: DebugRoot = defaultRoot(),\n): string | null {\n const registry = getRegistry(root);\n if (!registry) return null;\n\n const chunks: string[] = [];\n let found = false;\n for (const cls of classNames) {\n const info = registry.rules.get(cls);\n if (info?.cssText?.length) {\n chunks.push(...info.cssText);\n found = true;\n }\n }\n return found ? chunks.join('\\n') : null;\n}\n\n// ---------------------------------------------------------------------------\n// Definitions helper (internal)\n// ---------------------------------------------------------------------------\n\nfunction getDefs(root: DebugRoot = defaultRoot()) {\n const registry = getRegistry(root);\n let properties: string[] = [];\n if (registry?.injectedProperties) {\n properties = Array.from(\n (registry.injectedProperties as Map<string, string>).keys(),\n ).sort();\n }\n\n const keyframes: { name: string; refCount: number }[] = [];\n if (registry) {\n for (const entry of registry.keyframesCache.values()) {\n keyframes.push({ name: entry.name, refCount: entry.refCount });\n }\n keyframes.sort((a, b) => a.name.localeCompare(b.name));\n }\n\n return { properties, keyframes };\n}\n\n// ---------------------------------------------------------------------------\n// Chunk display order\n// ---------------------------------------------------------------------------\n\nconst CHUNK_ORDER = [\n CHUNK_NAMES.COMBINED,\n CHUNK_NAMES.APPEARANCE,\n CHUNK_NAMES.FONT,\n CHUNK_NAMES.DIMENSION,\n CHUNK_NAMES.DISPLAY,\n CHUNK_NAMES.LAYOUT,\n CHUNK_NAMES.POSITION,\n CHUNK_NAMES.MISC,\n CHUNK_NAMES.SUBCOMPONENTS,\n];\n\nfunction logChunkEntries(breakdown: ChunkBreakdown): void {\n for (const name of CHUNK_ORDER) {\n const data = breakdown.byChunk[name];\n if (data)\n console.log(\n ` ${name}: ${data.classes.length} cls, ${data.ruleCount} rules, ${fmtSize(data.cssSize)}`,\n );\n }\n for (const [name, data] of Object.entries(breakdown.byChunk)) {\n if (!CHUNK_ORDER.includes(name as (typeof CHUNK_ORDER)[number]))\n console.log(\n ` ${name}: ${data.classes.length} cls, ${data.ruleCount} rules, ${fmtSize(data.cssSize)}`,\n );\n }\n}\n\n// ---------------------------------------------------------------------------\n// tastyDebug API\n// ---------------------------------------------------------------------------\n\nexport const tastyDebug = {\n css(target: CSSTarget, opts?: CSSOptions): string {\n const {\n root = defaultRoot(),\n prettify = true,\n raw = false,\n source = false,\n } = opts || {};\n if (!root) {\n warnNoDom(raw);\n\n return '';\n }\n let css = '';\n\n const classRegex = tastyClassRegex(getNamePrefix());\n if (source && typeof target === 'string' && classRegex.test(target)) {\n const src = getSourceCssForClasses([target], root);\n if (src) {\n css = src;\n } else {\n if (!raw) {\n console.warn(\n '[Tasty] source CSS not available (requires dev mode or TASTY_DEBUG=true). Falling back to live CSSOM.',\n );\n }\n css = cssTextForClasses([target], root);\n }\n } else if (source && Array.isArray(target)) {\n const src = getSourceCssForClasses(target, root);\n if (src) {\n css = src;\n } else {\n if (!raw) {\n console.warn(\n '[Tasty] source CSS not available. Falling back to live CSSOM.',\n );\n }\n css = cssTextForClasses(target, root);\n }\n } else if (typeof target === 'string') {\n if (target === 'all') {\n // Documented as component + global + raw, and raw has its own sheet.\n css = getAllCSS(root);\n } else if (target === 'global') {\n css = getGlobalTypeCSS('global', root).css;\n return css; // already prettified\n } else if (target === 'active') {\n const active = findDomTastyClasses(root);\n css = cssTextForClasses(active, root);\n } else if (target === 'unused') {\n const unused = getUnusedClasses(root);\n css = cssTextForClasses(unused, root);\n } else if (target === 'page') {\n css = getPageCSS(root);\n } else if (classRegex.test(target)) {\n css = cssTextForClasses([target], root);\n } else {\n const el = (root as Document).querySelector?.(target);\n if (el) css = getCSSTextForNode(el, { root });\n }\n } else if (Array.isArray(target)) {\n css = cssTextForClasses(target, root);\n } else if (target instanceof Element) {\n css = getCSSTextForNode(target, { root });\n }\n\n const result = prettify ? prettifyCSS(css) : css;\n\n if (!raw) {\n const label = Array.isArray(target) ? `[${target.join(', ')}]` : target;\n const rc = countRules(css);\n console.group(`CSS for ${label} (${rc} rules, ${fmtSize(css.length)})`);\n console.log(result || '(empty)');\n console.groupEnd();\n }\n\n return result;\n },\n\n inspect(target: string | Element, opts?: DebugOptions): InspectResult {\n const { root = defaultRoot(), raw = false } = opts || {};\n const element = !root\n ? null\n : typeof target === 'string'\n ? (root as Document).querySelector?.(target)\n : target;\n if (!root) warnNoDom(raw);\n\n if (!element) {\n const empty: InspectResult = {\n element: null,\n classes: [],\n chunks: [],\n css: '',\n size: 0,\n rules: 0,\n };\n // With no DOM at all, `warnNoDom` above already said why; \"element not\n // found\" would only misdirect.\n if (!raw && root)\n console.warn('[Tasty] debug.inspect: element not found');\n return empty;\n }\n\n const classList = element.getAttribute('class') || '';\n const classRegex = tastyClassRegex(getNamePrefix());\n const tastyClasses = classList\n .split(/\\s+/)\n .filter((cls) => classRegex.test(cls));\n\n const chunks: DebugChunkInfo[] = tastyClasses.map((className) => ({\n className,\n chunkName: getChunkForClass(className, root),\n }));\n\n const css = getCSSTextForNode(element, { root: root ?? undefined });\n const rules = countRules(css);\n\n const result: InspectResult = {\n element,\n classes: tastyClasses,\n chunks,\n css: prettifyCSS(css),\n size: css.length,\n rules,\n };\n\n if (!raw) {\n const tag = element.tagName.toLowerCase();\n const id = element.id ? `#${element.id}` : '';\n console.group(\n `inspect ${tag}${id} — ${tastyClasses.length} classes, ${rules} rules, ${fmtSize(css.length)}`,\n );\n if (chunks.length) {\n console.log(\n 'Chunks:',\n chunks.map((c) => `${c.className}→${c.chunkName || '?'}`).join(', '),\n );\n }\n console.groupCollapsed('CSS');\n console.log(result.css || '(empty)');\n console.groupEnd();\n console.groupEnd();\n }\n\n return result;\n },\n\n summary(opts?: DebugOptions): Summary {\n const { root = defaultRoot(), raw = false } = opts || {};\n if (!root) warnNoDom(raw);\n\n const activeClasses = findDomTastyClasses(root);\n const unusedClasses = getUnusedClasses(root);\n // Everything, not just the two bands above: a class that went cold a\n // moment ago is in neither, and dropping it here is the accounting failure\n // this whole change started from.\n const ownedClasses = getOwnedClasses(root);\n const totalStyledClasses = sortTastyClasses(\n new Set([...activeClasses, ...ownedClasses]),\n );\n const unusedSet = new Set(unusedClasses);\n const activeSet = new Set(activeClasses);\n const hotClasses = ownedClasses.filter(\n (className) => !activeSet.has(className) && !unusedSet.has(className),\n );\n const hotCSS = cssTextForClasses(hotClasses, root);\n\n const activeCSS = cssTextForClasses(activeClasses, root);\n const unusedCSS = cssTextForClasses(unusedClasses, root);\n const allCSS = getAllCSS(root);\n\n const activeRuleCount = countRules(activeCSS);\n const unusedRuleCount = countRules(unusedCSS);\n\n const globalData = getGlobalTypeCSS('global', root, false);\n const rawData = getGlobalTypeCSS('raw', root, false);\n const kfData = getGlobalTypeCSS('keyframes', root, false);\n const propData = getGlobalTypeCSS('property', root, false);\n // Folded into the global line rather than given their own: they are all\n // at-rules injected once and kept forever, and leaving them out of the\n // total is what made it not a total.\n const atRuleData = (\n ['fontFace', 'counterStyle', 'function'] as const\n ).reduce(\n (total, type) => {\n const data = getGlobalTypeCSS(type, root, false);\n total.ruleCount += data.ruleCount;\n total.size += data.size;\n return total;\n },\n { ruleCount: 0, size: 0 },\n );\n\n const hotRuleCount = countRules(hotCSS);\n const globalRuleCount = globalData.ruleCount + atRuleData.ruleCount;\n const globalCSSSize = globalData.size + atRuleData.size;\n\n const totalRuleCount =\n activeRuleCount +\n unusedRuleCount +\n hotRuleCount +\n globalRuleCount +\n rawData.ruleCount +\n kfData.ruleCount +\n propData.ruleCount;\n\n const metrics = getInjectorMetrics(root);\n const defs = getDefs(root);\n const chunkBreakdown = buildChunkBreakdown(root);\n\n const summary: Summary = {\n activeClasses,\n unusedClasses,\n hotClasses,\n totalStyledClasses,\n activeCSSSize: activeCSS.length,\n unusedCSSSize: unusedCSS.length,\n globalCSSSize,\n rawCSSSize: rawData.size,\n keyframesCSSSize: kfData.size,\n propertyCSSSize: propData.size,\n totalCSSSize: allCSS.length,\n activeRuleCount,\n unusedRuleCount,\n globalRuleCount,\n rawRuleCount: rawData.ruleCount,\n keyframesRuleCount: kfData.ruleCount,\n propertyRuleCount: propData.ruleCount,\n totalRuleCount,\n metrics,\n definedProperties: defs.properties,\n definedKeyframes: defs.keyframes,\n chunkBreakdown,\n };\n\n if (!raw) {\n console.group('Tasty Summary');\n console.log(\n `Active: ${activeClasses.length} classes, ${activeRuleCount} rules, ${fmtSize(activeCSS.length)}`,\n );\n console.log(\n `Unused: ${unusedClasses.length} classes, ${unusedRuleCount} rules, ${fmtSize(unusedCSS.length)}`,\n );\n if (hotClasses.length)\n console.log(\n `Held: ${hotClasses.length} classes, ${hotRuleCount} rules, ${fmtSize(hotCSS.length)} (not rendered, not yet collectable)`,\n );\n console.log(\n `Global: ${globalRuleCount} rules, ${fmtSize(globalCSSSize)}`,\n );\n if (rawData.ruleCount)\n console.log(\n `Raw: ${rawData.ruleCount} rules, ${fmtSize(rawData.size)}`,\n );\n if (kfData.ruleCount)\n console.log(\n `Keyframes: ${kfData.ruleCount} rules, ${fmtSize(kfData.size)}`,\n );\n if (propData.ruleCount)\n console.log(\n `@property: ${propData.ruleCount} rules, ${fmtSize(propData.size)}`,\n );\n console.log(\n `Total: ${totalStyledClasses.length} classes, ${totalRuleCount} rules, ${fmtSize(allCSS.length)}`,\n );\n\n if (metrics) {\n const total = metrics.hits + metrics.misses;\n const rate = total > 0 ? ((metrics.hits / total) * 100).toFixed(1) : 0;\n console.log(`Cache: ${rate}% hit rate (${total} lookups)`);\n }\n\n if (chunkBreakdown.totalChunkTypes > 0) {\n console.groupCollapsed(\n `Chunks (${chunkBreakdown.totalChunkTypes} types, ${chunkBreakdown.totalClasses} classes)`,\n );\n logChunkEntries(chunkBreakdown);\n console.groupEnd();\n }\n\n if (defs.properties.length || defs.keyframes.length) {\n console.log(\n `Defs: ${defs.properties.length} @property, ${defs.keyframes.length} @keyframes`,\n );\n }\n\n console.groupEnd();\n }\n\n return summary;\n },\n\n chunks(opts?: DebugOptions): ChunkBreakdown {\n const { root = defaultRoot(), raw = false } = opts || {};\n if (!root) warnNoDom(raw);\n const breakdown = buildChunkBreakdown(root);\n\n if (!raw) {\n console.group(\n `Chunks (${breakdown.totalChunkTypes} types, ${breakdown.totalClasses} classes)`,\n );\n logChunkEntries(breakdown);\n console.groupEnd();\n }\n\n return breakdown;\n },\n\n cache(opts?: DebugOptions): CacheStatus {\n const { root = defaultRoot(), raw = false } = opts || {};\n if (!root) warnNoDom(raw);\n const active = findDomTastyClasses(root);\n const unused = getUnusedClasses(root);\n const metrics = getInjectorMetrics(root);\n\n // `all` is everything held, not the two bands above: a class that went cold\n // a moment ago is in neither, and it is still taking up a sheet.\n const all = sortTastyClasses(\n new Set([...active, ...getOwnedClasses(root)]),\n );\n\n const status: CacheStatus = {\n classes: { active, unused, all },\n metrics,\n };\n\n if (!raw) {\n console.group('Cache');\n console.log(`Active: ${active.length}, Unused: ${unused.length}`);\n if (metrics) {\n const total = metrics.hits + metrics.misses;\n const rate = total > 0 ? ((metrics.hits / total) * 100).toFixed(1) : 0;\n console.log(\n `Hits: ${metrics.hits}, Misses: ${metrics.misses}, Rate: ${rate}%`,\n );\n }\n console.groupEnd();\n }\n\n return status;\n },\n\n cleanup(opts?: { root?: Document | ShadowRoot }): void {\n const root = opts?.root ?? defaultRoot();\n if (!root) return;\n injector.instance.cleanup(root);\n },\n\n help(): void {\n console.log(`tastyDebug API:\n .summary() — overview (classes, rules, sizes)\n .css(\"active\") — CSS for classes in DOM\n .css(\"t3a5f\") — CSS for a specific class\n .css(\"t3a5f\",{source:true}) — original CSS before browser parsing (dev only)\n .css(\".selector\") — CSS for a DOM element\n .inspect(\".selector\") — element details (classes, chunks, rules)\n .chunks() — style chunk breakdown\n .cache() — cache status and metrics\n .cleanup() — force unused style cleanup\nOptions: { raw: true } suppresses logging, { root: shadowRoot } targets Shadow DOM`);\n },\n\n install(): void {\n if (typeof window !== 'undefined' && window.tastyDebug !== tastyDebug) {\n window.tastyDebug = tastyDebug;\n console.log('tastyDebug installed. Run tastyDebug.help() for commands.');\n }\n },\n};\n\n// ---------------------------------------------------------------------------\n// Page CSS (minimal, kept internal)\n// ---------------------------------------------------------------------------\n\nfunction getPageCSS(root: DebugRoot = defaultRoot()): string {\n if (!root) return '';\n const chunks: string[] = [];\n try {\n if ('styleSheets' in root) {\n for (const sheet of Array.from((root as Document).styleSheets)) {\n try {\n if (sheet.cssRules)\n chunks.push(\n Array.from(sheet.cssRules)\n .map((r) => r.cssText)\n .join('\\n'),\n );\n } catch {\n /* cross-origin */\n }\n }\n }\n } catch {\n /* ignore */\n }\n return chunks.join('\\n');\n}\n"],"mappings":"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"}
|
|
@@ -73,10 +73,10 @@ function normalizeDslName(name) {
|
|
|
73
73
|
const lower = first.toLowerCase();
|
|
74
74
|
return lower === first ? name : lower + name.slice(1);
|
|
75
75
|
}
|
|
76
|
-
const RE_DSL_IDENTIFIER = /(
|
|
76
|
+
const RE_DSL_IDENTIFIER = /(\$\$?|##?|--)([a-zA-Z_][a-zA-Z0-9_-]*)/g;
|
|
77
77
|
function foldDslCase(src) {
|
|
78
78
|
const folded = src.toLowerCase();
|
|
79
|
-
if (folded === src || !src.includes("$") && !src.includes("#")) return folded;
|
|
79
|
+
if (folded === src || !src.includes("$") && !src.includes("#") && !src.includes("--")) return folded;
|
|
80
80
|
RE_DSL_IDENTIFIER.lastIndex = 0;
|
|
81
81
|
let out = "";
|
|
82
82
|
let last = 0;
|
|
@@ -84,7 +84,7 @@ function foldDslCase(src) {
|
|
|
84
84
|
while (match = RE_DSL_IDENTIFIER.exec(src)) {
|
|
85
85
|
const [whole, prefix, body] = match;
|
|
86
86
|
out += src.slice(last, match.index).toLowerCase();
|
|
87
|
-
out += prefix + (prefix[0] === "#" && RE_HEX.test(body.toLowerCase()) ? body.toLowerCase() : normalizeDslName(body));
|
|
87
|
+
out += prefix + (prefix === "--" ? body : prefix[0] === "#" && RE_HEX.test(body.toLowerCase()) ? body.toLowerCase() : normalizeDslName(body));
|
|
88
88
|
last = match.index + whole.length;
|
|
89
89
|
}
|
|
90
90
|
return out + src.slice(last).toLowerCase();
|
|
@@ -379,6 +379,11 @@ function getNamedColorHex() {
|
|
|
379
379
|
for (let i = 0; i < names.length; i++) colors.set(names[i], `#${hex.slice(i * 6, i * 6 + 6)}`);
|
|
380
380
|
return _namedColorHex = colors;
|
|
381
381
|
}
|
|
382
|
+
const SYSTEM_COLORS = new Set("accentcolor accentcolortext activetext buttonborder buttonface buttontext canvas canvastext field fieldtext graytext highlight highlighttext linktext mark marktext selecteditem selecteditemtext visitedtext".split(" "));
|
|
383
|
+
function isColorKeyword(name) {
|
|
384
|
+
const lower = name.toLowerCase();
|
|
385
|
+
return getNamedColorHex().has(lower) || SYSTEM_COLORS.has(lower);
|
|
386
|
+
}
|
|
382
387
|
function hexToRgb(hex) {
|
|
383
388
|
const matched = hex.replace(/^#?([a-f\d])([a-f\d])([a-f\d])$/i, (_m, r, g, b) => "#" + r + r + g + g + b + b).substring(1).match(/.{2}/g);
|
|
384
389
|
if (!matched) return null;
|
|
@@ -458,20 +463,20 @@ function oklchStringToRgb(oklchStr) {
|
|
|
458
463
|
}
|
|
459
464
|
//#endregion
|
|
460
465
|
//#region src/utils/color-space.ts
|
|
461
|
-
function overrideColorAlpha(color, alpha) {
|
|
462
|
-
return `oklch(from ${color} l c h / ${alpha})`;
|
|
463
|
-
}
|
|
464
466
|
function mixColorAlpha(color, percentage) {
|
|
465
467
|
return `color-mix(in oklab, ${color} ${percentage}, transparent)`;
|
|
466
468
|
}
|
|
467
|
-
const
|
|
468
|
-
function
|
|
469
|
-
const match = value.match(
|
|
469
|
+
const RE_ALPHA_MIX = /^color-mix\(in oklab,\s*(.+) (\S+%|calc\(.+ \* 100%\)),\s*transparent\)$/;
|
|
470
|
+
function parseAlphaMix(value) {
|
|
471
|
+
const match = value.match(RE_ALPHA_MIX);
|
|
470
472
|
return match ? {
|
|
471
473
|
color: match[1],
|
|
472
|
-
|
|
474
|
+
percentage: match[2]
|
|
473
475
|
} : null;
|
|
474
476
|
}
|
|
477
|
+
function alphaToPercentage(alpha) {
|
|
478
|
+
return `${Number(((Number.isNaN(alpha) ? 1 : Math.min(1, Math.max(0, alpha))) * 100).toFixed(6))}%`;
|
|
479
|
+
}
|
|
475
480
|
//#endregion
|
|
476
481
|
//#region src/parser/types.ts
|
|
477
482
|
const makeEmptyPart = () => ({
|
|
@@ -492,28 +497,22 @@ const makeEmptyDetails = () => ({
|
|
|
492
497
|
});
|
|
493
498
|
//#endregion
|
|
494
499
|
//#region src/parser/classify.ts
|
|
495
|
-
function alphaSuffixToAlpha(rawAlpha) {
|
|
496
|
-
if (rawAlpha.startsWith("$")) return `var(--${rawAlpha.slice(1)})`;
|
|
497
|
-
if (rawAlpha === "0") return "0";
|
|
498
|
-
return `.${rawAlpha}`;
|
|
499
|
-
}
|
|
500
|
-
function fadeColor(color, rawAlpha) {
|
|
501
|
-
return overrideColorAlpha(color, alphaSuffixToAlpha(rawAlpha));
|
|
502
|
-
}
|
|
503
500
|
function alphaSuffixToPercentage(rawAlpha) {
|
|
504
501
|
if (rawAlpha.startsWith("$")) return `calc(var(--${rawAlpha.slice(1)}) * 100%)`;
|
|
505
502
|
if (rawAlpha === "0") return "0%";
|
|
506
503
|
const digits = rawAlpha.length === 1 ? `${rawAlpha}0` : rawAlpha;
|
|
507
504
|
const whole = String(Number(digits.slice(0, 2)));
|
|
508
|
-
const fraction = digits.slice(2);
|
|
505
|
+
const fraction = digits.slice(2).replace(/0+$/, "");
|
|
509
506
|
return `${fraction ? `${whole}.${fraction}` : whole}%`;
|
|
510
507
|
}
|
|
511
|
-
function
|
|
512
|
-
return mixColorAlpha(
|
|
508
|
+
function fadeColor(color, rawAlpha) {
|
|
509
|
+
return mixColorAlpha(color, alphaSuffixToPercentage(rawAlpha));
|
|
513
510
|
}
|
|
514
511
|
function hasColorArgs(parsed) {
|
|
515
|
-
|
|
516
|
-
|
|
512
|
+
return parsed.groups.some((group) => group.colors.length > 0);
|
|
513
|
+
}
|
|
514
|
+
function isSingleColor(group) {
|
|
515
|
+
return !!group && group.all.length === 1 && group.colors.length === 1;
|
|
517
516
|
}
|
|
518
517
|
function resolveUntilStable(value, opts, recurse, maxIterations = 10) {
|
|
519
518
|
let current = value;
|
|
@@ -614,7 +613,7 @@ function classify(raw, opts, recurse) {
|
|
|
614
613
|
const currentAlphaMatch = token.match(/^#current\.(\$[a-z_][a-z0-9-_]*|[0-9]+)$/i);
|
|
615
614
|
if (currentAlphaMatch) return {
|
|
616
615
|
bucket: 0,
|
|
617
|
-
processed:
|
|
616
|
+
processed: fadeColor("currentcolor", currentAlphaMatch[1])
|
|
618
617
|
};
|
|
619
618
|
if (token[0] === "$" || token[0] === "#") {
|
|
620
619
|
const predefinedTokens = getGlobalPredefinedTokens();
|
|
@@ -702,6 +701,11 @@ function classify(raw, opts, recurse) {
|
|
|
702
701
|
processed: constructed
|
|
703
702
|
};
|
|
704
703
|
}
|
|
704
|
+
const keyword = resolvedValue.trim().toLowerCase();
|
|
705
|
+
if (keyword === "currentcolor" || isColorKeyword(keyword)) return {
|
|
706
|
+
bucket: 0,
|
|
707
|
+
processed: fadeColor(keyword, rawAlpha)
|
|
708
|
+
};
|
|
705
709
|
return classify(`${resolvedValue}.${rawAlpha}`, opts, recurse);
|
|
706
710
|
}
|
|
707
711
|
}
|
|
@@ -766,10 +770,10 @@ function classify(raw, opts, recurse) {
|
|
|
766
770
|
functions: void 0
|
|
767
771
|
}, recurse);
|
|
768
772
|
}
|
|
769
|
-
const
|
|
773
|
+
const parsedInner = recurse(inner);
|
|
770
774
|
return {
|
|
771
|
-
bucket: 1,
|
|
772
|
-
processed: `${canonicalFuncName(fname)}(${
|
|
775
|
+
bucket: fname === "var" && parsedInner.groups.length === 2 && isSingleColor(parsedInner.groups[1]) ? 0 : 1,
|
|
776
|
+
processed: `${canonicalFuncName(fname)}(${parsedInner.output})`
|
|
773
777
|
};
|
|
774
778
|
}
|
|
775
779
|
if (token.startsWith("(") && token.endsWith(")")) {
|
|
@@ -786,10 +790,10 @@ function classify(raw, opts, recurse) {
|
|
|
786
790
|
const match = token.slice(1, -1).match(/^\$([a-z_][a-zA-Z0-9-_]*)\s*,\s*(.*)$/);
|
|
787
791
|
if (match) {
|
|
788
792
|
const [, name, fallback] = match;
|
|
789
|
-
const
|
|
793
|
+
const parsedFallback = recurse(fallback);
|
|
790
794
|
return {
|
|
791
|
-
bucket: name.endsWith("-color") ? 3 : 1,
|
|
792
|
-
processed: `var(--${name}, ${
|
|
795
|
+
bucket: name.endsWith("-color") ? 3 : parsedFallback.groups.length === 1 && isSingleColor(parsedFallback.groups[0]) ? 0 : 1,
|
|
796
|
+
processed: `var(--${name}, ${parsedFallback.output})`
|
|
793
797
|
};
|
|
794
798
|
}
|
|
795
799
|
}
|
|
@@ -839,7 +843,7 @@ function classify(raw, opts, recurse) {
|
|
|
839
843
|
bucket: 1,
|
|
840
844
|
processed: token
|
|
841
845
|
};
|
|
842
|
-
if (token === "transparent" || token === "currentcolor") return {
|
|
846
|
+
if (token === "transparent" || token === "currentcolor" || isColorKeyword(token)) return {
|
|
843
847
|
bucket: 0,
|
|
844
848
|
processed: token
|
|
845
849
|
};
|
|
@@ -1194,7 +1198,7 @@ function isSimpleColorFast(val) {
|
|
|
1194
1198
|
break;
|
|
1195
1199
|
case 116: if (val === "transparent") return true;
|
|
1196
1200
|
}
|
|
1197
|
-
return
|
|
1201
|
+
return isColorKeyword(val);
|
|
1198
1202
|
}
|
|
1199
1203
|
let colorWarningCount = 0;
|
|
1200
1204
|
const MAX_COLOR_WARNINGS = 10;
|
|
@@ -1296,14 +1300,13 @@ function parseColor(val, ignoreError = false) {
|
|
|
1296
1300
|
}
|
|
1297
1301
|
firstColor = extractedColor;
|
|
1298
1302
|
}
|
|
1299
|
-
const faded =
|
|
1303
|
+
const faded = parseAlphaMix(firstColor);
|
|
1300
1304
|
const baseColor = faded ? faded.color : firstColor;
|
|
1301
1305
|
const nameMatch = baseColor.match(COLOR_VAR_PATTERN);
|
|
1302
1306
|
let opacity;
|
|
1303
1307
|
if (faded) {
|
|
1304
|
-
const
|
|
1305
|
-
|
|
1306
|
-
if (!isNaN(v)) opacity = alpha.endsWith("%") ? v : v * 100;
|
|
1308
|
+
const v = parseFloat(faded.percentage);
|
|
1309
|
+
if (!isNaN(v)) opacity = v;
|
|
1307
1310
|
} else if (baseColor.startsWith("rgb") || baseColor.startsWith("hsl") || baseColor.startsWith("lch") || baseColor.startsWith("oklch")) {
|
|
1308
1311
|
const alphaMatch = baseColor.match(RGB_ALPHA_PATTERN);
|
|
1309
1312
|
if (alphaMatch) {
|
|
@@ -1374,10 +1377,10 @@ function resolveFunctionColor(str) {
|
|
|
1374
1377
|
//#endregion
|
|
1375
1378
|
//#region src/utils/colors.ts
|
|
1376
1379
|
function color(name, opacity = 1) {
|
|
1377
|
-
if (opacity !== 1) return
|
|
1380
|
+
if (opacity !== 1) return mixColorAlpha(`var(--${name}-color)`, alphaToPercentage(opacity));
|
|
1378
1381
|
return `var(--${name}-color)`;
|
|
1379
1382
|
}
|
|
1380
1383
|
//#endregion
|
|
1381
|
-
export {
|
|
1384
|
+
export { isColorKeyword as A, StyleParser as C, getRgbValuesFromRgbaString as D, getNamedColorHex as E, RE_NUMBER as F, RE_RAW_UNIT as I, normalizeDslName as M, toSnakeCase as N, hexToRgb as O, CSS_WIDE_KEYWORDS as P, createColorFunc as S, makeEmptyDetails as T, stringifyStyles as _, customFunction as a, okhslFunction as b, getGlobalParser as c, parseColor as d, parseStyle as f, setGlobalPredefinedTokens as g, resolveCustomProperties as h, DIRECTIONS as i, strToRgb as j, hslToRgbValues as k, getGlobalPredefinedTokens as l, resetGlobalPredefinedTokens as m, resolveFunctionColor as n, filterMods as o, resetGlobalParseFunctions as p, CUSTOM_UNITS as r, getGlobalParseFunctions as s, color as t, normalizeColorTokenValue as u, okhstFunction as v, Lru as w, okhslPlugin as x, okhstPlugin as y };
|
|
1382
1385
|
|
|
1383
|
-
//# sourceMappingURL=dsl-
|
|
1386
|
+
//# sourceMappingURL=dsl-rgu6XQcD.js.map
|