@@ -21,26 +21,39 @@ function sortObjectKeys(obj) {
2121}
2222
2323/**
24- * ブロック抽出ヘルパー: 指定トークン直後の {} をパース
25- * en: Extracts the brace block following a token (e.g. :root, @theme inline)
24+ * `token` に一致する {} ブロックをすべて抽出する。sparkle-design.css には
25+ * `:root { ... }` が2つある(プリミティブブロックと、実行時に参照できる
26+ * セマンティックトークンブロック)ため、両方を集める必要がある。
27+ * en: Extract every brace block matching `token`. sparkle-design.css
28+ * declares two `:root { ... }` blocks (a primitive block and a
29+ * semantic-token block meant to be usable at runtime), both of which need
30+ * to be collected here.
2631 */
27- function extractBraceBlock ( source , token ) {
28- const start = source . indexOf ( token ) ;
29- if ( start === - 1 ) return null ;
30- const open = source . indexOf ( "{" , start ) ;
31- if ( open === - 1 ) return null ;
32- let depth = 0 ;
33- for ( let i = open ; i < source . length ; i ++ ) {
34- if ( source [ i ] === "{" ) depth ++ ;
35- else if ( source [ i ] === "}" ) {
36- depth -- ;
37- if ( depth === 0 ) {
38- // return inner content (without braces)
39- return source . slice ( open + 1 , i ) ;
32+ function extractAllBraceBlocks ( source , token ) {
33+ const blocks = [ ] ;
34+ let searchFrom = 0 ;
35+ while ( true ) {
36+ const start = source . indexOf ( token , searchFrom ) ;
37+ if ( start === - 1 ) break ;
38+ const open = source . indexOf ( "{" , start ) ;
39+ if ( open === - 1 ) break ;
40+ let depth = 0 ;
41+ let end = - 1 ;
42+ for ( let i = open ; i < source . length ; i ++ ) {
43+ if ( source [ i ] === "{" ) depth ++ ;
44+ else if ( source [ i ] === "}" ) {
45+ depth -- ;
46+ if ( depth === 0 ) {
47+ end = i ;
48+ break ;
49+ }
4050 }
4151 }
52+ if ( end === - 1 ) break ; // unbalanced
53+ blocks . push ( source . slice ( open + 1 , end ) ) ;
54+ searchFrom = end + 1 ;
4255 }
43- return null ;
56+ return blocks ;
4457}
4558
4659/**
@@ -139,15 +152,31 @@ function buildTheme() {
139152 const importRules = parseImports ( noComments ) ;
140153
141154 // 2) :root variables
142- const rootBlock = extractBraceBlock ( noComments , ":root" ) ;
143- const rootVars = rootBlock ? parseDeclarations ( rootBlock ) : { } ;
144-
145- // 3) @theme inline variables (same treatment as vars)
146- const themeInlineBlock = extractBraceBlock ( noComments , "@theme inline" ) ;
147- const themeVars = themeInlineBlock ? parseDeclarations ( themeInlineBlock ) : { } ;
148-
149- // Merge vars (semantic overrides primitive)
150- const cssVarsTheme = { ...rootVars , ...themeVars } ;
155+ // sparkle-design.css には `:root { ... }` が2つある
156+ // (プリミティブトークンブロックと、実行時に参照できるセマンティックトークン
157+ // ブロック)。どちらも実際に解決可能な値(リテラル、または他の :root 変数への
158+ // 参照)を持つため、両方をマージしてレジストリの cssVars に使う。
159+ //
160+ // `@theme inline` は意図的にここでは使わない: sparkle-design-cli 2.4.1+ の
161+ // `@theme inline` は各セマンティック宣言が同名変数へ自己参照する
162+ // (例: `--color-primary-500: var(--color-primary-500)`)設計になっており、
163+ // これは Tailwind の compiled utility class 生成のためだけの仕組みで、
164+ // レジストリ消費者へそのまま渡すと解決不能な循環参照になってしまう
165+ // (goodpatch/sparkle-design#289 のレビュー指摘)。
166+ // en: sparkle-design.css declares two `:root { ... }` blocks (primitive
167+ // tokens, and semantic tokens meant to be usable at runtime). Both resolve
168+ // to real values (literals or references to other :root vars), so merge
169+ // both for the registry's cssVars.
170+ // `@theme inline` is intentionally NOT used here: as of sparkle-design-cli
171+ // 2.4.1+, every `@theme inline` declaration self-references its own
172+ // semantic variable name (e.g. `--color-primary-500: var(--color-primary-500)`)
173+ // — a Tailwind-compiler-only construct — which would become an unresolvable
174+ // circular reference if handed to registry consumers as-is.
175+ const rootBlocks = extractAllBraceBlocks ( noComments , ":root" ) ;
176+ const cssVarsTheme = rootBlocks . reduce (
177+ ( acc , block ) => ( { ...acc , ...parseDeclarations ( block ) } ) ,
178+ { }
179+ ) ;
151180
152181 // 4) @utility blocks -> css
153182 const utilities = parseUtilities ( noComments ) ;
@@ -190,4 +219,3 @@ if (import.meta.url === `file://${process.argv[1]}`) {
190219}
191220
192221export default buildTheme ;
193-
0 commit comments