@lgtm-hq/turbo-themes 0.19.2 → 0.20.1
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/dist/tokens/style-dictionary/themes.json +2 -2
- package/dist/tokens/style-dictionary/tokens.json +2 -2
- package/package.json +23 -3
- package/packages/core/dist/themes/css/helpers.d.ts.map +1 -1
- package/packages/core/dist/themes/css/helpers.js +1 -0
- package/packages/core/dist/themes/css/helpers.js.map +1 -1
- package/packages/core/dist/themes/tokens.json +2 -2
- package/packages/css/dist/index.js.map +1 -1
- package/packages/theme-selector/dist/index.js.map +1 -1
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://design-tokens.org/schema.json",
|
|
3
3
|
"$description": "Turbo Themes - Design tokens for 24 themes",
|
|
4
|
-
"$version": "0.
|
|
5
|
-
"$generated": "
|
|
4
|
+
"$version": "0.20.1",
|
|
5
|
+
"$generated": "a9b477ad41d846af684affc86ff9b2874c916a5ac5d6619678d543587d57aaa6",
|
|
6
6
|
"meta": {
|
|
7
7
|
"themeIds": [
|
|
8
8
|
"bulma-dark",
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://design-tokens.org/schema.json",
|
|
3
3
|
"$description": "Turbo Themes - Flat tokens for 24 themes",
|
|
4
|
-
"$version": "0.
|
|
5
|
-
"$generated": "
|
|
4
|
+
"$version": "0.20.1",
|
|
5
|
+
"$generated": "ec1adee158df7ea7949c69d4cb89cc468259b639817f43eb916c2b712d57baa6",
|
|
6
6
|
"meta": {
|
|
7
7
|
"themeIds": [
|
|
8
8
|
"bulma-dark",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lgtm-hq/turbo-themes",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.20.1",
|
|
4
4
|
"description": "Universal theme packs and an accessible theme selector.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -160,16 +160,18 @@
|
|
|
160
160
|
"@types/react": "19.2.10",
|
|
161
161
|
"@types/react-dom": "19.2.3",
|
|
162
162
|
"@vitest/coverage-v8": "4.0.18",
|
|
163
|
-
"ajv": "8.
|
|
163
|
+
"ajv": "8.18.0",
|
|
164
164
|
"ajv-formats": "3.0.1",
|
|
165
165
|
"bulma": "1.0.4",
|
|
166
166
|
"concurrently": "9.2.1",
|
|
167
167
|
"cssnano": "7.1.2",
|
|
168
|
-
"happy-dom": "20.
|
|
168
|
+
"happy-dom": "20.8.9",
|
|
169
169
|
"http-server": "14.1.1",
|
|
170
170
|
"husky": "9.1.7",
|
|
171
171
|
"lightningcss": "1.31.1",
|
|
172
172
|
"lint-staged": "16.2.7",
|
|
173
|
+
"oxfmt": "0.42.0",
|
|
174
|
+
"oxlint": "1.57.0",
|
|
173
175
|
"react": "19.2.4",
|
|
174
176
|
"react-dom": "19.2.4",
|
|
175
177
|
"sass": "1.97.3",
|
|
@@ -180,5 +182,23 @@
|
|
|
180
182
|
"vite": "7.3.1",
|
|
181
183
|
"vite-plugin-dts": "4.5.4",
|
|
182
184
|
"vitest": "4.0.18"
|
|
185
|
+
},
|
|
186
|
+
"overrides": {
|
|
187
|
+
"ajv": "8.18.0",
|
|
188
|
+
"devalue": "5.6.4",
|
|
189
|
+
"flatted": "3.4.2",
|
|
190
|
+
"picomatch": "4.0.4",
|
|
191
|
+
"yaml": "2.8.3",
|
|
192
|
+
"qs": "6.15.0",
|
|
193
|
+
"basic-ftp": "5.2.0",
|
|
194
|
+
"smol-toml": "1.6.1",
|
|
195
|
+
"path-to-regexp": "8.4.0",
|
|
196
|
+
"@isaacs/brace-expansion": "5.0.1",
|
|
197
|
+
"minimatch": "10.2.4",
|
|
198
|
+
"brace-expansion": "5.0.5",
|
|
199
|
+
"h3": "2.0.0",
|
|
200
|
+
"tmp": "0.2.5",
|
|
201
|
+
"esbuild": "0.27.4",
|
|
202
|
+
"happy-dom": "20.8.9"
|
|
183
203
|
}
|
|
184
204
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../../src/themes/css/helpers.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,KAAK,EACV,kBAAkB,EAClB,kBAAkB,EAClB,eAAe,EACf,qBAAqB,EACtB,MAAM,YAAY,CAAC;AAEpB;;GAEG;AACH,UAAU,mBAAmB;IAC3B,qEAAqE;IACrE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,iDAAiD;IACjD,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAsBD;;;GAGG;AACH,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,WAAW,EACnB,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE,mBAAmB,GAC5B,MAAM,GAAG,SAAS,CAqBpB;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAEnF;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,WAAW,EACnB,aAAa,EAAE,MAAM,EACrB,YAAY,EAAE,MAAM,GACnB,MAAM,CAQR;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAGlD;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,
|
|
1
|
+
{"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../../src/themes/css/helpers.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,KAAK,EACV,kBAAkB,EAClB,kBAAkB,EAClB,eAAe,EACf,qBAAqB,EACtB,MAAM,YAAY,CAAC;AAEpB;;GAEG;AACH,UAAU,mBAAmB;IAC3B,qEAAqE;IACrE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,iDAAiD;IACjD,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAsBD;;;GAGG;AACH,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,WAAW,EACnB,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE,mBAAmB,GAC5B,MAAM,GAAG,SAAS,CAqBpB;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAEnF;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,WAAW,EACnB,aAAa,EAAE,MAAM,EACrB,YAAY,EAAE,MAAM,GACnB,MAAM,CAQR;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAGlD;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAW9C;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CA4BlE;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,WAAW,EAAE,QAAQ,EAAE,kBAAkB,EAAE,GAAG,MAAM,EAAE,CAQ/F;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,WAAW,EAAE,OAAO,EAAE,kBAAkB,GAAG,MAAM,EAAE,CAUhG;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,WAAW,EAAE,QAAQ,EAAE,eAAe,EAAE,GAAG,MAAM,EAAE,CAM5F;AAED;;GAEG;AACH,wBAAgB,0BAA0B,CACxC,MAAM,EAAE,WAAW,EACnB,QAAQ,EAAE,qBAAqB,EAAE,GAChC,MAAM,EAAE,CA0BV"}
|
|
@@ -73,6 +73,7 @@ export function escapeCssId(id) {
|
|
|
73
73
|
return CSS.escape(id);
|
|
74
74
|
}
|
|
75
75
|
// Fallback: escape per CSSOM spec (simplified for valid identifier chars)
|
|
76
|
+
// oxlint-disable-next-line no-control-regex -- intentionally matching control characters
|
|
76
77
|
return id.replace(/[\0-\x1f\x7f]|^-?[0-9]|[^a-zA-Z0-9_-]/g, (char) => {
|
|
77
78
|
if (char === '\0')
|
|
78
79
|
return '\uFFFD';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"helpers.js","sourceRoot":"","sources":["../../../src/themes/css/helpers.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"helpers.js","sourceRoot":"","sources":["../../../src/themes/css/helpers.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://design-tokens.org/schema.json",
|
|
3
3
|
"$description": "Turbo Themes - Flat tokens for 24 themes",
|
|
4
|
-
"$version": "0.
|
|
5
|
-
"$generated": "
|
|
4
|
+
"$version": "0.20.1",
|
|
5
|
+
"$generated": "ec1adee158df7ea7949c69d4cb89cc468259b639817f43eb916c2b712d57baa6",
|
|
6
6
|
"meta": {
|
|
7
7
|
"themeIds": [
|
|
8
8
|
"bulma-dark",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../src/syntax.ts","../../core/dist/themes/css/mappings.js","../src/generator.ts","../src/base.ts"],"sourcesContent":["// SPDX-License-Identifier: MIT\n/**\n * Syntax highlighting styles for Turbo Themes.\n *\n * Provides CSS for code syntax highlighting that uses Turbo theme variables.\n * Compatible with Rouge (Jekyll), Prism, highlight.js, and other highlighters.\n *\n * @packageDocumentation\n */\n\nimport type { ThemeFlavor, ThemeTokens } from '@lgtm-hq/turbo-themes-core';\nimport { CSS_VAR_PREFIX } from './generator.js';\n\n/**\n * Syntax highlighting token types and their CSS class mappings.\n * These cover the common classes used by most syntax highlighters.\n */\nconst SYNTAX_CLASS_GROUPS = {\n // Comments\n comment: ['.c', '.cm', '.c1', '.cs', '.cp', '.cpf'],\n // Keywords (control flow, declarations)\n keyword: ['.k', '.kc', '.kd', '.kn', '.kp', '.kr', '.kt', '.kv'],\n // Strings\n string: ['.s', '.s1', '.s2', '.sb', '.sc', '.sd', '.se', '.sh', '.si', '.sr', '.ss', '.sx'],\n // Numbers\n number: ['.m', '.mi', '.mf', '.mh', '.mo', '.mb', '.mx', '.il'],\n // Functions and methods\n function: ['.nf', '.fm', '.nb'],\n // Classes and types\n type: ['.nc', '.nn', '.no', '.nd'],\n // Variables and identifiers\n variable: ['.n', '.na', '.nv', '.vc', '.vg', '.vi', '.vm'],\n // Operators\n operator: ['.o', '.ow'],\n // Punctuation\n punctuation: ['.p'],\n // HTML/XML tags\n tag: ['.nt', '.nx'],\n // Attributes\n attribute: ['.na', '.atn'],\n // Values (attribute values, etc.)\n value: ['.atv'],\n // Errors\n error: ['.err', '.gr'],\n // Deletions (diffs)\n deleted: ['.gd'],\n // Insertions (diffs)\n inserted: ['.gi'],\n} as const;\n\n/**\n * Generates CSS variable declarations for syntax highlighting.\n */\nexport function generateSyntaxVarsFromTokens(tokens: ThemeTokens): string[] {\n const lines: string[] = [];\n const add = (name: string, value: string): void => {\n lines.push(` --${CSS_VAR_PREFIX}-syntax-${name}: ${value};`);\n };\n\n // Map theme tokens to syntax colors\n add('fg', tokens.content?.codeBlock?.fg ?? tokens.text.primary);\n add('bg', tokens.content?.codeBlock?.bg ?? tokens.background.surface);\n add('comment', tokens.text.secondary);\n add('keyword', tokens.brand.primary);\n add('string', tokens.state.success);\n add('number', tokens.state.warning);\n add('function', tokens.state.info);\n add('type', tokens.brand.primary);\n add('variable', tokens.text.primary);\n add('operator', tokens.text.secondary);\n add('punctuation', tokens.text.secondary);\n add('tag', tokens.state.danger);\n add('attribute', tokens.state.info);\n add('value', tokens.state.success);\n add('error', tokens.state.danger);\n add('deleted', tokens.state.danger);\n add('inserted', tokens.state.success);\n\n return lines;\n}\n\n/**\n * CSS styles for syntax highlighting using Turbo variables.\n * Works with Rouge, Prism, highlight.js, and similar highlighters.\n */\nexport const CSS_SYNTAX = `/* Turbo Themes - Syntax Highlighting */\n\n/* Astro Code component css-variables theme mapping */\n:root {\n --astro-code-color-text: var(--turbo-syntax-fg, var(--turbo-text-primary));\n --astro-code-color-background: var(--turbo-syntax-bg, var(--turbo-code-block-bg));\n --astro-code-token-constant: var(--turbo-syntax-number);\n --astro-code-token-string: var(--turbo-syntax-string);\n --astro-code-token-comment: var(--turbo-syntax-comment);\n --astro-code-token-keyword: var(--turbo-syntax-keyword);\n --astro-code-token-parameter: var(--turbo-syntax-variable);\n --astro-code-token-function: var(--turbo-syntax-function);\n --astro-code-token-string-expression: var(--turbo-syntax-string);\n --astro-code-token-punctuation: var(--turbo-syntax-punctuation);\n --astro-code-token-link: var(--turbo-accent-link, var(--turbo-brand-primary));\n /* Additional Astro tokens */\n --astro-code-background: var(--turbo-syntax-bg, var(--turbo-code-block-bg));\n --astro-code-foreground: var(--turbo-syntax-fg, var(--turbo-text-primary));\n}\n\n/* Astro Code component styling */\n.astro-code,\npre.astro-code {\n background-color: var(--turbo-syntax-bg, var(--turbo-code-block-bg)) !important;\n padding: var(--space-lg);\n border-radius: var(--radius-lg);\n overflow-x: auto;\n border: 1px solid var(--turbo-border-default);\n}\n\n.astro-code code {\n background-color: transparent !important;\n color: inherit;\n}\n\n/* Base highlight container - only applies to pre elements */\n.highlight,\npre.highlight,\npre[class*=\"language-\"] {\n background-color: var(--turbo-syntax-bg, var(--turbo-code-block-bg));\n color: var(--turbo-syntax-fg, var(--turbo-code-block-fg));\n}\n\n/* Code inside pre should have transparent background */\n.highlight pre,\n.highlight code,\npre code,\npre code[class*=\"language-\"] {\n background-color: transparent;\n color: inherit;\n}\n\n/* Comments */\n.highlight .c,\n.highlight .cm,\n.highlight .c1,\n.highlight .cs,\n.highlight .cp,\n.highlight .cpf,\n.token.comment,\n.token.prolog,\n.token.doctype,\n.token.cdata,\n.hljs-comment,\n.hljs-quote {\n color: var(--turbo-syntax-comment);\n font-style: italic;\n}\n\n/* Keywords */\n.highlight .k,\n.highlight .kc,\n.highlight .kd,\n.highlight .kn,\n.highlight .kp,\n.highlight .kr,\n.highlight .kt,\n.highlight .kv,\n.token.keyword,\n.token.atrule,\n.token.important,\n.hljs-keyword,\n.hljs-selector-tag,\n.hljs-built_in,\n.hljs-type {\n color: var(--turbo-syntax-keyword);\n}\n\n/* Strings */\n.highlight .s,\n.highlight .s1,\n.highlight .s2,\n.highlight .sb,\n.highlight .sc,\n.highlight .sd,\n.highlight .se,\n.highlight .sh,\n.highlight .si,\n.highlight .sr,\n.highlight .ss,\n.highlight .sx,\n.token.string,\n.token.char,\n.token.regex,\n.token.template-string,\n.hljs-string,\n.hljs-regexp {\n color: var(--turbo-syntax-string);\n}\n\n/* Numbers */\n.highlight .m,\n.highlight .mi,\n.highlight .mf,\n.highlight .mh,\n.highlight .mo,\n.highlight .mb,\n.highlight .mx,\n.highlight .il,\n.token.number,\n.token.boolean,\n.token.constant,\n.hljs-number,\n.hljs-literal {\n color: var(--turbo-syntax-number);\n}\n\n/* Functions */\n.highlight .nf,\n.highlight .fm,\n.highlight .nb,\n.token.function,\n.token.builtin,\n.hljs-title.function_,\n.hljs-built_in {\n color: var(--turbo-syntax-function);\n}\n\n/* Classes and types */\n.highlight .nc,\n.highlight .nn,\n.highlight .no,\n.highlight .nd,\n.token.class-name,\n.token.namespace,\n.hljs-title.class_,\n.hljs-class .hljs-title {\n color: var(--turbo-syntax-type);\n}\n\n/* Variables and identifiers */\n.highlight .n,\n.highlight .nv,\n.highlight .vc,\n.highlight .vg,\n.highlight .vi,\n.highlight .vm,\n.token.variable,\n.hljs-variable,\n.hljs-template-variable {\n color: var(--turbo-syntax-variable);\n}\n\n/* Operators */\n.highlight .o,\n.highlight .ow,\n.token.operator,\n.hljs-operator {\n color: var(--turbo-syntax-operator);\n}\n\n/* Punctuation */\n.highlight .p,\n.token.punctuation,\n.hljs-punctuation {\n color: var(--turbo-syntax-punctuation);\n}\n\n/* HTML/XML tags */\n.highlight .nt,\n.highlight .nx,\n.token.tag,\n.hljs-tag,\n.hljs-name {\n color: var(--turbo-syntax-tag);\n}\n\n/* Attributes */\n.highlight .na,\n.highlight .atn,\n.token.attr-name,\n.hljs-attr {\n color: var(--turbo-syntax-attribute);\n}\n\n/* Attribute values */\n.highlight .atv,\n.token.attr-value,\n.hljs-attr .hljs-string {\n color: var(--turbo-syntax-value);\n}\n\n/* Errors */\n.highlight .err,\n.highlight .gr,\n.token.error,\n.hljs-error {\n color: var(--turbo-syntax-error);\n}\n\n/* Diff: deletions */\n.highlight .gd,\n.token.deleted,\n.hljs-deletion {\n color: var(--turbo-syntax-deleted);\n background-color: color-mix(in srgb, var(--turbo-syntax-deleted) 15%, transparent);\n}\n\n/* Diff: insertions */\n.highlight .gi,\n.token.inserted,\n.hljs-addition {\n color: var(--turbo-syntax-inserted);\n background-color: color-mix(in srgb, var(--turbo-syntax-inserted) 15%, transparent);\n}\n\n/* Line numbers (if used) */\n.highlight .lineno,\n.line-numbers .line-numbers-rows,\n.hljs-ln-numbers {\n color: var(--turbo-text-secondary);\n opacity: 0.5;\n user-select: none;\n}\n\n/* Selection within code */\n.highlight ::selection,\npre[class*=\"language-\"] ::selection,\ncode[class*=\"language-\"] ::selection {\n background-color: var(--turbo-selection-bg);\n color: var(--turbo-selection-fg);\n}\n`;\n\n/**\n * Generates syntax highlighting CSS for a specific theme.\n * This includes both the variable definitions and the styling rules.\n */\nexport function generateSyntaxCss(flavor: ThemeFlavor): string {\n const vars = generateSyntaxVarsFromTokens(flavor.tokens);\n\n return `/* Turbo Themes - Syntax Highlighting for ${flavor.label} */\n[data-theme=\"${flavor.id}\"] {\n${vars.join('\\n')}\n}\n`;\n}\n\n/**\n * Generates the complete syntax highlighting CSS file.\n * Includes base styles that work with any theme.\n */\nexport function generateSyntaxBaseCss(): string {\n return CSS_SYNTAX;\n}\n","// SPDX-License-Identifier: MIT\n// CSS Variable Mappings - Generated from config/token-mappings.json\n// This file reads from the single source of truth configuration\n// Import the centralized mapping configuration\n// Note: Using require for JSON import compatibility\nimport mappingConfig from '../../../../../config/token-mappings.json' with { type: 'json' };\n// Convert config entries to typed mappings\nfunction toVariableMapping(entry) {\n return {\n cssVar: entry.cssVar,\n tokenPath: entry.tokenPath,\n ...(entry.fallback ? { fallbackPath: entry.fallback } : {}),\n };\n}\nfunction toComponentMapping(entry) {\n return {\n cssVar: entry.cssVar,\n componentPath: entry.componentPath,\n fallbackPath: entry.fallback,\n };\n}\nfunction toHSLMapping(entry) {\n return {\n hVar: entry.hVar,\n sVar: entry.sVar,\n lVar: entry.lVar,\n tokenPath: entry.tokenPath,\n };\n}\nfunction toHSLColorMapping(entry) {\n return {\n cssVar: entry.cssVar,\n tokenPath: entry.tokenPath,\n };\n}\n// =============================================================================\n// Bulma Framework Mappings\n// =============================================================================\n/** Bulma scheme variables */\nexport const BULMA_SCHEME_MAPPINGS = mappingConfig.bulma.schemeMappings.map(toVariableMapping);\n/** Primary color HSL components */\nexport const PRIMARY_HSL_MAPPING = toHSLMapping(mappingConfig.bulma.primaryHsl);\n/** State colors as HSL */\nexport const STATE_HSL_MAPPINGS = mappingConfig.bulma.stateHslMappings.map(toHSLColorMapping);\n// =============================================================================\n// Theme Variable Mappings\n// =============================================================================\n/** Text variables */\nexport const TEXT_MAPPINGS = mappingConfig.theme.textMappings.map(toVariableMapping);\n/** Heading variables */\nexport const HEADING_MAPPINGS = mappingConfig.theme.headingMappings.map(toVariableMapping);\n/** Content element variables */\nexport const CONTENT_MAPPINGS = mappingConfig.theme.contentMappings.map(toVariableMapping);\n/** Table variables */\nexport const TABLE_MAPPINGS = mappingConfig.theme.tableMappings.map(toVariableMapping);\n/** Syntax highlighting variables */\nexport const SYNTAX_MAPPINGS = mappingConfig.theme.syntaxMappings.map(toVariableMapping);\n/** Surface/background variables */\nexport const SURFACE_MAPPINGS = mappingConfig.theme.surfaceMappings.map(toVariableMapping);\n// =============================================================================\n// Component Token Mappings\n// =============================================================================\n/** Component token mappings (optional, with fallbacks) */\nexport const COMPONENT_MAPPINGS = mappingConfig.components.map(toComponentMapping);\n// =============================================================================\n// Syntax Highlighting CSS Classes\n// =============================================================================\n/** Syntax highlighting CSS class mappings */\nexport const SYNTAX_CLASS_GROUPS = mappingConfig.syntaxClassGroups;\n// =============================================================================\n// Core Mappings (for generator.ts and Python)\n// =============================================================================\n/** Core token mappings used by CSS generator */\nexport const CORE_MAPPINGS = mappingConfig.coreMappings.map(toVariableMapping);\n/** CSS variable prefix */\nexport const CSS_VAR_PREFIX = mappingConfig.prefix;\n/** Optional group configurations */\nexport const OPTIONAL_GROUPS = mappingConfig.optionalGroups;\n//# sourceMappingURL=mappings.js.map","// SPDX-License-Identifier: MIT\n/**\n * CSS Custom Properties generator for Turbo Themes.\n *\n * Generates framework-agnostic CSS variables from theme tokens.\n * This is the primary output format for platform-agnostic theming.\n *\n * @packageDocumentation\n */\n\nimport type { ThemeFlavor, ThemeTokens } from '@lgtm-hq/turbo-themes-core';\nimport { generateSyntaxVarsFromTokens } from './syntax.js';\n\n// Import centralized mappings from config\nimport {\n CORE_MAPPINGS,\n CSS_VAR_PREFIX,\n OPTIONAL_GROUPS,\n} from '@lgtm-hq/turbo-themes-core/css/mappings';\n\n/**\n * Resolves a dot-separated path to a value in the tokens object.\n *\n * @param tokens - The tokens object to traverse\n * @param path - Dot-separated path (e.g., 'background.base')\n * @returns The resolved value or undefined if path doesn't exist\n */\nfunction resolveTokenPath(tokens: ThemeTokens, path: string): string | undefined {\n const parts = path.split('.');\n let current: unknown = tokens;\n\n for (const part of parts) {\n if (current === null || current === undefined || typeof current !== 'object') {\n return undefined;\n }\n // Safe: path is from hardcoded TOKEN_MAPPINGS, not user input\n // nosemgrep: prototype-pollution-loop\n current = (current as Record<string, unknown>)[part];\n }\n\n return typeof current === 'string' ? current : undefined;\n}\n\n/** Default modal backdrop color used when no component token is defined. */\nconst DEFAULT_MODAL_BACKDROP = 'rgba(10, 10, 10, 0.86)';\n\n/**\n * Trusted font provider domains for web font imports.\n * Only HTTPS URLs from these domains are allowed to prevent CSS injection.\n */\nconst TRUSTED_FONT_DOMAINS = [\n 'fonts.googleapis.com',\n 'fonts.gstatic.com',\n 'use.typekit.net',\n 'fonts.bunny.net',\n 'rsms.me', // Inter font\n 'fonts.cdnfonts.com',\n 'github.githubassets.com', // GitHub themes\n] as const;\n\n/**\n * Validates that a web font URL is safe to include in CSS.\n * Only allows HTTPS URLs from trusted font provider domains.\n *\n * @param url - The URL to validate\n * @returns true if the URL is from a trusted font provider\n */\nfunction isValidFontUrl(url: string): boolean {\n try {\n const parsed = new URL(url);\n if (parsed.protocol !== 'https:') {\n return false;\n }\n return TRUSTED_FONT_DOMAINS.some(\n (domain) => parsed.hostname === domain || parsed.hostname.endsWith(`.${domain}`),\n );\n } catch {\n return false;\n }\n}\n\n/**\n * Component token mappings: [cssVarName, componentPath, fallbackTokenPath].\n * Each entry maps a CSS variable to a component token path with a fallback.\n */\nconst COMPONENT_TOKEN_MAPPINGS: ReadonlyArray<[string, string, string]> = [\n ['card-bg', 'card.bg', 'background.surface'],\n ['card-border', 'card.border', 'border.default'],\n ['card-header-bg', 'card.headerBg', 'background.overlay'],\n ['card-footer-bg', 'card.footerBg', 'background.surface'],\n ['message-bg', 'message.bg', 'background.surface'],\n ['message-header-bg', 'message.headerBg', 'background.overlay'],\n ['message-border', 'message.border', 'border.default'],\n ['message-body-fg', 'message.bodyFg', 'text.primary'],\n ['panel-bg', 'panel.bg', 'background.surface'],\n ['panel-header-bg', 'panel.headerBg', 'background.overlay'],\n ['panel-header-fg', 'panel.headerFg', 'text.primary'],\n ['panel-border', 'panel.border', 'border.default'],\n ['panel-block-bg', 'panel.blockBg', 'background.surface'],\n ['panel-block-hover-bg', 'panel.blockHoverBg', 'background.overlay'],\n ['panel-block-active-bg', 'panel.blockActiveBg', 'background.overlay'],\n ['box-bg', 'box.bg', 'background.surface'],\n ['box-border', 'box.border', 'border.default'],\n ['notification-bg', 'notification.bg', 'background.surface'],\n ['notification-border', 'notification.border', 'border.default'],\n ['modal-bg', 'modal.bg', ''],\n ['modal-card-bg', 'modal.cardBg', 'background.surface'],\n ['modal-header-bg', 'modal.headerBg', 'background.overlay'],\n ['modal-footer-bg', 'modal.footerBg', 'background.surface'],\n ['dropdown-bg', 'dropdown.bg', 'background.surface'],\n ['dropdown-item-hover', 'dropdown.itemHoverBg', 'background.overlay'],\n ['dropdown-border', 'dropdown.border', 'border.default'],\n ['tabs-border', 'tabs.border', 'border.default'],\n ['tabs-link-bg', 'tabs.linkBg', 'background.surface'],\n ['tabs-link-active-bg', 'tabs.linkActiveBg', 'background.base'],\n ['tabs-link-hover-bg', 'tabs.linkHoverBg', 'background.overlay'],\n];\n\n/**\n * Resolves a component token value with fallback to a base token.\n * Uses the components section if available, otherwise falls back to base tokens.\n */\nfunction resolveComponentToken(\n tokens: ThemeTokens,\n componentPath: string,\n fallbackPath: string,\n): string {\n // Try component-specific value first\n const componentValue = resolveTokenPath(tokens, `components.${componentPath}`);\n if (componentValue !== undefined) return componentValue;\n\n // Special case: modal.bg has a non-token default\n if (componentPath === 'modal.bg') return DEFAULT_MODAL_BACKDROP;\n\n // Fall back to base token\n if (fallbackPath) return resolveTokenPath(tokens, fallbackPath) ?? '';\n return '';\n}\n\n/**\n * Generates CSS custom property declarations from theme tokens.\n * Uses centralized mapping configuration for consistency.\n *\n * @param tokens - The theme tokens to convert\n * @returns Array of CSS variable declaration lines\n *\n * @example\n * ```ts\n * const lines = generateCssVarsFromTokens(theme.tokens);\n * // [' --turbo-bg-base: #1e1e2e;', ' --turbo-bg-surface: #313244;', ...]\n * ```\n */\nexport function generateCssVarsFromTokens(tokens: ThemeTokens): string[] {\n const lines: string[] = [];\n const prefix = CSS_VAR_PREFIX;\n\n const add = (name: string, value: string): void => {\n lines.push(` --${prefix}-${name}: ${value};`);\n };\n\n // Apply core mappings from centralized config\n for (const mapping of CORE_MAPPINGS) {\n // Extract variable name from cssVar (remove prefix if present)\n const varName = mapping.cssVar.startsWith('--')\n ? mapping.cssVar.slice(2) // Remove leading --\n : mapping.cssVar;\n\n let value = resolveTokenPath(tokens, mapping.tokenPath);\n\n // Try fallback if primary path didn't resolve\n if (value === undefined && mapping.fallbackPath) {\n value = resolveTokenPath(tokens, mapping.fallbackPath);\n }\n\n if (value !== undefined) {\n add(varName, value);\n }\n }\n\n // Optional token groups\n const optionalGroups = OPTIONAL_GROUPS;\n\n // Spacing tokens (if available)\n if (tokens.spacing && optionalGroups.spacing) {\n const { properties } = optionalGroups.spacing;\n for (const prop of properties) {\n const value = (tokens.spacing as Record<string, string>)[prop];\n if (value) {\n add(`${optionalGroups.spacing.prefix}-${prop}`, value);\n }\n }\n }\n\n // Elevation tokens (if available)\n if (tokens.elevation && optionalGroups.elevation) {\n const { properties } = optionalGroups.elevation;\n for (const prop of properties) {\n const value = (tokens.elevation as Record<string, string>)[prop];\n if (value) {\n add(`${optionalGroups.elevation.prefix}-${prop}`, value);\n }\n }\n }\n\n // Animation tokens (if available) - uses custom mappings\n if (tokens.animation && optionalGroups.animation?.mappings) {\n for (const mapping of optionalGroups.animation.mappings) {\n const value = resolveTokenPath(tokens, mapping.tokenPath);\n if (value) {\n add(`${optionalGroups.animation.prefix}-${mapping.cssVar}`, value);\n }\n }\n }\n\n // Opacity tokens (if available)\n if (tokens.opacity && optionalGroups.opacity) {\n const { properties } = optionalGroups.opacity;\n for (const prop of properties) {\n const value = (tokens.opacity as Record<string, number>)[prop];\n if (value !== undefined) {\n add(`${optionalGroups.opacity.prefix}-${prop}`, String(value));\n }\n }\n }\n\n // Component tokens (always emitted with fallbacks from base tokens)\n for (const [cssVar, componentPath, fallbackPath] of COMPONENT_TOKEN_MAPPINGS) {\n const value = resolveComponentToken(tokens, componentPath, fallbackPath);\n if (value) {\n add(cssVar, value);\n }\n }\n\n // Syntax highlighting tokens\n const syntaxLines = generateSyntaxVarsFromTokens(tokens);\n lines.push(...syntaxLines);\n\n return lines;\n}\n\n/**\n * Generates a complete CSS file for a single theme flavor.\n *\n * @param flavor - The theme flavor to generate CSS for\n * @returns Complete CSS string with data-theme selector\n *\n * @example\n * ```ts\n * const css = generateThemeCss(catppuccinMocha);\n * // [data-theme=\"catppuccin-mocha\"] { --turbo-bg-base: #1e1e2e; ... }\n * ```\n */\nexport function generateThemeCss(flavor: ThemeFlavor): string {\n const vars = generateCssVarsFromTokens(flavor.tokens);\n const webFonts = flavor.tokens.typography?.webFonts ?? [];\n const fontImports = webFonts\n .filter(isValidFontUrl)\n .map((url) => `@import url('${url}');`)\n .join('\\n');\n const colorScheme = flavor.appearance === 'dark' ? 'dark' : 'light';\n\n const cssContent = `[data-theme=\"${flavor.id}\"] {\n${vars.join('\\n')}\n color-scheme: ${colorScheme};\n}`;\n\n return fontImports ? `${fontImports}\\n\\n${cssContent}\\n` : `${cssContent}\\n`;\n}\n\n/**\n * Design system tokens that are theme-agnostic.\n * These provide spacing, shadows, radius, and transitions for components.\n */\nconst DESIGN_SYSTEM_TOKENS = `\n /* Spacing */\n --space-xs: 0.25rem;\n --space-sm: 0.5rem;\n --space-md: 1rem;\n --space-lg: 1.5rem;\n --space-xl: 2rem;\n --space-2xl: 3rem;\n --space-3xl: 4rem;\n --space-4xl: 6rem;\n\n /* Border Radius */\n --radius-sm: 0.5rem;\n --radius-md: 0.75rem;\n --radius-lg: 1rem;\n --radius-xl: 1.5rem;\n --radius-2xl: 2rem;\n --radius-full: 9999px;\n\n /* Shadows */\n --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.05);\n --shadow-md: 0 4px 6px rgba(0, 0, 0, 0.07), 0 2px 4px rgba(0, 0, 0, 0.05);\n --shadow-lg: 0 10px 15px rgba(0, 0, 0, 0.1), 0 4px 6px rgba(0, 0, 0, 0.05);\n --shadow-xl: 0 20px 25px rgba(0, 0, 0, 0.15), 0 10px 10px rgba(0, 0, 0, 0.04);\n --shadow-glow: 0 0 30px color-mix(in srgb, var(--turbo-brand-primary) 30%, transparent);\n --shadow-glow-sm: 0 0 15px color-mix(in srgb, var(--turbo-brand-primary) 20%, transparent);\n\n /* Transitions */\n --transition-fast: 120ms ease-out;\n --transition-normal: 200ms ease-out;\n --transition-slow: 300ms cubic-bezier(0.4, 0, 0.2, 1);\n\n /* Gradients (theme-aware) */\n --gradient-primary: linear-gradient(135deg, var(--turbo-brand-primary), var(--turbo-state-info));\n --gradient-surface: linear-gradient(180deg, var(--turbo-bg-surface), var(--turbo-bg-base));\n`;\n\n/**\n * Generates the core CSS file with default variable values.\n *\n * @param defaultFlavor - The theme flavor to use as defaults\n * @returns CSS string with :root selector\n *\n * @example\n * ```ts\n * const coreCss = generateCoreCss(catppuccinMocha);\n * // :root { --turbo-bg-base: #1e1e2e; ... }\n * ```\n */\nexport function generateCoreCss(defaultFlavor: ThemeFlavor): string {\n const vars = generateCssVarsFromTokens(defaultFlavor.tokens);\n return `:root {\\n${vars.join('\\n')}\\n${DESIGN_SYSTEM_TOKENS}}\\n`;\n}\n\n/**\n * Generates a combined CSS file with all themes.\n *\n * @param flavors - Array of all theme flavors\n * @param defaultFlavorId - ID of the theme to use as :root defaults\n * @returns Complete CSS string with core and all theme selectors\n */\nexport function generateCombinedCss(\n flavors: readonly ThemeFlavor[],\n defaultFlavorId: string = 'catppuccin-mocha'\n): string {\n const defaultFlavor = flavors.find((f) => f.id === defaultFlavorId) || flavors[0];\n if (!defaultFlavor) {\n throw new Error('No flavors provided');\n }\n\n const coreCss = generateCoreCss(defaultFlavor);\n const themeCss = flavors.map((flavor) => generateThemeCss(flavor)).join('\\n');\n\n return `/* Turbo Themes - Pure CSS Custom Properties */\\n/* Generated automatically - do not edit */\\n\\n${coreCss}\\n${themeCss}`;\n}\n\n/**\n * Generates a CSS file containing only `[data-theme]` selectors for all themes.\n *\n * Unlike `generateCombinedCss()`, this does NOT include a `:root` block.\n * Designed for CSS-only theme switching where a blocking script sets\n * `data-theme` on `<html>` — no stylesheet swapping required, eliminating FOUC.\n *\n * @param flavors - Array of all theme flavors\n * @returns CSS string with all `[data-theme]` selectors\n *\n * @example\n * ```ts\n * const css = generateThemesOnlyCss(flavors);\n * // [data-theme=\"catppuccin-mocha\"] { ... }\n * // [data-theme=\"dracula\"] { ... }\n * ```\n */\nexport function generateThemesOnlyCss(flavors: readonly ThemeFlavor[]): string {\n if (!flavors || flavors.length === 0) {\n throw new Error('No flavors provided');\n }\n\n const allImports: string[] = [];\n const themeBlocks: string[] = [];\n\n for (const flavor of flavors) {\n const css = generateThemeCss(flavor);\n const lines = css.split('\\n');\n const imports: string[] = [];\n const rest: string[] = [];\n\n for (const line of lines) {\n if (line.startsWith('@import ')) {\n imports.push(line);\n } else {\n rest.push(line);\n }\n }\n\n for (const imp of imports) {\n if (!allImports.includes(imp)) {\n allImports.push(imp);\n }\n }\n themeBlocks.push(rest.join('\\n'));\n }\n\n const header = `/* Turbo Themes - All Theme Selectors (no :root defaults) */\\n/* Load alongside turbo-core.css + turbo-base.css for FOUC-free theme switching */\\n/* Generated automatically - do not edit */`;\n const importBlock = allImports.length > 0 ? `${allImports.join('\\n')}\\n\\n` : '';\n\n return `${importBlock}${header}\\n\\n${themeBlocks.join('\\n')}`;\n}\n\n// Re-export the prefix for external use\nexport { CSS_VAR_PREFIX };\n","// SPDX-License-Identifier: MIT\n/**\n * Base semantic styles for Turbo Themes.\n *\n * Provides optional CSS that applies theme variables to common HTML elements.\n * This is a lightweight alternative to a full CSS framework.\n *\n * @packageDocumentation\n */\n\n/**\n * Minimal CSS reset that works well with Turbo theme variables.\n * Approximately 500 bytes minified.\n */\nexport const CSS_RESET = `/* Turbo Themes - Minimal Reset */\n*,\n*::before,\n*::after {\n box-sizing: border-box;\n}\n\nbody,\nh1,\nh2,\nh3,\nh4,\nh5,\nh6,\np,\nfigure,\nblockquote,\ndl,\ndd {\n margin: 0;\n}\n\nhtml {\n -webkit-text-size-adjust: 100%;\n -moz-text-size-adjust: 100%;\n text-size-adjust: 100%;\n}\n\nbody {\n min-height: 100vh;\n line-height: 1.5;\n -webkit-font-smoothing: antialiased;\n}\n\nimg,\npicture,\nvideo,\ncanvas,\nsvg {\n display: block;\n max-width: 100%;\n}\n\ninput,\nbutton,\ntextarea,\nselect {\n font: inherit;\n}\n`;\n\n/**\n * Base semantic styles that use Turbo theme variables.\n * Approximately 2KB minified.\n */\nexport const CSS_BASE = `/* Turbo Themes - Base Semantic Styles */\n\n/* Root & Body */\n:root {\n color-scheme: light dark;\n}\n\nbody {\n font-family: var(--turbo-font-sans, system-ui, -apple-system, sans-serif);\n color: var(--turbo-text-primary, #000);\n background-color: var(--turbo-bg-base, #fff);\n}\n\n/* Typography */\nh1, h2, h3, h4, h5, h6 {\n line-height: 1.2;\n font-weight: 600;\n}\n\nh1 { color: var(--turbo-heading-h1, var(--turbo-text-primary)); font-size: 2.5rem; }\nh2 { color: var(--turbo-heading-h2, var(--turbo-text-primary)); font-size: 2rem; }\nh3 { color: var(--turbo-heading-h3, var(--turbo-text-primary)); font-size: 1.75rem; }\nh4 { color: var(--turbo-heading-h4, var(--turbo-text-primary)); font-size: 1.5rem; }\nh5 { color: var(--turbo-heading-h5, var(--turbo-text-primary)); font-size: 1.25rem; }\nh6 { color: var(--turbo-heading-h6, var(--turbo-text-primary)); font-size: 1rem; }\n\np {\n color: var(--turbo-body-primary, var(--turbo-text-primary));\n}\n\n/* Links */\na {\n color: var(--turbo-accent-link, var(--turbo-brand-primary));\n text-decoration: none;\n}\n\na:hover {\n text-decoration: underline;\n}\n\n/* Selection */\n::selection {\n color: var(--turbo-selection-fg, #fff);\n background-color: var(--turbo-selection-bg, #3273dc);\n}\n\n/* Code */\ncode,\nkbd,\nsamp,\npre {\n font-family: var(--turbo-font-mono, ui-monospace, monospace);\n}\n\ncode {\n padding: 0.125rem 0.25rem;\n color: var(--turbo-code-inline-fg, #e83e8c);\n background-color: var(--turbo-code-inline-bg, #f8f9fa);\n border-radius: 0.25rem;\n font-size: 0.875em;\n}\n\npre {\n padding: 1rem;\n color: var(--turbo-code-block-fg, #f8f9fa);\n background-color: var(--turbo-code-block-bg, #2b2b2b);\n border-radius: 0.5rem;\n overflow-x: auto;\n}\n\npre code {\n padding: 0;\n background-color: transparent;\n font-size: inherit;\n}\n\n/* Blockquote */\nblockquote {\n margin: 1rem 0;\n padding: 0.5rem 1rem;\n color: var(--turbo-blockquote-fg);\n background-color: var(--turbo-blockquote-bg);\n border-left: 4px solid var(--turbo-blockquote-border);\n border-radius: 0 0.25rem 0.25rem 0;\n}\n\n/* Tables */\ntable {\n width: 100%;\n border-collapse: collapse;\n}\n\nth,\ntd {\n padding: 0.75rem;\n text-align: left;\n border: 1px solid var(--turbo-table-border);\n}\n\nth {\n color: var(--turbo-table-header-fg, var(--turbo-text-primary));\n background-color: var(--turbo-table-thead-bg);\n font-weight: 600;\n}\n\ntr:nth-child(even) td {\n background-color: var(--turbo-table-stripe);\n}\n\n/* Form Elements */\nbutton,\ninput,\nselect,\ntextarea {\n border: 1px solid var(--turbo-border-default);\n border-radius: 0.25rem;\n background-color: var(--turbo-bg-surface);\n color: var(--turbo-text-primary);\n}\n\nbutton {\n padding: 0.5rem 1rem;\n cursor: pointer;\n background-color: var(--turbo-brand-primary);\n color: var(--turbo-text-inverse);\n border: none;\n font-weight: 500;\n}\n\nbutton:hover {\n opacity: 0.9;\n}\n\nbutton:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\ninput,\nselect,\ntextarea {\n padding: 0.5rem 0.75rem;\n}\n\nbutton:focus-visible,\ninput:focus,\nselect:focus,\ntextarea:focus {\n outline: 2px solid var(--turbo-brand-primary);\n outline-offset: 2px;\n}\n\n/* Utility classes */\n.surface {\n background-color: var(--turbo-bg-surface);\n}\n\n.surface-alt {\n background-color: var(--turbo-bg-overlay);\n}\n\n.text-primary {\n color: var(--turbo-text-primary);\n}\n\n.text-secondary {\n color: var(--turbo-text-secondary);\n}\n\n.text-success {\n color: var(--turbo-state-success);\n}\n\n.text-warning {\n color: var(--turbo-state-warning);\n}\n\n.text-danger {\n color: var(--turbo-state-danger);\n}\n\n.text-info {\n color: var(--turbo-state-info);\n}\n\n.border {\n border: 1px solid var(--turbo-border-default);\n}\n\n.rounded {\n border-radius: 0.25rem;\n}\n\n.rounded-lg {\n border-radius: 0.5rem;\n}\n`;\n\n/**\n * Generates the complete base CSS including reset and semantic styles.\n */\nexport function generateBaseCss(): string {\n return `${CSS_RESET}\\n${CSS_BASE}`;\n}\n\n/**\n * Generates only the reset CSS.\n */\nexport function generateResetCss(): string {\n return CSS_RESET;\n}\n"],"names":["prefix","optionalGroups"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/syntax.ts","../../core/dist/themes/css/mappings.js","../src/generator.ts","../src/base.ts"],"sourcesContent":["// SPDX-License-Identifier: MIT\n/**\n * Syntax highlighting styles for Turbo Themes.\n *\n * Provides CSS for code syntax highlighting that uses Turbo theme variables.\n * Compatible with Rouge (Jekyll), Prism, highlight.js, and other highlighters.\n *\n * @packageDocumentation\n */\n\nimport type { ThemeFlavor, ThemeTokens } from '@lgtm-hq/turbo-themes-core';\nimport { CSS_VAR_PREFIX } from './generator.js';\n\n/**\n * Syntax highlighting token types and their CSS class mappings.\n * These cover the common classes used by most syntax highlighters.\n */\nconst _SYNTAX_CLASS_GROUPS = {\n // Comments\n comment: ['.c', '.cm', '.c1', '.cs', '.cp', '.cpf'],\n // Keywords (control flow, declarations)\n keyword: ['.k', '.kc', '.kd', '.kn', '.kp', '.kr', '.kt', '.kv'],\n // Strings\n string: ['.s', '.s1', '.s2', '.sb', '.sc', '.sd', '.se', '.sh', '.si', '.sr', '.ss', '.sx'],\n // Numbers\n number: ['.m', '.mi', '.mf', '.mh', '.mo', '.mb', '.mx', '.il'],\n // Functions and methods\n function: ['.nf', '.fm', '.nb'],\n // Classes and types\n type: ['.nc', '.nn', '.no', '.nd'],\n // Variables and identifiers\n variable: ['.n', '.na', '.nv', '.vc', '.vg', '.vi', '.vm'],\n // Operators\n operator: ['.o', '.ow'],\n // Punctuation\n punctuation: ['.p'],\n // HTML/XML tags\n tag: ['.nt', '.nx'],\n // Attributes\n attribute: ['.na', '.atn'],\n // Values (attribute values, etc.)\n value: ['.atv'],\n // Errors\n error: ['.err', '.gr'],\n // Deletions (diffs)\n deleted: ['.gd'],\n // Insertions (diffs)\n inserted: ['.gi'],\n} as const;\n\n/**\n * Generates CSS variable declarations for syntax highlighting.\n */\nexport function generateSyntaxVarsFromTokens(tokens: ThemeTokens): string[] {\n const lines: string[] = [];\n const add = (name: string, value: string): void => {\n lines.push(` --${CSS_VAR_PREFIX}-syntax-${name}: ${value};`);\n };\n\n // Map theme tokens to syntax colors\n add('fg', tokens.content?.codeBlock?.fg ?? tokens.text.primary);\n add('bg', tokens.content?.codeBlock?.bg ?? tokens.background.surface);\n add('comment', tokens.text.secondary);\n add('keyword', tokens.brand.primary);\n add('string', tokens.state.success);\n add('number', tokens.state.warning);\n add('function', tokens.state.info);\n add('type', tokens.brand.primary);\n add('variable', tokens.text.primary);\n add('operator', tokens.text.secondary);\n add('punctuation', tokens.text.secondary);\n add('tag', tokens.state.danger);\n add('attribute', tokens.state.info);\n add('value', tokens.state.success);\n add('error', tokens.state.danger);\n add('deleted', tokens.state.danger);\n add('inserted', tokens.state.success);\n\n return lines;\n}\n\n/**\n * CSS styles for syntax highlighting using Turbo variables.\n * Works with Rouge, Prism, highlight.js, and similar highlighters.\n */\nexport const CSS_SYNTAX = `/* Turbo Themes - Syntax Highlighting */\n\n/* Astro Code component css-variables theme mapping */\n:root {\n --astro-code-color-text: var(--turbo-syntax-fg, var(--turbo-text-primary));\n --astro-code-color-background: var(--turbo-syntax-bg, var(--turbo-code-block-bg));\n --astro-code-token-constant: var(--turbo-syntax-number);\n --astro-code-token-string: var(--turbo-syntax-string);\n --astro-code-token-comment: var(--turbo-syntax-comment);\n --astro-code-token-keyword: var(--turbo-syntax-keyword);\n --astro-code-token-parameter: var(--turbo-syntax-variable);\n --astro-code-token-function: var(--turbo-syntax-function);\n --astro-code-token-string-expression: var(--turbo-syntax-string);\n --astro-code-token-punctuation: var(--turbo-syntax-punctuation);\n --astro-code-token-link: var(--turbo-accent-link, var(--turbo-brand-primary));\n /* Additional Astro tokens */\n --astro-code-background: var(--turbo-syntax-bg, var(--turbo-code-block-bg));\n --astro-code-foreground: var(--turbo-syntax-fg, var(--turbo-text-primary));\n}\n\n/* Astro Code component styling */\n.astro-code,\npre.astro-code {\n background-color: var(--turbo-syntax-bg, var(--turbo-code-block-bg)) !important;\n padding: var(--space-lg);\n border-radius: var(--radius-lg);\n overflow-x: auto;\n border: 1px solid var(--turbo-border-default);\n}\n\n.astro-code code {\n background-color: transparent !important;\n color: inherit;\n}\n\n/* Base highlight container - only applies to pre elements */\n.highlight,\npre.highlight,\npre[class*=\"language-\"] {\n background-color: var(--turbo-syntax-bg, var(--turbo-code-block-bg));\n color: var(--turbo-syntax-fg, var(--turbo-code-block-fg));\n}\n\n/* Code inside pre should have transparent background */\n.highlight pre,\n.highlight code,\npre code,\npre code[class*=\"language-\"] {\n background-color: transparent;\n color: inherit;\n}\n\n/* Comments */\n.highlight .c,\n.highlight .cm,\n.highlight .c1,\n.highlight .cs,\n.highlight .cp,\n.highlight .cpf,\n.token.comment,\n.token.prolog,\n.token.doctype,\n.token.cdata,\n.hljs-comment,\n.hljs-quote {\n color: var(--turbo-syntax-comment);\n font-style: italic;\n}\n\n/* Keywords */\n.highlight .k,\n.highlight .kc,\n.highlight .kd,\n.highlight .kn,\n.highlight .kp,\n.highlight .kr,\n.highlight .kt,\n.highlight .kv,\n.token.keyword,\n.token.atrule,\n.token.important,\n.hljs-keyword,\n.hljs-selector-tag,\n.hljs-built_in,\n.hljs-type {\n color: var(--turbo-syntax-keyword);\n}\n\n/* Strings */\n.highlight .s,\n.highlight .s1,\n.highlight .s2,\n.highlight .sb,\n.highlight .sc,\n.highlight .sd,\n.highlight .se,\n.highlight .sh,\n.highlight .si,\n.highlight .sr,\n.highlight .ss,\n.highlight .sx,\n.token.string,\n.token.char,\n.token.regex,\n.token.template-string,\n.hljs-string,\n.hljs-regexp {\n color: var(--turbo-syntax-string);\n}\n\n/* Numbers */\n.highlight .m,\n.highlight .mi,\n.highlight .mf,\n.highlight .mh,\n.highlight .mo,\n.highlight .mb,\n.highlight .mx,\n.highlight .il,\n.token.number,\n.token.boolean,\n.token.constant,\n.hljs-number,\n.hljs-literal {\n color: var(--turbo-syntax-number);\n}\n\n/* Functions */\n.highlight .nf,\n.highlight .fm,\n.highlight .nb,\n.token.function,\n.token.builtin,\n.hljs-title.function_,\n.hljs-built_in {\n color: var(--turbo-syntax-function);\n}\n\n/* Classes and types */\n.highlight .nc,\n.highlight .nn,\n.highlight .no,\n.highlight .nd,\n.token.class-name,\n.token.namespace,\n.hljs-title.class_,\n.hljs-class .hljs-title {\n color: var(--turbo-syntax-type);\n}\n\n/* Variables and identifiers */\n.highlight .n,\n.highlight .nv,\n.highlight .vc,\n.highlight .vg,\n.highlight .vi,\n.highlight .vm,\n.token.variable,\n.hljs-variable,\n.hljs-template-variable {\n color: var(--turbo-syntax-variable);\n}\n\n/* Operators */\n.highlight .o,\n.highlight .ow,\n.token.operator,\n.hljs-operator {\n color: var(--turbo-syntax-operator);\n}\n\n/* Punctuation */\n.highlight .p,\n.token.punctuation,\n.hljs-punctuation {\n color: var(--turbo-syntax-punctuation);\n}\n\n/* HTML/XML tags */\n.highlight .nt,\n.highlight .nx,\n.token.tag,\n.hljs-tag,\n.hljs-name {\n color: var(--turbo-syntax-tag);\n}\n\n/* Attributes */\n.highlight .na,\n.highlight .atn,\n.token.attr-name,\n.hljs-attr {\n color: var(--turbo-syntax-attribute);\n}\n\n/* Attribute values */\n.highlight .atv,\n.token.attr-value,\n.hljs-attr .hljs-string {\n color: var(--turbo-syntax-value);\n}\n\n/* Errors */\n.highlight .err,\n.highlight .gr,\n.token.error,\n.hljs-error {\n color: var(--turbo-syntax-error);\n}\n\n/* Diff: deletions */\n.highlight .gd,\n.token.deleted,\n.hljs-deletion {\n color: var(--turbo-syntax-deleted);\n background-color: color-mix(in srgb, var(--turbo-syntax-deleted) 15%, transparent);\n}\n\n/* Diff: insertions */\n.highlight .gi,\n.token.inserted,\n.hljs-addition {\n color: var(--turbo-syntax-inserted);\n background-color: color-mix(in srgb, var(--turbo-syntax-inserted) 15%, transparent);\n}\n\n/* Line numbers (if used) */\n.highlight .lineno,\n.line-numbers .line-numbers-rows,\n.hljs-ln-numbers {\n color: var(--turbo-text-secondary);\n opacity: 0.5;\n user-select: none;\n}\n\n/* Selection within code */\n.highlight ::selection,\npre[class*=\"language-\"] ::selection,\ncode[class*=\"language-\"] ::selection {\n background-color: var(--turbo-selection-bg);\n color: var(--turbo-selection-fg);\n}\n`;\n\n/**\n * Generates syntax highlighting CSS for a specific theme.\n * This includes both the variable definitions and the styling rules.\n */\nexport function generateSyntaxCss(flavor: ThemeFlavor): string {\n const vars = generateSyntaxVarsFromTokens(flavor.tokens);\n\n return `/* Turbo Themes - Syntax Highlighting for ${flavor.label} */\n[data-theme=\"${flavor.id}\"] {\n${vars.join('\\n')}\n}\n`;\n}\n\n/**\n * Generates the complete syntax highlighting CSS file.\n * Includes base styles that work with any theme.\n */\nexport function generateSyntaxBaseCss(): string {\n return CSS_SYNTAX;\n}\n","// SPDX-License-Identifier: MIT\n// CSS Variable Mappings - Generated from config/token-mappings.json\n// This file reads from the single source of truth configuration\n// Import the centralized mapping configuration\n// Note: Using require for JSON import compatibility\nimport mappingConfig from '../../../../../config/token-mappings.json' with { type: 'json' };\n// Convert config entries to typed mappings\nfunction toVariableMapping(entry) {\n return {\n cssVar: entry.cssVar,\n tokenPath: entry.tokenPath,\n ...(entry.fallback ? { fallbackPath: entry.fallback } : {}),\n };\n}\nfunction toComponentMapping(entry) {\n return {\n cssVar: entry.cssVar,\n componentPath: entry.componentPath,\n fallbackPath: entry.fallback,\n };\n}\nfunction toHSLMapping(entry) {\n return {\n hVar: entry.hVar,\n sVar: entry.sVar,\n lVar: entry.lVar,\n tokenPath: entry.tokenPath,\n };\n}\nfunction toHSLColorMapping(entry) {\n return {\n cssVar: entry.cssVar,\n tokenPath: entry.tokenPath,\n };\n}\n// =============================================================================\n// Bulma Framework Mappings\n// =============================================================================\n/** Bulma scheme variables */\nexport const BULMA_SCHEME_MAPPINGS = mappingConfig.bulma.schemeMappings.map(toVariableMapping);\n/** Primary color HSL components */\nexport const PRIMARY_HSL_MAPPING = toHSLMapping(mappingConfig.bulma.primaryHsl);\n/** State colors as HSL */\nexport const STATE_HSL_MAPPINGS = mappingConfig.bulma.stateHslMappings.map(toHSLColorMapping);\n// =============================================================================\n// Theme Variable Mappings\n// =============================================================================\n/** Text variables */\nexport const TEXT_MAPPINGS = mappingConfig.theme.textMappings.map(toVariableMapping);\n/** Heading variables */\nexport const HEADING_MAPPINGS = mappingConfig.theme.headingMappings.map(toVariableMapping);\n/** Content element variables */\nexport const CONTENT_MAPPINGS = mappingConfig.theme.contentMappings.map(toVariableMapping);\n/** Table variables */\nexport const TABLE_MAPPINGS = mappingConfig.theme.tableMappings.map(toVariableMapping);\n/** Syntax highlighting variables */\nexport const SYNTAX_MAPPINGS = mappingConfig.theme.syntaxMappings.map(toVariableMapping);\n/** Surface/background variables */\nexport const SURFACE_MAPPINGS = mappingConfig.theme.surfaceMappings.map(toVariableMapping);\n// =============================================================================\n// Component Token Mappings\n// =============================================================================\n/** Component token mappings (optional, with fallbacks) */\nexport const COMPONENT_MAPPINGS = mappingConfig.components.map(toComponentMapping);\n// =============================================================================\n// Syntax Highlighting CSS Classes\n// =============================================================================\n/** Syntax highlighting CSS class mappings */\nexport const SYNTAX_CLASS_GROUPS = mappingConfig.syntaxClassGroups;\n// =============================================================================\n// Core Mappings (for generator.ts and Python)\n// =============================================================================\n/** Core token mappings used by CSS generator */\nexport const CORE_MAPPINGS = mappingConfig.coreMappings.map(toVariableMapping);\n/** CSS variable prefix */\nexport const CSS_VAR_PREFIX = mappingConfig.prefix;\n/** Optional group configurations */\nexport const OPTIONAL_GROUPS = mappingConfig.optionalGroups;\n//# sourceMappingURL=mappings.js.map","// SPDX-License-Identifier: MIT\n/**\n * CSS Custom Properties generator for Turbo Themes.\n *\n * Generates framework-agnostic CSS variables from theme tokens.\n * This is the primary output format for platform-agnostic theming.\n *\n * @packageDocumentation\n */\n\nimport type { ThemeFlavor, ThemeTokens } from '@lgtm-hq/turbo-themes-core';\nimport { generateSyntaxVarsFromTokens } from './syntax.js';\n\n// Import centralized mappings from config\nimport {\n CORE_MAPPINGS,\n CSS_VAR_PREFIX,\n OPTIONAL_GROUPS,\n} from '@lgtm-hq/turbo-themes-core/css/mappings';\n\n/**\n * Resolves a dot-separated path to a value in the tokens object.\n *\n * @param tokens - The tokens object to traverse\n * @param path - Dot-separated path (e.g., 'background.base')\n * @returns The resolved value or undefined if path doesn't exist\n */\nfunction resolveTokenPath(tokens: ThemeTokens, path: string): string | undefined {\n const parts = path.split('.');\n let current: unknown = tokens;\n\n for (const part of parts) {\n if (current === null || current === undefined || typeof current !== 'object') {\n return undefined;\n }\n // Safe: path is from hardcoded TOKEN_MAPPINGS, not user input\n // nosemgrep: prototype-pollution-loop\n current = (current as Record<string, unknown>)[part];\n }\n\n return typeof current === 'string' ? current : undefined;\n}\n\n/** Default modal backdrop color used when no component token is defined. */\nconst DEFAULT_MODAL_BACKDROP = 'rgba(10, 10, 10, 0.86)';\n\n/**\n * Trusted font provider domains for web font imports.\n * Only HTTPS URLs from these domains are allowed to prevent CSS injection.\n */\nconst TRUSTED_FONT_DOMAINS = [\n 'fonts.googleapis.com',\n 'fonts.gstatic.com',\n 'use.typekit.net',\n 'fonts.bunny.net',\n 'rsms.me', // Inter font\n 'fonts.cdnfonts.com',\n 'github.githubassets.com', // GitHub themes\n] as const;\n\n/**\n * Validates that a web font URL is safe to include in CSS.\n * Only allows HTTPS URLs from trusted font provider domains.\n *\n * @param url - The URL to validate\n * @returns true if the URL is from a trusted font provider\n */\nfunction isValidFontUrl(url: string): boolean {\n try {\n const parsed = new URL(url);\n if (parsed.protocol !== 'https:') {\n return false;\n }\n return TRUSTED_FONT_DOMAINS.some(\n (domain) => parsed.hostname === domain || parsed.hostname.endsWith(`.${domain}`),\n );\n } catch {\n return false;\n }\n}\n\n/**\n * Component token mappings: [cssVarName, componentPath, fallbackTokenPath].\n * Each entry maps a CSS variable to a component token path with a fallback.\n */\nconst COMPONENT_TOKEN_MAPPINGS: ReadonlyArray<[string, string, string]> = [\n ['card-bg', 'card.bg', 'background.surface'],\n ['card-border', 'card.border', 'border.default'],\n ['card-header-bg', 'card.headerBg', 'background.overlay'],\n ['card-footer-bg', 'card.footerBg', 'background.surface'],\n ['message-bg', 'message.bg', 'background.surface'],\n ['message-header-bg', 'message.headerBg', 'background.overlay'],\n ['message-border', 'message.border', 'border.default'],\n ['message-body-fg', 'message.bodyFg', 'text.primary'],\n ['panel-bg', 'panel.bg', 'background.surface'],\n ['panel-header-bg', 'panel.headerBg', 'background.overlay'],\n ['panel-header-fg', 'panel.headerFg', 'text.primary'],\n ['panel-border', 'panel.border', 'border.default'],\n ['panel-block-bg', 'panel.blockBg', 'background.surface'],\n ['panel-block-hover-bg', 'panel.blockHoverBg', 'background.overlay'],\n ['panel-block-active-bg', 'panel.blockActiveBg', 'background.overlay'],\n ['box-bg', 'box.bg', 'background.surface'],\n ['box-border', 'box.border', 'border.default'],\n ['notification-bg', 'notification.bg', 'background.surface'],\n ['notification-border', 'notification.border', 'border.default'],\n ['modal-bg', 'modal.bg', ''],\n ['modal-card-bg', 'modal.cardBg', 'background.surface'],\n ['modal-header-bg', 'modal.headerBg', 'background.overlay'],\n ['modal-footer-bg', 'modal.footerBg', 'background.surface'],\n ['dropdown-bg', 'dropdown.bg', 'background.surface'],\n ['dropdown-item-hover', 'dropdown.itemHoverBg', 'background.overlay'],\n ['dropdown-border', 'dropdown.border', 'border.default'],\n ['tabs-border', 'tabs.border', 'border.default'],\n ['tabs-link-bg', 'tabs.linkBg', 'background.surface'],\n ['tabs-link-active-bg', 'tabs.linkActiveBg', 'background.base'],\n ['tabs-link-hover-bg', 'tabs.linkHoverBg', 'background.overlay'],\n];\n\n/**\n * Resolves a component token value with fallback to a base token.\n * Uses the components section if available, otherwise falls back to base tokens.\n */\nfunction resolveComponentToken(\n tokens: ThemeTokens,\n componentPath: string,\n fallbackPath: string,\n): string {\n // Try component-specific value first\n const componentValue = resolveTokenPath(tokens, `components.${componentPath}`);\n if (componentValue !== undefined) return componentValue;\n\n // Special case: modal.bg has a non-token default\n if (componentPath === 'modal.bg') return DEFAULT_MODAL_BACKDROP;\n\n // Fall back to base token\n if (fallbackPath) return resolveTokenPath(tokens, fallbackPath) ?? '';\n return '';\n}\n\n/**\n * Generates CSS custom property declarations from theme tokens.\n * Uses centralized mapping configuration for consistency.\n *\n * @param tokens - The theme tokens to convert\n * @returns Array of CSS variable declaration lines\n *\n * @example\n * ```ts\n * const lines = generateCssVarsFromTokens(theme.tokens);\n * // [' --turbo-bg-base: #1e1e2e;', ' --turbo-bg-surface: #313244;', ...]\n * ```\n */\nexport function generateCssVarsFromTokens(tokens: ThemeTokens): string[] {\n const lines: string[] = [];\n const prefix = CSS_VAR_PREFIX;\n\n const add = (name: string, value: string): void => {\n lines.push(` --${prefix}-${name}: ${value};`);\n };\n\n // Apply core mappings from centralized config\n for (const mapping of CORE_MAPPINGS) {\n // Extract variable name from cssVar (remove prefix if present)\n const varName = mapping.cssVar.startsWith('--')\n ? mapping.cssVar.slice(2) // Remove leading --\n : mapping.cssVar;\n\n let value = resolveTokenPath(tokens, mapping.tokenPath);\n\n // Try fallback if primary path didn't resolve\n if (value === undefined && mapping.fallbackPath) {\n value = resolveTokenPath(tokens, mapping.fallbackPath);\n }\n\n if (value !== undefined) {\n add(varName, value);\n }\n }\n\n // Optional token groups\n const optionalGroups = OPTIONAL_GROUPS;\n\n // Spacing tokens (if available)\n if (tokens.spacing && optionalGroups.spacing) {\n const { properties } = optionalGroups.spacing;\n for (const prop of properties) {\n const value = (tokens.spacing as Record<string, string>)[prop];\n if (value) {\n add(`${optionalGroups.spacing.prefix}-${prop}`, value);\n }\n }\n }\n\n // Elevation tokens (if available)\n if (tokens.elevation && optionalGroups.elevation) {\n const { properties } = optionalGroups.elevation;\n for (const prop of properties) {\n const value = (tokens.elevation as Record<string, string>)[prop];\n if (value) {\n add(`${optionalGroups.elevation.prefix}-${prop}`, value);\n }\n }\n }\n\n // Animation tokens (if available) - uses custom mappings\n if (tokens.animation && optionalGroups.animation?.mappings) {\n for (const mapping of optionalGroups.animation.mappings) {\n const value = resolveTokenPath(tokens, mapping.tokenPath);\n if (value) {\n add(`${optionalGroups.animation.prefix}-${mapping.cssVar}`, value);\n }\n }\n }\n\n // Opacity tokens (if available)\n if (tokens.opacity && optionalGroups.opacity) {\n const { properties } = optionalGroups.opacity;\n for (const prop of properties) {\n const value = (tokens.opacity as Record<string, number>)[prop];\n if (value !== undefined) {\n add(`${optionalGroups.opacity.prefix}-${prop}`, String(value));\n }\n }\n }\n\n // Component tokens (always emitted with fallbacks from base tokens)\n for (const [cssVar, componentPath, fallbackPath] of COMPONENT_TOKEN_MAPPINGS) {\n const value = resolveComponentToken(tokens, componentPath, fallbackPath);\n if (value) {\n add(cssVar, value);\n }\n }\n\n // Syntax highlighting tokens\n const syntaxLines = generateSyntaxVarsFromTokens(tokens);\n lines.push(...syntaxLines);\n\n return lines;\n}\n\n/**\n * Generates a complete CSS file for a single theme flavor.\n *\n * @param flavor - The theme flavor to generate CSS for\n * @returns Complete CSS string with data-theme selector\n *\n * @example\n * ```ts\n * const css = generateThemeCss(catppuccinMocha);\n * // [data-theme=\"catppuccin-mocha\"] { --turbo-bg-base: #1e1e2e; ... }\n * ```\n */\nexport function generateThemeCss(flavor: ThemeFlavor): string {\n const vars = generateCssVarsFromTokens(flavor.tokens);\n const webFonts = flavor.tokens.typography?.webFonts ?? [];\n const fontImports = webFonts\n .filter(isValidFontUrl)\n .map((url) => `@import url('${url}');`)\n .join('\\n');\n const colorScheme = flavor.appearance === 'dark' ? 'dark' : 'light';\n\n const cssContent = `[data-theme=\"${flavor.id}\"] {\n${vars.join('\\n')}\n color-scheme: ${colorScheme};\n}`;\n\n return fontImports ? `${fontImports}\\n\\n${cssContent}\\n` : `${cssContent}\\n`;\n}\n\n/**\n * Design system tokens that are theme-agnostic.\n * These provide spacing, shadows, radius, and transitions for components.\n */\nconst DESIGN_SYSTEM_TOKENS = `\n /* Spacing */\n --space-xs: 0.25rem;\n --space-sm: 0.5rem;\n --space-md: 1rem;\n --space-lg: 1.5rem;\n --space-xl: 2rem;\n --space-2xl: 3rem;\n --space-3xl: 4rem;\n --space-4xl: 6rem;\n\n /* Border Radius */\n --radius-sm: 0.5rem;\n --radius-md: 0.75rem;\n --radius-lg: 1rem;\n --radius-xl: 1.5rem;\n --radius-2xl: 2rem;\n --radius-full: 9999px;\n\n /* Shadows */\n --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.05);\n --shadow-md: 0 4px 6px rgba(0, 0, 0, 0.07), 0 2px 4px rgba(0, 0, 0, 0.05);\n --shadow-lg: 0 10px 15px rgba(0, 0, 0, 0.1), 0 4px 6px rgba(0, 0, 0, 0.05);\n --shadow-xl: 0 20px 25px rgba(0, 0, 0, 0.15), 0 10px 10px rgba(0, 0, 0, 0.04);\n --shadow-glow: 0 0 30px color-mix(in srgb, var(--turbo-brand-primary) 30%, transparent);\n --shadow-glow-sm: 0 0 15px color-mix(in srgb, var(--turbo-brand-primary) 20%, transparent);\n\n /* Transitions */\n --transition-fast: 120ms ease-out;\n --transition-normal: 200ms ease-out;\n --transition-slow: 300ms cubic-bezier(0.4, 0, 0.2, 1);\n\n /* Gradients (theme-aware) */\n --gradient-primary: linear-gradient(135deg, var(--turbo-brand-primary), var(--turbo-state-info));\n --gradient-surface: linear-gradient(180deg, var(--turbo-bg-surface), var(--turbo-bg-base));\n`;\n\n/**\n * Generates the core CSS file with default variable values.\n *\n * @param defaultFlavor - The theme flavor to use as defaults\n * @returns CSS string with :root selector\n *\n * @example\n * ```ts\n * const coreCss = generateCoreCss(catppuccinMocha);\n * // :root { --turbo-bg-base: #1e1e2e; ... }\n * ```\n */\nexport function generateCoreCss(defaultFlavor: ThemeFlavor): string {\n const vars = generateCssVarsFromTokens(defaultFlavor.tokens);\n return `:root {\\n${vars.join('\\n')}\\n${DESIGN_SYSTEM_TOKENS}}\\n`;\n}\n\n/**\n * Generates a combined CSS file with all themes.\n *\n * @param flavors - Array of all theme flavors\n * @param defaultFlavorId - ID of the theme to use as :root defaults\n * @returns Complete CSS string with core and all theme selectors\n */\nexport function generateCombinedCss(\n flavors: readonly ThemeFlavor[],\n defaultFlavorId: string = 'catppuccin-mocha'\n): string {\n const defaultFlavor = flavors.find((f) => f.id === defaultFlavorId) || flavors[0];\n if (!defaultFlavor) {\n throw new Error('No flavors provided');\n }\n\n const coreCss = generateCoreCss(defaultFlavor);\n const themeCss = flavors.map((flavor) => generateThemeCss(flavor)).join('\\n');\n\n return `/* Turbo Themes - Pure CSS Custom Properties */\\n/* Generated automatically - do not edit */\\n\\n${coreCss}\\n${themeCss}`;\n}\n\n/**\n * Generates a CSS file containing only `[data-theme]` selectors for all themes.\n *\n * Unlike `generateCombinedCss()`, this does NOT include a `:root` block.\n * Designed for CSS-only theme switching where a blocking script sets\n * `data-theme` on `<html>` — no stylesheet swapping required, eliminating FOUC.\n *\n * @param flavors - Array of all theme flavors\n * @returns CSS string with all `[data-theme]` selectors\n *\n * @example\n * ```ts\n * const css = generateThemesOnlyCss(flavors);\n * // [data-theme=\"catppuccin-mocha\"] { ... }\n * // [data-theme=\"dracula\"] { ... }\n * ```\n */\nexport function generateThemesOnlyCss(flavors: readonly ThemeFlavor[]): string {\n if (!flavors || flavors.length === 0) {\n throw new Error('No flavors provided');\n }\n\n const allImports: string[] = [];\n const themeBlocks: string[] = [];\n\n for (const flavor of flavors) {\n const css = generateThemeCss(flavor);\n const lines = css.split('\\n');\n const imports: string[] = [];\n const rest: string[] = [];\n\n for (const line of lines) {\n if (line.startsWith('@import ')) {\n imports.push(line);\n } else {\n rest.push(line);\n }\n }\n\n for (const imp of imports) {\n if (!allImports.includes(imp)) {\n allImports.push(imp);\n }\n }\n themeBlocks.push(rest.join('\\n'));\n }\n\n const header = `/* Turbo Themes - All Theme Selectors (no :root defaults) */\\n/* Load alongside turbo-core.css + turbo-base.css for FOUC-free theme switching */\\n/* Generated automatically - do not edit */`;\n const importBlock = allImports.length > 0 ? `${allImports.join('\\n')}\\n\\n` : '';\n\n return `${importBlock}${header}\\n\\n${themeBlocks.join('\\n')}`;\n}\n\n// Re-export the prefix for external use\nexport { CSS_VAR_PREFIX };\n","// SPDX-License-Identifier: MIT\n/**\n * Base semantic styles for Turbo Themes.\n *\n * Provides optional CSS that applies theme variables to common HTML elements.\n * This is a lightweight alternative to a full CSS framework.\n *\n * @packageDocumentation\n */\n\n/**\n * Minimal CSS reset that works well with Turbo theme variables.\n * Approximately 500 bytes minified.\n */\nexport const CSS_RESET = `/* Turbo Themes - Minimal Reset */\n*,\n*::before,\n*::after {\n box-sizing: border-box;\n}\n\nbody,\nh1,\nh2,\nh3,\nh4,\nh5,\nh6,\np,\nfigure,\nblockquote,\ndl,\ndd {\n margin: 0;\n}\n\nhtml {\n -webkit-text-size-adjust: 100%;\n -moz-text-size-adjust: 100%;\n text-size-adjust: 100%;\n}\n\nbody {\n min-height: 100vh;\n line-height: 1.5;\n -webkit-font-smoothing: antialiased;\n}\n\nimg,\npicture,\nvideo,\ncanvas,\nsvg {\n display: block;\n max-width: 100%;\n}\n\ninput,\nbutton,\ntextarea,\nselect {\n font: inherit;\n}\n`;\n\n/**\n * Base semantic styles that use Turbo theme variables.\n * Approximately 2KB minified.\n */\nexport const CSS_BASE = `/* Turbo Themes - Base Semantic Styles */\n\n/* Root & Body */\n:root {\n color-scheme: light dark;\n}\n\nbody {\n font-family: var(--turbo-font-sans, system-ui, -apple-system, sans-serif);\n color: var(--turbo-text-primary, #000);\n background-color: var(--turbo-bg-base, #fff);\n}\n\n/* Typography */\nh1, h2, h3, h4, h5, h6 {\n line-height: 1.2;\n font-weight: 600;\n}\n\nh1 { color: var(--turbo-heading-h1, var(--turbo-text-primary)); font-size: 2.5rem; }\nh2 { color: var(--turbo-heading-h2, var(--turbo-text-primary)); font-size: 2rem; }\nh3 { color: var(--turbo-heading-h3, var(--turbo-text-primary)); font-size: 1.75rem; }\nh4 { color: var(--turbo-heading-h4, var(--turbo-text-primary)); font-size: 1.5rem; }\nh5 { color: var(--turbo-heading-h5, var(--turbo-text-primary)); font-size: 1.25rem; }\nh6 { color: var(--turbo-heading-h6, var(--turbo-text-primary)); font-size: 1rem; }\n\np {\n color: var(--turbo-body-primary, var(--turbo-text-primary));\n}\n\n/* Links */\na {\n color: var(--turbo-accent-link, var(--turbo-brand-primary));\n text-decoration: none;\n}\n\na:hover {\n text-decoration: underline;\n}\n\n/* Selection */\n::selection {\n color: var(--turbo-selection-fg, #fff);\n background-color: var(--turbo-selection-bg, #3273dc);\n}\n\n/* Code */\ncode,\nkbd,\nsamp,\npre {\n font-family: var(--turbo-font-mono, ui-monospace, monospace);\n}\n\ncode {\n padding: 0.125rem 0.25rem;\n color: var(--turbo-code-inline-fg, #e83e8c);\n background-color: var(--turbo-code-inline-bg, #f8f9fa);\n border-radius: 0.25rem;\n font-size: 0.875em;\n}\n\npre {\n padding: 1rem;\n color: var(--turbo-code-block-fg, #f8f9fa);\n background-color: var(--turbo-code-block-bg, #2b2b2b);\n border-radius: 0.5rem;\n overflow-x: auto;\n}\n\npre code {\n padding: 0;\n background-color: transparent;\n font-size: inherit;\n}\n\n/* Blockquote */\nblockquote {\n margin: 1rem 0;\n padding: 0.5rem 1rem;\n color: var(--turbo-blockquote-fg);\n background-color: var(--turbo-blockquote-bg);\n border-left: 4px solid var(--turbo-blockquote-border);\n border-radius: 0 0.25rem 0.25rem 0;\n}\n\n/* Tables */\ntable {\n width: 100%;\n border-collapse: collapse;\n}\n\nth,\ntd {\n padding: 0.75rem;\n text-align: left;\n border: 1px solid var(--turbo-table-border);\n}\n\nth {\n color: var(--turbo-table-header-fg, var(--turbo-text-primary));\n background-color: var(--turbo-table-thead-bg);\n font-weight: 600;\n}\n\ntr:nth-child(even) td {\n background-color: var(--turbo-table-stripe);\n}\n\n/* Form Elements */\nbutton,\ninput,\nselect,\ntextarea {\n border: 1px solid var(--turbo-border-default);\n border-radius: 0.25rem;\n background-color: var(--turbo-bg-surface);\n color: var(--turbo-text-primary);\n}\n\nbutton {\n padding: 0.5rem 1rem;\n cursor: pointer;\n background-color: var(--turbo-brand-primary);\n color: var(--turbo-text-inverse);\n border: none;\n font-weight: 500;\n}\n\nbutton:hover {\n opacity: 0.9;\n}\n\nbutton:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\ninput,\nselect,\ntextarea {\n padding: 0.5rem 0.75rem;\n}\n\nbutton:focus-visible,\ninput:focus,\nselect:focus,\ntextarea:focus {\n outline: 2px solid var(--turbo-brand-primary);\n outline-offset: 2px;\n}\n\n/* Utility classes */\n.surface {\n background-color: var(--turbo-bg-surface);\n}\n\n.surface-alt {\n background-color: var(--turbo-bg-overlay);\n}\n\n.text-primary {\n color: var(--turbo-text-primary);\n}\n\n.text-secondary {\n color: var(--turbo-text-secondary);\n}\n\n.text-success {\n color: var(--turbo-state-success);\n}\n\n.text-warning {\n color: var(--turbo-state-warning);\n}\n\n.text-danger {\n color: var(--turbo-state-danger);\n}\n\n.text-info {\n color: var(--turbo-state-info);\n}\n\n.border {\n border: 1px solid var(--turbo-border-default);\n}\n\n.rounded {\n border-radius: 0.25rem;\n}\n\n.rounded-lg {\n border-radius: 0.5rem;\n}\n`;\n\n/**\n * Generates the complete base CSS including reset and semantic styles.\n */\nexport function generateBaseCss(): string {\n return `${CSS_RESET}\\n${CSS_BASE}`;\n}\n\n/**\n * Generates only the reset CSS.\n */\nexport function generateResetCss(): string {\n return CSS_RESET;\n}\n"],"names":["prefix","optionalGroups"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../core/dist/tokens/index.js","../../core/dist/themes/metadata.js","../src/constants.ts","../src/errors.ts","../src/storage.ts","../src/theme-loader.ts","../src/dropdown/helpers.ts","../src/theme-mapper.ts","../src/theme-resolver.ts","../src/apply-theme.ts","../src/dropdown/state.ts","../src/dropdown/events.ts","../src/dropdown/ui.ts","../src/navbar.ts","../src/accessibility.ts","../src/blocking-script.ts","../src/index.ts"],"sourcesContent":["// SPDX-License-Identifier: MIT\n/**\n * Platform-agnostic design tokens export\n *\n * This module exports pure theme data (colors, typography, etc.) without\n * any DOM, CSS, or platform-specific code. Use this for:\n *\n * - React Native apps\n * - Flutter apps (via JSON export)\n * - iOS/Android native apps\n * - Any platform that needs theme colors\n *\n * For web apps, you can also import the CSS files directly:\n * import '@lgtm-hq/turbo-themes/css/catppuccin-mocha.css'\n */\n// Import tokens data (copied from dist/tokens.json during build)\nimport tokensData from '../themes/tokens.json' with { type: 'json' };\nconst tokens = tokensData;\n/**\n * All available theme flavors as a flat array\n */\nexport const flavors = Object.values(tokens.themes).map((theme) => ({\n id: theme.id,\n label: theme.label,\n vendor: theme.vendor,\n appearance: theme.appearance,\n ...(theme.iconUrl !== undefined && { iconUrl: theme.iconUrl }),\n tokens: theme.tokens,\n}));\n/**\n * Theme flavors indexed by ID for quick lookup\n */\nexport const themesById = /*#__PURE__*/ Object.fromEntries(flavors.map((flavor) => [flavor.id, flavor]));\n/**\n * All available theme packages (grouped by vendor)\n */\nexport const packages = /*#__PURE__*/ Object.fromEntries(Object.entries(tokens.byVendor).map(([vendorId, vendor]) => [\n vendorId,\n {\n id: vendorId,\n name: vendor.name,\n homepage: vendor.homepage,\n flavors: vendor.themes.map((themeId) => themesById[themeId]).filter(Boolean),\n },\n]));\n/**\n * Get a theme by ID\n * @param id - Theme identifier (e.g., 'catppuccin-mocha')\n * @returns The theme flavor or undefined if not found\n */\nexport function getTheme(id) {\n return themesById[id];\n}\n/**\n * Get theme tokens by ID (convenience function)\n * @param id - Theme identifier (e.g., 'catppuccin-mocha')\n * @returns The theme tokens or undefined if not found\n */\nexport function getTokens(id) {\n return themesById[id]?.tokens;\n}\n/**\n * Get all themes matching an appearance (light/dark)\n * @param appearance - 'light' or 'dark'\n * @returns Array of matching theme flavors\n */\nexport function getThemesByAppearance(appearance) {\n return flavors.filter((f) => f.appearance === appearance);\n}\n/**\n * Get all themes from a specific vendor\n * @param vendor - Vendor name (e.g., 'catppuccin', 'github')\n * @returns Array of matching theme flavors\n */\nexport function getThemesByVendor(vendor) {\n return flavors.filter((f) => f.vendor === vendor);\n}\n/**\n * List of all available theme IDs\n */\nexport const themeIds = /*#__PURE__*/ flavors.map((f) => f.id);\n/**\n * List of all available vendors\n */\nexport const vendors = /*#__PURE__*/ [...new Set(flavors.map((f) => f.vendor))];\n//# sourceMappingURL=index.js.map","// SPDX-License-Identifier: MIT\n/**\n * Consolidated theme metadata derived from tokens.json.\n *\n * All display metadata (names, appearances, vendor groups) is computed from\n * the canonical token data at module evaluation time. Consumers should import\n * from here instead of maintaining their own hardcoded copies.\n */\nimport { flavors, themeIds, packages } from '../tokens/index.js';\n/** Default theme applied when no preference is stored. */\nexport const DEFAULT_THEME = 'catppuccin-mocha';\n/** All valid theme IDs (re-export for convenience). */\nexport const VALID_THEMES = themeIds;\n/** Set of valid theme IDs for O(1) lookup. */\nexport const VALID_THEME_SET = /*#__PURE__*/ new Set(themeIds);\n/** Full human-readable label for each theme (e.g., \"Catppuccin Mocha\"). */\nexport const THEME_NAMES = /*#__PURE__*/ Object.fromEntries(flavors.map((f) => [f.id, f.label]));\n/** Appearance (light/dark) for each theme. */\nexport const THEME_APPEARANCES = \n/*#__PURE__*/ Object.fromEntries(flavors.map((f) => [f.id, f.appearance]));\n/**\n * Ordered list of vendor IDs controlling display order in dropdowns.\n * New vendors should be appended here.\n */\nexport const VENDOR_ORDER = [\n 'catppuccin',\n 'dracula',\n 'gruvbox',\n 'github',\n 'bulma',\n 'nord',\n 'solarized',\n 'rose-pine',\n 'tokyo-night',\n];\n/**\n * Ordered array of vendor groups derived from packages + VENDOR_ORDER.\n * The \"(synced)\" suffix is stripped from display names.\n */\n// Dev-time validation: warn if packages has vendors not listed in VENDOR_ORDER\nconst _packageKeys = Object.keys(packages);\nconst _missingFromOrder = _packageKeys.filter((id) => !VENDOR_ORDER.includes(id));\nif (_missingFromOrder.length > 0) {\n console.warn(`[metadata] VENDOR_ORDER is missing vendor IDs present in packages: ${_missingFromOrder.join(', ')}. ` +\n 'Append them to VENDOR_ORDER so their themes are included in VENDOR_GROUPS.');\n}\nexport const VENDOR_GROUPS = /*#__PURE__*/ VENDOR_ORDER.filter((id) => id in packages).map((id) => {\n const pkg = packages[id];\n return {\n id,\n displayName: pkg.name.replace(/\\s*\\(synced\\)\\s*/i, ''),\n themeIds: pkg.flavors.flatMap((f) => (f ? [f.id] : [])),\n };\n});\n/** O(1) flavor lookup by ID, built once at module evaluation time. */\nconst flavorById = /*#__PURE__*/ new Map(flavors.map((f) => [f.id, f]));\n/** Cache for computed short labels. */\nconst shortLabelCache = new Map();\n/**\n * Strip the vendor prefix from a theme label to produce a short label.\n *\n * For single-flavor vendors (e.g., \"Dracula\", \"Nord\") the full label is returned.\n * For multi-flavor vendors the vendor name prefix is stripped:\n * \"Catppuccin Mocha\" -> \"Mocha\"\n * \"Gruvbox Dark Hard\" -> \"Dark Hard\"\n *\n * @param themeId - A valid theme ID\n * @returns The short display label, or the full label if the theme is not found\n */\nexport function getShortLabel(themeId) {\n const cached = shortLabelCache.get(themeId);\n if (cached !== undefined)\n return cached;\n const flavor = flavorById.get(themeId);\n if (!flavor)\n return themeId;\n const vendorPkg = packages[flavor.vendor];\n if (!vendorPkg) {\n shortLabelCache.set(themeId, flavor.label);\n return flavor.label;\n }\n // Single-flavor vendors keep their full label\n if (vendorPkg.flavors.length === 1) {\n shortLabelCache.set(themeId, flavor.label);\n return flavor.label;\n }\n // Strip vendor display name prefix (case-insensitive, NFC-normalized for\n // consistent handling of composed/decomposed Unicode accents).\n const displayName = vendorPkg.name.replace(/\\s*\\(synced\\)\\s*/i, '').normalize('NFC');\n const label = flavor.label;\n let result;\n if (label.normalize('NFC').toLowerCase().startsWith(displayName.toLowerCase())) {\n const stripped = label.slice(displayName.length).trim();\n result = stripped || label;\n }\n else {\n result = label;\n }\n shortLabelCache.set(themeId, result);\n return result;\n}\n/** Pre-computed short labels for all themes. */\nexport const THEME_SHORT_LABELS = \n/*#__PURE__*/ Object.fromEntries(flavors.map((f) => [f.id, getShortLabel(f.id)]));\n//# sourceMappingURL=metadata.js.map","// SPDX-License-Identifier: MIT\n/**\n * Constants for theme selector component\n */\n\nimport type { ThemeFamily } from './types.js';\nimport { DEFAULT_THEME as CORE_DEFAULT_THEME } from '@lgtm-hq/turbo-themes-core';\n\n// Re-export ThemeFamily for convenience\nexport type { ThemeFamily } from './types.js';\n\nexport const STORAGE_KEY = 'turbo-theme';\nexport const LEGACY_STORAGE_KEYS = ['bulma-theme-flavor'];\nexport const DEFAULT_THEME = CORE_DEFAULT_THEME;\n\n/** ID of the CSS link element used by the blocking script to prevent FOUC. */\nexport const CSS_LINK_ID = 'turbo-theme-css';\n\n// DOM element IDs and selectors - centralized to avoid magic strings\nexport const DOM_IDS = {\n THEME_FLAVOR_TRIGGER: 'theme-flavor-trigger',\n THEME_FLAVOR_TRIGGER_ICON: 'theme-flavor-trigger-icon',\n THEME_FLAVOR_TRIGGER_LABEL: 'theme-flavor-trigger-label',\n THEME_FLAVOR_MENU: 'theme-flavor-menu',\n THEME_FLAVOR_SELECT: 'theme-flavor-select',\n} as const;\n\nexport const DOM_SELECTORS = {\n DROPDOWN_ITEMS: `#${DOM_IDS.THEME_FLAVOR_MENU} .dropdown-item.theme-item`,\n NAVBAR_DROPDOWN: '.navbar-item.has-dropdown',\n NAV_REPORTS: '[data-testid=\"nav-reports\"]',\n NAVBAR_ITEM: '.navbar-item',\n HIGHLIGHT_PRE: '.highlight > pre',\n THEME_CSS_LINKS: 'link[id^=\"theme-\"][id$=\"-css\"]',\n} as const;\n\nexport interface ThemeFamilyMeta {\n name: string;\n description: string;\n}\n\nexport const THEME_FAMILIES: Record<ThemeFamily, ThemeFamilyMeta> = {\n bulma: { name: 'Bulma', description: 'Classic Bulma themes' },\n catppuccin: { name: 'Catppuccin', description: 'Soothing pastel themes' },\n dracula: { name: 'Dracula', description: 'Dark vampire aesthetic' },\n gruvbox: { name: 'Gruvbox', description: 'Retro groove palette with warm, earthy tones' },\n github: { name: 'GitHub', description: 'GitHub-inspired themes' },\n nord: { name: 'Nord', description: 'Arctic, north-bluish color palette' },\n 'rose-pine': { name: 'Rosé Pine', description: 'All natural pine, faux fur and a bit of soho vibes' },\n solarized: { name: 'Solarized', description: 'Precision-balanced light and dark modes' },\n 'tokyo-night': { name: 'Tokyo Night', description: 'Neon-infused nightscape with crisp contrast' },\n};\n","// SPDX-License-Identifier: MIT\n/**\n * Centralized error handling for Turbo Themes.\n *\n * Provides a consistent error logging strategy with standardized message\n * formatting, error levels, and optional context for debugging.\n */\n\n/** Log prefix for all theme-related messages */\nexport const LOG_PREFIX = '[turbo-themes]';\n\n/** Error severity levels */\nexport enum ErrorLevel {\n WARN = 'warn',\n ERROR = 'error',\n}\n\n/** Structured theme error with code, message, level, and optional context */\nexport interface ThemeError {\n code: string;\n message: string;\n level: ErrorLevel;\n context?: Record<string, unknown>;\n}\n\n/**\n * Factory functions for creating structured theme errors.\n * Each function returns a ThemeError with appropriate code, message, and level.\n */\nexport const ThemeErrors = {\n /** Invalid theme ID provided */\n INVALID_THEME_ID: (themeId: string): ThemeError => ({\n code: 'INVALID_THEME_ID',\n message: `Invalid theme ID \"${themeId}\" not saved to storage`,\n level: ErrorLevel.WARN,\n context: { themeId },\n }),\n\n /** No themes available in registry */\n NO_THEMES_AVAILABLE: (): ThemeError => ({\n code: 'NO_THEMES_AVAILABLE',\n message: 'No themes available',\n level: ErrorLevel.ERROR,\n }),\n\n /** Invalid theme icon path */\n INVALID_ICON_PATH: (themeId: string): ThemeError => ({\n code: 'INVALID_ICON_PATH',\n message: `Invalid theme icon path for ${themeId}`,\n level: ErrorLevel.WARN,\n context: { themeId },\n }),\n\n /** Theme initialization failed */\n INIT_FAILED: (error: unknown): ThemeError => ({\n code: 'INIT_FAILED',\n message: 'Theme switcher initialization failed',\n level: ErrorLevel.ERROR,\n context: { error: error instanceof Error ? error.message : String(error) },\n }),\n\n /** Protocol-relative URL rejected for security */\n PROTOCOL_REJECTED: (): ThemeError => ({\n code: 'PROTOCOL_REJECTED',\n message: 'Protocol-relative base URL rejected for security',\n level: ErrorLevel.WARN,\n }),\n\n /** Insecure HTTP URL rejected */\n INSECURE_HTTP_REJECTED: (): ThemeError => ({\n code: 'INSECURE_HTTP_REJECTED',\n message: 'Insecure HTTP base URL rejected',\n level: ErrorLevel.WARN,\n }),\n\n /** Cross-origin URL rejected */\n CROSS_ORIGIN_REJECTED: (origin: string): ThemeError => ({\n code: 'CROSS_ORIGIN_REJECTED',\n message: `Cross-origin base URL rejected: ${origin}`,\n level: ErrorLevel.WARN,\n context: { origin },\n }),\n\n /** Invalid CSS path for theme */\n INVALID_CSS_PATH: (themeId: string): ThemeError => ({\n code: 'INVALID_CSS_PATH',\n message: `Invalid theme CSS path for ${themeId}`,\n level: ErrorLevel.WARN,\n context: { themeId },\n }),\n\n /** CSS failed to load */\n CSS_LOAD_FAILED: (themeId: string, error: unknown): ThemeError => ({\n code: 'CSS_LOAD_FAILED',\n message: `Theme CSS failed to load for ${themeId}`,\n level: ErrorLevel.WARN,\n context: {\n themeId,\n error: error instanceof Error ? error.message : String(error),\n },\n }),\n\n /** Storage unavailable (private browsing or disabled) */\n STORAGE_UNAVAILABLE: (operation: string, error: unknown): ThemeError => ({\n code: 'STORAGE_UNAVAILABLE',\n message: `localStorage ${operation} failed - storage may be unavailable`,\n level: ErrorLevel.WARN,\n context: {\n operation,\n error: error instanceof Error ? error.message : String(error),\n },\n }),\n};\n\n/**\n * Log a theme error to the console with consistent formatting.\n *\n * @param themeError - The structured error to log\n */\nexport function logThemeError(themeError: ThemeError): void {\n const prefixedMessage = `${LOG_PREFIX} ${themeError.message}`;\n\n if (themeError.level === ErrorLevel.ERROR) {\n if (themeError.context) {\n // Safe: prefixedMessage is constructed from controlled internal strings\n // nosemgrep: unsafe-formatstring\n console.error(prefixedMessage, themeError.context);\n } else {\n console.error(prefixedMessage);\n }\n } else {\n if (themeError.context) {\n // Safe: prefixedMessage is constructed from controlled internal strings\n // nosemgrep: unsafe-formatstring\n console.warn(prefixedMessage, themeError.context);\n } else {\n console.warn(prefixedMessage);\n }\n }\n}\n\n/**\n * Convenience function to log a ThemeError.\n *\n * @param error - The ThemeError instance to log\n */\nexport function logError<T extends ThemeError>(error: T): void {\n logThemeError(error);\n}\n","// SPDX-License-Identifier: MIT\n/**\n * Storage utilities for theme persistence\n */\n\nimport { STORAGE_KEY, LEGACY_STORAGE_KEYS, DEFAULT_THEME } from './constants.js';\nimport { ThemeErrors, logThemeError } from './errors.js';\n\n// Re-export DEFAULT_THEME for convenience\nexport { DEFAULT_THEME } from './constants.js';\n\n/**\n * Safely get an item from localStorage.\n * Returns null if storage is unavailable (e.g., private browsing mode).\n */\nfunction safeGetItem(windowObj: Window, key: string): string | null {\n try {\n return windowObj.localStorage.getItem(key);\n } catch (error) {\n logThemeError(ThemeErrors.STORAGE_UNAVAILABLE('getItem', error));\n return null;\n }\n}\n\n/**\n * Safely set an item in localStorage.\n * Returns false if storage is unavailable.\n */\nfunction safeSetItem(windowObj: Window, key: string, value: string): boolean {\n try {\n windowObj.localStorage.setItem(key, value);\n return true;\n } catch (error) {\n logThemeError(ThemeErrors.STORAGE_UNAVAILABLE('setItem', error));\n return false;\n }\n}\n\n/**\n * Safely remove an item from localStorage.\n * Silently fails if storage is unavailable.\n */\nfunction safeRemoveItem(windowObj: Window, key: string): void {\n try {\n windowObj.localStorage.removeItem(key);\n } catch (error) {\n logThemeError(ThemeErrors.STORAGE_UNAVAILABLE('removeItem', error));\n }\n}\n\n/**\n * Validates a theme ID against a set of valid IDs.\n * Returns the theme ID if valid, otherwise returns the default theme.\n */\nexport function validateThemeId(themeId: string | null, validIds: Set<string>): string {\n if (themeId && validIds.has(themeId)) {\n return themeId;\n }\n return DEFAULT_THEME;\n}\n\n/**\n * Migrates legacy storage keys to the current format.\n * Safely handles unavailable localStorage (e.g., private browsing).\n */\nexport function migrateLegacyStorage(windowObj: Window): void {\n for (const legacyKey of LEGACY_STORAGE_KEYS) {\n const legacy = safeGetItem(windowObj, legacyKey);\n if (legacy && !safeGetItem(windowObj, STORAGE_KEY)) {\n safeSetItem(windowObj, STORAGE_KEY, legacy);\n safeRemoveItem(windowObj, legacyKey);\n }\n }\n}\n\n/**\n * Gets the saved theme from localStorage, or returns default.\n * Optionally validates against a set of valid theme IDs.\n * Safely handles unavailable localStorage (e.g., private browsing).\n */\nexport function getSavedTheme(windowObj: Window, validIds?: Set<string>): string {\n const stored = safeGetItem(windowObj, STORAGE_KEY);\n if (validIds) {\n return validateThemeId(stored, validIds);\n }\n return stored || DEFAULT_THEME;\n}\n\n/**\n * Saves a theme to localStorage.\n * Optionally validates the theme ID against a set of valid IDs before saving.\n * Safely handles unavailable localStorage (e.g., private browsing).\n *\n * @param windowObj - Window object with localStorage\n * @param themeId - Theme ID to save\n * @param validIds - Optional set of valid theme IDs for validation\n * @returns true if saved successfully, false otherwise\n */\nexport function saveTheme(windowObj: Window, themeId: string, validIds?: Set<string>): boolean {\n if (validIds && !validIds.has(themeId)) {\n logThemeError(ThemeErrors.INVALID_THEME_ID(themeId));\n return false;\n }\n return safeSetItem(windowObj, STORAGE_KEY, themeId);\n}\n","// SPDX-License-Identifier: MIT\n/**\n * Theme CSS loading utilities\n */\n\nimport { CSS_LINK_ID, DOM_SELECTORS } from './constants.js';\nimport { ThemeErrors, logThemeError } from './errors.js';\n\nexport interface ThemeInfo {\n id: string;\n cssFile: string;\n icon?: string | undefined;\n}\n\n/**\n * Resolves an asset path relative to the site's base URL.\n */\nexport function resolveAssetPath(assetPath: string, baseUrl: string): string {\n // Normalize baseUrl - remove trailing slash if present, then add one\n const normalizedBase = baseUrl.replace(/\\/$/, '');\n const base = normalizedBase ? `${window.location.origin}${normalizedBase}/` : `${window.location.origin}/`;\n return new URL(assetPath, base).pathname;\n}\n\n/**\n * Gets the base URL from the document's data-baseurl attribute.\n * Validates the URL to prevent injection attacks:\n * - Rejects protocol-relative URLs (//example.com)\n * - Rejects non-HTTPS absolute URLs (except localhost)\n * - Only allows same-origin or relative paths\n */\nexport function getBaseUrl(doc: Document): string {\n const baseElement = doc.documentElement;\n const raw = baseElement?.getAttribute('data-baseurl') || '';\n\n // Empty base URL is valid (use site root)\n if (!raw) return '';\n\n // Reject protocol-relative URLs (security risk)\n if (raw.startsWith('//')) {\n logThemeError(ThemeErrors.PROTOCOL_REJECTED());\n return '';\n }\n\n // Reject non-HTTPS absolute URLs (except localhost for development)\n if (raw.startsWith('http://') && !raw.startsWith('http://localhost')) {\n logThemeError(ThemeErrors.INSECURE_HTTP_REJECTED());\n return '';\n }\n\n try {\n // Parse relative to current origin to validate\n const currentOrigin = typeof window !== 'undefined' ? window.location.origin : 'http://localhost';\n const u = new URL(raw, currentOrigin);\n\n // Only allow same-origin URLs or relative paths\n if (u.origin !== currentOrigin) {\n logThemeError(ThemeErrors.CROSS_ORIGIN_REJECTED(u.origin));\n return '';\n }\n\n return u.pathname.replace(/\\/$/, '');\n } catch {\n return '';\n }\n}\n\n/**\n * Extracts the theme ID from a theme link element's ID.\n * Strips a leading \"theme-\" prefix and trailing \"-css\" suffix.\n */\nfunction extractThemeIdFromLinkId(linkId: string): string {\n return linkId.replace(/^theme-/, '').replace(/-css$/, '');\n}\n\n/**\n * Clears onload/onerror handlers from a link element to prevent memory leaks.\n */\nfunction clearLinkHandlers(link: HTMLLinkElement): void {\n link.onload = null;\n link.onerror = null;\n}\n\n/**\n * Loads a CSS file with a timeout, returning a promise that resolves when loaded.\n */\nexport function loadCSSWithTimeout(\n link: HTMLLinkElement,\n themeId: string,\n timeoutMs = 10000\n): Promise<void> {\n return new Promise((resolve, reject) => {\n const timeoutId = setTimeout(() => {\n clearLinkHandlers(link);\n reject(new Error(`Theme ${themeId} load timeout`));\n }, timeoutMs);\n\n link.onload = () => {\n clearTimeout(timeoutId);\n clearLinkHandlers(link);\n resolve();\n };\n\n link.onerror = () => {\n clearTimeout(timeoutId);\n clearLinkHandlers(link);\n reject(new Error(`Failed to load theme ${themeId}`));\n };\n });\n}\n\n/**\n * Gets the current theme from document element classes\n */\nexport function getCurrentThemeFromClasses(element: HTMLElement): string | null {\n const classList = Array.from(element.classList);\n for (const className of classList) {\n if (className.startsWith('theme-')) {\n return className.substring(6); // Remove 'theme-' prefix\n }\n }\n return null;\n}\n\n/**\n * Applies theme class to document element\n */\nexport function applyThemeClass(doc: Document, themeId: string): void {\n // Remove existing theme classes in a single batch operation\n const themeClasses = Array.from(doc.documentElement.classList).filter((className) =>\n className.startsWith('theme-'),\n );\n if (themeClasses.length > 0) {\n doc.documentElement.classList.remove(...themeClasses);\n }\n\n // Add the new theme class\n doc.documentElement.classList.add(`theme-${themeId}`);\n}\n\n/**\n * Loads theme CSS file if not already loaded\n */\nexport async function loadThemeCSS(\n doc: Document,\n theme: ThemeInfo,\n baseUrl: string\n): Promise<void> {\n const themeLinkId = `theme-${theme.id}-css`;\n let themeLink = doc.getElementById(themeLinkId) as HTMLLinkElement | null;\n\n // Adopt the blocking script's link element if present (prevents duplicate CSS loads)\n if (!themeLink) {\n const blockingLink = doc.getElementById(CSS_LINK_ID) as HTMLLinkElement | null;\n if (blockingLink) {\n blockingLink.id = themeLinkId;\n blockingLink.setAttribute('data-theme-id', theme.id);\n themeLink = blockingLink;\n }\n }\n\n if (!themeLink) {\n // Record existing theme links before appending the new one\n const existingLinks = doc.querySelectorAll(DOM_SELECTORS.THEME_CSS_LINKS);\n\n themeLink = doc.createElement('link');\n themeLink.id = themeLinkId;\n themeLink.rel = 'stylesheet';\n themeLink.type = 'text/css';\n themeLink.setAttribute('data-theme-id', theme.id);\n\n try {\n themeLink.href = resolveAssetPath(theme.cssFile, baseUrl);\n } catch {\n logThemeError(ThemeErrors.INVALID_CSS_PATH(theme.id));\n return;\n }\n\n doc.head.appendChild(themeLink);\n\n try {\n await loadCSSWithTimeout(themeLink, theme.id);\n\n // Only remove old theme links after successful load\n existingLinks.forEach((link) => {\n const linkThemeId = extractThemeIdFromLinkId(link.id);\n if (linkThemeId !== theme.id && linkThemeId !== 'base') {\n link.remove();\n }\n });\n } catch (error) {\n // Loading failed — remove the new link and keep prior theme intact\n themeLink.remove();\n logThemeError(ThemeErrors.CSS_LOAD_FAILED(theme.id, error));\n }\n } else {\n // Link already exists — clean up any other stale theme links\n doc.querySelectorAll(DOM_SELECTORS.THEME_CSS_LINKS).forEach((link) => {\n const linkThemeId = extractThemeIdFromLinkId(link.id);\n if (linkThemeId !== theme.id && linkThemeId !== 'base') {\n link.remove();\n }\n });\n }\n}\n","// SPDX-License-Identifier: MIT\n/**\n * Dropdown helper functions\n */\n\n/**\n * Sets the active state (is-active class and aria-checked) on a theme item element.\n */\nexport function setItemActiveState(item: Element, isActive: boolean): void {\n if (isActive) {\n item.classList.add('is-active');\n } else {\n item.classList.remove('is-active');\n }\n item.setAttribute('aria-checked', String(isActive));\n}\n\n/**\n * Sets tabindex attribute on all items in a collection.\n */\nexport function setTabindexBatch(items: HTMLElement[], value: string): void {\n for (const item of items) {\n item.setAttribute('tabindex', value);\n }\n}\n","// SPDX-License-Identifier: MIT\n/**\n * Maps core theme flavors to UI-specific format\n */\n\nimport type { ThemeFlavor as CanonicalThemeFlavor } from '@lgtm-hq/turbo-themes-core';\nimport type { ThemeFamily } from './types.js';\n\nexport interface ThemeColors {\n bg: string;\n surface: string;\n accent: string;\n text: string;\n}\n\nexport interface ThemeFlavor extends Pick<CanonicalThemeFlavor, 'id' | 'appearance' | 'vendor'> {\n id: string;\n name: string;\n description: string;\n cssFile: string;\n icon?: string | undefined;\n family: ThemeFamily;\n colors: ThemeColors;\n}\n\n// ============================================================================\n// Lookup Tables\n// ============================================================================\n\n/** Vendor to family mapping */\nconst VENDOR_FAMILY_MAP: Record<string, ThemeFamily> = {\n bulma: 'bulma',\n catppuccin: 'catppuccin',\n dracula: 'dracula',\n gruvbox: 'gruvbox',\n github: 'github',\n nord: 'nord',\n 'rose-pine': 'rose-pine',\n solarized: 'solarized',\n 'tokyo-night': 'tokyo-night',\n};\n\nconst DEFAULT_FAMILY: ThemeFamily = 'bulma';\n\n/** Icon configuration - string for single icon, object for appearance-specific */\ninterface AppearanceIcons {\n light: string;\n dark: string;\n}\n\nconst VENDOR_ICON_MAP: Record<string, string | AppearanceIcons> = {\n bulma: 'assets/img/turbo-themes-logo.png',\n catppuccin: {\n light: 'assets/img/catppuccin-logo-latte.png',\n dark: 'assets/img/catppuccin-logo-macchiato.png',\n },\n dracula: 'assets/img/dracula-logo.png',\n gruvbox: {\n light: 'assets/img/gruvbox-light.png',\n dark: 'assets/img/gruvbox-dark.png',\n },\n github: {\n light: 'assets/img/github-logo-light.png',\n dark: 'assets/img/github-logo-dark.png',\n },\n nord: 'assets/img/nord.png',\n 'rose-pine': {\n light: 'assets/img/rose-pine-dawn.png',\n dark: 'assets/img/rose-pine.png',\n },\n solarized: {\n light: 'assets/img/solarized-light.png',\n dark: 'assets/img/solarized-dark.png',\n },\n 'tokyo-night': 'assets/img/tokyo-night.png',\n};\n\n/** Predefined flavor descriptions */\nconst FLAVOR_DESCRIPTIONS: Record<string, string> = {\n 'bulma-light': 'Classic Bulma look with a bright, neutral palette.',\n 'bulma-dark': 'Dark Bulma theme tuned for low-light reading.',\n 'catppuccin-latte': 'Light, soft Catppuccin palette for daytime use.',\n 'catppuccin-frappe': 'Balanced dark Catppuccin theme for focused work.',\n 'catppuccin-macchiato': 'Deep, atmospheric Catppuccin variant with rich contrast.',\n 'catppuccin-mocha': 'Cozy, high-contrast Catppuccin theme for late-night sessions.',\n dracula: 'Iconic Dracula dark theme with vibrant accents.',\n 'gruvbox-dark-hard': 'Highest contrast dark Gruvbox palette with deep shadows.',\n 'gruvbox-dark': 'Classic Gruvbox dark palette with warm, muted tones.',\n 'gruvbox-dark-soft': 'Softer dark Gruvbox palette with reduced contrast.',\n 'gruvbox-light-hard': 'Bright, crisp Gruvbox light palette with extra contrast.',\n 'gruvbox-light': 'Classic Gruvbox light palette with warm paper tones.',\n 'gruvbox-light-soft': 'Soft, low-contrast Gruvbox light palette for long sessions.',\n 'github-light': 'GitHub-inspired light theme suited for documentation and UI heavy pages.',\n 'github-dark': 'GitHub dark theme optimized for code-heavy views.',\n nord: 'Arctic, north-bluish color palette inspired by the polar night.',\n 'rose-pine': 'Elegant dark theme with natural pine and soho vibes.',\n 'rose-pine-moon': 'Deeper variant of Rosé Pine with enhanced contrast.',\n 'rose-pine-dawn': 'Light Rosé Pine variant for daytime use.',\n 'solarized-dark': 'Solarized Dark with a balanced, low-contrast palette.',\n 'solarized-light': 'Solarized Light tuned for bright, daylight-friendly UIs.',\n 'tokyo-night-dark': 'Deep midnight blues with neon accents.',\n 'tokyo-night-storm': 'Stormy variant with richer contrast and depth.',\n 'tokyo-night-light': 'Clean daylight palette inspired by Tokyo mornings.',\n};\n\n// ============================================================================\n// Helper Functions\n// ============================================================================\n\n/**\n * Gets the theme family from vendor name\n */\nfunction getFamily(vendor: string): ThemeFamily {\n return VENDOR_FAMILY_MAP[vendor] ?? DEFAULT_FAMILY;\n}\n\n/**\n * Gets icon path for a vendor\n */\nfunction getIconForVendor(vendor: string, appearance: 'light' | 'dark'): string | undefined {\n const iconConfig = VENDOR_ICON_MAP[vendor];\n\n if (!iconConfig) {\n return undefined;\n }\n\n if (typeof iconConfig === 'string') {\n return iconConfig;\n }\n\n return iconConfig[appearance];\n}\n\n/**\n * Gets description for a flavor\n */\nfunction getDescriptionForFlavor(id: string, label: string): string {\n return FLAVOR_DESCRIPTIONS[id] ?? `${label} theme`;\n}\n\n/**\n * Extracts preview colors from theme tokens\n */\nfunction extractPreviewColors(tokens: CanonicalThemeFlavor['tokens']): ThemeColors {\n return {\n bg: tokens.background.base,\n surface: tokens.background.surface,\n accent: tokens.brand.primary,\n text: tokens.text.primary,\n };\n}\n\n// ============================================================================\n// Public API\n// ============================================================================\n\n/**\n * Maps a canonical theme flavor to UI-specific format\n */\nexport function mapFlavorToUI(flavor: CanonicalThemeFlavor): ThemeFlavor {\n const family = getFamily(flavor.vendor);\n return {\n id: flavor.id,\n name: flavor.label,\n description: getDescriptionForFlavor(flavor.id, flavor.label),\n cssFile: `packages/css/dist/themes/${flavor.id}.css`,\n icon: getIconForVendor(flavor.vendor, flavor.appearance),\n family,\n vendor: flavor.vendor,\n appearance: flavor.appearance,\n colors: extractPreviewColors(flavor.tokens),\n };\n}\n","// SPDX-License-Identifier: MIT\n/**\n * Theme resolution utilities - centralized theme lookup and validation.\n *\n * Provides cached access to theme data and validation to avoid\n * repeated mapping and set creation across the codebase.\n */\n\nimport { flavors } from '@lgtm-hq/turbo-themes-core';\nimport { mapFlavorToUI, type ThemeFlavor } from './theme-mapper.js';\nimport { DEFAULT_THEME } from './constants.js';\n\n// Cache mapped themes and valid IDs\nlet mappedThemes: ThemeFlavor[] | null = null;\nlet validThemeIds: Set<string> | null = null;\n\n/**\n * Gets all themes mapped to UI format.\n * Results are cached for performance.\n */\nexport function getThemes(): ThemeFlavor[] {\n if (!mappedThemes) {\n mappedThemes = flavors.map(mapFlavorToUI);\n }\n return mappedThemes || [];\n}\n\n/**\n * Gets a Set of all valid theme IDs.\n * Results are cached for performance.\n */\nexport function getValidThemeIds(): Set<string> {\n if (!validThemeIds) {\n validThemeIds = new Set(flavors.map((f) => f.id));\n }\n return validThemeIds;\n}\n\n/**\n * Resolves a theme by ID, falling back to default if not found.\n *\n * @param themeId - The theme ID to resolve\n * @returns The matching theme, default theme, or first available theme\n */\nexport function resolveTheme(themeId: string): ThemeFlavor | undefined {\n const themes = getThemes();\n return (\n themes.find((t) => t.id === themeId) ||\n themes.find((t) => t.id === DEFAULT_THEME) ||\n themes[0]\n );\n}\n\n/**\n * Validates a theme ID for safety and format correctness.\n *\n * Accepts only alphanumeric characters, hyphens, and underscores.\n * Rejects special characters, unicode, and excessively long IDs.\n *\n * @param id - The value to validate as a theme ID\n * @returns True if the ID is valid, false otherwise\n */\nexport function isValidThemeId(id: unknown): boolean {\n if (typeof id !== 'string') return false;\n if (id.length === 0) return false;\n if (id.length > 100) return false;\n return /^[a-zA-Z0-9_-]+$/.test(id);\n}\n\n/**\n * Sanitizes a theme ID by removing unsafe characters.\n *\n * Removes any characters that could cause DOM/CSS/XSS issues.\n * Used as a fallback when displaying potentially untrusted input.\n *\n * @param id - The theme ID to sanitize\n * @returns The sanitized ID containing only safe characters\n */\nexport function sanitizeThemeId(id: string): string {\n return id.replace(/[^a-zA-Z0-9_-]/g, '');\n}\n\n/**\n * Resets the cached themes. Used for testing.\n * @internal\n */\nexport function _resetThemeCache(): void {\n mappedThemes = null;\n validThemeIds = null;\n}\n","// SPDX-License-Identifier: MIT\n/**\n * Theme application logic\n */\n\nimport { DOM_IDS, DOM_SELECTORS, THEME_FAMILIES } from './constants.js';\nimport { getBaseUrl, applyThemeClass, loadThemeCSS, resolveAssetPath, getCurrentThemeFromClasses } from './theme-loader.js';\nimport { setItemActiveState } from './dropdown/helpers.js';\nimport { ThemeErrors, logThemeError } from './errors.js';\nimport { resolveTheme } from './theme-resolver.js';\n\n/**\n * Applies a theme to the document\n */\nexport async function applyTheme(doc: Document, themeId: string): Promise<void> {\n const theme = resolveTheme(themeId);\n if (!theme) {\n logThemeError(ThemeErrors.NO_THEMES_AVAILABLE());\n return;\n }\n const baseUrl = getBaseUrl(doc);\n\n // Add loading state to trigger button\n const trigger = doc.getElementById(DOM_IDS.THEME_FLAVOR_TRIGGER) as HTMLButtonElement | null;\n if (trigger) {\n trigger.classList.add('is-loading');\n }\n\n try {\n // Apply theme class immediately (before CSS loading)\n applyThemeClass(doc, theme.id);\n\n // Load theme CSS\n await loadThemeCSS(doc, theme, baseUrl);\n\n // Update trigger button icon\n const triggerIcon = doc.getElementById(\n DOM_IDS.THEME_FLAVOR_TRIGGER_ICON\n ) as HTMLImageElement | null;\n\n if (triggerIcon && theme.icon) {\n try {\n triggerIcon.src = resolveAssetPath(theme.icon, baseUrl);\n const familyMeta = THEME_FAMILIES[theme.family];\n const familyName = familyMeta?.name ?? theme.family;\n triggerIcon.alt = `${familyName} ${theme.name}`;\n triggerIcon.title = `${familyName} ${theme.name}`;\n } catch {\n logThemeError(ThemeErrors.INVALID_ICON_PATH(theme.id));\n }\n }\n\n // Update trigger button label\n const triggerLabel = doc.getElementById(\n DOM_IDS.THEME_FLAVOR_TRIGGER_LABEL\n ) as HTMLElement | null;\n if (triggerLabel) {\n triggerLabel.textContent = theme.name;\n }\n\n // Update active state in dropdown\n doc.querySelectorAll(DOM_SELECTORS.DROPDOWN_ITEMS).forEach((item) => {\n setItemActiveState(item, item.getAttribute('data-theme-id') === theme.id);\n });\n } finally {\n if (trigger) {\n trigger.classList.remove('is-loading');\n }\n }\n}\n\n/**\n * Gets the current theme from classes or returns default\n */\nexport function getCurrentTheme(doc: Document, defaultTheme: string): string {\n return getCurrentThemeFromClasses(doc.documentElement) || defaultTheme;\n}\n","// SPDX-License-Identifier: MIT\n/**\n * Dropdown state management\n */\n\nimport { setItemActiveState, setTabindexBatch } from './helpers.js';\n\nexport interface DropdownElements {\n dropdownMenu: HTMLElement;\n trigger: HTMLButtonElement;\n dropdown: HTMLElement;\n selectEl: HTMLSelectElement | null;\n}\n\nexport interface DropdownState {\n currentIndex: number;\n menuItems: HTMLElement[];\n}\n\nexport interface DropdownStateManager {\n updateAriaExpanded: (expanded: boolean) => void;\n focusMenuItem: (index: number) => void;\n closeDropdown: (options?: { restoreFocus?: boolean }) => void;\n toggleDropdown: (focusFirst?: boolean) => void;\n}\n\n/**\n * Creates dropdown state management functions.\n */\nexport function createDropdownStateManager(\n elements: DropdownElements,\n state: DropdownState\n): DropdownStateManager {\n const { trigger, dropdown } = elements;\n\n const updateAriaExpanded = (expanded: boolean): void => {\n trigger.setAttribute('aria-expanded', String(expanded));\n };\n\n const focusMenuItem = (index: number): void => {\n if (index < 0 || index >= state.menuItems.length) return;\n\n const item = state.menuItems[index]!;\n setTabindexBatch(state.menuItems, '-1');\n item.setAttribute('tabindex', '0');\n item.focus();\n state.currentIndex = index;\n };\n\n const closeDropdown = (options: { restoreFocus?: boolean } = {}): void => {\n const { restoreFocus = true } = options;\n dropdown.classList.remove('is-active');\n updateAriaExpanded(false);\n setTabindexBatch(state.menuItems, '-1');\n state.currentIndex = -1;\n if (restoreFocus) {\n trigger.focus();\n }\n };\n\n const toggleDropdown = (focusFirst = false): void => {\n const isActive = dropdown.classList.toggle('is-active');\n updateAriaExpanded(isActive);\n\n if (!isActive) {\n state.currentIndex = -1;\n setTabindexBatch(state.menuItems, '-1');\n for (const menuItem of state.menuItems) {\n const isActiveItem = menuItem.classList.contains('is-active');\n setItemActiveState(menuItem, isActiveItem);\n }\n } else if (focusFirst && state.menuItems.length > 0) {\n focusMenuItem(0);\n }\n };\n\n return { updateAriaExpanded, focusMenuItem, closeDropdown, toggleDropdown };\n}\n","// SPDX-License-Identifier: MIT\n/**\n * Dropdown event handlers\n */\n\nimport type { DropdownElements, DropdownState, DropdownStateManager } from './state.js';\n\n/**\n * Calculates the next index when navigating down through menu items.\n */\nfunction getNextIndex(currentIndex: number, totalItems: number): number {\n return currentIndex < totalItems - 1 ? currentIndex + 1 : 0;\n}\n\n/**\n * Calculates the previous index when navigating up through menu items.\n */\nfunction getPrevIndex(currentIndex: number, totalItems: number): number {\n return currentIndex > 0 ? currentIndex - 1 : totalItems - 1;\n}\n\n/**\n * Handles keyboard navigation on the trigger button.\n */\nfunction handleTriggerKeydown(\n e: KeyboardEvent,\n dropdown: HTMLElement,\n state: DropdownState,\n stateManager: DropdownStateManager\n): void {\n const { focusMenuItem, toggleDropdown, updateAriaExpanded } = stateManager;\n const totalItems = state.menuItems.length;\n\n switch (e.key) {\n case 'Enter':\n case ' ':\n e.preventDefault();\n toggleDropdown(!dropdown.classList.contains('is-active'));\n break;\n\n case 'ArrowDown':\n e.preventDefault();\n if (!dropdown.classList.contains('is-active')) {\n dropdown.classList.add('is-active');\n updateAriaExpanded(true);\n focusMenuItem(0);\n } else {\n const nextIndex = state.currentIndex < 0 ? 0 : getNextIndex(state.currentIndex, totalItems);\n focusMenuItem(nextIndex);\n }\n break;\n\n case 'ArrowUp':\n e.preventDefault();\n if (!dropdown.classList.contains('is-active')) {\n dropdown.classList.add('is-active');\n updateAriaExpanded(true);\n focusMenuItem(totalItems - 1);\n } else {\n const startIndex = state.currentIndex < 0 ? totalItems - 1 : state.currentIndex;\n focusMenuItem(getPrevIndex(startIndex, totalItems));\n }\n break;\n }\n}\n\n/**\n * Handles keyboard navigation on menu items.\n */\nfunction handleMenuItemKeydown(\n e: KeyboardEvent,\n index: number,\n item: HTMLElement,\n state: DropdownState,\n stateManager: DropdownStateManager\n): void {\n const { focusMenuItem, closeDropdown } = stateManager;\n const totalItems = state.menuItems.length;\n\n switch (e.key) {\n case 'ArrowDown':\n e.preventDefault();\n focusMenuItem(getNextIndex(index, totalItems));\n break;\n\n case 'ArrowUp':\n e.preventDefault();\n focusMenuItem(getPrevIndex(index, totalItems));\n break;\n\n case 'Escape':\n e.preventDefault();\n closeDropdown();\n break;\n\n case 'Enter':\n case ' ':\n e.preventDefault();\n item.click();\n break;\n\n case 'Home':\n e.preventDefault();\n focusMenuItem(0);\n break;\n\n case 'End':\n e.preventDefault();\n focusMenuItem(totalItems - 1);\n break;\n }\n}\n\n/**\n * Wires up all event handlers for the dropdown.\n */\nexport function wireDropdownEventHandlers(\n documentObj: Document,\n elements: DropdownElements,\n state: DropdownState,\n stateManager: DropdownStateManager,\n abortController: AbortController\n): void {\n const { trigger, dropdown } = elements;\n const { closeDropdown, toggleDropdown } = stateManager;\n const signal = abortController.signal;\n\n // Trigger click\n trigger.addEventListener(\n 'click',\n (e) => {\n e.preventDefault();\n toggleDropdown();\n },\n { signal }\n );\n\n // Outside click\n documentObj.addEventListener(\n 'click',\n (e: MouseEvent) => {\n if (!dropdown.contains(e.target as Node)) {\n closeDropdown({ restoreFocus: false });\n }\n },\n { signal }\n );\n\n // Escape key (document-level)\n documentObj.addEventListener(\n 'keydown',\n (e: KeyboardEvent) => {\n if (e.key === 'Escape' && dropdown.classList.contains('is-active')) {\n closeDropdown({ restoreFocus: true });\n }\n },\n { signal }\n );\n\n // Trigger keyboard navigation\n trigger.addEventListener(\n 'keydown',\n (e: KeyboardEvent) => handleTriggerKeydown(e, dropdown, state, stateManager),\n { signal }\n );\n\n // Menu item keyboard navigation\n for (const [index, item] of state.menuItems.entries()) {\n item.addEventListener(\n 'keydown',\n (e: KeyboardEvent) => handleMenuItemKeydown(e, index, item, state, stateManager),\n { signal }\n );\n }\n}\n","// SPDX-License-Identifier: MIT\n/**\n * Dropdown UI element creation\n */\n\nimport type { ThemeFlavor } from '../theme-mapper.js';\nimport type { ThemeFamilyMeta } from '../constants.js';\nimport { setItemActiveState } from './helpers.js';\nimport { DOM_IDS, DOM_SELECTORS } from '../constants.js';\nimport { resolveAssetPath } from '../theme-loader.js';\nimport { ThemeErrors, logThemeError } from '../errors.js';\nimport type { DropdownElements } from './state.js';\n\nexport interface DropdownContext {\n documentObj: Document;\n windowObj: Window;\n baseUrl: string;\n currentThemeId: string;\n selectEl: HTMLSelectElement | null;\n menuItems: HTMLElement[];\n closeDropdown: (options?: { restoreFocus?: boolean }) => void;\n onThemeSelect: (themeId: string) => void;\n}\n\n/**\n * Creates a checkmark SVG icon for the active theme indicator.\n */\nexport function createCheckmarkIcon(doc: Document): SVGSVGElement {\n const svg = doc.createElementNS('http://www.w3.org/2000/svg', 'svg');\n svg.setAttribute('width', '16');\n svg.setAttribute('height', '16');\n svg.setAttribute('viewBox', '0 0 24 24');\n svg.setAttribute('fill', 'none');\n svg.setAttribute('stroke', 'currentColor');\n svg.setAttribute('stroke-width', '3');\n svg.setAttribute('stroke-linecap', 'round');\n svg.setAttribute('stroke-linejoin', 'round');\n\n const polyline = doc.createElementNS('http://www.w3.org/2000/svg', 'polyline');\n polyline.setAttribute('points', '20 6 9 17 4 12');\n svg.appendChild(polyline);\n\n return svg;\n}\n\n/**\n * Creates a single theme item button element.\n */\nexport function createThemeItemElement(\n ctx: DropdownContext,\n theme: ThemeFlavor,\n familyMeta: ThemeFamilyMeta\n): HTMLButtonElement {\n const { documentObj, baseUrl, currentThemeId, selectEl, windowObj, closeDropdown, onThemeSelect } = ctx;\n\n const item = documentObj.createElement('button');\n item.type = 'button';\n item.className = 'dropdown-item theme-item';\n item.setAttribute('data-theme-id', theme.id);\n item.setAttribute('data-appearance', theme.appearance);\n item.setAttribute('role', 'menuitemradio');\n item.setAttribute(\n 'aria-label',\n `${familyMeta.name} ${theme.name} (${theme.appearance}). ${theme.description}`\n );\n item.setAttribute('tabindex', '-1');\n\n const isActive = theme.id === currentThemeId;\n setItemActiveState(item, isActive);\n\n // Icon (only render if theme has an icon)\n if (theme.icon) {\n const icon = documentObj.createElement('img');\n icon.className = 'theme-icon';\n try {\n icon.src = resolveAssetPath(theme.icon, baseUrl);\n } catch {\n logThemeError(ThemeErrors.INVALID_ICON_PATH(theme.id));\n icon.src = theme.icon;\n }\n icon.alt = `${familyMeta.name} ${theme.name}`;\n icon.width = 24;\n icon.height = 24;\n item.appendChild(icon);\n } else {\n // Add placeholder for consistent spacing\n const placeholder = documentObj.createElement('span');\n placeholder.className = 'theme-icon theme-icon-placeholder';\n placeholder.setAttribute('aria-hidden', 'true');\n item.appendChild(placeholder);\n }\n\n // Text content\n const copy = documentObj.createElement('div');\n copy.className = 'theme-copy';\n\n const titleEl = documentObj.createElement('span');\n titleEl.className = 'theme-title';\n titleEl.textContent = `${familyMeta.name} · ${theme.name}`;\n copy.appendChild(titleEl);\n\n const descriptionEl = documentObj.createElement('span');\n descriptionEl.className = 'theme-description';\n descriptionEl.textContent = theme.description;\n copy.appendChild(descriptionEl);\n\n item.appendChild(copy);\n\n // Checkmark for active state\n const check = documentObj.createElement('span');\n check.className = 'theme-check';\n check.appendChild(createCheckmarkIcon(documentObj));\n item.appendChild(check);\n\n // Click handler\n item.addEventListener('click', (e) => {\n e.preventDefault();\n onThemeSelect(theme.id);\n if (selectEl) {\n selectEl.value = theme.id;\n selectEl.dispatchEvent(new Event('change', { bubbles: true }));\n }\n closeDropdown({ restoreFocus: true });\n });\n\n return item;\n}\n\n/**\n * Creates a family group container with header and theme items.\n */\nexport function createFamilyGroup(\n ctx: DropdownContext,\n familyKey: string,\n themes: ThemeFlavor[],\n familyMeta: ThemeFamilyMeta,\n animationDelay: number\n): { group: HTMLDivElement; items: HTMLElement[] } | null {\n const { documentObj } = ctx;\n if (themes.length === 0) return null;\n\n const items: HTMLElement[] = [];\n\n // Create family group container\n const group = documentObj.createElement('div');\n group.className = 'theme-family-group';\n group.setAttribute('role', 'group');\n group.setAttribute('aria-labelledby', `theme-family-${familyKey}`);\n if (group.style && typeof group.style.setProperty === 'function') {\n group.style.setProperty('--animation-delay', `${animationDelay}ms`);\n }\n\n // Create family header\n const header = documentObj.createElement('div');\n header.className = 'theme-family-header';\n header.id = `theme-family-${familyKey}`;\n\n const headerTitle = documentObj.createElement('span');\n headerTitle.className = 'theme-family-name';\n headerTitle.textContent = familyMeta.name;\n header.appendChild(headerTitle);\n group.appendChild(header);\n\n // Create themes container\n const themesContainer = documentObj.createElement('div');\n themesContainer.className = 'theme-family-items';\n\n themes.forEach((theme) => {\n const item = createThemeItemElement(ctx, theme, familyMeta);\n items.push(item);\n themesContainer.appendChild(item);\n });\n\n group.appendChild(themesContainer);\n\n return { group, items };\n}\n\n/**\n * Populates the dropdown menu with all theme family groups.\n */\nexport function populateDropdownMenu(\n ctx: DropdownContext,\n dropdownMenu: HTMLElement,\n themes: ThemeFlavor[],\n themeFamilies: Record<string, ThemeFamilyMeta>\n): void {\n const families = Object.keys(themeFamilies);\n let animationDelay = 0;\n\n families.forEach((familyKey) => {\n const familyThemes = themes.filter((t) => t.family === familyKey);\n const familyMeta = themeFamilies[familyKey];\n if (!familyMeta) return;\n\n const result = createFamilyGroup(ctx, familyKey, familyThemes, familyMeta, animationDelay);\n if (result) {\n ctx.menuItems.push(...result.items);\n dropdownMenu.appendChild(result.group);\n animationDelay += 30;\n }\n });\n}\n\n/**\n * Wires up the native select element for theme selection.\n */\nexport function wireNativeSelect(\n ctx: DropdownContext,\n selectEl: HTMLSelectElement,\n themes: ThemeFlavor[],\n defaultTheme: string\n): void {\n const { documentObj, windowObj, onThemeSelect } = ctx;\n\n // Clear existing options\n while (selectEl.firstChild) {\n selectEl.removeChild(selectEl.firstChild);\n }\n\n // Populate options\n themes.forEach((theme) => {\n const option = documentObj.createElement('option');\n option.value = theme.id;\n option.textContent = theme.name;\n option.selected = theme.id === ctx.currentThemeId;\n selectEl.appendChild(option);\n });\n\n selectEl.disabled = false;\n\n // Change handler\n selectEl.addEventListener('change', (event) => {\n const target = event.target as HTMLSelectElement | null;\n const selectedThemeId = target?.value || defaultTheme;\n onThemeSelect(selectedThemeId);\n });\n}\n\n/**\n * Gets DOM elements required for the dropdown, returning null if any are missing.\n */\nexport function getDropdownElements(documentObj: Document): DropdownElements | null {\n const dropdownMenu = documentObj.getElementById(DOM_IDS.THEME_FLAVOR_MENU);\n const trigger = documentObj.getElementById(\n DOM_IDS.THEME_FLAVOR_TRIGGER\n ) as HTMLButtonElement | null;\n const dropdown = trigger?.closest(DOM_SELECTORS.NAVBAR_DROPDOWN) as HTMLElement | null;\n const selectEl = documentObj.getElementById(\n DOM_IDS.THEME_FLAVOR_SELECT\n ) as HTMLSelectElement | null;\n\n if (!dropdownMenu || !trigger || !dropdown) {\n return null;\n }\n\n return { dropdownMenu, trigger, dropdown, selectEl };\n}\n","// SPDX-License-Identifier: MIT\n/**\n * Navbar active state management\n */\n\nimport { DOM_SELECTORS } from './constants.js';\n\n/**\n * Normalizes a path by removing trailing slashes, defaulting to '/' if empty.\n */\nfunction normalizePath(path: string): string {\n return path.replace(/\\/$/, '') || '/';\n}\n\n/**\n * Initializes navbar active state based on current path\n */\nexport function initNavbar(documentObj: Document): void {\n const currentPath = documentObj.location.pathname;\n const normalizedCurrentPath = normalizePath(currentPath);\n const navbarItems = documentObj.querySelectorAll(DOM_SELECTORS.NAVBAR_ITEM);\n\n // Single pass: find matching item and collect items to deactivate\n let matchingItem: Element | null = null;\n const itemsToDeactivate: Element[] = [];\n\n navbarItems.forEach((item) => {\n const link = item as HTMLAnchorElement;\n if (!link.href) return;\n\n try {\n const normalizedLinkPath = normalizePath(new URL(link.href).pathname);\n if (normalizedCurrentPath === normalizedLinkPath) {\n matchingItem = item;\n } else {\n // Collect non-matching items with valid URLs for deactivation\n itemsToDeactivate.push(item);\n }\n } catch {\n // Ignore invalid URLs\n }\n });\n\n // Apply deactivation after finding match (single DOM batch)\n for (const item of itemsToDeactivate) {\n item.classList.remove('is-active');\n (item as HTMLAnchorElement).removeAttribute('aria-current');\n }\n\n // Set active state for the matching link\n if (matchingItem) {\n (matchingItem as HTMLElement).classList.add('is-active');\n (matchingItem as HTMLAnchorElement).setAttribute('aria-current', 'page');\n }\n\n // Handle Reports dropdown highlighting\n const reportsLink = documentObj.querySelector<HTMLElement>(DOM_SELECTORS.NAV_REPORTS);\n if (reportsLink) {\n const reportPaths = [\n '/coverage',\n '/coverage-python',\n '/coverage-swift',\n '/coverage-ruby',\n '/playwright',\n '/playwright-examples',\n '/lighthouse',\n ];\n const isOnReportsPage = reportPaths.some(\n (path) => normalizedCurrentPath === path || normalizedCurrentPath.startsWith(path + '/')\n );\n if (isOnReportsPage) {\n reportsLink.classList.add('is-active');\n } else {\n reportsLink.classList.remove('is-active');\n }\n }\n}\n\n// Expose function to global scope for use in HTML\ndeclare global {\n interface Window {\n initNavbar: typeof initNavbar;\n }\n}\n\n// Only assign to window in browser context\nif (typeof window !== 'undefined') {\n window.initNavbar = initNavbar;\n}\n","// SPDX-License-Identifier: MIT\n/**\n * Accessibility enhancements\n */\n\nimport { DOM_SELECTORS } from './constants.js';\n\n/**\n * Enhances accessibility for code blocks\n */\nexport function enhanceAccessibility(documentObj: Document): void {\n documentObj.querySelectorAll(DOM_SELECTORS.HIGHLIGHT_PRE).forEach((pre) => {\n if (!pre.hasAttribute('tabindex')) pre.setAttribute('tabindex', '0');\n if (!pre.hasAttribute('role')) pre.setAttribute('role', 'region');\n if (!pre.hasAttribute('aria-label')) pre.setAttribute('aria-label', 'Code block');\n });\n}\n","// SPDX-License-Identifier: MIT\n/**\n * Generates a self-contained inline JavaScript string that prevents FOUC\n * (Flash of Unstyled Content) by applying the saved theme before first paint.\n *\n * The returned string is a complete IIFE suitable for injection into a\n * `<script>` tag in the document `<head>`. It has no module dependencies.\n *\n * @example\n * // Astro frontmatter\n * import { generateBlockingScript } from '@lgtm-hq/turbo-theme-selector';\n * const blockingScript = generateBlockingScript();\n *\n * // Astro template\n * <Fragment set:html={`<script>${blockingScript}</script>`} />\n */\n\nimport { DEFAULT_THEME, VALID_THEMES } from '@lgtm-hq/turbo-themes-core';\nimport { CSS_LINK_ID, STORAGE_KEY, LEGACY_STORAGE_KEYS } from './constants.js';\n\nexport interface BlockingScriptOptions {\n /** Valid theme IDs to accept. Defaults to VALID_THEMES from core. */\n validThemes?: readonly string[];\n /** Fallback theme when no preference is stored. Defaults to DEFAULT_THEME from core. */\n defaultTheme?: string;\n /** localStorage key for the active theme. Defaults to STORAGE_KEY from core. */\n storageKey?: string;\n /** Legacy localStorage keys to migrate from. Defaults to LEGACY_STORAGE_KEYS from core. */\n legacyKeys?: readonly string[];\n}\n\n/**\n * Generates a self-contained inline JavaScript string that prevents FOUC.\n *\n * The returned string is a complete IIFE that:\n * 1. Migrates legacy storage keys\n * 2. Reads and validates the stored theme against the allowlist\n * 3. Sets `data-theme` on `<html>`\n * 4. Sets `window.__INITIAL_THEME__`\n * 5. Updates the CSS `<link>` href if the theme differs from the default\n */\nexport function generateBlockingScript(options: BlockingScriptOptions = {}): string {\n const {\n validThemes = VALID_THEMES,\n defaultTheme = DEFAULT_THEME,\n storageKey = STORAGE_KEY,\n legacyKeys = LEGACY_STORAGE_KEYS,\n } = options;\n\n const S = JSON.stringify(storageKey);\n const D = JSON.stringify(defaultTheme);\n const V = JSON.stringify(validThemes);\n const L = JSON.stringify(legacyKeys);\n const C = JSON.stringify(CSS_LINK_ID);\n\n return [\n '(function(){try{',\n `var S=${S};var D=${D};var V=${V};var L=${L};var C=${C};`,\n // Legacy migration\n 'for(var i=0;i<L.length;i++){var lv=localStorage.getItem(L[i]);',\n 'if(lv&&!localStorage.getItem(S)){localStorage.setItem(S,lv);localStorage.removeItem(L[i])}}',\n // Read and validate\n 'var t=localStorage.getItem(S)||D;if(V.indexOf(t)===-1)t=D;',\n // Apply to DOM\n 'document.documentElement.setAttribute(\"data-theme\",t);window.__INITIAL_THEME__=t;',\n // Update CSS link href for non-default theme\n 'if(t!==D){var b=document.documentElement.getAttribute(\"data-baseurl\")||\"\";',\n 'var l=document.getElementById(C);',\n 'if(l)l.href=b+\"/assets/css/themes/turbo/\"+t+\".css\"}',\n '}catch(e){console.warn(\"Unable to load saved theme:\",e)}})();',\n ].join('');\n}\n","// SPDX-License-Identifier: MIT\n/**\n * Theme selector package - main entry point\n */\n\nimport { migrateLegacyStorage, getSavedTheme, saveTheme, DEFAULT_THEME } from './storage.js';\nimport { getBaseUrl, getCurrentThemeFromClasses } from './theme-loader.js';\nimport { applyTheme, getCurrentTheme } from './apply-theme.js';\nimport { CSS_LINK_ID, DOM_IDS, THEME_FAMILIES } from './constants.js';\nimport { getThemes, getValidThemeIds } from './theme-resolver.js';\nimport { createDropdownStateManager, type DropdownState } from './dropdown/state.js';\nimport { wireDropdownEventHandlers } from './dropdown/events.js';\nimport { populateDropdownMenu, wireNativeSelect, getDropdownElements } from './dropdown/ui.js';\nimport { initNavbar } from './navbar.js';\nimport { enhanceAccessibility } from './accessibility.js';\nimport { ThemeErrors, logThemeError } from './errors.js';\n\n// Extend Window interface to include our custom property\ndeclare global {\n interface Window {\n __INITIAL_THEME__?: string;\n initNavbar: typeof initNavbar;\n }\n}\n\n/**\n * Initializes theme system\n */\nexport async function initTheme(documentObj: Document, windowObj: Window): Promise<void> {\n // Migrate legacy storage keys\n migrateLegacyStorage(windowObj);\n\n // Check if theme was already applied by blocking script\n const initialTheme = windowObj.__INITIAL_THEME__;\n const savedTheme = getSavedTheme(windowObj, getValidThemeIds());\n\n // If blocking script already applied theme and it matches saved, just load CSS if needed\n if (initialTheme && initialTheme === savedTheme) {\n const currentTheme = getCurrentThemeFromClasses(documentObj.documentElement);\n if (currentTheme === savedTheme) {\n // Theme class already applied by blocking script, just ensure CSS is loaded\n const themeLinkId = `theme-${savedTheme}-css`;\n const themeLink = documentObj.getElementById(themeLinkId) || documentObj.getElementById(CSS_LINK_ID);\n if (!themeLink) {\n // CSS not loaded yet, load it now\n await applyTheme(documentObj, savedTheme);\n }\n return;\n }\n }\n\n // Otherwise, apply theme normally\n await applyTheme(documentObj, savedTheme);\n}\n\n/**\n * Initializes and wires up the theme flavor selector dropdown.\n * Returns a Promise for API consistency with initTheme.\n */\nexport async function wireFlavorSelector(\n documentObj: Document,\n windowObj: Window\n): Promise<{ cleanup: () => void }> {\n const abortController = new AbortController();\n\n // Get required DOM elements\n const elements = getDropdownElements(documentObj);\n if (!elements) {\n return { cleanup: () => abortController.abort() };\n }\n\n const { dropdownMenu, selectEl } = elements;\n const baseUrl = getBaseUrl(documentObj);\n const themes = getThemes();\n\n // Initialize state\n const state: DropdownState = {\n currentIndex: -1,\n menuItems: [],\n };\n\n // Get current theme (validated against available themes)\n const currentThemeId =\n getSavedTheme(windowObj, getValidThemeIds()) ||\n getCurrentTheme(documentObj, DEFAULT_THEME);\n\n // Create state manager (needs elements and state)\n const stateManager = createDropdownStateManager(elements, state);\n\n // Create context for UI creation\n const ctx = {\n documentObj,\n windowObj,\n baseUrl,\n currentThemeId,\n selectEl,\n menuItems: state.menuItems,\n closeDropdown: stateManager.closeDropdown,\n onThemeSelect: async (themeId: string) => {\n saveTheme(windowObj, themeId, getValidThemeIds());\n await applyTheme(documentObj, themeId);\n },\n };\n\n // Wire native select if present\n if (selectEl) {\n wireNativeSelect(ctx, selectEl, themes, DEFAULT_THEME);\n }\n\n // Populate dropdown menu\n populateDropdownMenu(ctx, dropdownMenu, themes, THEME_FAMILIES);\n\n // Wire event handlers\n wireDropdownEventHandlers(documentObj, elements, state, stateManager, abortController);\n\n // Initialize state\n stateManager.updateAriaExpanded(false);\n elements.dropdown.classList.remove('is-active');\n\n return { cleanup: () => abortController.abort() };\n}\n\n// Re-export navbar, accessibility, and blocking script functions\nexport { initNavbar, enhanceAccessibility };\nexport { generateBlockingScript, type BlockingScriptOptions } from './blocking-script.js';\n\n// Re-export types\nexport type { ThemeMode, ThemeAppearance, ThemeFamily } from './types.js';\n\n// Auto-initialize on DOMContentLoaded\nif (typeof document !== 'undefined' && typeof window !== 'undefined') {\n document.addEventListener('DOMContentLoaded', async () => {\n try {\n await initTheme(document, window);\n\n const { cleanup } = await wireFlavorSelector(document, window);\n enhanceAccessibility(document);\n\n // Register cleanup to run on teardown\n const pagehideHandler = () => {\n cleanup();\n window.removeEventListener('pagehide', pagehideHandler);\n };\n window.addEventListener('pagehide', pagehideHandler);\n } catch (error) {\n logThemeError(ThemeErrors.INIT_FAILED(error));\n }\n });\n}\n"],"names":["DEFAULT_THEME","CORE_DEFAULT_THEME","tokens","themes"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../core/dist/tokens/index.js","../../core/dist/themes/metadata.js","../src/constants.ts","../src/errors.ts","../src/storage.ts","../src/theme-loader.ts","../src/dropdown/helpers.ts","../src/theme-mapper.ts","../src/theme-resolver.ts","../src/apply-theme.ts","../src/dropdown/state.ts","../src/dropdown/events.ts","../src/dropdown/ui.ts","../src/navbar.ts","../src/accessibility.ts","../src/blocking-script.ts","../src/index.ts"],"sourcesContent":["// SPDX-License-Identifier: MIT\n/**\n * Platform-agnostic design tokens export\n *\n * This module exports pure theme data (colors, typography, etc.) without\n * any DOM, CSS, or platform-specific code. Use this for:\n *\n * - React Native apps\n * - Flutter apps (via JSON export)\n * - iOS/Android native apps\n * - Any platform that needs theme colors\n *\n * For web apps, you can also import the CSS files directly:\n * import '@lgtm-hq/turbo-themes/css/catppuccin-mocha.css'\n */\n// Import tokens data (copied from dist/tokens.json during build)\nimport tokensData from '../themes/tokens.json' with { type: 'json' };\nconst tokens = tokensData;\n/**\n * All available theme flavors as a flat array\n */\nexport const flavors = Object.values(tokens.themes).map((theme) => ({\n id: theme.id,\n label: theme.label,\n vendor: theme.vendor,\n appearance: theme.appearance,\n ...(theme.iconUrl !== undefined && { iconUrl: theme.iconUrl }),\n tokens: theme.tokens,\n}));\n/**\n * Theme flavors indexed by ID for quick lookup\n */\nexport const themesById = /*#__PURE__*/ Object.fromEntries(flavors.map((flavor) => [flavor.id, flavor]));\n/**\n * All available theme packages (grouped by vendor)\n */\nexport const packages = /*#__PURE__*/ Object.fromEntries(Object.entries(tokens.byVendor).map(([vendorId, vendor]) => [\n vendorId,\n {\n id: vendorId,\n name: vendor.name,\n homepage: vendor.homepage,\n flavors: vendor.themes.map((themeId) => themesById[themeId]).filter(Boolean),\n },\n]));\n/**\n * Get a theme by ID\n * @param id - Theme identifier (e.g., 'catppuccin-mocha')\n * @returns The theme flavor or undefined if not found\n */\nexport function getTheme(id) {\n return themesById[id];\n}\n/**\n * Get theme tokens by ID (convenience function)\n * @param id - Theme identifier (e.g., 'catppuccin-mocha')\n * @returns The theme tokens or undefined if not found\n */\nexport function getTokens(id) {\n return themesById[id]?.tokens;\n}\n/**\n * Get all themes matching an appearance (light/dark)\n * @param appearance - 'light' or 'dark'\n * @returns Array of matching theme flavors\n */\nexport function getThemesByAppearance(appearance) {\n return flavors.filter((f) => f.appearance === appearance);\n}\n/**\n * Get all themes from a specific vendor\n * @param vendor - Vendor name (e.g., 'catppuccin', 'github')\n * @returns Array of matching theme flavors\n */\nexport function getThemesByVendor(vendor) {\n return flavors.filter((f) => f.vendor === vendor);\n}\n/**\n * List of all available theme IDs\n */\nexport const themeIds = /*#__PURE__*/ flavors.map((f) => f.id);\n/**\n * List of all available vendors\n */\nexport const vendors = /*#__PURE__*/ [...new Set(flavors.map((f) => f.vendor))];\n//# sourceMappingURL=index.js.map","// SPDX-License-Identifier: MIT\n/**\n * Consolidated theme metadata derived from tokens.json.\n *\n * All display metadata (names, appearances, vendor groups) is computed from\n * the canonical token data at module evaluation time. Consumers should import\n * from here instead of maintaining their own hardcoded copies.\n */\nimport { flavors, themeIds, packages } from '../tokens/index.js';\n/** Default theme applied when no preference is stored. */\nexport const DEFAULT_THEME = 'catppuccin-mocha';\n/** All valid theme IDs (re-export for convenience). */\nexport const VALID_THEMES = themeIds;\n/** Set of valid theme IDs for O(1) lookup. */\nexport const VALID_THEME_SET = /*#__PURE__*/ new Set(themeIds);\n/** Full human-readable label for each theme (e.g., \"Catppuccin Mocha\"). */\nexport const THEME_NAMES = /*#__PURE__*/ Object.fromEntries(flavors.map((f) => [f.id, f.label]));\n/** Appearance (light/dark) for each theme. */\nexport const THEME_APPEARANCES = \n/*#__PURE__*/ Object.fromEntries(flavors.map((f) => [f.id, f.appearance]));\n/**\n * Ordered list of vendor IDs controlling display order in dropdowns.\n * New vendors should be appended here.\n */\nexport const VENDOR_ORDER = [\n 'catppuccin',\n 'dracula',\n 'gruvbox',\n 'github',\n 'bulma',\n 'nord',\n 'solarized',\n 'rose-pine',\n 'tokyo-night',\n];\n/**\n * Ordered array of vendor groups derived from packages + VENDOR_ORDER.\n * The \"(synced)\" suffix is stripped from display names.\n */\n// Dev-time validation: warn if packages has vendors not listed in VENDOR_ORDER\nconst _packageKeys = Object.keys(packages);\nconst _missingFromOrder = _packageKeys.filter((id) => !VENDOR_ORDER.includes(id));\nif (_missingFromOrder.length > 0) {\n console.warn(`[metadata] VENDOR_ORDER is missing vendor IDs present in packages: ${_missingFromOrder.join(', ')}. ` +\n 'Append them to VENDOR_ORDER so their themes are included in VENDOR_GROUPS.');\n}\nexport const VENDOR_GROUPS = /*#__PURE__*/ VENDOR_ORDER.filter((id) => id in packages).map((id) => {\n const pkg = packages[id];\n return {\n id,\n displayName: pkg.name.replace(/\\s*\\(synced\\)\\s*/i, ''),\n themeIds: pkg.flavors.flatMap((f) => (f ? [f.id] : [])),\n };\n});\n/** O(1) flavor lookup by ID, built once at module evaluation time. */\nconst flavorById = /*#__PURE__*/ new Map(flavors.map((f) => [f.id, f]));\n/** Cache for computed short labels. */\nconst shortLabelCache = new Map();\n/**\n * Strip the vendor prefix from a theme label to produce a short label.\n *\n * For single-flavor vendors (e.g., \"Dracula\", \"Nord\") the full label is returned.\n * For multi-flavor vendors the vendor name prefix is stripped:\n * \"Catppuccin Mocha\" -> \"Mocha\"\n * \"Gruvbox Dark Hard\" -> \"Dark Hard\"\n *\n * @param themeId - A valid theme ID\n * @returns The short display label, or the full label if the theme is not found\n */\nexport function getShortLabel(themeId) {\n const cached = shortLabelCache.get(themeId);\n if (cached !== undefined)\n return cached;\n const flavor = flavorById.get(themeId);\n if (!flavor)\n return themeId;\n const vendorPkg = packages[flavor.vendor];\n if (!vendorPkg) {\n shortLabelCache.set(themeId, flavor.label);\n return flavor.label;\n }\n // Single-flavor vendors keep their full label\n if (vendorPkg.flavors.length === 1) {\n shortLabelCache.set(themeId, flavor.label);\n return flavor.label;\n }\n // Strip vendor display name prefix (case-insensitive, NFC-normalized for\n // consistent handling of composed/decomposed Unicode accents).\n const displayName = vendorPkg.name.replace(/\\s*\\(synced\\)\\s*/i, '').normalize('NFC');\n const label = flavor.label;\n let result;\n if (label.normalize('NFC').toLowerCase().startsWith(displayName.toLowerCase())) {\n const stripped = label.slice(displayName.length).trim();\n result = stripped || label;\n }\n else {\n result = label;\n }\n shortLabelCache.set(themeId, result);\n return result;\n}\n/** Pre-computed short labels for all themes. */\nexport const THEME_SHORT_LABELS = \n/*#__PURE__*/ Object.fromEntries(flavors.map((f) => [f.id, getShortLabel(f.id)]));\n//# sourceMappingURL=metadata.js.map","// SPDX-License-Identifier: MIT\n/**\n * Constants for theme selector component\n */\n\nimport type { ThemeFamily } from './types.js';\nimport { DEFAULT_THEME as CORE_DEFAULT_THEME } from '@lgtm-hq/turbo-themes-core';\n\n// Re-export ThemeFamily for convenience\nexport type { ThemeFamily } from './types.js';\n\nexport const STORAGE_KEY = 'turbo-theme';\nexport const LEGACY_STORAGE_KEYS = ['bulma-theme-flavor'];\nexport const DEFAULT_THEME = CORE_DEFAULT_THEME;\n\n/** ID of the CSS link element used by the blocking script to prevent FOUC. */\nexport const CSS_LINK_ID = 'turbo-theme-css';\n\n// DOM element IDs and selectors - centralized to avoid magic strings\nexport const DOM_IDS = {\n THEME_FLAVOR_TRIGGER: 'theme-flavor-trigger',\n THEME_FLAVOR_TRIGGER_ICON: 'theme-flavor-trigger-icon',\n THEME_FLAVOR_TRIGGER_LABEL: 'theme-flavor-trigger-label',\n THEME_FLAVOR_MENU: 'theme-flavor-menu',\n THEME_FLAVOR_SELECT: 'theme-flavor-select',\n} as const;\n\nexport const DOM_SELECTORS = {\n DROPDOWN_ITEMS: `#${DOM_IDS.THEME_FLAVOR_MENU} .dropdown-item.theme-item`,\n NAVBAR_DROPDOWN: '.navbar-item.has-dropdown',\n NAV_REPORTS: '[data-testid=\"nav-reports\"]',\n NAVBAR_ITEM: '.navbar-item',\n HIGHLIGHT_PRE: '.highlight > pre',\n THEME_CSS_LINKS: 'link[id^=\"theme-\"][id$=\"-css\"]',\n} as const;\n\nexport interface ThemeFamilyMeta {\n name: string;\n description: string;\n}\n\nexport const THEME_FAMILIES: Record<ThemeFamily, ThemeFamilyMeta> = {\n bulma: { name: 'Bulma', description: 'Classic Bulma themes' },\n catppuccin: { name: 'Catppuccin', description: 'Soothing pastel themes' },\n dracula: { name: 'Dracula', description: 'Dark vampire aesthetic' },\n gruvbox: { name: 'Gruvbox', description: 'Retro groove palette with warm, earthy tones' },\n github: { name: 'GitHub', description: 'GitHub-inspired themes' },\n nord: { name: 'Nord', description: 'Arctic, north-bluish color palette' },\n 'rose-pine': { name: 'Rosé Pine', description: 'All natural pine, faux fur and a bit of soho vibes' },\n solarized: { name: 'Solarized', description: 'Precision-balanced light and dark modes' },\n 'tokyo-night': { name: 'Tokyo Night', description: 'Neon-infused nightscape with crisp contrast' },\n};\n","// SPDX-License-Identifier: MIT\n/**\n * Centralized error handling for Turbo Themes.\n *\n * Provides a consistent error logging strategy with standardized message\n * formatting, error levels, and optional context for debugging.\n */\n\n/** Log prefix for all theme-related messages */\nexport const LOG_PREFIX = '[turbo-themes]';\n\n/** Error severity levels */\nexport enum ErrorLevel {\n WARN = 'warn',\n ERROR = 'error',\n}\n\n/** Structured theme error with code, message, level, and optional context */\nexport interface ThemeError {\n code: string;\n message: string;\n level: ErrorLevel;\n context?: Record<string, unknown>;\n}\n\n/**\n * Factory functions for creating structured theme errors.\n * Each function returns a ThemeError with appropriate code, message, and level.\n */\nexport const ThemeErrors = {\n /** Invalid theme ID provided */\n INVALID_THEME_ID: (themeId: string): ThemeError => ({\n code: 'INVALID_THEME_ID',\n message: `Invalid theme ID \"${themeId}\" not saved to storage`,\n level: ErrorLevel.WARN,\n context: { themeId },\n }),\n\n /** No themes available in registry */\n NO_THEMES_AVAILABLE: (): ThemeError => ({\n code: 'NO_THEMES_AVAILABLE',\n message: 'No themes available',\n level: ErrorLevel.ERROR,\n }),\n\n /** Invalid theme icon path */\n INVALID_ICON_PATH: (themeId: string): ThemeError => ({\n code: 'INVALID_ICON_PATH',\n message: `Invalid theme icon path for ${themeId}`,\n level: ErrorLevel.WARN,\n context: { themeId },\n }),\n\n /** Theme initialization failed */\n INIT_FAILED: (error: unknown): ThemeError => ({\n code: 'INIT_FAILED',\n message: 'Theme switcher initialization failed',\n level: ErrorLevel.ERROR,\n context: { error: error instanceof Error ? error.message : String(error) },\n }),\n\n /** Protocol-relative URL rejected for security */\n PROTOCOL_REJECTED: (): ThemeError => ({\n code: 'PROTOCOL_REJECTED',\n message: 'Protocol-relative base URL rejected for security',\n level: ErrorLevel.WARN,\n }),\n\n /** Insecure HTTP URL rejected */\n INSECURE_HTTP_REJECTED: (): ThemeError => ({\n code: 'INSECURE_HTTP_REJECTED',\n message: 'Insecure HTTP base URL rejected',\n level: ErrorLevel.WARN,\n }),\n\n /** Cross-origin URL rejected */\n CROSS_ORIGIN_REJECTED: (origin: string): ThemeError => ({\n code: 'CROSS_ORIGIN_REJECTED',\n message: `Cross-origin base URL rejected: ${origin}`,\n level: ErrorLevel.WARN,\n context: { origin },\n }),\n\n /** Invalid CSS path for theme */\n INVALID_CSS_PATH: (themeId: string): ThemeError => ({\n code: 'INVALID_CSS_PATH',\n message: `Invalid theme CSS path for ${themeId}`,\n level: ErrorLevel.WARN,\n context: { themeId },\n }),\n\n /** CSS failed to load */\n CSS_LOAD_FAILED: (themeId: string, error: unknown): ThemeError => ({\n code: 'CSS_LOAD_FAILED',\n message: `Theme CSS failed to load for ${themeId}`,\n level: ErrorLevel.WARN,\n context: {\n themeId,\n error: error instanceof Error ? error.message : String(error),\n },\n }),\n\n /** Storage unavailable (private browsing or disabled) */\n STORAGE_UNAVAILABLE: (operation: string, error: unknown): ThemeError => ({\n code: 'STORAGE_UNAVAILABLE',\n message: `localStorage ${operation} failed - storage may be unavailable`,\n level: ErrorLevel.WARN,\n context: {\n operation,\n error: error instanceof Error ? error.message : String(error),\n },\n }),\n};\n\n/**\n * Log a theme error to the console with consistent formatting.\n *\n * @param themeError - The structured error to log\n */\nexport function logThemeError(themeError: ThemeError): void {\n const prefixedMessage = `${LOG_PREFIX} ${themeError.message}`;\n\n if (themeError.level === ErrorLevel.ERROR) {\n if (themeError.context) {\n // Safe: prefixedMessage is constructed from controlled internal strings\n // nosemgrep: unsafe-formatstring\n console.error(prefixedMessage, themeError.context);\n } else {\n console.error(prefixedMessage);\n }\n } else {\n if (themeError.context) {\n // Safe: prefixedMessage is constructed from controlled internal strings\n // nosemgrep: unsafe-formatstring\n console.warn(prefixedMessage, themeError.context);\n } else {\n console.warn(prefixedMessage);\n }\n }\n}\n\n/**\n * Convenience function to log a ThemeError.\n *\n * @param error - The ThemeError instance to log\n */\nexport function logError<T extends ThemeError>(error: T): void {\n logThemeError(error);\n}\n","// SPDX-License-Identifier: MIT\n/**\n * Storage utilities for theme persistence\n */\n\nimport { STORAGE_KEY, LEGACY_STORAGE_KEYS, DEFAULT_THEME } from './constants.js';\nimport { ThemeErrors, logThemeError } from './errors.js';\n\n// Re-export DEFAULT_THEME for convenience\nexport { DEFAULT_THEME } from './constants.js';\n\n/**\n * Safely get an item from localStorage.\n * Returns null if storage is unavailable (e.g., private browsing mode).\n */\nfunction safeGetItem(windowObj: Window, key: string): string | null {\n try {\n return windowObj.localStorage.getItem(key);\n } catch (error) {\n logThemeError(ThemeErrors.STORAGE_UNAVAILABLE('getItem', error));\n return null;\n }\n}\n\n/**\n * Safely set an item in localStorage.\n * Returns false if storage is unavailable.\n */\nfunction safeSetItem(windowObj: Window, key: string, value: string): boolean {\n try {\n windowObj.localStorage.setItem(key, value);\n return true;\n } catch (error) {\n logThemeError(ThemeErrors.STORAGE_UNAVAILABLE('setItem', error));\n return false;\n }\n}\n\n/**\n * Safely remove an item from localStorage.\n * Silently fails if storage is unavailable.\n */\nfunction safeRemoveItem(windowObj: Window, key: string): void {\n try {\n windowObj.localStorage.removeItem(key);\n } catch (error) {\n logThemeError(ThemeErrors.STORAGE_UNAVAILABLE('removeItem', error));\n }\n}\n\n/**\n * Validates a theme ID against a set of valid IDs.\n * Returns the theme ID if valid, otherwise returns the default theme.\n */\nexport function validateThemeId(themeId: string | null, validIds: Set<string>): string {\n if (themeId && validIds.has(themeId)) {\n return themeId;\n }\n return DEFAULT_THEME;\n}\n\n/**\n * Migrates legacy storage keys to the current format.\n * Safely handles unavailable localStorage (e.g., private browsing).\n */\nexport function migrateLegacyStorage(windowObj: Window): void {\n for (const legacyKey of LEGACY_STORAGE_KEYS) {\n const legacy = safeGetItem(windowObj, legacyKey);\n if (legacy && !safeGetItem(windowObj, STORAGE_KEY)) {\n safeSetItem(windowObj, STORAGE_KEY, legacy);\n safeRemoveItem(windowObj, legacyKey);\n }\n }\n}\n\n/**\n * Gets the saved theme from localStorage, or returns default.\n * Optionally validates against a set of valid theme IDs.\n * Safely handles unavailable localStorage (e.g., private browsing).\n */\nexport function getSavedTheme(windowObj: Window, validIds?: Set<string>): string {\n const stored = safeGetItem(windowObj, STORAGE_KEY);\n if (validIds) {\n return validateThemeId(stored, validIds);\n }\n return stored || DEFAULT_THEME;\n}\n\n/**\n * Saves a theme to localStorage.\n * Optionally validates the theme ID against a set of valid IDs before saving.\n * Safely handles unavailable localStorage (e.g., private browsing).\n *\n * @param windowObj - Window object with localStorage\n * @param themeId - Theme ID to save\n * @param validIds - Optional set of valid theme IDs for validation\n * @returns true if saved successfully, false otherwise\n */\nexport function saveTheme(windowObj: Window, themeId: string, validIds?: Set<string>): boolean {\n if (validIds && !validIds.has(themeId)) {\n logThemeError(ThemeErrors.INVALID_THEME_ID(themeId));\n return false;\n }\n return safeSetItem(windowObj, STORAGE_KEY, themeId);\n}\n","// SPDX-License-Identifier: MIT\n/**\n * Theme CSS loading utilities\n */\n\nimport { CSS_LINK_ID, DOM_SELECTORS } from './constants.js';\nimport { ThemeErrors, logThemeError } from './errors.js';\n\nexport interface ThemeInfo {\n id: string;\n cssFile: string;\n icon?: string | undefined;\n}\n\n/**\n * Resolves an asset path relative to the site's base URL.\n */\nexport function resolveAssetPath(assetPath: string, baseUrl: string): string {\n // Normalize baseUrl - remove trailing slash if present, then add one\n const normalizedBase = baseUrl.replace(/\\/$/, '');\n const base = normalizedBase ? `${window.location.origin}${normalizedBase}/` : `${window.location.origin}/`;\n return new URL(assetPath, base).pathname;\n}\n\n/**\n * Gets the base URL from the document's data-baseurl attribute.\n * Validates the URL to prevent injection attacks:\n * - Rejects protocol-relative URLs (//example.com)\n * - Rejects non-HTTPS absolute URLs (except localhost)\n * - Only allows same-origin or relative paths\n */\nexport function getBaseUrl(doc: Document): string {\n const baseElement = doc.documentElement;\n const raw = baseElement?.getAttribute('data-baseurl') || '';\n\n // Empty base URL is valid (use site root)\n if (!raw) return '';\n\n // Reject protocol-relative URLs (security risk)\n if (raw.startsWith('//')) {\n logThemeError(ThemeErrors.PROTOCOL_REJECTED());\n return '';\n }\n\n // Reject non-HTTPS absolute URLs (except localhost for development)\n if (raw.startsWith('http://') && !raw.startsWith('http://localhost')) {\n logThemeError(ThemeErrors.INSECURE_HTTP_REJECTED());\n return '';\n }\n\n try {\n // Parse relative to current origin to validate\n const currentOrigin = typeof window !== 'undefined' ? window.location.origin : 'http://localhost';\n const u = new URL(raw, currentOrigin);\n\n // Only allow same-origin URLs or relative paths\n if (u.origin !== currentOrigin) {\n logThemeError(ThemeErrors.CROSS_ORIGIN_REJECTED(u.origin));\n return '';\n }\n\n return u.pathname.replace(/\\/$/, '');\n } catch {\n return '';\n }\n}\n\n/**\n * Extracts the theme ID from a theme link element's ID.\n * Strips a leading \"theme-\" prefix and trailing \"-css\" suffix.\n */\nfunction extractThemeIdFromLinkId(linkId: string): string {\n return linkId.replace(/^theme-/, '').replace(/-css$/, '');\n}\n\n/**\n * Clears onload/onerror handlers from a link element to prevent memory leaks.\n */\nfunction clearLinkHandlers(link: HTMLLinkElement): void {\n link.onload = null;\n link.onerror = null;\n}\n\n/**\n * Loads a CSS file with a timeout, returning a promise that resolves when loaded.\n */\nexport function loadCSSWithTimeout(\n link: HTMLLinkElement,\n themeId: string,\n timeoutMs = 10000\n): Promise<void> {\n return new Promise((resolve, reject) => {\n const timeoutId = setTimeout(() => {\n clearLinkHandlers(link);\n reject(new Error(`Theme ${themeId} load timeout`));\n }, timeoutMs);\n\n link.onload = () => {\n clearTimeout(timeoutId);\n clearLinkHandlers(link);\n resolve();\n };\n\n link.onerror = () => {\n clearTimeout(timeoutId);\n clearLinkHandlers(link);\n reject(new Error(`Failed to load theme ${themeId}`));\n };\n });\n}\n\n/**\n * Gets the current theme from document element classes\n */\nexport function getCurrentThemeFromClasses(element: HTMLElement): string | null {\n const classList = Array.from(element.classList);\n for (const className of classList) {\n if (className.startsWith('theme-')) {\n return className.substring(6); // Remove 'theme-' prefix\n }\n }\n return null;\n}\n\n/**\n * Applies theme class to document element\n */\nexport function applyThemeClass(doc: Document, themeId: string): void {\n // Remove existing theme classes in a single batch operation\n const themeClasses = Array.from(doc.documentElement.classList).filter((className) =>\n className.startsWith('theme-'),\n );\n if (themeClasses.length > 0) {\n doc.documentElement.classList.remove(...themeClasses);\n }\n\n // Add the new theme class\n doc.documentElement.classList.add(`theme-${themeId}`);\n}\n\n/**\n * Loads theme CSS file if not already loaded\n */\nexport async function loadThemeCSS(\n doc: Document,\n theme: ThemeInfo,\n baseUrl: string\n): Promise<void> {\n const themeLinkId = `theme-${theme.id}-css`;\n let themeLink = doc.getElementById(themeLinkId) as HTMLLinkElement | null;\n\n // Adopt the blocking script's link element if present (prevents duplicate CSS loads)\n if (!themeLink) {\n const blockingLink = doc.getElementById(CSS_LINK_ID) as HTMLLinkElement | null;\n if (blockingLink) {\n blockingLink.id = themeLinkId;\n blockingLink.setAttribute('data-theme-id', theme.id);\n themeLink = blockingLink;\n }\n }\n\n if (!themeLink) {\n // Record existing theme links before appending the new one\n const existingLinks = doc.querySelectorAll(DOM_SELECTORS.THEME_CSS_LINKS);\n\n themeLink = doc.createElement('link');\n themeLink.id = themeLinkId;\n themeLink.rel = 'stylesheet';\n themeLink.type = 'text/css';\n themeLink.setAttribute('data-theme-id', theme.id);\n\n try {\n themeLink.href = resolveAssetPath(theme.cssFile, baseUrl);\n } catch {\n logThemeError(ThemeErrors.INVALID_CSS_PATH(theme.id));\n return;\n }\n\n doc.head.appendChild(themeLink);\n\n try {\n await loadCSSWithTimeout(themeLink, theme.id);\n\n // Only remove old theme links after successful load\n existingLinks.forEach((link) => {\n const linkThemeId = extractThemeIdFromLinkId(link.id);\n if (linkThemeId !== theme.id && linkThemeId !== 'base') {\n link.remove();\n }\n });\n } catch (error) {\n // Loading failed — remove the new link and keep prior theme intact\n themeLink.remove();\n logThemeError(ThemeErrors.CSS_LOAD_FAILED(theme.id, error));\n }\n } else {\n // Link already exists — clean up any other stale theme links\n doc.querySelectorAll(DOM_SELECTORS.THEME_CSS_LINKS).forEach((link) => {\n const linkThemeId = extractThemeIdFromLinkId(link.id);\n if (linkThemeId !== theme.id && linkThemeId !== 'base') {\n link.remove();\n }\n });\n }\n}\n","// SPDX-License-Identifier: MIT\n/**\n * Dropdown helper functions\n */\n\n/**\n * Sets the active state (is-active class and aria-checked) on a theme item element.\n */\nexport function setItemActiveState(item: Element, isActive: boolean): void {\n if (isActive) {\n item.classList.add('is-active');\n } else {\n item.classList.remove('is-active');\n }\n item.setAttribute('aria-checked', String(isActive));\n}\n\n/**\n * Sets tabindex attribute on all items in a collection.\n */\nexport function setTabindexBatch(items: HTMLElement[], value: string): void {\n for (const item of items) {\n item.setAttribute('tabindex', value);\n }\n}\n","// SPDX-License-Identifier: MIT\n/**\n * Maps core theme flavors to UI-specific format\n */\n\nimport type { ThemeFlavor as CanonicalThemeFlavor } from '@lgtm-hq/turbo-themes-core';\nimport type { ThemeFamily } from './types.js';\n\nexport interface ThemeColors {\n bg: string;\n surface: string;\n accent: string;\n text: string;\n}\n\nexport interface ThemeFlavor extends Pick<CanonicalThemeFlavor, 'id' | 'appearance' | 'vendor'> {\n id: string;\n name: string;\n description: string;\n cssFile: string;\n icon?: string | undefined;\n family: ThemeFamily;\n colors: ThemeColors;\n}\n\n// ============================================================================\n// Lookup Tables\n// ============================================================================\n\n/** Vendor to family mapping */\nconst VENDOR_FAMILY_MAP: Record<string, ThemeFamily> = {\n bulma: 'bulma',\n catppuccin: 'catppuccin',\n dracula: 'dracula',\n gruvbox: 'gruvbox',\n github: 'github',\n nord: 'nord',\n 'rose-pine': 'rose-pine',\n solarized: 'solarized',\n 'tokyo-night': 'tokyo-night',\n};\n\nconst DEFAULT_FAMILY: ThemeFamily = 'bulma';\n\n/** Icon configuration - string for single icon, object for appearance-specific */\ninterface AppearanceIcons {\n light: string;\n dark: string;\n}\n\nconst VENDOR_ICON_MAP: Record<string, string | AppearanceIcons> = {\n bulma: 'assets/img/turbo-themes-logo.png',\n catppuccin: {\n light: 'assets/img/catppuccin-logo-latte.png',\n dark: 'assets/img/catppuccin-logo-macchiato.png',\n },\n dracula: 'assets/img/dracula-logo.png',\n gruvbox: {\n light: 'assets/img/gruvbox-light.png',\n dark: 'assets/img/gruvbox-dark.png',\n },\n github: {\n light: 'assets/img/github-logo-light.png',\n dark: 'assets/img/github-logo-dark.png',\n },\n nord: 'assets/img/nord.png',\n 'rose-pine': {\n light: 'assets/img/rose-pine-dawn.png',\n dark: 'assets/img/rose-pine.png',\n },\n solarized: {\n light: 'assets/img/solarized-light.png',\n dark: 'assets/img/solarized-dark.png',\n },\n 'tokyo-night': 'assets/img/tokyo-night.png',\n};\n\n/** Predefined flavor descriptions */\nconst FLAVOR_DESCRIPTIONS: Record<string, string> = {\n 'bulma-light': 'Classic Bulma look with a bright, neutral palette.',\n 'bulma-dark': 'Dark Bulma theme tuned for low-light reading.',\n 'catppuccin-latte': 'Light, soft Catppuccin palette for daytime use.',\n 'catppuccin-frappe': 'Balanced dark Catppuccin theme for focused work.',\n 'catppuccin-macchiato': 'Deep, atmospheric Catppuccin variant with rich contrast.',\n 'catppuccin-mocha': 'Cozy, high-contrast Catppuccin theme for late-night sessions.',\n dracula: 'Iconic Dracula dark theme with vibrant accents.',\n 'gruvbox-dark-hard': 'Highest contrast dark Gruvbox palette with deep shadows.',\n 'gruvbox-dark': 'Classic Gruvbox dark palette with warm, muted tones.',\n 'gruvbox-dark-soft': 'Softer dark Gruvbox palette with reduced contrast.',\n 'gruvbox-light-hard': 'Bright, crisp Gruvbox light palette with extra contrast.',\n 'gruvbox-light': 'Classic Gruvbox light palette with warm paper tones.',\n 'gruvbox-light-soft': 'Soft, low-contrast Gruvbox light palette for long sessions.',\n 'github-light': 'GitHub-inspired light theme suited for documentation and UI heavy pages.',\n 'github-dark': 'GitHub dark theme optimized for code-heavy views.',\n nord: 'Arctic, north-bluish color palette inspired by the polar night.',\n 'rose-pine': 'Elegant dark theme with natural pine and soho vibes.',\n 'rose-pine-moon': 'Deeper variant of Rosé Pine with enhanced contrast.',\n 'rose-pine-dawn': 'Light Rosé Pine variant for daytime use.',\n 'solarized-dark': 'Solarized Dark with a balanced, low-contrast palette.',\n 'solarized-light': 'Solarized Light tuned for bright, daylight-friendly UIs.',\n 'tokyo-night-dark': 'Deep midnight blues with neon accents.',\n 'tokyo-night-storm': 'Stormy variant with richer contrast and depth.',\n 'tokyo-night-light': 'Clean daylight palette inspired by Tokyo mornings.',\n};\n\n// ============================================================================\n// Helper Functions\n// ============================================================================\n\n/**\n * Gets the theme family from vendor name\n */\nfunction getFamily(vendor: string): ThemeFamily {\n return VENDOR_FAMILY_MAP[vendor] ?? DEFAULT_FAMILY;\n}\n\n/**\n * Gets icon path for a vendor\n */\nfunction getIconForVendor(vendor: string, appearance: 'light' | 'dark'): string | undefined {\n const iconConfig = VENDOR_ICON_MAP[vendor];\n\n if (!iconConfig) {\n return undefined;\n }\n\n if (typeof iconConfig === 'string') {\n return iconConfig;\n }\n\n return iconConfig[appearance];\n}\n\n/**\n * Gets description for a flavor\n */\nfunction getDescriptionForFlavor(id: string, label: string): string {\n return FLAVOR_DESCRIPTIONS[id] ?? `${label} theme`;\n}\n\n/**\n * Extracts preview colors from theme tokens\n */\nfunction extractPreviewColors(tokens: CanonicalThemeFlavor['tokens']): ThemeColors {\n return {\n bg: tokens.background.base,\n surface: tokens.background.surface,\n accent: tokens.brand.primary,\n text: tokens.text.primary,\n };\n}\n\n// ============================================================================\n// Public API\n// ============================================================================\n\n/**\n * Maps a canonical theme flavor to UI-specific format\n */\nexport function mapFlavorToUI(flavor: CanonicalThemeFlavor): ThemeFlavor {\n const family = getFamily(flavor.vendor);\n return {\n id: flavor.id,\n name: flavor.label,\n description: getDescriptionForFlavor(flavor.id, flavor.label),\n cssFile: `packages/css/dist/themes/${flavor.id}.css`,\n icon: getIconForVendor(flavor.vendor, flavor.appearance),\n family,\n vendor: flavor.vendor,\n appearance: flavor.appearance,\n colors: extractPreviewColors(flavor.tokens),\n };\n}\n","// SPDX-License-Identifier: MIT\n/**\n * Theme resolution utilities - centralized theme lookup and validation.\n *\n * Provides cached access to theme data and validation to avoid\n * repeated mapping and set creation across the codebase.\n */\n\nimport { flavors } from '@lgtm-hq/turbo-themes-core';\nimport { mapFlavorToUI, type ThemeFlavor } from './theme-mapper.js';\nimport { DEFAULT_THEME } from './constants.js';\n\n// Cache mapped themes and valid IDs\nlet mappedThemes: ThemeFlavor[] | null = null;\nlet validThemeIds: Set<string> | null = null;\n\n/**\n * Gets all themes mapped to UI format.\n * Results are cached for performance.\n */\nexport function getThemes(): ThemeFlavor[] {\n if (!mappedThemes) {\n mappedThemes = flavors.map(mapFlavorToUI);\n }\n return mappedThemes || [];\n}\n\n/**\n * Gets a Set of all valid theme IDs.\n * Results are cached for performance.\n */\nexport function getValidThemeIds(): Set<string> {\n if (!validThemeIds) {\n validThemeIds = new Set(flavors.map((f) => f.id));\n }\n return validThemeIds;\n}\n\n/**\n * Resolves a theme by ID, falling back to default if not found.\n *\n * @param themeId - The theme ID to resolve\n * @returns The matching theme, default theme, or first available theme\n */\nexport function resolveTheme(themeId: string): ThemeFlavor | undefined {\n const themes = getThemes();\n return (\n themes.find((t) => t.id === themeId) ||\n themes.find((t) => t.id === DEFAULT_THEME) ||\n themes[0]\n );\n}\n\n/**\n * Validates a theme ID for safety and format correctness.\n *\n * Accepts only alphanumeric characters, hyphens, and underscores.\n * Rejects special characters, unicode, and excessively long IDs.\n *\n * @param id - The value to validate as a theme ID\n * @returns True if the ID is valid, false otherwise\n */\nexport function isValidThemeId(id: unknown): boolean {\n if (typeof id !== 'string') return false;\n if (id.length === 0) return false;\n if (id.length > 100) return false;\n return /^[a-zA-Z0-9_-]+$/.test(id);\n}\n\n/**\n * Sanitizes a theme ID by removing unsafe characters.\n *\n * Removes any characters that could cause DOM/CSS/XSS issues.\n * Used as a fallback when displaying potentially untrusted input.\n *\n * @param id - The theme ID to sanitize\n * @returns The sanitized ID containing only safe characters\n */\nexport function sanitizeThemeId(id: string): string {\n return id.replace(/[^a-zA-Z0-9_-]/g, '');\n}\n\n/**\n * Resets the cached themes. Used for testing.\n * @internal\n */\nexport function _resetThemeCache(): void {\n mappedThemes = null;\n validThemeIds = null;\n}\n","// SPDX-License-Identifier: MIT\n/**\n * Theme application logic\n */\n\nimport { DOM_IDS, DOM_SELECTORS, THEME_FAMILIES } from './constants.js';\nimport { getBaseUrl, applyThemeClass, loadThemeCSS, resolveAssetPath, getCurrentThemeFromClasses } from './theme-loader.js';\nimport { setItemActiveState } from './dropdown/helpers.js';\nimport { ThemeErrors, logThemeError } from './errors.js';\nimport { resolveTheme } from './theme-resolver.js';\n\n/**\n * Applies a theme to the document\n */\nexport async function applyTheme(doc: Document, themeId: string): Promise<void> {\n const theme = resolveTheme(themeId);\n if (!theme) {\n logThemeError(ThemeErrors.NO_THEMES_AVAILABLE());\n return;\n }\n const baseUrl = getBaseUrl(doc);\n\n // Add loading state to trigger button\n const trigger = doc.getElementById(DOM_IDS.THEME_FLAVOR_TRIGGER) as HTMLButtonElement | null;\n if (trigger) {\n trigger.classList.add('is-loading');\n }\n\n try {\n // Apply theme class immediately (before CSS loading)\n applyThemeClass(doc, theme.id);\n\n // Load theme CSS\n await loadThemeCSS(doc, theme, baseUrl);\n\n // Update trigger button icon\n const triggerIcon = doc.getElementById(\n DOM_IDS.THEME_FLAVOR_TRIGGER_ICON\n ) as HTMLImageElement | null;\n\n if (triggerIcon && theme.icon) {\n try {\n triggerIcon.src = resolveAssetPath(theme.icon, baseUrl);\n const familyMeta = THEME_FAMILIES[theme.family];\n const familyName = familyMeta?.name ?? theme.family;\n triggerIcon.alt = `${familyName} ${theme.name}`;\n triggerIcon.title = `${familyName} ${theme.name}`;\n } catch {\n logThemeError(ThemeErrors.INVALID_ICON_PATH(theme.id));\n }\n }\n\n // Update trigger button label\n const triggerLabel = doc.getElementById(\n DOM_IDS.THEME_FLAVOR_TRIGGER_LABEL\n ) as HTMLElement | null;\n if (triggerLabel) {\n triggerLabel.textContent = theme.name;\n }\n\n // Update active state in dropdown\n doc.querySelectorAll(DOM_SELECTORS.DROPDOWN_ITEMS).forEach((item) => {\n setItemActiveState(item, item.getAttribute('data-theme-id') === theme.id);\n });\n } finally {\n if (trigger) {\n trigger.classList.remove('is-loading');\n }\n }\n}\n\n/**\n * Gets the current theme from classes or returns default\n */\nexport function getCurrentTheme(doc: Document, defaultTheme: string): string {\n return getCurrentThemeFromClasses(doc.documentElement) || defaultTheme;\n}\n","// SPDX-License-Identifier: MIT\n/**\n * Dropdown state management\n */\n\nimport { setItemActiveState, setTabindexBatch } from './helpers.js';\n\nexport interface DropdownElements {\n dropdownMenu: HTMLElement;\n trigger: HTMLButtonElement;\n dropdown: HTMLElement;\n selectEl: HTMLSelectElement | null;\n}\n\nexport interface DropdownState {\n currentIndex: number;\n menuItems: HTMLElement[];\n}\n\nexport interface DropdownStateManager {\n updateAriaExpanded: (expanded: boolean) => void;\n focusMenuItem: (index: number) => void;\n closeDropdown: (options?: { restoreFocus?: boolean }) => void;\n toggleDropdown: (focusFirst?: boolean) => void;\n}\n\n/**\n * Creates dropdown state management functions.\n */\nexport function createDropdownStateManager(\n elements: DropdownElements,\n state: DropdownState\n): DropdownStateManager {\n const { trigger, dropdown } = elements;\n\n const updateAriaExpanded = (expanded: boolean): void => {\n trigger.setAttribute('aria-expanded', String(expanded));\n };\n\n const focusMenuItem = (index: number): void => {\n if (index < 0 || index >= state.menuItems.length) return;\n\n const item = state.menuItems[index]!;\n setTabindexBatch(state.menuItems, '-1');\n item.setAttribute('tabindex', '0');\n item.focus();\n state.currentIndex = index;\n };\n\n const closeDropdown = (options: { restoreFocus?: boolean } = {}): void => {\n const { restoreFocus = true } = options;\n dropdown.classList.remove('is-active');\n updateAriaExpanded(false);\n setTabindexBatch(state.menuItems, '-1');\n state.currentIndex = -1;\n if (restoreFocus) {\n trigger.focus();\n }\n };\n\n const toggleDropdown = (focusFirst = false): void => {\n const isActive = dropdown.classList.toggle('is-active');\n updateAriaExpanded(isActive);\n\n if (!isActive) {\n state.currentIndex = -1;\n setTabindexBatch(state.menuItems, '-1');\n for (const menuItem of state.menuItems) {\n const isActiveItem = menuItem.classList.contains('is-active');\n setItemActiveState(menuItem, isActiveItem);\n }\n } else if (focusFirst && state.menuItems.length > 0) {\n focusMenuItem(0);\n }\n };\n\n return { updateAriaExpanded, focusMenuItem, closeDropdown, toggleDropdown };\n}\n","// SPDX-License-Identifier: MIT\n/**\n * Dropdown event handlers\n */\n\nimport type { DropdownElements, DropdownState, DropdownStateManager } from './state.js';\n\n/**\n * Calculates the next index when navigating down through menu items.\n */\nfunction getNextIndex(currentIndex: number, totalItems: number): number {\n return currentIndex < totalItems - 1 ? currentIndex + 1 : 0;\n}\n\n/**\n * Calculates the previous index when navigating up through menu items.\n */\nfunction getPrevIndex(currentIndex: number, totalItems: number): number {\n return currentIndex > 0 ? currentIndex - 1 : totalItems - 1;\n}\n\n/**\n * Handles keyboard navigation on the trigger button.\n */\nfunction handleTriggerKeydown(\n e: KeyboardEvent,\n dropdown: HTMLElement,\n state: DropdownState,\n stateManager: DropdownStateManager\n): void {\n const { focusMenuItem, toggleDropdown, updateAriaExpanded } = stateManager;\n const totalItems = state.menuItems.length;\n\n switch (e.key) {\n case 'Enter':\n case ' ':\n e.preventDefault();\n toggleDropdown(!dropdown.classList.contains('is-active'));\n break;\n\n case 'ArrowDown':\n e.preventDefault();\n if (!dropdown.classList.contains('is-active')) {\n dropdown.classList.add('is-active');\n updateAriaExpanded(true);\n focusMenuItem(0);\n } else {\n const nextIndex = state.currentIndex < 0 ? 0 : getNextIndex(state.currentIndex, totalItems);\n focusMenuItem(nextIndex);\n }\n break;\n\n case 'ArrowUp':\n e.preventDefault();\n if (!dropdown.classList.contains('is-active')) {\n dropdown.classList.add('is-active');\n updateAriaExpanded(true);\n focusMenuItem(totalItems - 1);\n } else {\n const startIndex = state.currentIndex < 0 ? totalItems - 1 : state.currentIndex;\n focusMenuItem(getPrevIndex(startIndex, totalItems));\n }\n break;\n }\n}\n\n/**\n * Handles keyboard navigation on menu items.\n */\nfunction handleMenuItemKeydown(\n e: KeyboardEvent,\n index: number,\n item: HTMLElement,\n state: DropdownState,\n stateManager: DropdownStateManager\n): void {\n const { focusMenuItem, closeDropdown } = stateManager;\n const totalItems = state.menuItems.length;\n\n switch (e.key) {\n case 'ArrowDown':\n e.preventDefault();\n focusMenuItem(getNextIndex(index, totalItems));\n break;\n\n case 'ArrowUp':\n e.preventDefault();\n focusMenuItem(getPrevIndex(index, totalItems));\n break;\n\n case 'Escape':\n e.preventDefault();\n closeDropdown();\n break;\n\n case 'Enter':\n case ' ':\n e.preventDefault();\n item.click();\n break;\n\n case 'Home':\n e.preventDefault();\n focusMenuItem(0);\n break;\n\n case 'End':\n e.preventDefault();\n focusMenuItem(totalItems - 1);\n break;\n }\n}\n\n/**\n * Wires up all event handlers for the dropdown.\n */\nexport function wireDropdownEventHandlers(\n documentObj: Document,\n elements: DropdownElements,\n state: DropdownState,\n stateManager: DropdownStateManager,\n abortController: AbortController\n): void {\n const { trigger, dropdown } = elements;\n const { closeDropdown, toggleDropdown } = stateManager;\n const signal = abortController.signal;\n\n // Trigger click\n trigger.addEventListener(\n 'click',\n (e) => {\n e.preventDefault();\n toggleDropdown();\n },\n { signal }\n );\n\n // Outside click\n documentObj.addEventListener(\n 'click',\n (e: MouseEvent) => {\n if (!dropdown.contains(e.target as Node)) {\n closeDropdown({ restoreFocus: false });\n }\n },\n { signal }\n );\n\n // Escape key (document-level)\n documentObj.addEventListener(\n 'keydown',\n (e: KeyboardEvent) => {\n if (e.key === 'Escape' && dropdown.classList.contains('is-active')) {\n closeDropdown({ restoreFocus: true });\n }\n },\n { signal }\n );\n\n // Trigger keyboard navigation\n trigger.addEventListener(\n 'keydown',\n (e: KeyboardEvent) => handleTriggerKeydown(e, dropdown, state, stateManager),\n { signal }\n );\n\n // Menu item keyboard navigation\n for (const [index, item] of state.menuItems.entries()) {\n item.addEventListener(\n 'keydown',\n (e: KeyboardEvent) => handleMenuItemKeydown(e, index, item, state, stateManager),\n { signal }\n );\n }\n}\n","// SPDX-License-Identifier: MIT\n/**\n * Dropdown UI element creation\n */\n\nimport type { ThemeFlavor } from '../theme-mapper.js';\nimport type { ThemeFamilyMeta } from '../constants.js';\nimport { setItemActiveState } from './helpers.js';\nimport { DOM_IDS, DOM_SELECTORS } from '../constants.js';\nimport { resolveAssetPath } from '../theme-loader.js';\nimport { ThemeErrors, logThemeError } from '../errors.js';\nimport type { DropdownElements } from './state.js';\n\nexport interface DropdownContext {\n documentObj: Document;\n windowObj: Window;\n baseUrl: string;\n currentThemeId: string;\n selectEl: HTMLSelectElement | null;\n menuItems: HTMLElement[];\n closeDropdown: (options?: { restoreFocus?: boolean }) => void;\n onThemeSelect: (themeId: string) => void;\n}\n\n/**\n * Creates a checkmark SVG icon for the active theme indicator.\n */\nexport function createCheckmarkIcon(doc: Document): SVGSVGElement {\n const svg = doc.createElementNS('http://www.w3.org/2000/svg', 'svg');\n svg.setAttribute('width', '16');\n svg.setAttribute('height', '16');\n svg.setAttribute('viewBox', '0 0 24 24');\n svg.setAttribute('fill', 'none');\n svg.setAttribute('stroke', 'currentColor');\n svg.setAttribute('stroke-width', '3');\n svg.setAttribute('stroke-linecap', 'round');\n svg.setAttribute('stroke-linejoin', 'round');\n\n const polyline = doc.createElementNS('http://www.w3.org/2000/svg', 'polyline');\n polyline.setAttribute('points', '20 6 9 17 4 12');\n svg.appendChild(polyline);\n\n return svg;\n}\n\n/**\n * Creates a single theme item button element.\n */\nexport function createThemeItemElement(\n ctx: DropdownContext,\n theme: ThemeFlavor,\n familyMeta: ThemeFamilyMeta\n): HTMLButtonElement {\n const { documentObj, baseUrl, currentThemeId, selectEl, closeDropdown, onThemeSelect } = ctx;\n\n const item = documentObj.createElement('button');\n item.type = 'button';\n item.className = 'dropdown-item theme-item';\n item.setAttribute('data-theme-id', theme.id);\n item.setAttribute('data-appearance', theme.appearance);\n item.setAttribute('role', 'menuitemradio');\n item.setAttribute(\n 'aria-label',\n `${familyMeta.name} ${theme.name} (${theme.appearance}). ${theme.description}`\n );\n item.setAttribute('tabindex', '-1');\n\n const isActive = theme.id === currentThemeId;\n setItemActiveState(item, isActive);\n\n // Icon (only render if theme has an icon)\n if (theme.icon) {\n const icon = documentObj.createElement('img');\n icon.className = 'theme-icon';\n try {\n icon.src = resolveAssetPath(theme.icon, baseUrl);\n } catch {\n logThemeError(ThemeErrors.INVALID_ICON_PATH(theme.id));\n icon.src = theme.icon;\n }\n icon.alt = `${familyMeta.name} ${theme.name}`;\n icon.width = 24;\n icon.height = 24;\n item.appendChild(icon);\n } else {\n // Add placeholder for consistent spacing\n const placeholder = documentObj.createElement('span');\n placeholder.className = 'theme-icon theme-icon-placeholder';\n placeholder.setAttribute('aria-hidden', 'true');\n item.appendChild(placeholder);\n }\n\n // Text content\n const copy = documentObj.createElement('div');\n copy.className = 'theme-copy';\n\n const titleEl = documentObj.createElement('span');\n titleEl.className = 'theme-title';\n titleEl.textContent = `${familyMeta.name} · ${theme.name}`;\n copy.appendChild(titleEl);\n\n const descriptionEl = documentObj.createElement('span');\n descriptionEl.className = 'theme-description';\n descriptionEl.textContent = theme.description;\n copy.appendChild(descriptionEl);\n\n item.appendChild(copy);\n\n // Checkmark for active state\n const check = documentObj.createElement('span');\n check.className = 'theme-check';\n check.appendChild(createCheckmarkIcon(documentObj));\n item.appendChild(check);\n\n // Click handler\n item.addEventListener('click', (e) => {\n e.preventDefault();\n onThemeSelect(theme.id);\n if (selectEl) {\n selectEl.value = theme.id;\n selectEl.dispatchEvent(new Event('change', { bubbles: true }));\n }\n closeDropdown({ restoreFocus: true });\n });\n\n return item;\n}\n\n/**\n * Creates a family group container with header and theme items.\n */\nexport function createFamilyGroup(\n ctx: DropdownContext,\n familyKey: string,\n themes: ThemeFlavor[],\n familyMeta: ThemeFamilyMeta,\n animationDelay: number\n): { group: HTMLDivElement; items: HTMLElement[] } | null {\n const { documentObj } = ctx;\n if (themes.length === 0) return null;\n\n const items: HTMLElement[] = [];\n\n // Create family group container\n const group = documentObj.createElement('div');\n group.className = 'theme-family-group';\n group.setAttribute('role', 'group');\n group.setAttribute('aria-labelledby', `theme-family-${familyKey}`);\n if (group.style && typeof group.style.setProperty === 'function') {\n group.style.setProperty('--animation-delay', `${animationDelay}ms`);\n }\n\n // Create family header\n const header = documentObj.createElement('div');\n header.className = 'theme-family-header';\n header.id = `theme-family-${familyKey}`;\n\n const headerTitle = documentObj.createElement('span');\n headerTitle.className = 'theme-family-name';\n headerTitle.textContent = familyMeta.name;\n header.appendChild(headerTitle);\n group.appendChild(header);\n\n // Create themes container\n const themesContainer = documentObj.createElement('div');\n themesContainer.className = 'theme-family-items';\n\n themes.forEach((theme) => {\n const item = createThemeItemElement(ctx, theme, familyMeta);\n items.push(item);\n themesContainer.appendChild(item);\n });\n\n group.appendChild(themesContainer);\n\n return { group, items };\n}\n\n/**\n * Populates the dropdown menu with all theme family groups.\n */\nexport function populateDropdownMenu(\n ctx: DropdownContext,\n dropdownMenu: HTMLElement,\n themes: ThemeFlavor[],\n themeFamilies: Record<string, ThemeFamilyMeta>\n): void {\n const families = Object.keys(themeFamilies);\n let animationDelay = 0;\n\n families.forEach((familyKey) => {\n const familyThemes = themes.filter((t) => t.family === familyKey);\n const familyMeta = themeFamilies[familyKey];\n if (!familyMeta) return;\n\n const result = createFamilyGroup(ctx, familyKey, familyThemes, familyMeta, animationDelay);\n if (result) {\n ctx.menuItems.push(...result.items);\n dropdownMenu.appendChild(result.group);\n animationDelay += 30;\n }\n });\n}\n\n/**\n * Wires up the native select element for theme selection.\n */\nexport function wireNativeSelect(\n ctx: DropdownContext,\n selectEl: HTMLSelectElement,\n themes: ThemeFlavor[],\n defaultTheme: string\n): void {\n const { documentObj, onThemeSelect } = ctx;\n\n // Clear existing options\n while (selectEl.firstChild) {\n selectEl.removeChild(selectEl.firstChild);\n }\n\n // Populate options\n themes.forEach((theme) => {\n const option = documentObj.createElement('option');\n option.value = theme.id;\n option.textContent = theme.name;\n option.selected = theme.id === ctx.currentThemeId;\n selectEl.appendChild(option);\n });\n\n selectEl.disabled = false;\n\n // Change handler\n selectEl.addEventListener('change', (event) => {\n const target = event.target as HTMLSelectElement | null;\n const selectedThemeId = target?.value || defaultTheme;\n onThemeSelect(selectedThemeId);\n });\n}\n\n/**\n * Gets DOM elements required for the dropdown, returning null if any are missing.\n */\nexport function getDropdownElements(documentObj: Document): DropdownElements | null {\n const dropdownMenu = documentObj.getElementById(DOM_IDS.THEME_FLAVOR_MENU);\n const trigger = documentObj.getElementById(\n DOM_IDS.THEME_FLAVOR_TRIGGER\n ) as HTMLButtonElement | null;\n const dropdown = trigger?.closest(DOM_SELECTORS.NAVBAR_DROPDOWN) as HTMLElement | null;\n const selectEl = documentObj.getElementById(\n DOM_IDS.THEME_FLAVOR_SELECT\n ) as HTMLSelectElement | null;\n\n if (!dropdownMenu || !trigger || !dropdown) {\n return null;\n }\n\n return { dropdownMenu, trigger, dropdown, selectEl };\n}\n","// SPDX-License-Identifier: MIT\n/**\n * Navbar active state management\n */\n\nimport { DOM_SELECTORS } from './constants.js';\n\n/**\n * Normalizes a path by removing trailing slashes, defaulting to '/' if empty.\n */\nfunction normalizePath(path: string): string {\n return path.replace(/\\/$/, '') || '/';\n}\n\n/**\n * Initializes navbar active state based on current path\n */\nexport function initNavbar(documentObj: Document): void {\n const currentPath = documentObj.location.pathname;\n const normalizedCurrentPath = normalizePath(currentPath);\n const navbarItems = documentObj.querySelectorAll(DOM_SELECTORS.NAVBAR_ITEM);\n\n // Single pass: find matching item and collect items to deactivate\n let matchingItem: Element | null = null;\n const itemsToDeactivate: Element[] = [];\n\n navbarItems.forEach((item) => {\n const link = item as HTMLAnchorElement;\n if (!link.href) return;\n\n try {\n const normalizedLinkPath = normalizePath(new URL(link.href).pathname);\n if (normalizedCurrentPath === normalizedLinkPath) {\n matchingItem = item;\n } else {\n // Collect non-matching items with valid URLs for deactivation\n itemsToDeactivate.push(item);\n }\n } catch {\n // Ignore invalid URLs\n }\n });\n\n // Apply deactivation after finding match (single DOM batch)\n for (const item of itemsToDeactivate) {\n item.classList.remove('is-active');\n (item as HTMLAnchorElement).removeAttribute('aria-current');\n }\n\n // Set active state for the matching link\n if (matchingItem) {\n (matchingItem as HTMLElement).classList.add('is-active');\n (matchingItem as HTMLAnchorElement).setAttribute('aria-current', 'page');\n }\n\n // Handle Reports dropdown highlighting\n const reportsLink = documentObj.querySelector<HTMLElement>(DOM_SELECTORS.NAV_REPORTS);\n if (reportsLink) {\n const reportPaths = [\n '/coverage',\n '/coverage-python',\n '/coverage-swift',\n '/coverage-ruby',\n '/playwright',\n '/playwright-examples',\n '/lighthouse',\n ];\n const isOnReportsPage = reportPaths.some(\n (path) => normalizedCurrentPath === path || normalizedCurrentPath.startsWith(path + '/')\n );\n if (isOnReportsPage) {\n reportsLink.classList.add('is-active');\n } else {\n reportsLink.classList.remove('is-active');\n }\n }\n}\n\n// Expose function to global scope for use in HTML\ndeclare global {\n interface Window {\n initNavbar: typeof initNavbar;\n }\n}\n\n// Only assign to window in browser context\nif (typeof window !== 'undefined') {\n window.initNavbar = initNavbar;\n}\n","// SPDX-License-Identifier: MIT\n/**\n * Accessibility enhancements\n */\n\nimport { DOM_SELECTORS } from './constants.js';\n\n/**\n * Enhances accessibility for code blocks\n */\nexport function enhanceAccessibility(documentObj: Document): void {\n documentObj.querySelectorAll(DOM_SELECTORS.HIGHLIGHT_PRE).forEach((pre) => {\n if (!pre.hasAttribute('tabindex')) pre.setAttribute('tabindex', '0');\n if (!pre.hasAttribute('role')) pre.setAttribute('role', 'region');\n if (!pre.hasAttribute('aria-label')) pre.setAttribute('aria-label', 'Code block');\n });\n}\n","// SPDX-License-Identifier: MIT\n/**\n * Generates a self-contained inline JavaScript string that prevents FOUC\n * (Flash of Unstyled Content) by applying the saved theme before first paint.\n *\n * The returned string is a complete IIFE suitable for injection into a\n * `<script>` tag in the document `<head>`. It has no module dependencies.\n *\n * @example\n * // Astro frontmatter\n * import { generateBlockingScript } from '@lgtm-hq/turbo-theme-selector';\n * const blockingScript = generateBlockingScript();\n *\n * // Astro template\n * <Fragment set:html={`<script>${blockingScript}</script>`} />\n */\n\nimport { DEFAULT_THEME, VALID_THEMES } from '@lgtm-hq/turbo-themes-core';\nimport { CSS_LINK_ID, STORAGE_KEY, LEGACY_STORAGE_KEYS } from './constants.js';\n\nexport interface BlockingScriptOptions {\n /** Valid theme IDs to accept. Defaults to VALID_THEMES from core. */\n validThemes?: readonly string[];\n /** Fallback theme when no preference is stored. Defaults to DEFAULT_THEME from core. */\n defaultTheme?: string;\n /** localStorage key for the active theme. Defaults to STORAGE_KEY from core. */\n storageKey?: string;\n /** Legacy localStorage keys to migrate from. Defaults to LEGACY_STORAGE_KEYS from core. */\n legacyKeys?: readonly string[];\n}\n\n/**\n * Generates a self-contained inline JavaScript string that prevents FOUC.\n *\n * The returned string is a complete IIFE that:\n * 1. Migrates legacy storage keys\n * 2. Reads and validates the stored theme against the allowlist\n * 3. Sets `data-theme` on `<html>`\n * 4. Sets `window.__INITIAL_THEME__`\n * 5. Updates the CSS `<link>` href if the theme differs from the default\n */\nexport function generateBlockingScript(options: BlockingScriptOptions = {}): string {\n const {\n validThemes = VALID_THEMES,\n defaultTheme = DEFAULT_THEME,\n storageKey = STORAGE_KEY,\n legacyKeys = LEGACY_STORAGE_KEYS,\n } = options;\n\n const S = JSON.stringify(storageKey);\n const D = JSON.stringify(defaultTheme);\n const V = JSON.stringify(validThemes);\n const L = JSON.stringify(legacyKeys);\n const C = JSON.stringify(CSS_LINK_ID);\n\n return [\n '(function(){try{',\n `var S=${S};var D=${D};var V=${V};var L=${L};var C=${C};`,\n // Legacy migration\n 'for(var i=0;i<L.length;i++){var lv=localStorage.getItem(L[i]);',\n 'if(lv&&!localStorage.getItem(S)){localStorage.setItem(S,lv);localStorage.removeItem(L[i])}}',\n // Read and validate\n 'var t=localStorage.getItem(S)||D;if(V.indexOf(t)===-1)t=D;',\n // Apply to DOM\n 'document.documentElement.setAttribute(\"data-theme\",t);window.__INITIAL_THEME__=t;',\n // Update CSS link href for non-default theme\n 'if(t!==D){var b=document.documentElement.getAttribute(\"data-baseurl\")||\"\";',\n 'var l=document.getElementById(C);',\n 'if(l)l.href=b+\"/assets/css/themes/turbo/\"+t+\".css\"}',\n '}catch(e){console.warn(\"Unable to load saved theme:\",e)}})();',\n ].join('');\n}\n","// SPDX-License-Identifier: MIT\n/**\n * Theme selector package - main entry point\n */\n\nimport { migrateLegacyStorage, getSavedTheme, saveTheme, DEFAULT_THEME } from './storage.js';\nimport { getBaseUrl, getCurrentThemeFromClasses } from './theme-loader.js';\nimport { applyTheme, getCurrentTheme } from './apply-theme.js';\nimport { CSS_LINK_ID, THEME_FAMILIES } from './constants.js';\nimport { getThemes, getValidThemeIds } from './theme-resolver.js';\nimport { createDropdownStateManager, type DropdownState } from './dropdown/state.js';\nimport { wireDropdownEventHandlers } from './dropdown/events.js';\nimport { populateDropdownMenu, wireNativeSelect, getDropdownElements } from './dropdown/ui.js';\nimport { initNavbar } from './navbar.js';\nimport { enhanceAccessibility } from './accessibility.js';\nimport { ThemeErrors, logThemeError } from './errors.js';\n\n// Extend Window interface to include our custom property\ndeclare global {\n interface Window {\n __INITIAL_THEME__?: string;\n initNavbar: typeof initNavbar;\n }\n}\n\n/**\n * Initializes theme system\n */\nexport async function initTheme(documentObj: Document, windowObj: Window): Promise<void> {\n // Migrate legacy storage keys\n migrateLegacyStorage(windowObj);\n\n // Check if theme was already applied by blocking script\n const initialTheme = windowObj.__INITIAL_THEME__;\n const savedTheme = getSavedTheme(windowObj, getValidThemeIds());\n\n // If blocking script already applied theme and it matches saved, just load CSS if needed\n if (initialTheme && initialTheme === savedTheme) {\n const currentTheme = getCurrentThemeFromClasses(documentObj.documentElement);\n if (currentTheme === savedTheme) {\n // Theme class already applied by blocking script, just ensure CSS is loaded\n const themeLinkId = `theme-${savedTheme}-css`;\n const themeLink = documentObj.getElementById(themeLinkId) || documentObj.getElementById(CSS_LINK_ID);\n if (!themeLink) {\n // CSS not loaded yet, load it now\n await applyTheme(documentObj, savedTheme);\n }\n return;\n }\n }\n\n // Otherwise, apply theme normally\n await applyTheme(documentObj, savedTheme);\n}\n\n/**\n * Initializes and wires up the theme flavor selector dropdown.\n * Returns a Promise for API consistency with initTheme.\n */\nexport async function wireFlavorSelector(\n documentObj: Document,\n windowObj: Window\n): Promise<{ cleanup: () => void }> {\n const abortController = new AbortController();\n\n // Get required DOM elements\n const elements = getDropdownElements(documentObj);\n if (!elements) {\n return { cleanup: () => abortController.abort() };\n }\n\n const { dropdownMenu, selectEl } = elements;\n const baseUrl = getBaseUrl(documentObj);\n const themes = getThemes();\n\n // Initialize state\n const state: DropdownState = {\n currentIndex: -1,\n menuItems: [],\n };\n\n // Get current theme (validated against available themes)\n const currentThemeId =\n getSavedTheme(windowObj, getValidThemeIds()) ||\n getCurrentTheme(documentObj, DEFAULT_THEME);\n\n // Create state manager (needs elements and state)\n const stateManager = createDropdownStateManager(elements, state);\n\n // Create context for UI creation\n const ctx = {\n documentObj,\n windowObj,\n baseUrl,\n currentThemeId,\n selectEl,\n menuItems: state.menuItems,\n closeDropdown: stateManager.closeDropdown,\n onThemeSelect: async (themeId: string) => {\n saveTheme(windowObj, themeId, getValidThemeIds());\n await applyTheme(documentObj, themeId);\n },\n };\n\n // Wire native select if present\n if (selectEl) {\n wireNativeSelect(ctx, selectEl, themes, DEFAULT_THEME);\n }\n\n // Populate dropdown menu\n populateDropdownMenu(ctx, dropdownMenu, themes, THEME_FAMILIES);\n\n // Wire event handlers\n wireDropdownEventHandlers(documentObj, elements, state, stateManager, abortController);\n\n // Initialize state\n stateManager.updateAriaExpanded(false);\n elements.dropdown.classList.remove('is-active');\n\n return { cleanup: () => abortController.abort() };\n}\n\n// Re-export navbar, accessibility, and blocking script functions\nexport { initNavbar, enhanceAccessibility };\nexport { generateBlockingScript, type BlockingScriptOptions } from './blocking-script.js';\n\n// Re-export types\nexport type { ThemeMode, ThemeAppearance, ThemeFamily } from './types.js';\n\n// Auto-initialize on DOMContentLoaded\nif (typeof document !== 'undefined' && typeof window !== 'undefined') {\n document.addEventListener('DOMContentLoaded', async () => {\n try {\n await initTheme(document, window);\n\n const { cleanup } = await wireFlavorSelector(document, window);\n enhanceAccessibility(document);\n\n // Register cleanup to run on teardown\n const pagehideHandler = () => {\n cleanup();\n window.removeEventListener('pagehide', pagehideHandler);\n };\n window.addEventListener('pagehide', pagehideHandler);\n } catch (error) {\n logThemeError(ThemeErrors.INIT_FAILED(error));\n }\n });\n}\n"],"names":["DEFAULT_THEME","CORE_DEFAULT_THEME","tokens","themes"],"mappings":"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"}
|