zyzz 0.0.28 → 0.0.30

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (302) hide show
  1. package/binding/wasi/wasi-worker.mjs +186 -0
  2. package/binding/wasi/zyzz.wasi.cjs +2302 -0
  3. package/binding/wasi/zyzz.wasm32-wasi.wasm +0 -0
  4. package/binding/zyzz.linux-x64-gnu.node +0 -0
  5. package/dist/babel/index.d.ts.map +1 -1
  6. package/dist/babel/index.js +2 -4
  7. package/dist/babel/index.js.map +1 -1
  8. package/dist/babel/internal/Compilation.d.ts +0 -1
  9. package/dist/babel/internal/Compilation.d.ts.map +1 -1
  10. package/dist/compiler/Graph.d.ts +14 -11
  11. package/dist/compiler/Graph.d.ts.map +1 -1
  12. package/dist/compiler/Graph.js +57 -1442
  13. package/dist/compiler/Graph.js.map +1 -1
  14. package/dist/compiler/Native.d.ts +7 -9
  15. package/dist/compiler/Native.d.ts.map +1 -1
  16. package/dist/compiler/Native.js +12 -716
  17. package/dist/compiler/Native.js.map +1 -1
  18. package/dist/compiler/Source.d.ts +122 -24
  19. package/dist/compiler/Source.d.ts.map +1 -1
  20. package/dist/compiler/Source.js +10 -1267
  21. package/dist/compiler/Source.js.map +1 -1
  22. package/dist/compiler/Transform.d.ts +4 -3
  23. package/dist/compiler/Transform.d.ts.map +1 -1
  24. package/dist/compiler/Transform.js +13 -961
  25. package/dist/compiler/Transform.js.map +1 -1
  26. package/dist/compiler/internal/AtRules.d.ts +5 -1
  27. package/dist/compiler/internal/AtRules.d.ts.map +1 -1
  28. package/dist/compiler/internal/AtRules.js +12 -106
  29. package/dist/compiler/internal/AtRules.js.map +1 -1
  30. package/dist/compiler/internal/Context.d.ts +11 -0
  31. package/dist/compiler/internal/Context.d.ts.map +1 -0
  32. package/dist/compiler/internal/Context.js +11 -0
  33. package/dist/compiler/internal/Context.js.map +1 -0
  34. package/dist/compiler/internal/Results.d.ts +148 -0
  35. package/dist/compiler/internal/Results.d.ts.map +1 -0
  36. package/dist/compiler/internal/Results.js +259 -0
  37. package/dist/compiler/internal/Results.js.map +1 -0
  38. package/dist/compiler/internal/Syntax.d.ts +0 -2
  39. package/dist/compiler/internal/Syntax.d.ts.map +1 -1
  40. package/dist/compiler/internal/Syntax.js +0 -2
  41. package/dist/compiler/internal/Syntax.js.map +1 -1
  42. package/dist/compiler/internal/Wire.d.ts +17 -0
  43. package/dist/compiler/internal/Wire.d.ts.map +1 -0
  44. package/dist/compiler/internal/Wire.js +795 -0
  45. package/dist/compiler/internal/Wire.js.map +1 -0
  46. package/dist/internal/Addon.d.ts +28 -0
  47. package/dist/internal/Addon.d.ts.map +1 -0
  48. package/dist/internal/Addon.js +87 -0
  49. package/dist/internal/Addon.js.map +1 -0
  50. package/dist/internal/Literal.d.ts +4 -1
  51. package/dist/internal/Literal.d.ts.map +1 -1
  52. package/dist/internal/Literal.js +4 -2
  53. package/dist/internal/Literal.js.map +1 -1
  54. package/dist/internal/Token.d.ts +2 -1
  55. package/dist/internal/Token.d.ts.map +1 -1
  56. package/dist/internal/Token.js +2 -2
  57. package/dist/internal/Token.js.map +1 -1
  58. package/dist/internal/Vlq.d.ts +14 -0
  59. package/dist/internal/Vlq.d.ts.map +1 -0
  60. package/dist/internal/Vlq.js +47 -0
  61. package/dist/internal/Vlq.js.map +1 -0
  62. package/dist/internal/Wasm.d.ts +22 -0
  63. package/dist/internal/Wasm.d.ts.map +1 -0
  64. package/dist/internal/Wasm.js +83 -0
  65. package/dist/internal/Wasm.js.map +1 -0
  66. package/dist/metro/Graph.d.ts +0 -1
  67. package/dist/metro/Graph.d.ts.map +1 -1
  68. package/dist/metro/transformer.d.ts.map +1 -1
  69. package/dist/metro/transformer.js +0 -1
  70. package/dist/metro/transformer.js.map +1 -1
  71. package/dist/next/internal/Project.d.ts.map +1 -1
  72. package/dist/next/internal/Project.js +2 -5
  73. package/dist/next/internal/Project.js.map +1 -1
  74. package/dist/node/Host.d.ts.map +1 -1
  75. package/dist/node/Host.js +0 -2
  76. package/dist/node/Host.js.map +1 -1
  77. package/dist/node/internal/Contracts.d.ts.map +1 -1
  78. package/dist/node/internal/Contracts.js +3 -7
  79. package/dist/node/internal/Contracts.js.map +1 -1
  80. package/dist/node/internal/Snapshot.d.ts +0 -1
  81. package/dist/node/internal/Snapshot.d.ts.map +1 -1
  82. package/dist/node/internal/Snapshot.js +0 -6
  83. package/dist/node/internal/Snapshot.js.map +1 -1
  84. package/dist/runtime/Composition.d.ts +2 -3
  85. package/dist/runtime/Composition.d.ts.map +1 -1
  86. package/dist/runtime/Composition.js +51 -30
  87. package/dist/runtime/Composition.js.map +1 -1
  88. package/dist/runtime/Recipe.d.ts.map +1 -1
  89. package/dist/runtime/Recipe.js +16 -12
  90. package/dist/runtime/Recipe.js.map +1 -1
  91. package/dist/unplugin/index.d.ts.map +1 -1
  92. package/dist/unplugin/index.js +3 -6
  93. package/dist/unplugin/index.js.map +1 -1
  94. package/dist/vite/index.d.ts.map +1 -1
  95. package/dist/vite/index.js +696 -201
  96. package/dist/vite/index.js.map +1 -1
  97. package/dist/web/Css.d.ts +8 -3
  98. package/dist/web/Css.d.ts.map +1 -1
  99. package/dist/web/Css.js +5 -721
  100. package/dist/web/Css.js.map +1 -1
  101. package/dist/web/internal/Block.d.ts +0 -2
  102. package/dist/web/internal/Block.d.ts.map +1 -1
  103. package/dist/web/internal/Block.js +1 -12
  104. package/dist/web/internal/Block.js.map +1 -1
  105. package/dist/web/internal/ClassName.d.ts +23 -18
  106. package/dist/web/internal/ClassName.d.ts.map +1 -1
  107. package/dist/web/internal/ClassName.js +26 -55
  108. package/dist/web/internal/ClassName.js.map +1 -1
  109. package/dist/web/internal/Contributions.d.ts +3 -5
  110. package/dist/web/internal/Contributions.d.ts.map +1 -1
  111. package/dist/web/internal/Contributions.js +0 -45
  112. package/dist/web/internal/Contributions.js.map +1 -1
  113. package/dist/web/internal/Engine.browser.d.ts +8 -0
  114. package/dist/web/internal/Engine.browser.d.ts.map +1 -0
  115. package/dist/web/internal/Engine.browser.js +42 -0
  116. package/dist/web/internal/Engine.browser.js.map +1 -0
  117. package/dist/web/internal/Engine.d.ts +9 -0
  118. package/dist/web/internal/Engine.d.ts.map +1 -0
  119. package/dist/web/internal/Engine.js +14 -0
  120. package/dist/web/internal/Engine.js.map +1 -0
  121. package/dist/web/internal/Themes.d.ts +1 -9
  122. package/dist/web/internal/Themes.d.ts.map +1 -1
  123. package/dist/web/internal/Themes.js +3 -221
  124. package/dist/web/internal/Themes.js.map +1 -1
  125. package/dist/web/internal/Wasm.generated.d.ts +4 -0
  126. package/dist/web/internal/Wasm.generated.d.ts.map +1 -0
  127. package/dist/web/internal/Wasm.generated.js +4 -0
  128. package/dist/web/internal/Wasm.generated.js.map +1 -0
  129. package/dist/web/internal/Wire.d.ts +19 -0
  130. package/dist/web/internal/Wire.d.ts.map +1 -0
  131. package/dist/web/internal/Wire.js +387 -0
  132. package/dist/web/internal/Wire.js.map +1 -0
  133. package/package.json +20 -1
  134. package/src/babel/index.ts +2 -5
  135. package/src/babel/internal/Compilation.ts +0 -1
  136. package/src/compiler/Graph.ts +89 -1930
  137. package/src/compiler/Native.ts +18 -871
  138. package/src/compiler/Source.ts +144 -1803
  139. package/src/compiler/Transform.ts +16 -1315
  140. package/src/compiler/internal/AtRules.ts +27 -115
  141. package/src/compiler/internal/Context.ts +11 -0
  142. package/src/compiler/internal/Results.ts +406 -0
  143. package/src/compiler/internal/Syntax.ts +0 -3
  144. package/src/compiler/internal/Wire.ts +1045 -0
  145. package/src/internal/Addon.ts +118 -0
  146. package/src/internal/Literal.ts +4 -2
  147. package/src/internal/Token.ts +2 -2
  148. package/src/internal/Vlq.ts +59 -0
  149. package/src/internal/Wasm.ts +111 -0
  150. package/src/metro/transformer.ts +0 -1
  151. package/src/next/internal/Project.ts +2 -9
  152. package/src/node/Host.ts +0 -2
  153. package/src/node/internal/Contracts.ts +3 -7
  154. package/src/node/internal/Snapshot.ts +0 -8
  155. package/src/runtime/Composition.ts +48 -25
  156. package/src/runtime/Recipe.ts +21 -14
  157. package/src/unplugin/index.ts +6 -6
  158. package/src/vite/index.ts +922 -221
  159. package/src/web/Css.ts +12 -908
  160. package/src/web/internal/Block.ts +0 -14
  161. package/src/web/internal/ClassName.ts +52 -85
  162. package/src/web/internal/Contributions.ts +3 -59
  163. package/src/web/internal/Engine.browser.ts +51 -0
  164. package/src/web/internal/Engine.ts +17 -0
  165. package/src/web/internal/Themes.ts +3 -279
  166. package/src/web/internal/Wasm.generated.ts +3 -0
  167. package/src/web/internal/Wire.ts +466 -0
  168. package/src/web/internal/wasm.d.ts +9 -0
  169. package/dist/compiler/internal/Applications.d.ts +0 -55
  170. package/dist/compiler/internal/Applications.d.ts.map +0 -1
  171. package/dist/compiler/internal/Applications.js +0 -393
  172. package/dist/compiler/internal/Applications.js.map +0 -1
  173. package/dist/compiler/internal/ColorProfiles.d.ts +0 -3
  174. package/dist/compiler/internal/ColorProfiles.d.ts.map +0 -1
  175. package/dist/compiler/internal/ColorProfiles.js +0 -84
  176. package/dist/compiler/internal/ColorProfiles.js.map +0 -1
  177. package/dist/compiler/internal/CompositionBindings.d.ts +0 -16
  178. package/dist/compiler/internal/CompositionBindings.d.ts.map +0 -1
  179. package/dist/compiler/internal/CompositionBindings.js +0 -89
  180. package/dist/compiler/internal/CompositionBindings.js.map +0 -1
  181. package/dist/compiler/internal/Compositions.d.ts +0 -37
  182. package/dist/compiler/internal/Compositions.d.ts.map +0 -1
  183. package/dist/compiler/internal/Compositions.js +0 -494
  184. package/dist/compiler/internal/Compositions.js.map +0 -1
  185. package/dist/compiler/internal/Configurations.d.ts +0 -26
  186. package/dist/compiler/internal/Configurations.d.ts.map +0 -1
  187. package/dist/compiler/internal/Configurations.js +0 -259
  188. package/dist/compiler/internal/Configurations.js.map +0 -1
  189. package/dist/compiler/internal/Contract.d.ts +0 -30
  190. package/dist/compiler/internal/Contract.d.ts.map +0 -1
  191. package/dist/compiler/internal/Contract.js +0 -753
  192. package/dist/compiler/internal/Contract.js.map +0 -1
  193. package/dist/compiler/internal/Contributions.d.ts +0 -54
  194. package/dist/compiler/internal/Contributions.d.ts.map +0 -1
  195. package/dist/compiler/internal/Contributions.js +0 -1151
  196. package/dist/compiler/internal/Contributions.js.map +0 -1
  197. package/dist/compiler/internal/Descriptors.d.ts +0 -15
  198. package/dist/compiler/internal/Descriptors.d.ts.map +0 -1
  199. package/dist/compiler/internal/Descriptors.js +0 -192
  200. package/dist/compiler/internal/Descriptors.js.map +0 -1
  201. package/dist/compiler/internal/Dynamic.d.ts +0 -14
  202. package/dist/compiler/internal/Dynamic.d.ts.map +0 -1
  203. package/dist/compiler/internal/Dynamic.js +0 -175
  204. package/dist/compiler/internal/Dynamic.js.map +0 -1
  205. package/dist/compiler/internal/Expression.d.ts +0 -19
  206. package/dist/compiler/internal/Expression.d.ts.map +0 -1
  207. package/dist/compiler/internal/Expression.js +0 -164
  208. package/dist/compiler/internal/Expression.js.map +0 -1
  209. package/dist/compiler/internal/Functions.d.ts +0 -5
  210. package/dist/compiler/internal/Functions.d.ts.map +0 -1
  211. package/dist/compiler/internal/Functions.js +0 -191
  212. package/dist/compiler/internal/Functions.js.map +0 -1
  213. package/dist/compiler/internal/Keyframes.d.ts +0 -5
  214. package/dist/compiler/internal/Keyframes.d.ts.map +0 -1
  215. package/dist/compiler/internal/Keyframes.js +0 -51
  216. package/dist/compiler/internal/Keyframes.js.map +0 -1
  217. package/dist/compiler/internal/Names.d.ts +0 -5
  218. package/dist/compiler/internal/Names.d.ts.map +0 -1
  219. package/dist/compiler/internal/Names.js +0 -37
  220. package/dist/compiler/internal/Names.js.map +0 -1
  221. package/dist/compiler/internal/NativeBindings.d.ts +0 -72
  222. package/dist/compiler/internal/NativeBindings.d.ts.map +0 -1
  223. package/dist/compiler/internal/NativeBindings.js +0 -171
  224. package/dist/compiler/internal/NativeBindings.js.map +0 -1
  225. package/dist/compiler/internal/NativeMedia.d.ts +0 -14
  226. package/dist/compiler/internal/NativeMedia.d.ts.map +0 -1
  227. package/dist/compiler/internal/NativeMedia.js +0 -287
  228. package/dist/compiler/internal/NativeMedia.js.map +0 -1
  229. package/dist/compiler/internal/NativeVars.d.ts +0 -28
  230. package/dist/compiler/internal/NativeVars.d.ts.map +0 -1
  231. package/dist/compiler/internal/NativeVars.js +0 -160
  232. package/dist/compiler/internal/NativeVars.js.map +0 -1
  233. package/dist/compiler/internal/PackedStyles.d.ts +0 -37
  234. package/dist/compiler/internal/PackedStyles.d.ts.map +0 -1
  235. package/dist/compiler/internal/PackedStyles.js +0 -344
  236. package/dist/compiler/internal/PackedStyles.js.map +0 -1
  237. package/dist/compiler/internal/Properties.d.ts +0 -5
  238. package/dist/compiler/internal/Properties.d.ts.map +0 -1
  239. package/dist/compiler/internal/Properties.js +0 -82
  240. package/dist/compiler/internal/Properties.js.map +0 -1
  241. package/dist/compiler/internal/RecipeConditions.d.ts +0 -41
  242. package/dist/compiler/internal/RecipeConditions.d.ts.map +0 -1
  243. package/dist/compiler/internal/RecipeConditions.js +0 -82
  244. package/dist/compiler/internal/RecipeConditions.js.map +0 -1
  245. package/dist/compiler/internal/RecipePayloads.d.ts +0 -31
  246. package/dist/compiler/internal/RecipePayloads.d.ts.map +0 -1
  247. package/dist/compiler/internal/RecipePayloads.js +0 -99
  248. package/dist/compiler/internal/RecipePayloads.js.map +0 -1
  249. package/dist/compiler/internal/Recipes.d.ts +0 -32
  250. package/dist/compiler/internal/Recipes.d.ts.map +0 -1
  251. package/dist/compiler/internal/Recipes.js +0 -339
  252. package/dist/compiler/internal/Recipes.js.map +0 -1
  253. package/dist/compiler/internal/Selectors.d.ts +0 -13
  254. package/dist/compiler/internal/Selectors.d.ts.map +0 -1
  255. package/dist/compiler/internal/Selectors.js +0 -280
  256. package/dist/compiler/internal/Selectors.js.map +0 -1
  257. package/dist/compiler/internal/Static.d.ts +0 -39
  258. package/dist/compiler/internal/Static.d.ts.map +0 -1
  259. package/dist/compiler/internal/Static.js +0 -534
  260. package/dist/compiler/internal/Static.js.map +0 -1
  261. package/dist/compiler/internal/Themes.d.ts +0 -190
  262. package/dist/compiler/internal/Themes.d.ts.map +0 -1
  263. package/dist/compiler/internal/Themes.js +0 -1577
  264. package/dist/compiler/internal/Themes.js.map +0 -1
  265. package/dist/compiler/internal/Vars.d.ts +0 -33
  266. package/dist/compiler/internal/Vars.d.ts.map +0 -1
  267. package/dist/compiler/internal/Vars.js +0 -387
  268. package/dist/compiler/internal/Vars.js.map +0 -1
  269. package/dist/compiler/internal/ViewTransitions.d.ts +0 -3
  270. package/dist/compiler/internal/ViewTransitions.d.ts.map +0 -1
  271. package/dist/compiler/internal/ViewTransitions.js +0 -68
  272. package/dist/compiler/internal/ViewTransitions.js.map +0 -1
  273. package/dist/internal/Cascade.d.ts +0 -74
  274. package/dist/internal/Cascade.d.ts.map +0 -1
  275. package/dist/internal/Cascade.js +0 -210
  276. package/dist/internal/Cascade.js.map +0 -1
  277. package/src/compiler/internal/Applications.ts +0 -610
  278. package/src/compiler/internal/ColorProfiles.ts +0 -93
  279. package/src/compiler/internal/CompositionBindings.ts +0 -120
  280. package/src/compiler/internal/Compositions.ts +0 -678
  281. package/src/compiler/internal/Configurations.ts +0 -349
  282. package/src/compiler/internal/Contract.ts +0 -1028
  283. package/src/compiler/internal/Contributions.ts +0 -1561
  284. package/src/compiler/internal/Descriptors.ts +0 -242
  285. package/src/compiler/internal/Dynamic.ts +0 -275
  286. package/src/compiler/internal/Expression.ts +0 -218
  287. package/src/compiler/internal/Functions.ts +0 -206
  288. package/src/compiler/internal/Keyframes.ts +0 -62
  289. package/src/compiler/internal/Names.ts +0 -48
  290. package/src/compiler/internal/NativeBindings.ts +0 -235
  291. package/src/compiler/internal/NativeMedia.ts +0 -342
  292. package/src/compiler/internal/NativeVars.ts +0 -231
  293. package/src/compiler/internal/PackedStyles.ts +0 -473
  294. package/src/compiler/internal/Properties.ts +0 -121
  295. package/src/compiler/internal/RecipeConditions.ts +0 -139
  296. package/src/compiler/internal/RecipePayloads.ts +0 -132
  297. package/src/compiler/internal/Recipes.ts +0 -531
  298. package/src/compiler/internal/Selectors.ts +0 -353
  299. package/src/compiler/internal/Static.ts +0 -784
  300. package/src/compiler/internal/Themes.ts +0 -2398
  301. package/src/compiler/internal/Vars.ts +0 -516
  302. package/src/compiler/internal/ViewTransitions.ts +0 -82
@@ -2,49 +2,20 @@
2
2
  * Extracts literal styles and local themes through lexical source analysis.
3
3
  * @module
4
4
  */
5
- import * as Identity from '../internal/Identity.js'
6
- import * as Identifiers from './internal/Identifiers.js'
7
- import type * as Ast from '@oxc-project/types'
8
- import * as AtRules from './internal/AtRules.js'
9
- import * as Binding from '../internal/Binding.js'
10
- import * as Condition from '../internal/Condition.js'
11
- import type * as Composition from '../runtime/Composition.js'
12
- import * as Compositions from './internal/Compositions.js'
13
- import * as Contributions from './internal/Contributions.js'
14
- import * as Css from '../web/Css.js'
15
- import * as Dynamic from './internal/Dynamic.js'
16
- import * as Expression from './internal/Expression.js'
17
- import * as Selectors from './internal/Selectors.js'
18
- import type * as Namespace from '../web/internal/Namespace.js'
19
- import * as Syntax from './internal/Syntax.js'
20
- import * as RuleReference from '../internal/RuleReference.js'
21
- import type * as Recipe from '../runtime/Recipe.js'
5
+ import * as Addon from '../internal/Addon.js'
6
+ import type * as Binding from '../internal/Binding.js'
22
7
  import type * as StaticRecipe from '../internal/Recipe.js'
23
- import type * as RecipePayloads from './internal/RecipePayloads.js'
24
- import * as Recipes from './internal/Recipes.js'
25
- import * as PackedStyles from './internal/PackedStyles.js'
26
- import * as Scope from './internal/Scope.js'
8
+ import type * as RuleReference from '../internal/RuleReference.js'
27
9
  import type * as Shorthands from '../internal/Shorthands.js'
28
- import * as Static from './internal/Static.js'
29
- import * as Style from '../Style.js'
30
10
  import type * as Theme from '../internal/Theme.js'
31
- import * as Themes from './internal/Themes.js'
32
- import * as ThemeValues from '../web/internal/Themes.js'
33
- import * as Token from '../internal/Token.js'
34
- import * as Literal from '../internal/Literal.js'
35
- import * as Names from './internal/Names.js'
36
- import * as ClassName from '../web/internal/ClassName.js'
37
- import * as Typography from '../internal/Typography.js'
38
- import * as Value from '../internal/Value.js'
39
- import * as Vars from './internal/Vars.js'
40
- import * as Walker from 'oxc-walker'
41
-
42
- // JavaScript extraction supplies untyped values. Keep structural checks without
43
- // asserting that those values already satisfy the TypeScript authoring contract.
44
- const define = Style.define as unknown as (
45
- styles: Record<string, unknown>,
46
- options: Style.define.Options,
47
- ) => Style.Definition
11
+ import type * as Composition from '../runtime/Composition.js'
12
+ import type * as Recipe from '../runtime/Recipe.js'
13
+ import type * as Style from '../Style.js'
14
+ import type * as Vars from '../Vars.js'
15
+ import type * as Css from '../web/Css.js'
16
+ import type { cssFunction } from '../web/cssFunction.js'
17
+ import type * as Namespace from '../web/internal/Namespace.js'
18
+ import * as Wire from './internal/Wire.js'
48
19
 
49
20
  /** A direct definition call available for a later source rewriter. */
50
21
  export type Call = {
@@ -102,8 +73,6 @@ export type Call = {
102
73
  | undefined
103
74
  /** Stable selector identity retained independently of declaration deduplication. */
104
75
  readonly identity?: string | undefined
105
- /** Expanded immutable source data retained for declaration mapping. */
106
- readonly body?: Ast.ObjectExpression | undefined
107
76
  /** Alias targets retained for declaration source locations. */
108
77
  readonly shorthands?: Shorthands.Map | undefined
109
78
  /** Emitted typography field counts keyed by authored property offsets. */
@@ -113,7 +82,7 @@ export type Call = {
113
82
  /** Native HTML attribute output selected by the bound configuration. */
114
83
  readonly output?: 'html' | undefined
115
84
  /** Typed runtime slots for callback definitions. */
116
- readonly slots?: Dynamic.Slots | undefined
85
+ readonly slots?: Readonly<Record<string, Binding.Reference>> | undefined
117
86
  /** Authored scalar input type retained in packed declarations. */
118
87
  readonly valuesType?: string | undefined
119
88
  /** Exclusive UTF-16 offset of the complete call. */
@@ -142,1720 +111,135 @@ export type Diagnostic = {
142
111
  readonly start: number
143
112
  }
144
113
 
114
+ /** A static stylesheet effect call replaced by its compiled data. */
115
+ type ContributionCall = {
116
+ /** Exported binding offset of a named factory result. */
117
+ readonly binding?: number | undefined
118
+ /** Exclusive UTF-16 offset of the complete call. */
119
+ readonly end: number
120
+ /** Whether the factory result is exported. */
121
+ readonly exported?: boolean | undefined
122
+ /** CSS function signature of a `cssFunction` call. */
123
+ readonly function?: ThemeCall['function']
124
+ /** Stylesheet factory that created the effect. */
125
+ readonly kind: string
126
+ /** Authored binding of a named factory result. */
127
+ readonly name?: string | undefined
128
+ /** Inclusive UTF-16 offset of the complete call. */
129
+ readonly start: number
130
+ }
131
+
132
+ /** Local bound-authoring initializer replaced while retaining its inferred type. */
133
+ type ThemeAlias = ThemeCall & {
134
+ /** Ordered authoring members replaced in a shared destructuring initializer. */
135
+ readonly bindings?: readonly ('style' | 'variants')[] | undefined
136
+ /** Whether the initializer supplies destructured authoring bindings. */
137
+ readonly destructured: boolean
138
+ /** Retains an immutable theme/configuration alias value with an explicit type. */
139
+ readonly retained?: boolean | undefined
140
+ }
141
+
142
+ /** Theme factory span and generated scope key. */
143
+ type ThemeCall = {
144
+ /** Whether the compiled configuration supplies root controls. */
145
+ readonly appearance?: boolean | undefined
146
+ /** Legacy packed catalog exposes members but lacks callable-selection capability. */
147
+ readonly catalogOnly?: boolean | undefined
148
+ readonly directVariables?: boolean | undefined
149
+ /** Exclusive source offset. */
150
+ readonly end: number
151
+ /** Static CSS function signature shared during extraction and packed serialization. */
152
+ readonly function?:
153
+ | {
154
+ parameters: readonly cssFunction.Parameter[]
155
+ returns: cssFunction.Syntax
156
+ }
157
+ | undefined
158
+ /** Bound root initialization script export. */
159
+ readonly initialization?: boolean | undefined
160
+ /** JSON-encoded member path tuples and their compiled scope keys. */
161
+ readonly members?: Readonly<Record<string, string>> | undefined
162
+ /** Stable module/binding scope key. */
163
+ readonly name: string
164
+ /** Whether native defineConfig retains a typed React Provider. */
165
+ readonly nativeProvider?: boolean | undefined
166
+ /** Validated inline configuration options retained for packed declarations. */
167
+ readonly options?: Readonly<Record<string, unknown>> | undefined
168
+ readonly output?: 'html' | undefined
169
+ /** Whether this bound authoring alias declares recipes. */
170
+ readonly recipe?: boolean | undefined
171
+ /** Named stylesheet identity domain. */
172
+ readonly reference?: RuleReference.Kind | undefined
173
+ /** Bound root controls export. */
174
+ readonly root?: boolean | undefined
175
+ /** Whether the compiled configuration supplies initialization. */
176
+ readonly script?: boolean | undefined
177
+ /** Config helper represented by this linked binding. */
178
+ readonly selection?: boolean | undefined
179
+ /** Inclusive source offset. */
180
+ readonly start: number
181
+ /** Literal token contract retained in rewritten TypeScript type assertions. */
182
+ readonly tokenType: string
183
+ /** Complete authoring type retained for configuration declarations. */
184
+ readonly type?: string | undefined
185
+ readonly variableConfig?: boolean | undefined
186
+ readonly variableMappings?: Vars.Mappings | false | undefined
187
+ /** Canonical defining module for multi-entry variable contracts. */
188
+ readonly variableOwner?: string | undefined
189
+ /** Portable explicit variable references. */
190
+ readonly variables?: Readonly<Record<string, Binding.Reference>> | undefined
191
+ readonly variableSet?: boolean | undefined
192
+ }
193
+
194
+ /** An explicit variable contract replaced by fixed slot data. */
195
+ type VariableCall = {
196
+ /** Exclusive source offset. */
197
+ readonly end: number
198
+ /** Whether the consumer supplied a portable variable identity. */
199
+ readonly explicit?: boolean | undefined
200
+ /** Fixed scalar reference retained in portable metadata. */
201
+ readonly slots: Readonly<Record<string, Binding.Reference>>
202
+ /** Inclusive source offset. */
203
+ readonly start: number
204
+ }
205
+
206
+ /** A readonly variable argument consumed by a native React hook. */
207
+ type VarsRead = {
208
+ /** Owning configuration fallback. */
209
+ readonly defaultVars: string
210
+ /** Exclusive source offset. */
211
+ readonly end: number
212
+ /** Stable configuration identity for graph-owned native profiles. */
213
+ readonly owner: string
214
+ /** Inclusive source offset. */
215
+ readonly start: number
216
+ /** A standalone definition that does not select a named catalog entry. */
217
+ readonly unnamed: boolean
218
+ /** Complete compatible variable alternatives. */
219
+ readonly vars: Readonly<Record<string, Theme.Definition>>
220
+ }
221
+
145
222
  /**
146
223
  * Extracts direct style calls and local Theme definitions imported from zyzz.
147
- * Parses TypeScript and JSX without reading files, loading config, or evaluating source.
224
+ * Parses TypeScript and JSX in the Rust compiler without reading files, loading config, or
225
+ * evaluating source. The returned calls carry no syntax trees.
148
226
  * @param options - Source text and a portable package-relative module identity.
149
227
  * @returns Frozen style/theme definitions and rewrite spans. Source text is unchanged.
150
228
  * @throws {ExtractError} For syntax errors, unsupported imported references, or invalid literals.
151
229
  */
152
230
  export function extract(options: extract.Options): extract.ReturnType {
153
- const calls: Call[] = []
154
- const diagnostics: Diagnostic[] = []
155
- const pending: Ast.CallExpression[] = []
156
- const recipes = new Set<number>()
157
- const styles: Style.NamedStyle[] = []
158
-
159
- function report(
160
- code: Diagnostic['code'],
161
- message: string,
162
- node?: Pick<Ast.Node, 'end' | 'start'>,
163
- ) {
164
- diagnostics.push({
165
- code,
166
- end: node?.end ?? 0,
167
- message,
168
- source: options.moduleId,
169
- start: node?.start ?? 0,
170
- })
171
- }
172
-
173
- if (
174
- !options.moduleId ||
175
- options.moduleId.includes('\\') ||
176
- options.moduleId.includes(':') ||
177
- options.moduleId
178
- .split('/')
179
- .some((part) => !part || part === '.' || part === '..')
180
- ) {
181
- report(
182
- 'invalid_module',
183
- 'Expected a portable package-relative module ID without absolute paths, backslashes, or traversal segments.',
184
- )
185
- throw new ExtractError(diagnostics)
186
- }
187
-
188
- const namespace = identity(options.moduleId)
189
- const parsed = options[Themes.context]?.parsed ?? Syntax.parse(options)
190
- for (const node of parsed.program.body) {
191
- if (node.type !== 'ImportDeclaration' || node.source.value !== 'zyzz')
192
- continue
193
- for (const specifier of node.specifiers) {
194
- if (specifier.type !== 'ImportSpecifier') continue
195
- const name =
196
- specifier.imported.type === 'Identifier'
197
- ? specifier.imported.name
198
- : specifier.imported.value
199
- if (name === 'Theme' || name === 'Variables')
200
- throw new ExtractError([
201
- {
202
- code: 'unsupported_syntax',
203
- message: `Import Vars instead of ${name}.`,
204
- source: options.moduleId,
205
- start: specifier.start,
206
- end: specifier.end,
207
- },
208
- ])
209
- }
210
- }
211
-
212
- if (parsed.errors.length) {
213
- for (const error of parsed.errors) {
214
- const span = error.labels[0]
215
-
216
- report('syntax_error', error.message, span)
217
- }
218
-
219
- throw new ExtractError(diagnostics)
220
- }
221
-
222
- const program = parsed.program
223
- const authoredNames = Names.collect(program)
224
- const scopeTracker = new Scope.Tracker({ preserveExitedScopes: true })
225
-
226
- Walker.walk(program, { scopeTracker })
227
- scopeTracker.freeze()
228
-
229
- const staticData = Static.create(
230
- program,
231
- scopeTracker,
232
- options[Themes.context]?.constants,
233
- )
234
-
235
- const contributions = (() => {
236
- try {
237
- return Contributions.scan(
238
- program,
239
- scopeTracker,
240
- namespace,
241
- options[Themes.context]?.links,
242
- options[Themes.context]?.factories,
243
- )
244
- } catch (error) {
245
- if (!(error instanceof Themes.InvalidError)) throw error
246
-
247
- report('unsupported_syntax', error.message, error)
248
- throw new ExtractError(diagnostics)
249
- }
250
- })()
251
-
252
- const variables = (() => {
253
- try {
254
- return Vars.collect(
255
- program,
256
- namespace,
257
- scopeTracker,
258
- options[Themes.context]?.links,
259
- options.moduleId,
260
- )
261
- } catch (error) {
262
- if (!(error instanceof Themes.InvalidError)) throw error
263
-
264
- report('unsupported_syntax', error.message, error)
265
- throw new ExtractError(diagnostics)
266
- }
267
- })()
268
-
269
- const themes = (() => {
270
- try {
271
- return Themes.collect(program, {
272
- native: options.target === 'native',
273
- staticBindings: staticData.bindings,
274
- namespace: `src-${Identity.label(
275
- options.moduleId
276
- .split('/')
277
- .at(-1)!
278
- .replace(/\.[cm]?[jt]sx?$/, ''),
279
- )}-${Identity.compact(options.moduleId)}`,
280
- contributionCalls: new Set(
281
- contributions.calls.map((call) => call.start),
282
- ),
283
- linked: options[Themes.context] !== undefined,
284
- links: options[Themes.context]?.links,
285
- })
286
- } catch (error) {
287
- if (!(error instanceof Themes.InvalidError)) throw error
288
-
289
- report('unsupported_syntax', error.message, error)
290
- throw new ExtractError(diagnostics)
291
- }
292
- })()
293
-
294
- const ancestors: Ast.Node[] = []
295
- const typeAncestors = new Set<Ast.Node>()
296
- const typeNodes = new Set([
297
- 'TSInterfaceDeclaration',
298
- 'TSTypeAliasDeclaration',
299
- 'TSTypeAnnotation',
300
- 'TSTypeParameterDeclaration',
301
- 'TSTypeParameterInstantiation',
302
- 'TSTypeQuery',
303
- ])
304
-
305
- Walker.walk(program, {
306
- enter(node, parent) {
307
- const declaration = staticData.visitor.enter(node, parent)
308
- ancestors.push(node)
309
- if (
310
- (parent &&
311
- 'typeAnnotation' in parent &&
312
- parent.typeAnnotation === node) ||
313
- typeNodes.has(node.type) ||
314
- (node.type === 'ExportNamedDeclaration' &&
315
- (node.source !== null || node.exportKind === 'type')) ||
316
- (node.type === 'ExportSpecifier' && node.exportKind === 'type')
317
- )
318
- typeAncestors.add(node)
319
-
320
- if (
321
- (node.type !== 'Identifier' && node.type !== 'JSXIdentifier') ||
322
- !parent ||
323
- (node.type === 'Identifier'
324
- ? declaration === undefined
325
- : !Walker.isReferenceIdentifier(node, parent))
326
- )
327
- return
328
-
329
- // Both passes visit identical scopes; skipping type subtrees changes scope IDs.
330
- if (typeAncestors.size) return
331
-
332
- const binding =
333
- node.type === 'Identifier'
334
- ? (declaration ?? null)
335
- : scopeTracker.getDeclaration(node.name)
336
-
337
- contributions.read(node, parent, binding)
338
-
339
- try {
340
- if (variables.reference(node, parent, ancestors, binding)) return
341
- } catch (error) {
342
- if (!(error instanceof Themes.InvalidError)) throw error
343
-
344
- report('unsupported_syntax', error.message, error)
345
-
346
- return
347
- }
348
-
349
- if (themes)
350
- try {
351
- if (
352
- themes.reference(
353
- node,
354
- parent,
355
- ancestors,
356
- binding,
357
- (name) => scopeTracker.getDeclaration(name) ?? null,
358
- )
359
- )
360
- return
361
- } catch (error) {
362
- if (!(error instanceof Themes.InvalidError)) throw error
363
-
364
- report('unsupported_syntax', error.message, error)
365
-
366
- return
367
- }
368
-
369
- if (
370
- binding?.type !== 'Import' ||
371
- binding.importNode.source.value !== 'zyzz' ||
372
- binding.importNode.importKind === 'type'
373
- )
374
- return
375
-
376
- const specifier = binding.node
377
-
378
- if (specifier.type === 'ImportNamespaceSpecifier') {
379
- if (parent.type === 'MemberExpression' && parent.object === node) {
380
- const name = (() => {
381
- if (parent.property.type === 'Identifier' && !parent.computed) {
382
- return parent.property.name
383
- }
384
-
385
- if (parent.property.type === 'Literal') {
386
- return parent.property.value
387
- }
388
-
389
- return undefined
390
- })()
391
-
392
- if (
393
- name === 'Config' ||
394
- name === 'cx' ||
395
- name === 'defineConfig' ||
396
- name === 'defineVars' ||
397
- name === 'extendVars' ||
398
- name === 'style' ||
399
- name === 'Theme' ||
400
- name === 'Vars' ||
401
- name === 'variable' ||
402
- name === 'variants'
403
- )
404
- report(
405
- 'unsupported_syntax',
406
- `Import ${name} by name; namespace authoring calls are not supported yet.`,
407
- parent,
408
- )
409
- }
410
-
411
- return
412
- }
413
-
414
- if (
415
- specifier.type !== 'ImportSpecifier' ||
416
- specifier.importKind === 'type' ||
417
- !['style', 'variants'].includes(
418
- specifier.imported.type === 'Identifier'
419
- ? specifier.imported.name
420
- : specifier.imported.value,
421
- )
422
- )
423
- return
424
-
425
- // Follow only assignment targets; computed keys and default values are reads.
426
- let target: Ast.Node = node
427
- let write: Ast.Node | undefined
428
-
429
- for (let index = ancestors.length - 2; index >= 0; index--) {
430
- const ancestor = ancestors[index]!
431
-
432
- if (
433
- (ancestor.type === 'AssignmentExpression' &&
434
- ancestor.left === target) ||
435
- (ancestor.type === 'UpdateExpression' &&
436
- ancestor.argument === target) ||
437
- ((ancestor.type === 'ForInStatement' ||
438
- ancestor.type === 'ForOfStatement') &&
439
- ancestor.left === target)
440
- ) {
441
- write = ancestor
442
- break
443
- }
444
-
445
- if (
446
- (ancestor.type === 'Property' && ancestor.value === target) ||
447
- ancestor.type === 'ObjectPattern' ||
448
- ancestor.type === 'ArrayPattern' ||
449
- (ancestor.type === 'RestElement' && ancestor.argument === target) ||
450
- (ancestor.type === 'AssignmentPattern' && ancestor.left === target)
451
- )
452
- target = ancestor
453
- else break
454
- }
455
-
456
- if (write)
457
- report(
458
- 'unsupported_syntax',
459
- 'Imported style bindings cannot be reassigned.',
460
- write,
461
- )
462
- else if (
463
- parent.type === 'CallExpression' &&
464
- parent.callee === node &&
465
- !parent.optional
466
- ) {
467
- pending.push(parent)
468
- if (
469
- (specifier.imported.type === 'Identifier'
470
- ? specifier.imported.name
471
- : specifier.imported.value) === 'variants'
472
- )
473
- recipes.add(parent.start)
474
- } else
475
- report(
476
- 'unsupported_syntax',
477
- 'Use a direct style call; aliases, re-exports, and indirect references are not supported yet.',
478
- node,
479
- )
480
- },
481
- leave(node) {
482
- ancestors.pop()
483
- typeAncestors.delete(node)
484
- staticData.visitor.leave()
485
- },
486
- scopeTracker,
487
- })
488
-
489
- Contributions.resolve(contributions)
490
-
491
- // Imports and reference lists can have a different order from authored calls.
492
- if (themes)
493
- for (const entry of themes.styles.values()) {
494
- pending.push(entry.call)
495
- if (entry.recipe) recipes.add(entry.call.start)
496
- }
497
-
498
- pending.sort((a, b) => a.start - b.start)
499
-
500
- const staticCalls = new Set([
501
- ...pending.map((call) => call.start),
502
- ...contributions.calls.map((call) => call.start),
503
- ])
504
- const opaque = new Set(variables.references.keys())
505
- const normalized = new Map<number, Ast.Node | Error>()
506
- const selectorKeys = new Set<number>()
507
- const composed: Ast.Node[] = []
508
- for (const call of pending) {
509
- if (!call.arguments[0]) continue
510
- try {
511
- const value = staticData.normalize(call.arguments[0], staticCalls, opaque)
512
- normalized.set(call.start, value)
513
- if (value.type === 'ArrayExpression')
514
- for (const element of value.elements) {
515
- const entry = element && Expression.unwrap(element)
516
- if (
517
- entry?.type === 'Identifier' ||
518
- entry?.type === 'MemberExpression'
519
- )
520
- composed.push(entry)
521
- }
522
- const body =
523
- value.type === 'ArrowFunctionExpression'
524
- ? staticData.normalize(value.body, staticCalls, opaque)
525
- : value
526
-
527
- Walker.walk(body, {
528
- enter(node) {
529
- if (
530
- node.type !== 'Property' ||
531
- node.computed ||
532
- node.value.type !== 'ObjectExpression' ||
533
- !(
534
- (node.key.type === 'Identifier' &&
535
- node.key.name === 'selectors') ||
536
- (node.key.type === 'Literal' && node.key.value === 'selectors')
537
- )
538
- )
539
- return
540
-
541
- for (const property of node.value.properties)
542
- if (property.type === 'Property')
543
- selectorKeys.add(property.key.start)
544
- },
545
- })
546
- } catch (error) {
547
- if (!(error instanceof Themes.InvalidError)) throw error
548
- normalized.set(call.start, error)
549
- }
550
- }
551
-
552
- for (const call of pending) {
553
- try {
554
- Identifiers.explicit(call)
555
- } catch (error) {
556
- report('unsupported_syntax', (error as Error).message, call)
557
- }
558
- }
559
- if (diagnostics.length) throw new ExtractError(diagnostics)
560
-
561
- const selectors = (() => {
562
- try {
563
- return Selectors.scan(
564
- program,
565
- scopeTracker,
566
- namespace,
567
- pending,
568
- options[Themes.context]?.links,
569
- selectorKeys,
570
- new Map(
571
- [...(themes?.styles ?? [])].flatMap(([start, context]) => {
572
- const id = context.theme[Token.definition].contract[Token.identity]
573
- return id?.startsWith('id-') ? [[start, id.slice(3)] as const] : []
574
- }),
575
- ),
576
- options.moduleId,
577
- composed,
578
- )
579
- } catch (error) {
580
- if (!(error instanceof Themes.InvalidError)) throw error
581
-
582
- report('unsupported_syntax', error.message, error)
583
- throw new ExtractError(diagnostics)
584
- }
585
- })()
586
-
587
- const bodies = new Map<number, Ast.ObjectExpression>()
588
- const cssNameCounts = new Map<string, number>()
589
- for (const call of pending) {
590
- const name = authoredNames.get(call.start)!
591
- cssNameCounts.set(name, (cssNameCounts.get(name) ?? 0) + 1)
592
- }
593
- const cssNameIndices = new Map<string, number>()
594
- for (const [callIndex, call] of pending.entries()) {
595
- const explicitId = (() => {
596
- try {
597
- return Identifiers.explicit(call)
598
- } catch (error) {
599
- report('unsupported_syntax', (error as Error).message, call)
600
- return undefined
601
- }
602
- })()
603
- const contractIdentity = themes?.styles.get(call.start)?.theme[
604
- Token.definition
605
- ].contract[Token.identity]
606
- const cssNamespace = contractIdentity?.startsWith('id-')
607
- ? contractIdentity.slice(3)
608
- : undefined
609
- const authoredName = authoredNames.get(call.start)!
610
- const nameIndex = cssNameIndices.get(authoredName) ?? 0
611
- cssNameIndices.set(authoredName, nameIndex + 1)
612
- const cssName =
613
- explicitId !== undefined
614
- ? Identity.name(explicitId)
615
- : `${Identity.compact(options.moduleId).slice(-6)}-${
616
- authoredName === 'style'
617
- ? `style-${callIndex}`
618
- : cssNameCounts.get(authoredName)! > 1
619
- ? `${authoredName}-${nameIndex}`
620
- : authoredName
621
- }`
622
- const definitionId =
623
- explicitId === undefined
624
- ? `${cssNamespace ? `${cssNamespace}-` : ''}${cssName}`
625
- : `id-${cssNamespace ? `${cssNamespace}-` : ''}${Identity.requireId(explicitId, 'style').slice(3)}`
626
- let argument = call.arguments[0]
627
-
628
- if (call.arguments.length === 0)
629
- argument = {
630
- end: call.end - 1,
631
- properties: [],
632
- start: call.end - 1,
633
- type: 'ObjectExpression',
634
- }
635
-
636
- while (
637
- argument?.type === 'TSAsExpression' ||
638
- argument?.type === 'TSSatisfiesExpression'
639
- )
640
- argument = argument.expression
641
-
642
- const original = argument
643
-
644
- try {
645
- const value = normalized.get(call.start)
646
- if (value instanceof Error) throw value
647
- if (value) argument = value as Ast.Expression
648
- } catch (error) {
649
- if (!(error instanceof Themes.InvalidError)) throw error
650
-
651
- report('unsupported_syntax', error.message, error)
652
- continue
653
- }
654
-
655
- const diagnosticCount = diagnostics.length
656
-
657
- const dynamic = (() => {
658
- if (!argument) return undefined
659
-
660
- try {
661
- return Dynamic.read(argument, definitionId, staticData.type)
662
- } catch (error) {
663
- if (!(error instanceof Themes.InvalidError)) throw error
664
-
665
- report('unsupported_syntax', error.message, error)
666
-
667
- return undefined
668
- }
669
- })()
670
- if (diagnostics.length !== diagnosticCount) continue
671
-
672
- let dynamicValues: RecipePayloads.Bindings | undefined = dynamic
673
-
674
- function resolveDynamic(node: Ast.Node) {
675
- try {
676
- return dynamicValues?.resolve(node)
677
- } catch (error) {
678
- if (!(error instanceof Themes.InvalidError)) throw error
679
-
680
- report('unsupported_syntax', error.message, error)
681
-
682
- return undefined
683
- }
684
- }
685
-
686
- if (dynamic) {
687
- try {
688
- argument = staticData.normalize(
689
- dynamic.body,
690
- staticCalls,
691
- opaque,
692
- ) as Ast.Expression
693
- } catch (error) {
694
- if (!(error instanceof Themes.InvalidError)) throw error
695
-
696
- report('unsupported_syntax', error.message, error)
697
- continue
698
- }
699
- }
700
-
701
- const entries =
702
- argument?.type === 'ArrayExpression' &&
703
- !dynamic &&
704
- !recipes.has(call.start)
705
- ? argument.elements
706
- : undefined
707
-
708
- if (
709
- call.arguments.length > 2 ||
710
- (argument?.type !== 'ObjectExpression' && !entries)
711
- ) {
712
- report(
713
- 'unsupported_syntax',
714
- 'Expected one literal object, typed callback, or array of style definitions and literal objects; spreads are not supported.',
715
- call,
716
- )
717
- continue
718
- }
719
-
720
- const before = diagnostics.length
721
- let recipe: Recipe.Definition | undefined
722
- let recipeTypes: Call['recipeTypes']
723
- let staticRecipe: StaticRecipe.Definition<Ast.ObjectExpression> | undefined
724
- let dynamicRecipe: StaticRecipe.Definition<Ast.ObjectExpression> | undefined
725
- if (recipes.has(call.start) && argument?.type === 'ObjectExpression') {
726
- try {
727
- if (dynamic)
728
- throw new Themes.InvalidError(
729
- 'Recipes require static top-level objects.',
730
- original ?? call,
731
- )
732
- const expanded = Recipes.expand(argument, {
733
- identity: definitionId,
734
- normalize: (node) => staticData.normalize(node, staticCalls, opaque),
735
- queries: themes?.styles.get(call.start)?.theme[Token.definition]
736
- .queries,
737
- resolveType: staticData.type,
738
- source: options.source,
739
- })
740
- argument = expanded.body
741
- recipe = expanded.recipe
742
- staticRecipe = expanded.staticRecipe
743
- dynamicRecipe = expanded.dynamicRecipe
744
- recipeTypes = expanded.types
745
- dynamicValues = expanded.bindings
746
- } catch (error) {
747
- if (!(error instanceof Themes.InvalidError)) throw error
748
- report('unsupported_syntax', error.message, error)
749
- continue
750
- }
751
- }
752
- const name = `style-${namespace}-${call.start}`
753
- const locations: Style.SourceLocation[] = []
754
- const typography = new Map<number, number>()
755
- const typographyQueries = new Map<number, number>()
756
- const conditionKeys = new Map<string, Ast.Node>()
757
-
758
- function object(
759
- argument: Ast.ObjectExpression,
760
- prefix: readonly string[] = [],
761
- ): Record<string, unknown> {
762
- const values: Record<string, unknown> = Object.create(null)
763
- const target = prefix.lastIndexOf('targets')
764
- if (target !== -1 && prefix.length > 64) {
765
- report(
766
- 'unsupported_syntax',
767
- 'Target nesting exceeds 64 levels.',
768
- argument,
769
- )
770
- return values
771
- }
772
- const depth = prefix.length + 2
773
-
774
- function localSlot(node: Ast.Node) {
775
- const slot = resolveDynamic(node)
776
-
777
- if (
778
- slot &&
779
- prefix.some(
780
- (key) =>
781
- !Condition.local(key) && !selectors.localConditions.has(key),
782
- )
783
- ) {
784
- report(
785
- 'unsupported_syntax',
786
- 'Dynamic values require conditions that select the styled element.',
787
- node,
788
- )
789
-
790
- return undefined
791
- }
792
-
793
- return slot
794
- }
795
-
796
- const properties: Ast.ObjectExpression['properties'] = []
797
- for (const entry of argument.properties) {
798
- const key =
799
- entry.type === 'Property' && !entry.computed
800
- ? entry.key.type === 'Identifier'
801
- ? entry.key.name
802
- : entry.key.type === 'Literal'
803
- ? entry.key.value
804
- : undefined
805
- : undefined
806
- if (key !== 'selectors' && key !== 'vars') {
807
- properties.push(entry)
808
- continue
809
- }
810
- if (
811
- entry.type !== 'Property' ||
812
- entry.kind !== 'init' ||
813
- entry.method ||
814
- entry.shorthand ||
815
- entry.value.type !== 'ObjectExpression'
816
- ) {
817
- report(
818
- 'unsupported_syntax',
819
- `${key} requires an explicit literal object.`,
820
- entry,
821
- )
822
- continue
823
- }
824
- for (const property of entry.value.properties) {
825
- if (
826
- property.type !== 'Property' ||
827
- (key === 'selectors'
828
- ? !selectors.conditions.has(property.key.start)
829
- : !property.computed ||
830
- !variables.references.has(property.key.start))
831
- ) {
832
- report(
833
- 'unsupported_syntax',
834
- key === 'selectors'
835
- ? 'Selectors require explicit & targets.'
836
- : 'Variable assignments require declared variable keys.',
837
- property,
838
- )
839
- continue
840
- }
841
- properties.push(property)
842
- }
843
- }
844
-
845
- for (const property of properties) {
846
- if (
847
- property.type !== 'Property' ||
848
- property.kind !== 'init' ||
849
- property.method ||
850
- (property.computed &&
851
- !selectors.conditions.has(property.key.start) &&
852
- !variables.references.has(property.key.start) &&
853
- !contributions.queryKeys.has(property.key.start)) ||
854
- property.shorthand ||
855
- (!selectors.conditions.has(property.key.start) &&
856
- !variables.references.has(property.key.start) &&
857
- property.key.type !== 'Identifier' &&
858
- (property.key.type !== 'Literal' ||
859
- typeof property.key.value !== 'string'))
860
- ) {
861
- report(
862
- 'unsupported_syntax',
863
- (() => {
864
- const key =
865
- property.type === 'Property' && property.computed
866
- ? Expression.unwrap(property.key)
867
- : undefined
868
-
869
- // Template keys with an & target are selectors outside their group.
870
- return key?.type === 'TemplateLiteral' &&
871
- key.quasis.some((quasi) => quasi.value.raw.includes('&'))
872
- ? 'Template selector keys require a selectors object.'
873
- : 'Only explicit literal properties are supported; spreads, computed keys, shorthand, and methods are not evaluated.'
874
- })(),
875
- property,
876
- )
877
- continue
878
- }
879
-
880
- const key =
881
- variables.references.get(property.key.start)?.reference.name ??
882
- selectors.conditions.get(property.key.start) ??
883
- contributions.queryKeys.get(property.key.start) ??
884
- (property.key.type === 'Identifier'
885
- ? property.key.name
886
- : property.key.type === 'Literal'
887
- ? String(property.key.value)
888
- : '')
889
-
890
- if (Object.hasOwn(values, key)) {
891
- report(
892
- 'unsupported_syntax',
893
- 'Duplicate properties are not supported in source definitions yet.',
894
- property,
895
- )
896
- continue
897
- }
898
-
899
- if (
900
- (key === 'targets' || target !== -1) &&
901
- staticData.absent(property.value)
902
- )
903
- continue
904
-
905
- if (key === 'targets' || prefix.at(-1) === 'targets') {
906
- const input = Expression.unwrap(property.value)
907
- if (input.type !== 'ObjectExpression') {
908
- report(
909
- 'unsupported_syntax',
910
- 'Target branches require static declaration objects.',
911
- input,
912
- )
913
- continue
914
- }
915
- values[key] = object(input, [...prefix, key])
916
- continue
917
- }
918
- if (target !== -1 && prefix[target + 1] !== 'web') {
919
- function nativeValue(input: Ast.Node, depth = 0): unknown {
920
- const node = Expression.unwrap(input)
921
- if (depth > 64) {
922
- report(
923
- 'unsupported_syntax',
924
- 'Native value nesting exceeds 64 levels.',
925
- node,
926
- )
927
- return undefined
928
- }
929
- if (node.type === 'ObjectExpression')
930
- return object(node, [...prefix, key])
931
- if (node.type === 'ArrayExpression')
932
- return node.elements.map((entry) => {
933
- if (!entry || entry.type === 'SpreadElement') {
934
- report(
935
- 'unsupported_syntax',
936
- 'Native arrays require dense static entries.',
937
- node,
938
- )
939
- return undefined
940
- }
941
- return nativeValue(entry, depth + 1)
942
- })
943
- if (
944
- node.type === 'Literal' &&
945
- (node.value === null ||
946
- ['boolean', 'number', 'string'].includes(typeof node.value))
947
- )
948
- return node.value
949
- if (
950
- node.type === 'UnaryExpression' &&
951
- ['+', '-'].includes(node.operator) &&
952
- node.argument.type === 'Literal' &&
953
- typeof node.argument.value === 'number'
954
- )
955
- return (node.operator === '-' ? -1 : 1) * node.argument.value
956
- if (node.type === 'TemplateLiteral') {
957
- const value = Expression.template(node)
958
- if (typeof value === 'string') return value
959
- }
960
- report(
961
- 'unsupported_syntax',
962
- 'Native branches require static literal values.',
963
- node,
964
- )
965
- return undefined
966
- }
967
- values[key] = nativeValue(property.value)
968
- continue
969
- }
970
- if (Condition.is(key)) {
971
- conditionKeys.set(
972
- JSON.stringify([name, ...prefix, key]),
973
- property.key,
974
- )
975
-
976
- const input = Expression.unwrap(property.value)
977
-
978
- if (input.type !== 'ObjectExpression') {
979
- report(
980
- 'unsupported_syntax',
981
- 'Conditions require literal declaration objects.',
982
- input,
983
- )
984
- continue
985
- }
986
-
987
- locations.push({
988
- source: options.moduleId,
989
- start: property.start,
990
- end: property.end,
991
- path: [name, ...prefix, key],
992
- })
993
- values[key] = object(input, [...prefix, key])
994
- continue
995
- }
996
-
997
- const targets = themes?.styles.get(call.start)?.theme[Token.definition]
998
- .contract.shorthands?.[key] ?? [key as Style.Declaration['property']]
999
-
1000
- function value(node: Ast.Node, path: readonly string[]): unknown {
1001
- const unwrapped = Expression.unwrap(node)
1002
- const token =
1003
- variables.references.get(unwrapped.start) ??
1004
- themes?.tokens.get(unwrapped.start)
1005
- const reference =
1006
- localSlot(node) ??
1007
- (token && token.end === unwrapped.end ? token.reference : undefined)
1008
-
1009
- if (
1010
- dynamicValues &&
1011
- reference &&
1012
- Object.values(dynamicValues.slots).includes(
1013
- reference as Binding.Reference,
1014
- ) &&
1015
- path.length > depth
1016
- ) {
1017
- report(
1018
- 'unsupported_syntax',
1019
- 'Dynamic fallback entries are not supported.',
1020
- node,
1021
- )
1022
-
1023
- return undefined
1024
- }
1025
-
1026
- node = Expression.unwrap(node)
1027
-
1028
- const animation = contributions.references.get(node.start)
1029
- if (animation) {
1030
- const kind = contributions.kinds.get(animation)
1031
- if (
1032
- kind &&
1033
- targets.some((target) => !RuleReference.accepts(kind, target))
1034
- ) {
1035
- report(
1036
- 'unsupported_syntax',
1037
- 'Named stylesheet reference is incompatible with this property.',
1038
- node,
1039
- )
1040
- return undefined
1041
- }
1042
- return animation
1043
- }
1044
-
1045
- const template =
1046
- node.type === 'TemplateLiteral'
1047
- ? Expression.template(node, 0, (expression, prefix) => {
1048
- const animation = contributions.references.get(
1049
- Expression.unwrap(expression).start,
1050
- )
1051
- if (animation) {
1052
- const kind = contributions.kinds.get(animation)
1053
- if (
1054
- kind &&
1055
- targets.some(
1056
- (target) =>
1057
- !RuleReference.acceptsExpression(
1058
- kind,
1059
- target,
1060
- prefix,
1061
- ),
1062
- )
1063
- ) {
1064
- report(
1065
- 'unsupported_syntax',
1066
- 'Named stylesheet reference is incompatible with this property.',
1067
- expression,
1068
- )
1069
- return undefined
1070
- }
1071
- return animation
1072
- }
1073
-
1074
- const token =
1075
- variables.references.get(expression.start) ??
1076
- themes?.tokens.get(expression.start)
1077
- const slot = localSlot(expression)
1078
-
1079
- if (slot) {
1080
- if (path.length > depth) {
1081
- report(
1082
- 'unsupported_syntax',
1083
- 'Dynamic fallback entries are not supported.',
1084
- expression,
1085
- )
1086
-
1087
- return undefined
1088
- }
1089
-
1090
- return slot
1091
- }
1092
-
1093
- return token?.end === expression.end
1094
- ? token.reference
1095
- : undefined
1096
- })
1097
- : undefined
1098
-
1099
- if (Token.isExpression(template)) {
1100
- for (const part of template.parts) {
1101
- if (
1102
- typeof part !== 'string' &&
1103
- !(Binding.is(part)
1104
- ? (dynamicValues !== undefined &&
1105
- Object.values(dynamicValues.slots).includes(part)) ||
1106
- targets.every(
1107
- (target) =>
1108
- Binding.accepts(part.type, target) ||
1109
- (part.type === 'color' &&
1110
- Expression.acceptsColor(template, target)),
1111
- )
1112
- : targets.every(
1113
- (target) =>
1114
- Token.acceptsReference(part, target) ||
1115
- (part.contract.variableSet &&
1116
- Expression.acceptsVariables(template, target)) ||
1117
- (part.group === 'color' &&
1118
- Expression.acceptsColor(template, target)),
1119
- ))
1120
- ) {
1121
- report(
1122
- 'unsupported_syntax',
1123
- Binding.is(part)
1124
- ? 'Variable domain is incompatible with this property.'
1125
- : 'Theme variable domain is incompatible with this property.',
1126
- node,
1127
- )
1128
-
1129
- return undefined
1130
- }
1131
- }
1132
- }
1133
-
1134
- if (
1135
- reference &&
1136
- Token.is(reference) &&
1137
- !targets.every((target) =>
1138
- Token.acceptsReference(reference, target),
1139
- ) &&
1140
- !targets.every((target) =>
1141
- dynamicValues?.accepts(
1142
- reference as unknown as Binding.Reference,
1143
- target,
1144
- ),
1145
- )
1146
- ) {
1147
- report(
1148
- 'unsupported_syntax',
1149
- 'Theme variable domain is incompatible with this property.',
1150
- node,
1151
- )
1152
-
1153
- return undefined
1154
- }
1155
-
1156
- if (
1157
- reference &&
1158
- Binding.is(reference) &&
1159
- !(
1160
- dynamicValues &&
1161
- Object.values(dynamicValues.slots).includes(reference) &&
1162
- reference.type !== 'number'
1163
- ) &&
1164
- !targets.every(
1165
- (target) =>
1166
- Binding.accepts(reference.type, target) ||
1167
- dynamicValues?.accepts(
1168
- reference as unknown as Binding.Reference,
1169
- target,
1170
- ),
1171
- )
1172
- ) {
1173
- report(
1174
- 'unsupported_syntax',
1175
- 'Variable domain is incompatible with this property.',
1176
- node,
1177
- )
1178
-
1179
- return undefined
1180
- }
1181
-
1182
- let result: unknown
1183
-
1184
- if (reference) result = reference
1185
- else if (template !== undefined) result = template
1186
- else if (
1187
- node.type === 'Literal' &&
1188
- (typeof node.value === 'string' || typeof node.value === 'number')
1189
- )
1190
- result = node.value
1191
- else if (
1192
- node.type === 'UnaryExpression' &&
1193
- (node.operator === '-' || node.operator === '+') &&
1194
- node.argument.type === 'Literal' &&
1195
- typeof node.argument.value === 'number'
1196
- )
1197
- result =
1198
- node.operator === '-' ? -node.argument.value : node.argument.value
1199
- else if (node.type === 'ArrayExpression' && path.length === depth) {
1200
- result = node.elements.map((element, index) => {
1201
- if (!element || element.type === 'SpreadElement') {
1202
- report(
1203
- 'unsupported_syntax',
1204
- 'Fallback arrays require dense literal entries without spreads.',
1205
- element ?? node,
1206
- )
1207
-
1208
- return undefined
1209
- }
1210
-
1211
- return value(element, [...path, String(index)])
1212
- })
1213
- } else {
1214
- report(
1215
- 'unsupported_syntax',
1216
- 'Expected a literal string or number; expressions are not evaluated.',
1217
- node,
1218
- )
1219
-
1220
- return undefined
1221
- }
1222
-
1223
- locations.push({
1224
- end: node.end,
1225
- path,
1226
- source: options.moduleId,
1227
- start: node.start,
1228
- })
1229
-
1230
- return result
1231
- }
1232
-
1233
- values[key] = value(property.value, [name, ...prefix, key])
1234
- }
1235
-
1236
- if (typeof values.typography === 'string') {
1237
- const theme = themes?.styles.get(call.start)?.theme
1238
- const mappings = theme?.[Token.definition].contract.shorthands
1239
- const explicit = new Set(
1240
- Object.keys(values).flatMap((key) => mappings?.[key] ?? [key]),
1241
- )
1242
- const parsed = Value.parse(values.typography, 'fontFamily')
1243
- const keys = Typography.keys(
1244
- theme,
1245
- parsed && !('invalid' in parsed) ? parsed.value : values.typography,
1246
- explicit,
1247
- )
1248
- const queries = keys.filter(Typography.condition).length
1249
- for (const property of properties) {
1250
- if (property.type !== 'Property') continue
1251
- const key =
1252
- property.key.type === 'Identifier'
1253
- ? property.key.name
1254
- : property.key.type === 'Literal'
1255
- ? property.key.value
1256
- : undefined
1257
- if (key === 'typography') {
1258
- typography.set(property.start, keys.length - queries)
1259
- if (queries) typographyQueries.set(property.start, queries)
1260
- }
1261
- }
1262
- }
1263
-
1264
- return values
1265
- }
1266
-
1267
- // Each entry becomes an ordered declaration segment, so later entries win as authored declarations do.
1268
- function compose(elements: Ast.ArrayExpression['elements']) {
1269
- const parts: Style.NamedStyle[] = []
1270
- const properties: Ast.ObjectExpression['properties'] = []
1271
-
1272
- for (const element of elements) {
1273
- const entry =
1274
- element && element.type !== 'SpreadElement'
1275
- ? Expression.unwrap(element)
1276
- : undefined
1277
-
1278
- if (entry?.type === 'ObjectExpression') {
1279
- const values = object(entry)
1280
- if (diagnostics.length !== before) continue
1281
-
1282
- parts.push(
1283
- define(
1284
- { [name]: values },
1285
- { locations, vars: themes?.styles.get(call.start)?.theme },
1286
- ).styles[0]!,
1287
- )
1288
- properties.push(...entry.properties)
1289
- continue
1290
- }
1291
-
1292
- const target = entry && selectors.compositions.get(entry.start)
1293
- const local =
1294
- target && 'type' in target
1295
- ? calls.find((value) => value.start === target.start)
1296
- : undefined
1297
- const packed = target && !('type' in target) ? target.style : undefined
1298
- const style = local
1299
- ? styles.find((style) => style.name === local.name)
1300
- : packed?.style
1301
-
1302
- if (!style) {
1303
- report(
1304
- 'unsupported_syntax',
1305
- 'Composition entries require literal objects or previously declared style definitions.',
1306
- element ?? call,
1307
- )
1308
- continue
1309
- }
1310
-
1311
- if (
1312
- local?.recipe ||
1313
- local?.slots ||
1314
- packed?.dynamic ||
1315
- (packed?.staticRecipe &&
1316
- !(
1317
- packed.staticRecipe.rules.length === 1 &&
1318
- packed.staticRecipe.rules[0]!.value.styles.length === 1 &&
1319
- packed.staticRecipe.rules[0]!.value.styles[0]!.name ===
1320
- packed.style.name
1321
- ))
1322
- ) {
1323
- report(
1324
- 'unsupported_syntax',
1325
- 'Composition entries cannot be variants or dynamic styles; apply them with cx.',
1326
- entry!,
1327
- )
1328
- continue
1329
- }
1330
-
1331
- // Native tables select variable alternatives from one context per call.
1332
- if (
1333
- options.target === 'native' &&
1334
- !context(
1335
- local
1336
- ? themes?.nativeContext(local.start, local.end)
1337
- : packed?.nativeContext,
1338
- themes?.nativeContext(call.start, call.end),
1339
- )
1340
- ) {
1341
- report(
1342
- 'unsupported_syntax',
1343
- 'Native composition entries require the variable catalog of the composing style.',
1344
- entry!,
1345
- )
1346
- continue
1347
- }
1348
-
1349
- // The composing configuration decides output for every copied entry.
1350
- parts.push(
1351
- Object.fromEntries(
1352
- Object.entries(style).filter(
1353
- ([key]) => key !== 'composition' && key !== 'cssOutput',
1354
- ),
1355
- ) as Style.NamedStyle,
1356
- )
1357
-
1358
- if (local) {
1359
- properties.push(...(bodies.get(local.start)?.properties ?? []))
1360
- for (const [start, count] of local.typography ?? [])
1361
- typography.set(start, count)
1362
- for (const [start, count] of local.typographyQueries ?? [])
1363
- typographyQueries.set(start, count)
1364
- continue
1365
- }
1366
-
1367
- // Packed declarations have no authored source here, so they map to the entry.
1368
- properties.push(
1369
- ...declarations(style).map(
1370
- (declaration): Ast.ObjectProperty => ({
1371
- type: 'Property',
1372
- computed: false,
1373
- kind: 'init',
1374
- method: false,
1375
- shorthand: false,
1376
- start: entry!.start,
1377
- end: entry!.end,
1378
- key: {
1379
- type: 'Literal',
1380
- value: declaration.property,
1381
- raw: JSON.stringify(declaration.property),
1382
- start: entry!.start,
1383
- end: entry!.end,
1384
- },
1385
- value: {
1386
- type: 'Literal',
1387
- value: '',
1388
- raw: '""',
1389
- start: entry!.start,
1390
- end: entry!.end,
1391
- },
1392
- }),
1393
- ),
1394
- )
1395
- }
1396
-
1397
- return {
1398
- body: {
1399
- type: 'ObjectExpression',
1400
- start: call.start,
1401
- end: call.end,
1402
- properties,
1403
- } satisfies Ast.ObjectExpression,
1404
- definition: {
1405
- styles: [
1406
- Object.freeze<Style.NamedStyle>({
1407
- name,
1408
- declarations: Object.freeze([]),
1409
- rules: Object.freeze(
1410
- parts.map((style) => Object.freeze({ style })),
1411
- ),
1412
- }),
1413
- ],
1414
- } satisfies Style.Definition as Style.Definition,
1415
- }
1416
- }
1417
-
1418
- const values = entries
1419
- ? undefined
1420
- : object(argument as Ast.ObjectExpression)
1421
- if (diagnostics.length !== before) continue
1422
-
1423
- try {
1424
- const composite = entries && compose(entries)
1425
- if (diagnostics.length !== before) continue
1426
-
1427
- const definition =
1428
- composite?.definition ??
1429
- define(
1430
- { [name]: values! },
1431
- { locations, vars: themes?.styles.get(call.start)?.theme },
1432
- )
1433
-
1434
- const body = composite?.body ?? (argument as Ast.ObjectExpression)
1435
- bodies.set(call.start, body)
1436
-
1437
- function validate(style: Style.NamedStyle, path: readonly string[]) {
1438
- for (const declaration of style.declarations) {
1439
- if (
1440
- Token.is(declaration.value) &&
1441
- declaration.value.contract.variableSet &&
1442
- Literal.rule(declaration.property)?.kind === 'identifier' &&
1443
- !Expression.acceptsIdentifier(
1444
- declaration.value,
1445
- declaration.property,
1446
- )
1447
- )
1448
- report(
1449
- 'invalid_literal',
1450
- 'Variable value is incompatible with this property.',
1451
- call,
1452
- )
1453
- }
1454
- if (style.targets?.web)
1455
- validate(style.targets.web, [...path, 'targets', 'web'])
1456
- for (const rule of style.rules ?? []) {
1457
- if (rule.condition !== undefined) {
1458
- const location =
1459
- conditionKeys.get(JSON.stringify([...path, rule.condition])) ??
1460
- call
1461
-
1462
- try {
1463
- AtRules.transform({
1464
- filename: options.moduleId,
1465
- code: Buffer.from(`.z{${rule.condition}{color:red;}}`),
1466
- errorRecovery: false,
1467
- })
1468
- } catch (error) {
1469
- report(
1470
- 'unsupported_syntax',
1471
- `Invalid selector or condition: ${(error as Error).message}`,
1472
- location,
1473
- )
1474
- }
1475
- }
1476
-
1477
- validate(
1478
- rule.style,
1479
- rule.condition === undefined ? path : [...path, rule.condition],
1480
- )
1481
- }
1482
- }
1483
-
1484
- for (const style of definition.styles) validate(style, [style.name])
1485
-
1486
- if (diagnostics.length !== before) continue
1487
-
1488
- const contract = themes?.styles.get(call.start)?.theme[Token.definition]
1489
- .contract
1490
- const composition = contract?.composition
1491
- const cssOutput = contract?.cssOutput
1492
- styles.push(
1493
- ...definition.styles.map((style) =>
1494
- composition || cssOutput
1495
- ? Object.freeze({
1496
- ...style,
1497
- ...(composition ? { composition } : {}),
1498
- ...(cssOutput ? { cssOutput } : {}),
1499
- })
1500
- : style,
1501
- ),
1502
- )
1503
-
1504
- const shorthands = themes?.styles.get(call.start)?.theme[Token.definition]
1505
- .contract.shorthands
1506
-
1507
- const retained = staticRecipe ?? dynamicRecipe
1508
- const targetRecipe = retained && {
1509
- ...retained,
1510
- rules: retained.rules.map(({ matches, value }, index) => ({
1511
- matches,
1512
- value: define(
1513
- { [`${name}-${index}`]: object(value) },
1514
- { locations, vars: themes?.styles.get(call.start)?.theme },
1515
- ),
1516
- })),
1517
- }
1518
- calls.push({
1519
- ...(recipe ? { recipe, recipeTypes } : {}),
1520
- ...(staticRecipe
1521
- ? { staticRecipe: targetRecipe }
1522
- : dynamicRecipe
1523
- ? { dynamicRecipe: targetRecipe }
1524
- : {}),
1525
- ...(selectors.identities.has(call.start)
1526
- ? { identity: selectors.identities.get(call.start)! }
1527
- : {}),
1528
- ...(body !== (dynamic?.body ?? original) ? { body } : {}),
1529
- ...(shorthands ? { shorthands } : {}),
1530
- ...(typography.size ? { typography } : {}),
1531
- ...(typographyQueries.size ? { typographyQueries } : {}),
1532
- ...(themes?.styles.get(call.start)?.output
1533
- ? { output: 'html' as const }
1534
- : {}),
1535
- ...(dynamic
1536
- ? {
1537
- slots: dynamic.slots,
1538
- valuesType: options.source.slice(
1539
- dynamic.type.start,
1540
- dynamic.type.end,
1541
- ),
1542
- }
1543
- : {}),
1544
- ...(options.compiler === false
1545
- ? {
1546
- portable: (() => {
1547
- if (explicitId !== undefined) return `z-style-${definitionId}`
1548
- if (
1549
- dynamic ||
1550
- recipe ||
1551
- entries?.length === 0 ||
1552
- (!definition.styles[0]!.declarations.length &&
1553
- !definition.styles[0]!.rules &&
1554
- !definition.styles[0]!.targets)
1555
- )
1556
- return undefined
1557
- return Identity.style(definition.styles[0]!, cssNamespace)
1558
- })(),
1559
- }
1560
- : {}),
1561
- cssName,
1562
- cssNamespace,
1563
- end: call.end,
1564
- name,
1565
- start: call.start,
1566
- })
1567
- } catch (error) {
1568
- if (!(error instanceof Style.InvalidError)) throw error
1569
-
1570
- for (const diagnostic of error.diagnostics)
1571
- diagnostics.push({
1572
- code: 'invalid_literal',
1573
- end: diagnostic.location?.end ?? call.end,
1574
- message: diagnostic.message,
1575
- source: options.moduleId,
1576
- start: diagnostic.location?.start ?? call.start,
1577
- })
1578
- }
1579
- }
1580
-
1581
- try {
1582
- let compositionIndex = 0
1583
- for (const entry of options.target === 'native'
1584
- ? []
1585
- : Compositions.collect({
1586
- calls,
1587
- identity: namespace,
1588
- links: options[Themes.context]?.links,
1589
- program,
1590
- scopes: themes?.scopeApplications,
1591
- source: options.source,
1592
- styles,
1593
- })) {
1594
- const authored = authoredNames.get(entry.call.start)
1595
- const name = authored && authored !== 'style' ? authored : 'composition'
1596
- const cssName = `${name}-${compositionIndex++}-${entry.call.cssName ?? 'style'}`
1597
- calls.push(
1598
- ...(entry.cases ?? []).map((value, index) => ({
1599
- ...value.call,
1600
- cssName: `${cssName}-${index}`,
1601
- })),
1602
- { ...entry.call, cssName },
1603
- )
1604
- styles.push(
1605
- ...(entry.cases ?? []).map((entry) => entry.style),
1606
- entry.style,
1607
- )
1608
- }
1609
- } catch (error) {
1610
- if (!(error instanceof Themes.InvalidError)) throw error
1611
- report('unsupported_syntax', error.message, error)
1612
- }
1613
-
1614
- if (themes && !diagnostics.length)
1615
- for (const [start, token] of themes.tokens) {
1616
- if (
1617
- !staticData.used.has(start) &&
1618
- !themes.staticTokens.some((node) => node.start === start) &&
1619
- ![...calls, ...contributions.calls].some(
1620
- (call) => start >= call.start && token.end <= call.end,
1621
- )
1622
- )
1623
- report(
1624
- 'unsupported_syntax',
1625
- 'Theme references require a compiled style declaration.',
1626
- { start, end: token.end },
1627
- )
1628
- }
1629
-
1630
- let contributionData: readonly Css.Contribution[] = []
1631
- const contributionStarts = [...variables.registrationStarts]
1632
-
1633
- try {
1634
- for (const [index, registration] of variables.registrations.entries()) {
1635
- try {
1636
- const css = Css.compile({
1637
- styles: { styles: [] },
1638
- contributions: [registration],
1639
- }).css
1640
- AtRules.transform({
1641
- filename: options.moduleId,
1642
- code: new TextEncoder().encode(css),
1643
- errorRecovery: false,
1644
- })
1645
- } catch (error) {
1646
- throw new Themes.InvalidError(
1647
- (error as Error).message,
1648
- variables.registrationLocations[index]!,
1649
- )
1650
- }
1651
- }
1652
-
1653
- contributionData = [
1654
- ...variables.registrations,
1655
- ...Contributions.extract(
1656
- contributions,
1657
- themes?.tokens ?? new Map(),
1658
- contributionStarts,
1659
- (node) => staticData.resolve(node, staticCalls),
1660
- ),
1661
- ...(themes?.calls ?? []).flatMap((call) =>
1662
- call.options?.layers
1663
- ? [
1664
- {
1665
- kind: 'layers' as const,
1666
- names: call.options.layers as readonly string[],
1667
- },
1668
- ]
1669
- : [],
1670
- ),
1671
- ]
1672
-
1673
- if (contributionData.length) {
1674
- const rendered = Css.compile({
1675
- styles: { styles: [] },
1676
- contributions: contributionData,
1677
- vars: themes?.themes,
1678
- }).css
1679
- AtRules.transform({
1680
- filename: options.moduleId,
1681
- code: new TextEncoder().encode(rendered),
1682
- errorRecovery: false,
1683
- ...(!options[Themes.context]
1684
- ? {
1685
- visitor: {
1686
- Rule(rule) {
1687
- if (
1688
- rule.type === 'import' &&
1689
- rule.value.url &&
1690
- !/^(?:\/|[?#]|[a-z][a-z\d+.-]*:)/i.test(rule.value.url)
1691
- )
1692
- throw new Error(
1693
- 'Relative contribution assets require Graph.compile and a relocation host.',
1694
- )
1695
- },
1696
- Url(url) {
1697
- if (
1698
- url.url &&
1699
- !/^(?:\/|[?#]|[a-z][a-z\d+.-]*:)/i.test(url.url)
1700
- )
1701
- throw new Error(
1702
- 'Relative contribution assets require Graph.compile and a relocation host.',
1703
- )
1704
- },
1705
- },
1706
- }
1707
- : {}),
1708
- })
1709
- }
1710
- } catch (error) {
1711
- report(
1712
- 'unsupported_syntax',
1713
- (error as Error).message,
1714
- error instanceof Themes.InvalidError ? error : contributions.calls[0],
1715
- )
1716
- }
1717
-
1718
- for (const token of themes?.staticTokens ?? [])
1719
- if (!staticData.used.has(Expression.unwrap(token).start))
1720
- report(
1721
- 'unsupported_syntax',
1722
- 'Token references must be direct property values in bound theme style calls.',
1723
- token,
1724
- )
1725
-
1726
- if (diagnostics.length) throw new ExtractError(diagnostics)
1727
-
1728
- function exportedStyle(link: Themes.Link): Themes.Link {
1729
- const call = calls.find((call) => call.identity === link.binding)
1730
- const style = call && styles.find((style) => style.name === call.name)
1731
- return {
1732
- ...link,
1733
- ...(call && style
1734
- ? {
1735
- style: PackedStyles.create(
1736
- {
1737
- ...call,
1738
- nativeContext: themes?.nativeContext(call.start, call.end),
1739
- },
1740
- style,
1741
- ),
1742
- }
1743
- : {}),
1744
- ...(link.members
1745
- ? {
1746
- members: Object.fromEntries(
1747
- Object.entries(link.members).map(([name, member]) => [
1748
- name,
1749
- exportedStyle(member),
1750
- ]),
1751
- ),
1752
- }
1753
- : {}),
1754
- }
1755
- }
1756
-
1757
- const callsByName = new Map(calls.map((call) => [call.name, call]))
1758
- const definition = {
1759
- styles: Object.freeze(styles),
1760
- [ClassName.labels]: Object.freeze(
1761
- Object.fromEntries(
1762
- styles.map((style) => {
1763
- let name = style.name
1764
- let call = callsByName.get(name)
1765
- while (!call && name.includes('-')) {
1766
- name = name.slice(0, name.lastIndexOf('-'))
1767
- call = callsByName.get(name)
1768
- }
1769
- return [
1770
- style.name,
1771
- {
1772
- name: call?.cssName
1773
- ? call.cssName + style.name.slice(call.name.length)
1774
- : style.name,
1775
- namespace: call?.cssNamespace,
1776
- },
1777
- ]
1778
- }),
1779
- ),
1780
- ),
1781
- }
1782
- Object.defineProperty(definition, ClassName.labels, { enumerable: false })
1783
- const selections =
1784
- options.target === 'native' ? themes?.selectionUses : themes?.selections
1785
-
1786
- return Object.freeze({
1787
- namespaces: contributionData.filter(
1788
- (value): value is Extract<Css.Contribution, { kind: 'namespace' }> =>
1789
- value.kind === 'namespace',
1790
- ),
1791
- ...(contributionData.length
1792
- ? { contributions: contributionData, contributionStarts }
1793
- : {}),
1794
- ...(contributions.calls.length
1795
- ? { contributionCalls: contributions.calls }
1796
- : {}),
1797
- ...(options[Themes.context]
1798
- ? {
1799
- themeExports: Object.freeze({
1800
- ...themes?.exports,
1801
- ...Object.fromEntries(
1802
- Object.entries(selectors.exports).map(([name, link]) => [
1803
- name,
1804
- exportedStyle(link),
1805
- ]),
1806
- ),
1807
- ...contributions.exports,
1808
- ...variables.exports,
1809
- }),
1810
- }
1811
- : {}),
1812
- calls: Object.freeze(
1813
- calls
1814
- .sort((a, b) => a.start - b.start)
1815
- .map((call) => {
1816
- const nativeContext =
1817
- options.target === 'native'
1818
- ? themes?.nativeContext(call.start, call.end)
1819
- : undefined
1820
- return Object.freeze(
1821
- nativeContext ? { ...call, nativeContext } : call,
1822
- )
1823
- }),
231
+ return Wire.decode(
232
+ Addon.load().call(
233
+ 'source.extract',
234
+ JSON.stringify({
235
+ compiler: options.compiler,
236
+ moduleId: options.moduleId,
237
+ source: options.source,
238
+ target: options.target,
239
+ }),
1824
240
  ),
1825
- styles: Object.freeze(definition),
1826
- ...(variables.calls.length
1827
- ? { variableCalls: Object.freeze(variables.calls) }
1828
- : {}),
1829
- themeAliases: Object.freeze(themes?.aliases ?? []),
1830
- ...(themes?.appearances.size
1831
- ? { themeAppearances: Object.freeze([...themes.appearances]) }
1832
- : {}),
1833
- ...(themes?.scripts.size
1834
- ? { themeScripts: Object.freeze([...themes.scripts]) }
1835
- : {}),
1836
- ...(selections?.size
1837
- ? { themeSelections: Object.freeze([...selections]) }
1838
- : {}),
1839
- themeCalls: Object.freeze(themes?.calls ?? []),
1840
- ...(themes?.staticTokens.length
1841
- ? {
1842
- staticThemeReferences: Object.freeze(
1843
- (themes?.staticTokens ?? []).map((node) => ({
1844
- start: node.start,
1845
- end: node.end,
1846
- value: ThemeValues.create().serialize(
1847
- themes!.tokens.get(node.start)!.reference,
1848
- ),
1849
- })),
1850
- ),
1851
- }
1852
- : {}),
1853
- themeReferences: Object.freeze(themes?.references ?? []),
1854
- vars: themes?.themes ?? Object.freeze({}),
1855
- ...(themes?.varsReads.length
1856
- ? { nativeVars: Object.freeze(themes.varsReads) }
1857
- : {}),
1858
- })
241
+ { compiler: options.compiler },
242
+ )
1859
243
  }
1860
244
 
1861
245
  /** Input and output of source extraction. */
@@ -1871,8 +255,6 @@ export declare namespace extract {
1871
255
  readonly compiler?: boolean | undefined
1872
256
  /** Portable identity including package and module path; no filesystem access occurs. */
1873
257
  readonly moduleId: string
1874
- /** Compiler-owned graph context. */
1875
- readonly [Themes.context]?: Themes.Context | undefined
1876
258
  /** Complete module text, parsed as TypeScript with JSX. */
1877
259
  readonly source: string
1878
260
  }
@@ -1880,21 +262,21 @@ export declare namespace extract {
1880
262
  /** Ordered public compiler input and spans for later rewriting. */
1881
263
  type ReturnType = {
1882
264
  /** Readonly native variable arguments and their complete catalogs. */
1883
- readonly nativeVars?: readonly Themes.VarsRead[] | undefined
265
+ readonly nativeVars?: readonly VarsRead[] | undefined
1884
266
  /** Module-owned namespace bindings retained when contributions are shared. */
1885
267
  readonly namespaces?: readonly Namespace.Definition[] | undefined
1886
268
  /** Static stylesheet effects and their source replacements. */
1887
269
  readonly contributionStarts?: readonly number[] | undefined
1888
270
  readonly contributions?: readonly Css.Contribution[] | undefined
1889
- readonly contributionCalls?: readonly Contributions.Call[] | undefined
271
+ readonly contributionCalls?: readonly ContributionCall[] | undefined
1890
272
  /** Explicit variable contracts replaced by fixed slot data. */
1891
- readonly variableCalls?: readonly Vars.Call[] | undefined
273
+ readonly variableCalls?: readonly VariableCall[] | undefined
1892
274
  /** Direct calls in source order. */
1893
275
  readonly calls: readonly Call[]
1894
276
  /** Validated definitions accepted by Css.compile. */
1895
277
  readonly styles: Style.Definition
1896
278
  /** Local bound-authoring initializers and their retained token types. */
1897
- readonly themeAliases: readonly Themes.Alias[]
279
+ readonly themeAliases: readonly ThemeAlias[]
1898
280
  /** Configuration identities retaining their root controls. */
1899
281
  readonly themeAppearances?: readonly string[] | undefined
1900
282
  /** Configuration identities retaining their initialization helper. */
@@ -1902,7 +284,7 @@ export declare namespace extract {
1902
284
  /** Configuration identities whose theme selector is called, passed, or bound. */
1903
285
  readonly themeSelections?: readonly string[] | undefined
1904
286
  /** Local factory spans replaced by compiled scope data. */
1905
- readonly themeCalls: readonly Themes.Call[]
287
+ readonly themeCalls: readonly ThemeCall[]
1906
288
  /** Scope reads replaced by class constants. */
1907
289
  readonly staticThemeReferences?:
1908
290
  | readonly {
@@ -1911,9 +293,12 @@ export declare namespace extract {
1911
293
  readonly value: string
1912
294
  }[]
1913
295
  | undefined
1914
- readonly themeReferences: readonly Themes.Reference[]
1915
- /** Resolved authoring exports when extracted as part of a source graph. */
1916
- readonly themeExports?: Readonly<Record<string, Themes.Link>> | undefined
296
+ readonly themeReferences: readonly Pick<
297
+ ThemeCall,
298
+ 'end' | 'name' | 'start'
299
+ >[]
300
+ /** Resolved authoring exports when extracted as part of a source graph, absent from a direct call. */
301
+ readonly themeExports?: Readonly<Record<string, object>> | undefined
1917
302
  /** Stable scope keys and validated local theme definitions. */
1918
303
  readonly vars: Readonly<Record<string, Theme.Definition>>
1919
304
  }
@@ -1939,47 +324,3 @@ export class ExtractError extends Error {
1939
324
  /** Stable namespaced error identifier. */
1940
325
  override name = 'Source.ExtractError'
1941
326
  }
1942
-
1943
- /** Accepts an entry context that the composing call selects identically. */
1944
- function context(
1945
- entry: Call['nativeContext'],
1946
- composite: Call['nativeContext'],
1947
- ): boolean {
1948
- if (!entry || entry === composite) return true
1949
- if (!composite || entry.defaultVars !== composite.defaultVars) return false
1950
-
1951
- const names = Object.keys(entry.vars)
1952
- return (
1953
- names.length === Object.keys(composite.vars).length &&
1954
- names.every((name) => {
1955
- const left = entry.vars[name]?.[Token.definition].contract
1956
- const right = composite.vars[name]?.[Token.definition].contract
1957
- return (
1958
- !!left &&
1959
- !!right &&
1960
- (left === right ||
1961
- (left[Token.identity] !== undefined &&
1962
- left[Token.identity] === right[Token.identity]))
1963
- )
1964
- })
1965
- )
1966
- }
1967
-
1968
- /** Lists declarations in emitted order, through conditions and segments. */
1969
- function declarations(style: Style.NamedStyle): readonly Style.Declaration[] {
1970
- return style.rules
1971
- ? style.rules.flatMap((rule) => declarations(rule.style))
1972
- : style.declarations
1973
- }
1974
-
1975
- function identity(value: string): string {
1976
- let first = 2166136261
1977
- let second = 2246822507
1978
-
1979
- for (let index = 0; index < value.length; index++) {
1980
- first = Math.imul(first ^ value.charCodeAt(index), 16777619)
1981
- second = Math.imul(second ^ value.charCodeAt(index), 3266489909)
1982
- }
1983
-
1984
- return `${(first >>> 0).toString(36)}${(second >>> 0).toString(36)}`
1985
- }