zyzz 0.0.27 → 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 (320) 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 -1113
  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 -958
  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/Authoring.d.ts.map +1 -1
  51. package/dist/internal/Authoring.js +37 -7
  52. package/dist/internal/Authoring.js.map +1 -1
  53. package/dist/internal/Configuration.d.ts +6 -1
  54. package/dist/internal/Configuration.d.ts.map +1 -1
  55. package/dist/internal/Configuration.js.map +1 -1
  56. package/dist/internal/Literal.d.ts +5 -2
  57. package/dist/internal/Literal.d.ts.map +1 -1
  58. package/dist/internal/Literal.js +7 -2
  59. package/dist/internal/Literal.js.map +1 -1
  60. package/dist/internal/Theme.d.ts +4 -0
  61. package/dist/internal/Theme.d.ts.map +1 -1
  62. package/dist/internal/Theme.js.map +1 -1
  63. package/dist/internal/Token.d.ts +2 -1
  64. package/dist/internal/Token.d.ts.map +1 -1
  65. package/dist/internal/Token.js +2 -2
  66. package/dist/internal/Token.js.map +1 -1
  67. package/dist/internal/Vlq.d.ts +14 -0
  68. package/dist/internal/Vlq.d.ts.map +1 -0
  69. package/dist/internal/Vlq.js +47 -0
  70. package/dist/internal/Vlq.js.map +1 -0
  71. package/dist/internal/Wasm.d.ts +22 -0
  72. package/dist/internal/Wasm.d.ts.map +1 -0
  73. package/dist/internal/Wasm.js +83 -0
  74. package/dist/internal/Wasm.js.map +1 -0
  75. package/dist/metro/Graph.d.ts +0 -1
  76. package/dist/metro/Graph.d.ts.map +1 -1
  77. package/dist/metro/transformer.d.ts.map +1 -1
  78. package/dist/metro/transformer.js +0 -1
  79. package/dist/metro/transformer.js.map +1 -1
  80. package/dist/next/internal/Project.d.ts.map +1 -1
  81. package/dist/next/internal/Project.js +2 -5
  82. package/dist/next/internal/Project.js.map +1 -1
  83. package/dist/node/Host.d.ts.map +1 -1
  84. package/dist/node/Host.js +0 -2
  85. package/dist/node/Host.js.map +1 -1
  86. package/dist/node/internal/Contracts.d.ts.map +1 -1
  87. package/dist/node/internal/Contracts.js +3 -7
  88. package/dist/node/internal/Contracts.js.map +1 -1
  89. package/dist/node/internal/Snapshot.d.ts +0 -1
  90. package/dist/node/internal/Snapshot.d.ts.map +1 -1
  91. package/dist/node/internal/Snapshot.js +0 -6
  92. package/dist/node/internal/Snapshot.js.map +1 -1
  93. package/dist/runtime/Composition.d.ts +2 -3
  94. package/dist/runtime/Composition.d.ts.map +1 -1
  95. package/dist/runtime/Composition.js +51 -30
  96. package/dist/runtime/Composition.js.map +1 -1
  97. package/dist/runtime/Recipe.d.ts.map +1 -1
  98. package/dist/runtime/Recipe.js +16 -12
  99. package/dist/runtime/Recipe.js.map +1 -1
  100. package/dist/styleFunction.d.ts +11 -2
  101. package/dist/styleFunction.d.ts.map +1 -1
  102. package/dist/styleFunction.js +3 -1
  103. package/dist/styleFunction.js.map +1 -1
  104. package/dist/unplugin/index.d.ts.map +1 -1
  105. package/dist/unplugin/index.js +3 -6
  106. package/dist/unplugin/index.js.map +1 -1
  107. package/dist/vite/index.d.ts +7 -0
  108. package/dist/vite/index.d.ts.map +1 -1
  109. package/dist/vite/index.js +862 -216
  110. package/dist/vite/index.js.map +1 -1
  111. package/dist/web/Css.d.ts +8 -3
  112. package/dist/web/Css.d.ts.map +1 -1
  113. package/dist/web/Css.js +5 -721
  114. package/dist/web/Css.js.map +1 -1
  115. package/dist/web/internal/Block.d.ts +0 -2
  116. package/dist/web/internal/Block.d.ts.map +1 -1
  117. package/dist/web/internal/Block.js +1 -12
  118. package/dist/web/internal/Block.js.map +1 -1
  119. package/dist/web/internal/ClassName.d.ts +23 -18
  120. package/dist/web/internal/ClassName.d.ts.map +1 -1
  121. package/dist/web/internal/ClassName.js +26 -55
  122. package/dist/web/internal/ClassName.js.map +1 -1
  123. package/dist/web/internal/Contributions.d.ts +3 -5
  124. package/dist/web/internal/Contributions.d.ts.map +1 -1
  125. package/dist/web/internal/Contributions.js +0 -45
  126. package/dist/web/internal/Contributions.js.map +1 -1
  127. package/dist/web/internal/Engine.browser.d.ts +8 -0
  128. package/dist/web/internal/Engine.browser.d.ts.map +1 -0
  129. package/dist/web/internal/Engine.browser.js +42 -0
  130. package/dist/web/internal/Engine.browser.js.map +1 -0
  131. package/dist/web/internal/Engine.d.ts +9 -0
  132. package/dist/web/internal/Engine.d.ts.map +1 -0
  133. package/dist/web/internal/Engine.js +14 -0
  134. package/dist/web/internal/Engine.js.map +1 -0
  135. package/dist/web/internal/Themes.d.ts +1 -9
  136. package/dist/web/internal/Themes.d.ts.map +1 -1
  137. package/dist/web/internal/Themes.js +3 -221
  138. package/dist/web/internal/Themes.js.map +1 -1
  139. package/dist/web/internal/Wasm.generated.d.ts +4 -0
  140. package/dist/web/internal/Wasm.generated.d.ts.map +1 -0
  141. package/dist/web/internal/Wasm.generated.js +4 -0
  142. package/dist/web/internal/Wasm.generated.js.map +1 -0
  143. package/dist/web/internal/Wire.d.ts +19 -0
  144. package/dist/web/internal/Wire.d.ts.map +1 -0
  145. package/dist/web/internal/Wire.js +387 -0
  146. package/dist/web/internal/Wire.js.map +1 -0
  147. package/package.json +20 -1
  148. package/src/babel/index.ts +2 -5
  149. package/src/babel/internal/Compilation.ts +0 -1
  150. package/src/compiler/Graph.ts +89 -1930
  151. package/src/compiler/Native.ts +18 -871
  152. package/src/compiler/Source.ts +144 -1579
  153. package/src/compiler/Transform.ts +16 -1312
  154. package/src/compiler/internal/AtRules.ts +27 -115
  155. package/src/compiler/internal/Context.ts +11 -0
  156. package/src/compiler/internal/Results.ts +406 -0
  157. package/src/compiler/internal/Syntax.ts +0 -3
  158. package/src/compiler/internal/Wire.ts +1045 -0
  159. package/src/internal/Addon.ts +118 -0
  160. package/src/internal/Authoring.ts +53 -18
  161. package/src/internal/Configuration.ts +38 -1
  162. package/src/internal/Literal.ts +7 -2
  163. package/src/internal/Theme.ts +15 -0
  164. package/src/internal/Token.ts +2 -2
  165. package/src/internal/Vlq.ts +59 -0
  166. package/src/internal/Wasm.ts +111 -0
  167. package/src/metro/transformer.ts +0 -1
  168. package/src/next/internal/Project.ts +2 -9
  169. package/src/node/Host.ts +0 -2
  170. package/src/node/internal/Contracts.ts +3 -7
  171. package/src/node/internal/Snapshot.ts +0 -8
  172. package/src/runtime/Composition.ts +48 -25
  173. package/src/runtime/Recipe.ts +21 -14
  174. package/src/styleFunction.ts +31 -2
  175. package/src/unplugin/index.ts +6 -6
  176. package/src/vite/index.ts +1157 -241
  177. package/src/web/Css.ts +12 -908
  178. package/src/web/internal/Block.ts +0 -14
  179. package/src/web/internal/ClassName.ts +52 -85
  180. package/src/web/internal/Contributions.ts +3 -59
  181. package/src/web/internal/Engine.browser.ts +51 -0
  182. package/src/web/internal/Engine.ts +17 -0
  183. package/src/web/internal/Themes.ts +3 -279
  184. package/src/web/internal/Wasm.generated.ts +3 -0
  185. package/src/web/internal/Wire.ts +466 -0
  186. package/src/web/internal/wasm.d.ts +9 -0
  187. package/dist/compiler/internal/Applications.d.ts +0 -55
  188. package/dist/compiler/internal/Applications.d.ts.map +0 -1
  189. package/dist/compiler/internal/Applications.js +0 -352
  190. package/dist/compiler/internal/Applications.js.map +0 -1
  191. package/dist/compiler/internal/ColorProfiles.d.ts +0 -3
  192. package/dist/compiler/internal/ColorProfiles.d.ts.map +0 -1
  193. package/dist/compiler/internal/ColorProfiles.js +0 -84
  194. package/dist/compiler/internal/ColorProfiles.js.map +0 -1
  195. package/dist/compiler/internal/CompositionBindings.d.ts +0 -16
  196. package/dist/compiler/internal/CompositionBindings.d.ts.map +0 -1
  197. package/dist/compiler/internal/CompositionBindings.js +0 -89
  198. package/dist/compiler/internal/CompositionBindings.js.map +0 -1
  199. package/dist/compiler/internal/Compositions.d.ts +0 -37
  200. package/dist/compiler/internal/Compositions.d.ts.map +0 -1
  201. package/dist/compiler/internal/Compositions.js +0 -494
  202. package/dist/compiler/internal/Compositions.js.map +0 -1
  203. package/dist/compiler/internal/Configurations.d.ts +0 -26
  204. package/dist/compiler/internal/Configurations.d.ts.map +0 -1
  205. package/dist/compiler/internal/Configurations.js +0 -259
  206. package/dist/compiler/internal/Configurations.js.map +0 -1
  207. package/dist/compiler/internal/Contract.d.ts +0 -30
  208. package/dist/compiler/internal/Contract.d.ts.map +0 -1
  209. package/dist/compiler/internal/Contract.js +0 -753
  210. package/dist/compiler/internal/Contract.js.map +0 -1
  211. package/dist/compiler/internal/Contributions.d.ts +0 -54
  212. package/dist/compiler/internal/Contributions.d.ts.map +0 -1
  213. package/dist/compiler/internal/Contributions.js +0 -1151
  214. package/dist/compiler/internal/Contributions.js.map +0 -1
  215. package/dist/compiler/internal/Descriptors.d.ts +0 -15
  216. package/dist/compiler/internal/Descriptors.d.ts.map +0 -1
  217. package/dist/compiler/internal/Descriptors.js +0 -192
  218. package/dist/compiler/internal/Descriptors.js.map +0 -1
  219. package/dist/compiler/internal/Dynamic.d.ts +0 -14
  220. package/dist/compiler/internal/Dynamic.d.ts.map +0 -1
  221. package/dist/compiler/internal/Dynamic.js +0 -175
  222. package/dist/compiler/internal/Dynamic.js.map +0 -1
  223. package/dist/compiler/internal/Expression.d.ts +0 -19
  224. package/dist/compiler/internal/Expression.d.ts.map +0 -1
  225. package/dist/compiler/internal/Expression.js +0 -164
  226. package/dist/compiler/internal/Expression.js.map +0 -1
  227. package/dist/compiler/internal/Functions.d.ts +0 -5
  228. package/dist/compiler/internal/Functions.d.ts.map +0 -1
  229. package/dist/compiler/internal/Functions.js +0 -191
  230. package/dist/compiler/internal/Functions.js.map +0 -1
  231. package/dist/compiler/internal/Keyframes.d.ts +0 -5
  232. package/dist/compiler/internal/Keyframes.d.ts.map +0 -1
  233. package/dist/compiler/internal/Keyframes.js +0 -51
  234. package/dist/compiler/internal/Keyframes.js.map +0 -1
  235. package/dist/compiler/internal/Names.d.ts +0 -5
  236. package/dist/compiler/internal/Names.d.ts.map +0 -1
  237. package/dist/compiler/internal/Names.js +0 -37
  238. package/dist/compiler/internal/Names.js.map +0 -1
  239. package/dist/compiler/internal/NativeBindings.d.ts +0 -72
  240. package/dist/compiler/internal/NativeBindings.d.ts.map +0 -1
  241. package/dist/compiler/internal/NativeBindings.js +0 -171
  242. package/dist/compiler/internal/NativeBindings.js.map +0 -1
  243. package/dist/compiler/internal/NativeMedia.d.ts +0 -14
  244. package/dist/compiler/internal/NativeMedia.d.ts.map +0 -1
  245. package/dist/compiler/internal/NativeMedia.js +0 -287
  246. package/dist/compiler/internal/NativeMedia.js.map +0 -1
  247. package/dist/compiler/internal/NativeVars.d.ts +0 -28
  248. package/dist/compiler/internal/NativeVars.d.ts.map +0 -1
  249. package/dist/compiler/internal/NativeVars.js +0 -160
  250. package/dist/compiler/internal/NativeVars.js.map +0 -1
  251. package/dist/compiler/internal/PackedStyles.d.ts +0 -37
  252. package/dist/compiler/internal/PackedStyles.d.ts.map +0 -1
  253. package/dist/compiler/internal/PackedStyles.js +0 -344
  254. package/dist/compiler/internal/PackedStyles.js.map +0 -1
  255. package/dist/compiler/internal/Properties.d.ts +0 -5
  256. package/dist/compiler/internal/Properties.d.ts.map +0 -1
  257. package/dist/compiler/internal/Properties.js +0 -82
  258. package/dist/compiler/internal/Properties.js.map +0 -1
  259. package/dist/compiler/internal/RecipeConditions.d.ts +0 -41
  260. package/dist/compiler/internal/RecipeConditions.d.ts.map +0 -1
  261. package/dist/compiler/internal/RecipeConditions.js +0 -82
  262. package/dist/compiler/internal/RecipeConditions.js.map +0 -1
  263. package/dist/compiler/internal/RecipePayloads.d.ts +0 -31
  264. package/dist/compiler/internal/RecipePayloads.d.ts.map +0 -1
  265. package/dist/compiler/internal/RecipePayloads.js +0 -99
  266. package/dist/compiler/internal/RecipePayloads.js.map +0 -1
  267. package/dist/compiler/internal/Recipes.d.ts +0 -32
  268. package/dist/compiler/internal/Recipes.d.ts.map +0 -1
  269. package/dist/compiler/internal/Recipes.js +0 -339
  270. package/dist/compiler/internal/Recipes.js.map +0 -1
  271. package/dist/compiler/internal/Selectors.d.ts +0 -12
  272. package/dist/compiler/internal/Selectors.d.ts.map +0 -1
  273. package/dist/compiler/internal/Selectors.js +0 -268
  274. package/dist/compiler/internal/Selectors.js.map +0 -1
  275. package/dist/compiler/internal/Static.d.ts +0 -39
  276. package/dist/compiler/internal/Static.d.ts.map +0 -1
  277. package/dist/compiler/internal/Static.js +0 -534
  278. package/dist/compiler/internal/Static.js.map +0 -1
  279. package/dist/compiler/internal/Themes.d.ts +0 -190
  280. package/dist/compiler/internal/Themes.d.ts.map +0 -1
  281. package/dist/compiler/internal/Themes.js +0 -1577
  282. package/dist/compiler/internal/Themes.js.map +0 -1
  283. package/dist/compiler/internal/Vars.d.ts +0 -33
  284. package/dist/compiler/internal/Vars.d.ts.map +0 -1
  285. package/dist/compiler/internal/Vars.js +0 -387
  286. package/dist/compiler/internal/Vars.js.map +0 -1
  287. package/dist/compiler/internal/ViewTransitions.d.ts +0 -3
  288. package/dist/compiler/internal/ViewTransitions.d.ts.map +0 -1
  289. package/dist/compiler/internal/ViewTransitions.js +0 -68
  290. package/dist/compiler/internal/ViewTransitions.js.map +0 -1
  291. package/dist/internal/Cascade.d.ts +0 -74
  292. package/dist/internal/Cascade.d.ts.map +0 -1
  293. package/dist/internal/Cascade.js +0 -210
  294. package/dist/internal/Cascade.js.map +0 -1
  295. package/src/compiler/internal/Applications.ts +0 -554
  296. package/src/compiler/internal/ColorProfiles.ts +0 -93
  297. package/src/compiler/internal/CompositionBindings.ts +0 -120
  298. package/src/compiler/internal/Compositions.ts +0 -678
  299. package/src/compiler/internal/Configurations.ts +0 -349
  300. package/src/compiler/internal/Contract.ts +0 -1028
  301. package/src/compiler/internal/Contributions.ts +0 -1561
  302. package/src/compiler/internal/Descriptors.ts +0 -242
  303. package/src/compiler/internal/Dynamic.ts +0 -275
  304. package/src/compiler/internal/Expression.ts +0 -218
  305. package/src/compiler/internal/Functions.ts +0 -206
  306. package/src/compiler/internal/Keyframes.ts +0 -62
  307. package/src/compiler/internal/Names.ts +0 -48
  308. package/src/compiler/internal/NativeBindings.ts +0 -235
  309. package/src/compiler/internal/NativeMedia.ts +0 -342
  310. package/src/compiler/internal/NativeVars.ts +0 -231
  311. package/src/compiler/internal/PackedStyles.ts +0 -473
  312. package/src/compiler/internal/Properties.ts +0 -121
  313. package/src/compiler/internal/RecipeConditions.ts +0 -139
  314. package/src/compiler/internal/RecipePayloads.ts +0 -132
  315. package/src/compiler/internal/Recipes.ts +0 -531
  316. package/src/compiler/internal/Selectors.ts +0 -339
  317. package/src/compiler/internal/Static.ts +0 -784
  318. package/src/compiler/internal/Themes.ts +0 -2398
  319. package/src/compiler/internal/Vars.ts +0 -516
  320. 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,1223 +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
34
 
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 } })
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 })
1043
38
 
1044
- return rule
1045
- }
1046
-
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
- const location = authored[propertyIndex]!
1193
- used.add(propertyIndex)
1194
-
1195
- Mapping.addMapping(cssMap, {
1196
- generated: {
1197
- column: selectorStart + selector.length + start,
1198
- line,
1199
- },
1200
- name: declaration.property,
1201
- original: position(location.start),
1202
- source: options.moduleId,
1203
- })
1204
- cursor = start + text.length
1205
- }
1206
-
1207
- return rule.slice(0, selectorStart) + selector + body
1208
- })
1209
- .join('\n'),
1210
- ]
1211
- .filter(Boolean)
1212
- .join('\n')
1213
-
1214
- const map = (portable ? new MagicString(options.source) : module).generateMap(
1215
- {
1216
- hires: true,
1217
- includeContent: true,
1218
- source: options.moduleId,
1219
- },
1220
- )
1221
-
1222
- const namespaced = Namespaces.rewrite(
1223
- css,
1224
- extracted.namespaces ?? [],
1225
- Mapping.toEncodedMap(cssMap),
1226
- true,
1227
- )
1228
- const result = {
1229
- ...(emitted[ThemeRules.shared]
1230
- ? { [ThemeRules.shared]: emitted[ThemeRules.shared] }
1231
- : {}),
1232
- [ClassName.rules]: emitted[ClassName.rules],
1233
- [ClassName.units]: emitted[ClassName.units],
1234
- classes,
1235
- code: portable ? options.source : module.toString(),
1236
- css: namespaced.css,
1237
- cssMap: namespaced.map ?? Mapping.toEncodedMap(cssMap),
1238
- map: {
1239
- file: options.moduleId,
1240
- mappings: map.mappings,
1241
- names: map.names,
1242
- sources: map.sources,
1243
- sourcesContent: map.sourcesContent!,
1244
- version: 3 as const,
1245
- },
1246
- vars: emitted.vars,
1247
- }
1248
- Object.defineProperty(result, ClassName.rules, { enumerable: false })
1249
- Object.defineProperty(result, ClassName.units, { enumerable: false })
1250
- return Object.freeze(result)
39
+ return Results.transform(input, options.source)
1251
40
  }
1252
41
 
1253
42
  /** Source transform contracts. */
@@ -1299,88 +88,3 @@ export declare namespace compile {
1299
88
  readonly vars: Readonly<Record<string, string>>
1300
89
  }
1301
90
  }
1302
-
1303
- /** Locates emitted declarations while skipping selectors, conditions, and quoted CSS data. */
1304
- function declarationStarts(
1305
- body: string,
1306
- conditions = false,
1307
- openers?: Map<number, number>,
1308
- ): readonly number[] {
1309
- const starts: number[] = []
1310
- let start = 0
1311
- let depth = 0
1312
- let blocks = 0
1313
- let custom = false
1314
- let quote = ''
1315
-
1316
- for (let index = 0; index < body.length; index++) {
1317
- const char = body[index]!
1318
-
1319
- if (char === '\\') {
1320
- index++
1321
- continue
1322
- }
1323
-
1324
- if (quote) {
1325
- if (char === quote) quote = ''
1326
-
1327
- continue
1328
- }
1329
-
1330
- if (char === '"' || char === "'") {
1331
- quote = char
1332
- continue
1333
- }
1334
-
1335
- if (char === '/' && body[index + 1] === '*') {
1336
- const end = body.indexOf('*/', index + 2)
1337
-
1338
- if (end < 0) break
1339
-
1340
- index = end + 1
1341
- continue
1342
- }
1343
-
1344
- if (char === '(' || char === '[') {
1345
- depth++
1346
- continue
1347
- }
1348
-
1349
- if (char === ')' || char === ']') {
1350
- depth--
1351
- continue
1352
- }
1353
-
1354
- if (depth) continue
1355
-
1356
- if (char === ':' && body.slice(start, index).trimStart().startsWith('--'))
1357
- custom = true
1358
-
1359
- if (char === '{') {
1360
- if (custom) blocks++
1361
- else {
1362
- if (conditions && index > start) {
1363
- starts.push(start)
1364
- openers?.set(start, index)
1365
- }
1366
-
1367
- start = index + 1
1368
- }
1369
- } else if (char === '}') {
1370
- if (blocks) blocks--
1371
- else {
1372
- start = index + 1
1373
- custom = false
1374
- }
1375
- } else if (char === ';' && !blocks) {
1376
- while (/\s/.test(body[start] ?? '') && start < index) start++
1377
-
1378
- if (!conditions) starts.push(start)
1379
-
1380
- start = index + 1
1381
- custom = false
1382
- }
1383
- }
1384
-
1385
- return starts
1386
- }