zyzz 0.0.28 → 0.0.29

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
@@ -1,25 +1,15 @@
1
1
  /**
2
2
  * Rewrites extracted style calls into executable modules with CSS and source maps.
3
+ * The Rust compiler performs the rewrite through the native addon.
3
4
  * @module
4
5
  */
5
6
  import * as Edits from './internal/Edits.js'
6
- import * as Token from '../internal/Token.js'
7
- import * as Applications from './internal/Applications.js'
8
- import type * as Ast from '@oxc-project/types'
9
- import * as Css from '../web/Css.js'
7
+ import type * as Css from '../web/Css.js'
10
8
  import * as ClassName from '../web/internal/ClassName.js'
11
- import * as Expression from './internal/Expression.js'
12
- import * as Identity from '../internal/Identity.js'
13
- import MagicString from 'magic-string'
14
- import * as Mapping from '@jridgewell/gen-mapping'
15
- import * as Namespaces from './internal/Namespaces.js'
16
- import * as Scheme from '../internal/Scheme.js'
17
- import * as Syntax from './internal/Syntax.js'
18
- import * as Source from './Source.js'
19
- import type * as Style from '../Style.js'
9
+ import type * as Mapping from '@jridgewell/gen-mapping'
10
+ import * as Results from './internal/Results.js'
11
+ import type * as Source from './Source.js'
20
12
  import * as ThemeRules from '../web/internal/Themes.js'
21
- import * as Themes from './internal/Themes.js'
22
- import * as Walker from 'oxc-walker'
23
13
 
24
14
  /**
25
15
  * Rewrites literal web styles and local themes without evaluation or file access.
@@ -31,1226 +21,22 @@ import * as Walker from 'oxc-walker'
31
21
  * @throws {Css.CompileError} If literal CSS compilation fails.
32
22
  */
33
23
  export function compile(options: compile.Options): compile.ReturnType {
34
- if (options.target === 'native')
35
- throw new Error('Use Native.compile for native source output.')
36
- const extracted =
37
- options[Themes.context]?.extracted ?? Source.extract(options)
38
-
39
- const portable = options.compiler === false
40
- const portableNames: Record<string, string> = {}
41
- if (portable) {
42
- for (const call of extracted.calls) {
43
- if (!call.portable)
44
- throw new Error(
45
- 'CSS-only output requires an explicit id for dynamic styles, variants, and compositions.',
46
- )
47
- portableNames[call.name] = call.portable
48
- }
49
- for (const [name, theme] of Object.entries(extracted.vars))
50
- if (
51
- (Object.keys(theme[Token.definition].values).length ||
52
- extracted.themeCalls.some(
53
- (call) =>
54
- (call.name === name ||
55
- Object.values(call.members ?? {}).includes(name)) &&
56
- (!call.options ||
57
- Object.hasOwn(call.options, 'themes') ||
58
- Object.hasOwn(call.options, 'theme')),
59
- )) &&
60
- !theme[Token.definition].contract[Token.identity]?.startsWith('id-')
61
- )
62
- throw new Error(
63
- 'CSS-only themes require an explicit id on Config.create or Vars.define.',
64
- )
65
- for (const call of extracted.contributionCalls ?? [])
66
- if (
67
- call.name &&
68
- !/^(?:--)?z-(?:k|counterstyle|positiontry|colorprofile|fontpalettevalues|custommedia|cssfunction)id-/.test(
69
- call.name,
70
- )
71
- )
72
- throw new Error(
73
- 'CSS-only named stylesheet declarations require an explicit id.',
74
- )
75
- for (const call of extracted.variableCalls ?? [])
76
- if (!call.explicit)
77
- throw new Error('CSS-only output requires an explicit variable id.')
78
- }
79
-
80
- if (portable) {
81
- function selectors(style: Style.NamedStyle) {
82
- for (const rule of style.rules ?? []) {
83
- if (
84
- rule.condition &&
85
- !rule.condition.startsWith('@') &&
86
- /\.z-style-(?!id-)/.test(rule.condition)
87
- )
88
- throw new Error(
89
- 'CSS-only selector references require an explicit style id.',
90
- )
91
- selectors(rule.style)
92
- }
93
- }
94
- for (const style of extracted.styles.styles) selectors(style)
95
- }
96
-
97
- const module = new MagicString(options.source)
98
- const program = (options[Themes.context]?.parsed ?? Syntax.parse(options))
99
- .program
100
-
101
- for (const call of extracted.contributionCalls ?? [])
102
- module.overwrite(
103
- call.start,
104
- call.end,
105
- (() => {
106
- const typed = /\.[cm]?tsx?$/.test(options.moduleId)
107
- if (call.kind === 'cssFunction')
108
- return `((...args${typed ? ': readonly (string | number)[]' : ''}) => ${JSON.stringify(call.name + '(')} + args.map(value => typeof value === 'string' && value.includes(',') && !value.trimStart().startsWith('{') ? '{' + value + '}' : value).join(',') + ')')${typed ? ` as import('zyzz/web').cssFunction.Reference<${JSON.stringify(call.function?.parameters ?? [])}, ${JSON.stringify(call.function?.returns ?? '*')}>` : ''}`
109
- if (call.kind === 'customMedia')
110
- return `${JSON.stringify(`@media (${call.name})`)}${typed ? ` as unknown as import('zyzz/web').customMedia.Reference` : ''}`
111
- if (!call.name) return 'void 0'
112
- return `${JSON.stringify(call.name)}${call.kind === 'keyframes' || !typed ? '' : ` as import('zyzz/web').${call.kind}.Reference`}`
113
- })(),
114
- )
115
-
116
- type Span = Pick<Ast.Node, 'end' | 'start'>
117
-
118
- const applications = new Map<number, { end: number; folded: boolean }>()
119
- const calls = new Map(extracted.calls.map((call) => [call.start, call]))
120
- const definitions = new Map<number, Ast.ObjectExpression>()
121
- const unusedSelections = new Set<number>()
122
- const identifiers = new Map<string, Span[]>()
123
-
124
- const localApplications = Applications.create(program, extracted.calls)
125
-
126
- Walker.walk(program, {
127
- enter(node, parent) {
128
- localApplications?.enter(node, parent)
129
-
130
- if (
131
- node.type === 'VariableDeclarator' &&
132
- node.init &&
133
- node.id.type === 'ObjectPattern' &&
134
- node.id.properties.every(
135
- (property) =>
136
- property.type === 'Property' &&
137
- (property.key.type === 'Identifier'
138
- ? property.key.name
139
- : property.key.type === 'Literal'
140
- ? property.key.value
141
- : undefined) !== 'themes' &&
142
- (property.key.type !== 'Identifier' ||
143
- property.key.name !== 'variables'),
144
- )
145
- )
146
- unusedSelections.add(Expression.unwrap(node.init).start)
147
-
148
- if (node.type === 'Identifier') {
149
- const references = identifiers.get(node.name) ?? []
150
-
151
- references.push(node)
152
- identifiers.set(node.name, references)
153
- }
154
-
155
- if (node.type !== 'CallExpression') return
156
-
157
- const call = calls.get(node.start)
158
- if (!call || node.end !== call.end) return
159
-
160
- const folded =
161
- !!call.composition ||
162
- (!call.recipe &&
163
- !call.slots &&
164
- parent?.type === 'CallExpression' &&
165
- parent.callee === node &&
166
- !parent.optional &&
167
- parent.arguments.length === 0)
168
-
169
- applications.set(call.start, {
170
- end: folded && !call.composition ? parent!.end : call.end,
171
- folded,
172
- })
173
-
174
- let argument = node.arguments[0]
175
- ? Expression.unwrap(node.arguments[0])
176
- : undefined
177
-
178
- if (argument?.type === 'ArrowFunctionExpression')
179
- argument = Expression.unwrap(argument.body) as Ast.Expression
180
-
181
- if (call.body) definitions.set(call.start, call.body)
182
- else if (argument?.type === 'ObjectExpression')
183
- definitions.set(call.start, argument)
184
- },
185
- })
186
-
187
- const found = localApplications?.find() ?? []
188
- // Compositions supersede their inputs' classes, so those reads stay unfolded.
189
- const composing = (application: Span) =>
190
- extracted.calls.some(
191
- (call) =>
192
- (call.composition || call.runtimeComposition) &&
193
- call.start < application.start &&
194
- application.end <= call.end,
195
- )
196
- const folded = new Set(
197
- found.filter(
198
- (application) =>
199
- !composing(application) &&
200
- !extracted.calls.some(
201
- (call) =>
202
- call.output === 'html' &&
203
- call.runtimeComposition?.some(
204
- (input) => input.applicationStart === application.start,
205
- ),
206
- ),
207
- ),
208
- )
209
-
210
- const local =
211
- portable || options.development
212
- ? undefined
213
- : localApplications?.definitions()
214
-
215
- // Styles applied only alone to DOM elements, or inside cx, never meet another
216
- // style's classes. Atomic ones share rules like independent styles.
217
- const standalone = new Set(
218
- [...(local?.values.keys() ?? [])].filter((name) =>
219
- found.every(
220
- (application) =>
221
- application.name !== name ||
222
- application.terminal ||
223
- composing(application),
224
- ),
225
- ),
226
- )
227
-
228
- // Scheme rules accompany modules whose runtime helpers can apply a scheme class.
229
- const schemes =
230
- options.schemes ??
231
- Boolean(
232
- extracted.themeAppearances?.length ||
233
- extracted.themeScripts?.length ||
234
- extracted.themeSelections?.length,
235
- )
236
-
237
- const emitted = Css.compile({
238
- [ThemeRules.shared]: options[ThemeRules.shared],
239
- development: options.development,
240
- [ClassName.labels]: extracted.styles[ClassName.labels],
241
- [ClassName.units]:
242
- options[ClassName.units] ??
243
- ClassName.registry().scope({
244
- owner: options.moduleId,
245
- qualifier: Identity.compact(options.moduleId).slice(-6),
246
- }),
24
+ const input = {
25
+ compiler: options.compiler,
247
26
  composition: options.composition,
248
27
  cssOutput: options.cssOutput,
249
- names: portable ? portableNames : undefined,
250
- schemes,
251
- // Keep definition positions stable while removing proven unreachable rules.
252
- // CSS-only consumers retain executable authoring, and development keeps slots.
253
- styles: (() => {
254
- if (portable || options.development) return extracted.styles
255
-
256
- const dead = localApplications?.dead()
257
- if (!dead?.size && !standalone.size) return extracted.styles
258
-
259
- return {
260
- styles: extracted.styles.styles.map((style) => {
261
- if (dead?.has(style.name))
262
- return {
263
- cssOutput: style.cssOutput,
264
- declarations: [],
265
- name: style.name,
266
- }
267
-
268
- // Grouped output keeps one class per style.
269
- return standalone.has(style.name) &&
270
- (style.cssOutput ?? options.cssOutput ?? 'atomic') === 'atomic'
271
- ? { ...style, composition: 'independent' as const }
272
- : style
273
- }),
274
- }
275
- })(),
276
- contributions: extracted.contributions,
277
- vars: Object.keys(extracted.vars).length ? extracted.vars : undefined,
278
- })
279
-
280
- let runtime = '__zyzzProps'
281
-
282
- while (identifiers.has(runtime)) runtime += '_'
283
-
284
- let html = '__zyzzHtml'
285
-
286
- while (identifiers.has(html)) html += '_'
287
-
288
- let usesHtml = false
289
- let conditionalRecipe = '__zyzzConditionalRecipe'
290
- while (identifiers.has(conditionalRecipe)) conditionalRecipe += '_'
291
- let usesConditionalRecipe = false
292
- let payloadRecipe = '__zyzzPayloadRecipe'
293
- while (identifiers.has(payloadRecipe)) payloadRecipe += '_'
294
- let usesPayloadRecipe = false
295
- let recipe = '__zyzzRecipe'
296
- while (identifiers.has(recipe)) recipe += '_'
297
- let usesRecipe = false
298
- let compositionHtml = '__zyzzCompositionHtml'
299
- while (identifiers.has(compositionHtml)) compositionHtml += '_'
300
- let usesCompositionHtml = false
301
- const preparedHtml = new Set(
302
- extracted.calls.flatMap((call) =>
303
- call.output === 'html'
304
- ? (call.runtimeComposition ?? []).map((input) => input.name)
305
- : [],
306
- ),
307
- )
308
- function prepareExport(link: Themes.Link) {
309
- if (link.style?.output === 'html') {
310
- const call = extracted.calls.find(
311
- (call) => call.identity === link.binding,
312
- )
313
- if (call) preparedHtml.add(call.name)
314
- }
315
- for (const member of Object.values(link.members ?? {}))
316
- prepareExport(member)
317
- }
318
- for (const link of Object.values(extracted.themeExports ?? {}))
319
- prepareExport(link)
320
- let composition = '__zyzzComposition'
321
- while (identifiers.has(composition)) composition += '_'
322
- let usesComposition = false
323
- const compositions: string[] = []
324
- const compositionArguments = new Map<string, string>()
325
-
326
- let appearance = '__zyzzAppearance'
327
-
328
- while (identifiers.has(appearance)) appearance += '_'
329
-
330
- let usesAppearance = false
331
- let selection = '__zyzzSelection'
332
-
333
- while (identifiers.has(selection)) selection += '_'
334
-
335
- let usesSelection = false
336
-
337
- let variables = '__zyzzVariable'
338
-
339
- while (identifiers.has(variables)) variables += '_'
340
-
341
- for (const call of extracted.variableCalls ?? [])
342
- module.overwrite(
343
- call.start,
344
- call.end,
345
- `${variables}.create(${JSON.stringify(call.slots.value)})`,
346
- )
347
-
348
- const identities = new Map(
349
- extracted.calls
350
- .filter((call) => call.identity)
351
- .map((call) => [call.name, call.identity!]),
352
- )
353
-
354
- const classes = Object.freeze(
355
- Object.fromEntries(
356
- Object.entries(emitted.classes).map(([name, value]) => [
357
- name,
358
- [
359
- ...new Set([
360
- ...value.split(' ').filter(Boolean),
361
- ...(identities.has(name) &&
362
- (!portable || portableNames[name]?.startsWith('z-compose-'))
363
- ? [
364
- portable
365
- ? identities
366
- .get(name)!
367
- .split(' ')
368
- .filter((name) => name.startsWith('z-style-id-'))
369
- .join(' ')
370
- : identities.get(name)!,
371
- ]
372
- : []),
373
- ]),
374
- ].join(' '),
375
- ]),
376
- ),
377
- )
378
-
379
- // Definitions read only through folded applications need no class list of
380
- // their own. True marks definitions whose every read follows initialization.
381
- const unread = new Map(
382
- [...(local?.values ?? [])].filter(([name]) =>
383
- found.every(
384
- (application) => application.name !== name || folded.has(application),
385
- ),
386
- ),
387
- )
388
- const namespaces = (local?.namespaces ?? []).filter((namespace) =>
389
- [...namespace.ends.keys()].every((name) => unread.get(name)),
390
- )
391
-
392
- const erased = new Map(namespaces.flatMap((namespace) => [...namespace.ends]))
393
-
394
- // An ambient namespace keeps member types without runtime initialization.
395
- for (const namespace of namespaces)
396
- module.prependRight(namespace.start, 'declare ')
397
-
398
- for (const call of extracted.calls) {
399
- const end = erased.get(call.name)
400
- if (end !== undefined)
401
- module.overwrite(
402
- end,
403
- call.start,
404
- `: import('zyzz').style.ReturnType${call.output === 'html' ? "<'html'>" : ''}`,
405
- )
406
- }
407
-
408
- let callable = false
409
-
410
- const composed = (node: Span) =>
411
- extracted.calls.some(
412
- (call) =>
413
- call.composition && call.start < node.start && node.end <= call.end,
414
- )
415
- // Rewrite contained expressions before their enclosing composition reads them.
416
- const rewrites = [...extracted.calls].sort((a, b) =>
417
- a.start < b.start && a.end >= b.end
418
- ? 1
419
- : b.start < a.start && b.end >= a.end
420
- ? -1
421
- : a.start - b.start,
422
- )
423
- for (const call of rewrites) {
424
- if (call.compositionCase || composed(call)) continue
425
- const application = applications.get(call.start)!
426
- const props = `{${call.output === 'html' ? 'class' : 'className'}:${JSON.stringify(classes[call.name])}}`
427
-
428
- const composeHtml = call.output === 'html' && preparedHtml.has(call.name)
429
- if (composeHtml) usesCompositionHtml = true
430
- const replacement = (() => {
431
- if (call.runtimeComposition) {
432
- const helper = call.output === 'html' ? compositionHtml : composition
433
- if (call.output === 'html') usesCompositionHtml = true
434
- else usesComposition = true
435
- let factory = `${composition}${call.start}`
436
- while (identifiers.has(factory)) factory += '_'
437
- const inputs = call.runtimeComposition.map((input) => ({
438
- className:
439
- classes[input.name] ??
440
- options[Themes.context]?.styleClasses?.[input.name] ??
441
- '',
442
- condition: input.condition,
443
- owners: input.owners,
444
- }))
445
- compositions.push(
446
- `const ${factory}=/*#__PURE__*/${helper}.create(${JSON.stringify({ className: classes[call.name], cases: call.compositionCases?.map((name) => classes[name]!), inputs })});`,
447
- )
448
- return `${factory}(${call.runtimeComposition
449
- .map((input) => {
450
- const key = `${input.start}:${input.end}`
451
- const value =
452
- compositionArguments.get(key) ??
453
- module.slice(input.start, input.end)
454
- compositionArguments.set(key, value)
455
- return value
456
- })
457
- .join(',')})`
458
- }
459
- if (call.composition)
460
- return call.composition.reduceRight(
461
- (result, guard) =>
462
- `((${guard}${/\.[cm]?tsx?$/.test(options.moduleId) ? ' as unknown' : ''})?${result}:${guard}())`,
463
- composeHtml
464
- ? `${compositionHtml}.from({className:${JSON.stringify(classes[call.name])}})`
465
- : `(${props})`,
466
- )
467
- if (call.recipe) {
468
- const helper = call.recipe.conditions?.length
469
- ? conditionalRecipe
470
- : recipe
471
- if (call.recipe.conditions?.length) usesConditionalRecipe = true
472
- else usesRecipe = true
473
-
474
- const payload = !!call.recipe.payloads?.length
475
- if (payload) usesPayloadRecipe = true
476
- const selection = `${helper}.create(${JSON.stringify({ axes: call.recipe.axes, defaults: call.recipe.defaults, conditions: call.recipe.conditions, className: classes[call.name], ...(!payload && call.output === 'html' && !composeHtml ? { html: true } : {}) })})`
477
- const value = payload
478
- ? `${payloadRecipe}.create({...${JSON.stringify({ ...call.recipe, html: call.output === 'html' && !composeHtml })},select:${selection}})`
479
- : selection
480
- const bound = composeHtml ? `${compositionHtml}.bind(${value})` : value
481
- const axes = Object.entries(call.recipe.axes)
482
- .map(
483
- ([axis, choices]) =>
484
- `${JSON.stringify(axis)}:{${choices.map((choice) => `${JSON.stringify(choice)}:${call.recipeTypes?.[axis]?.[choice] ? `(values:${call.recipeTypes[axis]![choice]})=>{}` : '{}'}`).join(';')}}`,
485
- )
486
- .join(';')
487
- const conditions = call.recipe.conditions
488
- ?.map((name) => `${JSON.stringify(name)}:unknown`)
489
- .join(';')
490
- const type = `import('zyzz').variants.ReturnType<{variants:{${axes}}${conditions ? `;conditions:{${conditions}}` : ''}}${call.output === 'html' ? ',"html"' : ''}>`
491
- return /\.[cm]?tsx?$/.test(options.moduleId)
492
- ? `(${bound} as ${type})`
493
- : bound
494
- }
495
- if (call.slots) {
496
- const type = `import('zyzz').style.Dynamic<${call.valuesType}${call.output === 'html' ? ',"html"' : ''}>`
497
- const typed = /\.[cm]?tsx?$/.test(options.moduleId)
498
- const slots = Object.entries(call.slots)
499
-
500
- const reads = slots
501
- .map(
502
- ([key], index) =>
503
- `const v${index}=input[${JSON.stringify(key)}]${typed ? ' as string | number' : ''};`,
504
- )
505
- .join('')
506
-
507
- const assignments = slots
508
- .map(
509
- ([, slot], index) =>
510
- `${JSON.stringify(slot.name)}:v${index}===''?' ':v${index}`,
511
- )
512
- .join(',')
513
-
514
- const className = JSON.stringify(classes[call.name])
515
- const value = `(input${typed ? `:Parameters<${type}>[0]` : ''})=>{${reads}const external=input.className;const style=input.style;return {className:external?${className}+" "+external:${className},style:{...input.vars,...style,${assignments}}}}`
516
- const result = composeHtml
517
- ? `${compositionHtml}.bind(${value})`
518
- : call.output === 'html'
519
- ? `${html}.bind(${value})`
520
- : `(${value})`
521
-
522
- if (call.output === 'html' && !composeHtml) usesHtml = true
523
-
524
- return typed ? `(${result} as ${type})` : result
525
- }
526
-
527
- const initialized = unread.get(call.name)
528
- if (initialized !== undefined) {
529
- if (erased.has(call.name)) return ''
530
-
531
- // Guards read only truthiness, and failures before initialization still call it.
532
- const value = initialized ? 'void 0' : '1'
533
- return /\.[cm]?tsx?$/.test(options.moduleId)
534
- ? `(${value} as unknown as import('zyzz').style.ReturnType${call.output === 'html' ? "<'html'>" : ''})`
535
- : value
536
- }
537
-
538
- if (application.folded)
539
- return composeHtml
540
- ? `${compositionHtml}.from({className:${JSON.stringify(classes[call.name])}})`
541
- : `(${props})`
542
-
543
- if (call.output === 'html') {
544
- if (composeHtml) {
545
- callable = true
546
- return `(${compositionHtml}.bind(${runtime}.create({className:${JSON.stringify(classes[call.name])}}))${/\.[cm]?tsx?$/.test(options.moduleId) ? " as import('zyzz').style.ReturnType<'html'>" : ''})`
547
- }
548
- usesHtml = true
549
-
550
- return `${html}.create({className:${JSON.stringify(classes[call.name])}})`
551
- }
552
-
553
- return `${runtime}.create(${props})`
554
- })()
555
-
556
- module.overwrite(call.start, application.end, replacement)
557
-
558
- if (
559
- !call.recipe &&
560
- !call.slots &&
561
- !call.runtimeComposition &&
562
- !application.folded &&
563
- !unread.has(call.name) &&
564
- call.output !== 'html'
565
- )
566
- callable = true
567
- }
568
-
569
- for (const application of folded) {
570
- const className = JSON.stringify(classes[application.name])
571
-
572
- const key =
573
- extracted.calls.find((call) => call.name === application.name)?.output ===
574
- 'html'
575
- ? 'class'
576
- : 'className'
577
- const callee = options.source.slice(
578
- application.start,
579
- application.calleeEnd,
580
- )
581
-
582
- module.overwrite(
583
- application.start,
584
- application.end,
585
- application.initialized
586
- ? `({${key}:${className}})`
587
- : // Keep a callable guard so bundlers also retain failures before initialization.
588
- `(${callee}?{${key}:${className}}:${callee}())`,
589
- )
590
- }
591
-
592
- for (const call of extracted.themeCalls) {
593
- const scope = (name: string) => ({ className: emitted.vars[name] })
594
-
595
- const props = (() => {
596
- if (call.variableSet) return '{}'
597
- if (!call.members)
598
- return `{className:${JSON.stringify(emitted.vars[call.name])}}`
599
-
600
- const script = extracted.themeScripts?.includes(call.name)
601
- const root = extracted.themeAppearances?.includes(call.name)
602
-
603
- if (script || root) usesAppearance = true
604
-
605
- // Helpers are emitted only when referenced; both share the configured storage key.
606
- const storage = call.options?.storageKey
607
- const helpers = (entries: string, defaultTheme?: string) => {
608
- const scriptOptions = storage
609
- ? `,${JSON.stringify({ storageKey: storage })}`
610
- : ''
611
- const rootOptions =
612
- storage || defaultTheme
613
- ? `,${JSON.stringify({ ...(defaultTheme ? { defaultVars: defaultTheme } : {}), ...(storage ? { storageKey: storage } : {}) })}`
614
- : ''
615
-
616
- return `${root ? `appearance:${appearance}.root(${entries}${rootOptions}),` : ''}${script ? `script:${appearance}.create(${entries}${scriptOptions}),` : ''}`
617
- }
618
-
619
- if (call.variableConfig) {
620
- const selected =
621
- extracted.themeSelections?.includes(call.name) ||
622
- Object.values(extracted.themeExports ?? {}).some(
623
- (link) =>
624
- link.call.name === call.name &&
625
- link.kind === 'config' &&
626
- !link.call.initialization &&
627
- !link.call.root,
628
- )
629
- const entries = call.options?.themes
630
- ? Object.entries(call.members)
631
- .filter(([key]) => {
632
- const path = JSON.parse(key) as string[]
633
- return path[0] === 'themes' && path.length === 2
634
- })
635
- .map(([key, name]) => [
636
- (JSON.parse(key) as string[])[1],
637
- emitted.vars[name],
638
- ])
639
- : [['default', emitted.vars[call.name]]]
640
- const fallback = call.options?.defaultTheme ?? 'default'
641
- if (!selected)
642
- return `{${helpers(JSON.stringify(call.options?.themes ? entries : []), call.options?.themes ? String(fallback) : undefined).replace(/,$/, '')}}`
643
- usesSelection = true
644
- const selector = `${selection}.create(${JSON.stringify(entries)},${call.options?.output === 'html'},'set',${JSON.stringify(fallback)})`
645
- // Rollup drops required selectors when a pure call initializes a destructured object property.
646
- return `{${helpers(JSON.stringify(call.options?.themes ? entries : []), call.options?.themes ? String(fallback) : undefined)}vars:${selector}}`
647
- }
648
-
649
- if (call.options?.themes) {
650
- const catalog = Object.fromEntries(
651
- Object.entries(call.members)
652
- .filter(([key]) => (JSON.parse(key) as string[]).length === 2)
653
- .map(([key, name]) => [
654
- (JSON.parse(key) as string[])[1]!,
655
- emitted.vars[name],
656
- ]),
657
- )
658
-
659
- const entries = JSON.stringify(Object.entries(catalog))
660
- const defaultTheme =
661
- typeof call.options.defaultTheme === 'string'
662
- ? call.options.defaultTheme
663
- : undefined
664
- if (unusedSelections.has(call.start))
665
- return `{${helpers(entries, defaultTheme)}theme:${JSON.stringify(scope(call.members['["theme"]']!))}}`
666
-
667
- usesSelection = true
668
-
669
- return `{${helpers(entries, defaultTheme)}theme:${JSON.stringify(scope(call.members['["theme"]']!))},themes:/*#__PURE__*/${selection}.create(${entries},${call.options.output === 'html'})}`
670
- }
671
-
672
- if (Object.hasOwn(call.members, '["theme"]'))
673
- return `{${helpers('[]')}theme:${JSON.stringify(scope(call.members['["theme"]']!))}}`
674
-
675
- return script || root ? `{${helpers('[]').slice(0, -1)}}` : '{}'
676
- })()
677
-
678
- const assertion = /\.[cm]?tsx?$/.test(options.moduleId)
679
- ? ` as ${call.type ?? `import('zyzz').Vars.Definition<${call.tokenType}>`}`
680
- : ''
681
-
682
- module.overwrite(call.start, call.end, `(${props}${assertion})`)
683
- }
684
-
685
- for (const alias of extracted.themeAliases) {
686
- if (alias.retained) {
687
- if (/\.[cm]?tsx?$/.test(options.moduleId))
688
- module.overwrite(
689
- alias.start,
690
- alias.end,
691
- `(${options.source.slice(alias.start, alias.end)} as ${alias.type ?? `import('zyzz').Vars.Definition<${alias.tokenType}>`})`,
692
- )
693
-
694
- continue
695
- }
696
-
697
- const member = alias.recipe ? 'variants' : 'style'
698
- const members = [...new Set(alias.bindings ?? [member])]
699
- const value = alias.destructured
700
- ? `{${members.map((member) => `${member}:undefined`).join(',')}}`
701
- : 'undefined'
702
- const type =
703
- alias.type ?? `import('zyzz').Vars.Definition<${alias.tokenType}>`
704
- const assertion = /\.[cm]?tsx?$/.test(options.moduleId)
705
- ? ` as unknown as ${alias.destructured ? `{${members.map((member) => `readonly ${member}:${type}['${member}']`).join(';')}}` : `${type}['${member}']`}`
706
- : ''
707
-
708
- module.overwrite(alias.start, alias.end, `(${value}${assertion})`)
709
- }
710
-
711
- const replacements = [
712
- ...extracted.calls.map((call) => ({
713
- end: applications.get(call.start)!.end,
714
- start: call.start,
715
- })),
716
- ...(extracted.contributionCalls ?? []),
717
- ...(extracted.variableCalls ?? []),
718
- ...extracted.themeAliases,
719
- ...extracted.themeCalls,
720
- ].sort((a, b) => a.start - b.start)
721
-
722
- function replaced(reference: Span) {
723
- let low = 0
724
- let high = replacements.length
725
-
726
- while (low < high) {
727
- const middle = (low + high) >>> 1
728
-
729
- if (replacements[middle]!.start <= reference.start) low = middle + 1
730
- else high = middle
731
- }
732
-
733
- const call = replacements[low - 1]
734
-
735
- return call !== undefined && reference.end <= call.end
736
- }
737
-
738
- for (const reference of extracted.staticThemeReferences ?? [])
739
- if (!replaced(reference))
740
- module.overwrite(
741
- reference.start,
742
- reference.end,
743
- JSON.stringify(reference.value),
744
- )
745
-
746
- for (const reference of extracted.themeReferences)
747
- if (!replaced(reference))
748
- module.overwrite(
749
- reference.start,
750
- reference.end,
751
- JSON.stringify(emitted.vars[reference.name]),
752
- )
753
-
754
- replacements.push(
755
- ...extracted.themeReferences,
756
- ...(extracted.staticThemeReferences ?? []),
757
- )
758
- replacements.sort((a, b) => a.start - b.start)
759
-
760
- for (const node of program.body) {
761
- if (
762
- node.type !== 'ImportDeclaration' ||
763
- !['zyzz', 'zyzz/web'].includes(node.source.value)
764
- )
765
- continue
766
-
767
- const removed = new Set<Ast.ImportDeclaration['specifiers'][number]>()
768
-
769
- for (const specifier of node.specifiers) {
770
- if (
771
- node.importKind === 'type' ||
772
- specifier.type !== 'ImportSpecifier' ||
773
- specifier.importKind === 'type' ||
774
- !(
775
- node.source.value === 'zyzz'
776
- ? [
777
- 'Config',
778
- 'cx',
779
- 'defineConfig',
780
- 'defineVars',
781
- 'extendVars',
782
- 'style',
783
- 'Vars',
784
- 'variable',
785
- 'variants',
786
- ]
787
- : [
788
- 'Css',
789
- 'cssFunction',
790
- 'customMedia',
791
- 'importCss',
792
- 'namespace',
793
- 'colorProfile',
794
- 'counterStyle',
795
- 'fontPaletteValues',
796
- 'fontFeatureValues',
797
- 'page',
798
- 'property',
799
- 'viewTransition',
800
- 'global',
801
- 'fontFace',
802
- 'keyframes',
803
- 'layers',
804
- 'positionTry',
805
- ]
806
- ).includes(
807
- specifier.imported.type === 'Identifier'
808
- ? specifier.imported.name
809
- : specifier.imported.value,
810
- )
811
- )
812
- continue
813
-
814
- // Conservative retention also protects type queries and shadowed references.
815
- const remaining = identifiers
816
- .get(specifier.local.name)
817
- ?.some(
818
- (reference) =>
819
- !(reference.start >= node.start && reference.end <= node.end) &&
820
- !replaced(reference),
821
- )
822
-
823
- if (!remaining) removed.add(specifier)
824
- }
825
-
826
- if (!removed.size) continue
827
-
828
- const retained = node.specifiers.filter(
829
- (specifier) => !removed.has(specifier),
830
- )
831
-
832
- if (!retained.length) module.remove(node.start, node.end)
833
- else if (
834
- retained.every((specifier) => specifier.type !== 'ImportSpecifier')
835
- ) {
836
- module.overwrite(
837
- node.start,
838
- node.source.start,
839
- `import ${retained.map((specifier) => options.source.slice(specifier.start, specifier.end)).join(', ')} from `,
840
- )
841
- } else {
842
- // Preserve the import source, attributes, and untouched specifier spelling.
843
- for (let index = 0; index < node.specifiers.length; index++) {
844
- const specifier = node.specifiers[index]!
845
- if (!removed.has(specifier)) continue
846
-
847
- const next = node.specifiers[index + 1]
848
- const previous = node.specifiers[index - 1]
849
-
850
- if (next) module.remove(specifier.start, next.start)
851
- else if (previous) module.remove(previous.end, specifier.end)
852
- }
853
- }
854
- }
855
-
856
- if (
857
- callable ||
858
- usesRecipe ||
859
- usesComposition ||
860
- usesCompositionHtml ||
861
- usesConditionalRecipe ||
862
- usesPayloadRecipe ||
863
- usesHtml ||
864
- usesSelection ||
865
- usesAppearance ||
866
- extracted.variableCalls?.length
867
- ) {
868
- // Insertion after a hashbang keeps executable module syntax intact.
869
- let offset = options.source.startsWith('#!')
870
- ? options.source.indexOf('\n') + 1
871
- : 0
872
-
873
- for (const node of program.body) {
874
- if (node.type !== 'ExpressionStatement' || !node.directive) break
875
-
876
- offset = node.end
877
- }
878
-
879
- if (compositions.length)
880
- module.appendLeft(offset, '\n' + compositions.join('\n') + '\n')
881
-
882
- module.appendLeft(
883
- offset,
884
- `\nimport { ${[usesAppearance ? `Appearance as ${appearance}` : '', usesComposition ? `Composition as ${composition}` : '', usesCompositionHtml ? `CompositionHtml as ${compositionHtml}` : '', usesConditionalRecipe ? `ConditionalRecipe as ${conditionalRecipe}` : '', usesHtml ? `Html as ${html}` : '', usesPayloadRecipe ? `PayloadRecipe as ${payloadRecipe}` : '', callable ? `Props as ${runtime}` : '', usesRecipe ? `Recipe as ${recipe}` : '', usesSelection ? `Selection as ${selection}` : '', extracted.variableCalls?.length ? `Variable as ${variables}` : ''].filter(Boolean).join(', ')} } from 'zyzz/runtime';\n`,
885
- )
886
- }
887
-
888
- const cssMap = new Mapping.GenMapping({ file: `${options.moduleId}.css` })
889
-
890
- Mapping.setSourceContent(cssMap, options.moduleId, options.source)
891
-
892
- const lines = [0]
893
-
894
- for (let index = 0; index < options.source.length; index++)
895
- if (options.source[index] === '\n') lines.push(index + 1)
896
-
897
- function position(offset: number) {
898
- let low = 0
899
- let high = lines.length
900
-
901
- while (low + 1 < high) {
902
- const middle = (low + high) >>> 1
903
-
904
- if (lines[middle]! <= offset) low = middle
905
- else high = middle
906
- }
907
-
908
- return { column: offset - lines[low]!, line: low + 1 }
909
- }
910
-
911
- const owners = new Map<string, Source.Call>()
912
-
913
- for (const call of extracted.calls)
914
- for (const name of emitted.classes[call.name]!.split(' '))
915
- if (!owners.has(name)) owners.set(name, call)
916
-
917
- const styles = new Map(
918
- extracted.styles.styles.map((style) => [style.name, style]),
919
- )
920
-
921
- const themeOwners = new Map(
922
- extracted.themeCalls.flatMap((call) =>
923
- [...new Set([call.name, ...Object.values(call.members ?? {})])].map(
924
- (name) => [emitted.vars[name], { ...call, name }] as const,
925
- ),
926
- ),
927
- )
928
-
929
- const linkedOwners = new Map(
930
- Object.entries(options[Themes.context]?.owners ?? {}).map(
931
- ([key, owner]) => [emitted.vars[key], owner],
932
- ),
933
- )
934
-
935
- // Literal and scalar-theme rules each occupy one line at this boundary.
936
- const prefix = emitted.contributionCss ?? ''
937
- const contributions = (extracted.contributions ?? []).map(
938
- (definition, index) => ({
939
- definition,
940
- start: extracted.contributionStarts?.[index],
941
- }),
942
- )
943
- const rank = (kind: string) =>
944
- kind === 'import' ? 0 : kind === 'namespace' ? 1 : 2
945
- const layered = contributions.find(
946
- (value) =>
947
- value.definition.kind === 'layers' && value.definition.names.length > 0,
948
- )
949
- let contributionLine = 1
950
- if (layered) {
951
- if (layered.start !== undefined)
952
- Mapping.addMapping(cssMap, {
953
- generated: { line: contributionLine, column: 0 },
954
- original: position(layered.start),
955
- source: options.moduleId,
956
- })
957
- contributionLine++
958
- }
959
- for (const contribution of contributions.toSorted(
960
- (a, b) => rank(a.definition.kind) - rank(b.definition.kind),
961
- )) {
962
- if (contribution.definition.kind === 'layers') continue
963
- const rendered =
964
- Css.compile({
965
- styles: { styles: [] },
966
- contributions: [contribution.definition],
967
- vars: Object.keys(extracted.vars).length ? extracted.vars : undefined,
968
- }).contributionCss ?? ''
969
- if (!rendered) continue
970
- for (const _ of rendered.split('\n')) {
971
- if (contribution.start !== undefined)
972
- Mapping.addMapping(cssMap, {
973
- generated: { line: contributionLine, column: 0 },
974
- original: position(contribution.start),
975
- source: options.moduleId,
976
- })
977
- contributionLine++
978
- }
28
+ development: options.development,
29
+ moduleId: options.moduleId,
30
+ schemes: options.schemes,
31
+ shared: options[ThemeRules.shared],
32
+ target: options.target,
979
33
  }
980
- const declarationOwners = new Map<string, Set<number>>()
981
- const scoped = emitted.scopedCss ?? emitted.css
982
-
983
- const css = [
984
- prefix,
985
- (scoped ? scoped.split('\n') : [])
986
- .map((rule, index) => {
987
- const line = index + 1 + (prefix ? prefix.split('\n').length : 0)
988
- const openers = new Map<number, number>()
989
- const conditionStarts = declarationStarts(rule, true, openers)
990
- const selectorStart =
991
- conditionStarts.find((start) => rule[start] === '.') ?? 0
992
- const brace = openers.get(selectorStart) ?? rule.indexOf('{')
993
- const name = rule
994
- .slice(selectorStart + 1, brace)
995
- .replace(/\\([0-9a-f]+) ?/gi, (_, code: string) =>
996
- String.fromCodePoint(Number.parseInt(code, 16)),
997
- )
998
- const linkedOwner = linkedOwners.get(name)
999
-
1000
- if (linkedOwner) {
1001
- const lines = linkedOwner.source
1002
- .slice(0, linkedOwner.call.start)
1003
- .split('\n')
1004
-
1005
- Mapping.setSourceContent(
1006
- cssMap,
1007
- linkedOwner.moduleId,
1008
- linkedOwner.source,
1009
- )
1010
- Mapping.addMapping(cssMap, {
1011
- generated: { column: 0, line },
1012
- name: linkedOwner.call.name,
1013
- original: { line: lines.length, column: lines.at(-1)!.length },
1014
- source: linkedOwner.moduleId,
1015
- })
1016
-
1017
- return rule
1018
- }
1019
-
1020
- const themeOwner = themeOwners.get(name)
1021
-
1022
- if (themeOwner) {
1023
- Mapping.addMapping(cssMap, {
1024
- generated: { column: 0, line },
1025
- name: themeOwner.name,
1026
- original: position(themeOwner.start),
1027
- source: options.moduleId,
1028
- })
1029
-
1030
- return rule
1031
- }
1032
-
1033
- if (Object.values(emitted.vars).includes(name)) {
1034
- // Packed theme declarations have no authored source in this graph.
1035
- Mapping.addMapping(cssMap, { generated: { column: 0, line } })
1036
-
1037
- return rule
1038
- }
1039
-
1040
- if (Object.values(Scheme.classes).includes(name)) {
1041
- // Scheme selection rules accompany the scopes and have no authored source.
1042
- Mapping.addMapping(cssMap, { generated: { column: 0, line } })
1043
34
 
1044
- return rule
1045
- }
35
+ // Untyped callers can pass other values, which the engine reads from JSON as before.
36
+ if (typeof options.source !== 'string')
37
+ return Results.transform({ ...input, source: options.source })
1046
38
 
1047
- if (
1048
- rule.startsWith(':root{') ||
1049
- rule.startsWith(':where(*){--z-') ||
1050
- (rule.startsWith('@media ') &&
1051
- (rule.includes(':root{') ||
1052
- rule.includes(':where(*){--z-') ||
1053
- Object.values(emitted.vars).some((name) =>
1054
- rule.includes(`.${name}{`),
1055
- )))
1056
- ) {
1057
- Mapping.addMapping(cssMap, { generated: { column: 0, line } })
1058
- return rule
1059
- }
1060
-
1061
- const selector = `.${ClassName.selector(name)}`
1062
- const call = owners.get(name)!
1063
-
1064
- Mapping.addMapping(cssMap, {
1065
- generated: { column: selectorStart, line },
1066
- name: call.name,
1067
- original: position(call.start),
1068
- source: options.moduleId,
1069
- })
1070
-
1071
- const body = rule.slice(brace)
1072
- const style = styles.get(call.name)!
1073
-
1074
- function declarations(
1075
- style: Style.NamedStyle,
1076
- ): readonly Style.Declaration[] {
1077
- return style.rules
1078
- ? style.rules.flatMap((rule) => declarations(rule.style))
1079
- : style.declarations
1080
- }
1081
-
1082
- const conditionNodes: Extract<Ast.Node, { type: 'Property' }>[] = []
1083
-
1084
- function locations(node: Ast.ObjectExpression): readonly Ast.Node[] {
1085
- return node.properties.flatMap((property) => {
1086
- if (property.type !== 'Property') return []
1087
-
1088
- const value = Expression.unwrap(property.value)
1089
-
1090
- if (value.type === 'ObjectExpression') {
1091
- const key =
1092
- property.key.type === 'Identifier'
1093
- ? property.key.name
1094
- : property.key.type === 'Literal'
1095
- ? property.key.value
1096
- : undefined
1097
- if (key !== 'selectors') conditionNodes.push(property)
1098
-
1099
- return locations(value)
1100
- }
1101
-
1102
- const key =
1103
- property.key.type === 'Identifier'
1104
- ? property.key.name
1105
- : property.key.type === 'Literal'
1106
- ? String(property.key.value)
1107
- : ''
1108
-
1109
- if (key === 'typography' && call.typography?.has(property.start)) {
1110
- conditionNodes.push(
1111
- ...Array.from(
1112
- { length: call.typographyQueries?.get(property.start) ?? 0 },
1113
- () => property,
1114
- ),
1115
- )
1116
- return Array.from(
1117
- { length: call.typography.get(property.start)! },
1118
- () => property,
1119
- )
1120
- }
1121
-
1122
- const authoredLocations: readonly Ast.Node[] =
1123
- value.type === 'ArrayExpression'
1124
- ? value.elements.filter(
1125
- (node): node is NonNullable<typeof node> => node !== null,
1126
- )
1127
- : [property]
1128
-
1129
- return (call.shorthands?.[key] ?? [key]).flatMap(
1130
- () => authoredLocations,
1131
- )
1132
- })
1133
- }
1134
-
1135
- const ordered = declarations(style)
1136
- const authored = locations(call.body ?? definitions.get(call.start)!)
1137
- const conditions: string[] = []
1138
-
1139
- function collectConditions(style: Style.NamedStyle) {
1140
- for (const rule of style.rules ?? []) {
1141
- if (rule.condition !== undefined) conditions.push(rule.condition)
1142
-
1143
- collectConditions(rule.style)
1144
- }
1145
- }
1146
-
1147
- collectConditions(style)
1148
- const mappedConditions = new Set<number>()
1149
-
1150
- for (const start of conditionStarts) {
1151
- const condition = rule.slice(start, openers.get(start))
1152
- const index = conditions.findIndex(
1153
- (value, index) =>
1154
- value === condition && !mappedConditions.has(index),
1155
- )
1156
- const node = conditionNodes[index]
1157
- if (!node) continue
1158
-
1159
- mappedConditions.add(index)
1160
- Mapping.addMapping(cssMap, {
1161
- generated: {
1162
- column:
1163
- start +
1164
- (start > brace ? selector.length - (brace - selectorStart) : 0),
1165
- line,
1166
- },
1167
- name: options.source.slice(node.key.start, node.key.end),
1168
- original: position(node.key.start),
1169
- source: options.moduleId,
1170
- })
1171
- }
1172
-
1173
- const starts = declarationStarts(body)
1174
- const used = declarationOwners.get(call.name) ?? new Set<number>()
1175
- declarationOwners.set(call.name, used)
1176
- let cursor = 1
1177
-
1178
- for (
1179
- let propertyIndex = 0;
1180
- propertyIndex < ordered.length;
1181
- propertyIndex++
1182
- ) {
1183
- if (used.has(propertyIndex)) continue
1184
- const declaration = ordered[propertyIndex]!
1185
- const text = `${declaration.property.replace(/[A-Z]/g, (letter) => `-${letter.toLowerCase()}`)}:`
1186
- const start =
1187
- starts.find(
1188
- (start) => start >= cursor && body.startsWith(text, start),
1189
- ) ?? -1
1190
- if (start < 0) continue
1191
-
1192
- // Composed packed entries can expand differently from the composite's shorthands.
1193
- const location = authored[propertyIndex]
1194
- if (!location) continue
1195
-
1196
- used.add(propertyIndex)
1197
-
1198
- Mapping.addMapping(cssMap, {
1199
- generated: {
1200
- column: selectorStart + selector.length + start,
1201
- line,
1202
- },
1203
- name: declaration.property,
1204
- original: position(location.start),
1205
- source: options.moduleId,
1206
- })
1207
- cursor = start + text.length
1208
- }
1209
-
1210
- return rule.slice(0, selectorStart) + selector + body
1211
- })
1212
- .join('\n'),
1213
- ]
1214
- .filter(Boolean)
1215
- .join('\n')
1216
-
1217
- const map = (portable ? new MagicString(options.source) : module).generateMap(
1218
- {
1219
- hires: true,
1220
- includeContent: true,
1221
- source: options.moduleId,
1222
- },
1223
- )
1224
-
1225
- const namespaced = Namespaces.rewrite(
1226
- css,
1227
- extracted.namespaces ?? [],
1228
- Mapping.toEncodedMap(cssMap),
1229
- true,
1230
- )
1231
- const result = {
1232
- ...(emitted[ThemeRules.shared]
1233
- ? { [ThemeRules.shared]: emitted[ThemeRules.shared] }
1234
- : {}),
1235
- [ClassName.rules]: emitted[ClassName.rules],
1236
- [ClassName.units]: emitted[ClassName.units],
1237
- classes,
1238
- code: portable ? options.source : module.toString(),
1239
- css: namespaced.css,
1240
- cssMap: namespaced.map ?? Mapping.toEncodedMap(cssMap),
1241
- map: {
1242
- file: options.moduleId,
1243
- mappings: map.mappings,
1244
- names: map.names,
1245
- sources: map.sources,
1246
- sourcesContent: map.sourcesContent!,
1247
- version: 3 as const,
1248
- },
1249
- vars: emitted.vars,
1250
- }
1251
- Object.defineProperty(result, ClassName.rules, { enumerable: false })
1252
- Object.defineProperty(result, ClassName.units, { enumerable: false })
1253
- return Object.freeze(result)
39
+ return Results.transform(input, options.source)
1254
40
  }
1255
41
 
1256
42
  /** Source transform contracts. */
@@ -1302,88 +88,3 @@ export declare namespace compile {
1302
88
  readonly vars: Readonly<Record<string, string>>
1303
89
  }
1304
90
  }
1305
-
1306
- /** Locates emitted declarations while skipping selectors, conditions, and quoted CSS data. */
1307
- function declarationStarts(
1308
- body: string,
1309
- conditions = false,
1310
- openers?: Map<number, number>,
1311
- ): readonly number[] {
1312
- const starts: number[] = []
1313
- let start = 0
1314
- let depth = 0
1315
- let blocks = 0
1316
- let custom = false
1317
- let quote = ''
1318
-
1319
- for (let index = 0; index < body.length; index++) {
1320
- const char = body[index]!
1321
-
1322
- if (char === '\\') {
1323
- index++
1324
- continue
1325
- }
1326
-
1327
- if (quote) {
1328
- if (char === quote) quote = ''
1329
-
1330
- continue
1331
- }
1332
-
1333
- if (char === '"' || char === "'") {
1334
- quote = char
1335
- continue
1336
- }
1337
-
1338
- if (char === '/' && body[index + 1] === '*') {
1339
- const end = body.indexOf('*/', index + 2)
1340
-
1341
- if (end < 0) break
1342
-
1343
- index = end + 1
1344
- continue
1345
- }
1346
-
1347
- if (char === '(' || char === '[') {
1348
- depth++
1349
- continue
1350
- }
1351
-
1352
- if (char === ')' || char === ']') {
1353
- depth--
1354
- continue
1355
- }
1356
-
1357
- if (depth) continue
1358
-
1359
- if (char === ':' && body.slice(start, index).trimStart().startsWith('--'))
1360
- custom = true
1361
-
1362
- if (char === '{') {
1363
- if (custom) blocks++
1364
- else {
1365
- if (conditions && index > start) {
1366
- starts.push(start)
1367
- openers?.set(start, index)
1368
- }
1369
-
1370
- start = index + 1
1371
- }
1372
- } else if (char === '}') {
1373
- if (blocks) blocks--
1374
- else {
1375
- start = index + 1
1376
- custom = false
1377
- }
1378
- } else if (char === ';' && !blocks) {
1379
- while (/\s/.test(body[start] ?? '') && start < index) start++
1380
-
1381
- if (!conditions) starts.push(start)
1382
-
1383
- start = index + 1
1384
- custom = false
1385
- }
1386
- }
1387
-
1388
- return starts
1389
- }