@fluixi/compiler 1.0.0-alpha.100

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 (303) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +131 -0
  3. package/dist/analyze/expr-shape.cjs +62 -0
  4. package/dist/analyze/expr-shape.d.cts +14 -0
  5. package/dist/analyze/expr-shape.d.ts +15 -0
  6. package/dist/analyze/expr-shape.d.ts.map +1 -0
  7. package/dist/analyze/expr-shape.js +37 -0
  8. package/dist/analyze/expr-shape.mjs +41 -0
  9. package/dist/analyze/intrinsics.cjs +112 -0
  10. package/dist/analyze/intrinsics.d.cts +80 -0
  11. package/dist/analyze/intrinsics.d.ts +81 -0
  12. package/dist/analyze/intrinsics.d.ts.map +1 -0
  13. package/dist/analyze/intrinsics.js +126 -0
  14. package/dist/analyze/intrinsics.mjs +91 -0
  15. package/dist/analyze/paren.cjs +134 -0
  16. package/dist/analyze/paren.d.cts +23 -0
  17. package/dist/analyze/paren.d.ts +24 -0
  18. package/dist/analyze/paren.d.ts.map +1 -0
  19. package/dist/analyze/paren.js +168 -0
  20. package/dist/analyze/paren.mjs +113 -0
  21. package/dist/analyze/props-destructure.cjs +226 -0
  22. package/dist/analyze/props-destructure.d.cts +83 -0
  23. package/dist/analyze/props-destructure.d.ts +84 -0
  24. package/dist/analyze/props-destructure.d.ts.map +1 -0
  25. package/dist/analyze/props-destructure.js +272 -0
  26. package/dist/analyze/props-destructure.mjs +205 -0
  27. package/dist/analyze/reactive-bindings.cjs +210 -0
  28. package/dist/analyze/reactive-bindings.d.cts +42 -0
  29. package/dist/analyze/reactive-bindings.d.ts +43 -0
  30. package/dist/analyze/reactive-bindings.d.ts.map +1 -0
  31. package/dist/analyze/reactive-bindings.js +191 -0
  32. package/dist/analyze/reactive-bindings.mjs +187 -0
  33. package/dist/analyze/reactive-expr.cjs +38 -0
  34. package/dist/analyze/reactive-expr.d.cts +38 -0
  35. package/dist/analyze/reactive-expr.d.ts +39 -0
  36. package/dist/analyze/reactive-expr.d.ts.map +1 -0
  37. package/dist/analyze/reactive-expr.js +31 -0
  38. package/dist/analyze/reactive-expr.mjs +17 -0
  39. package/dist/analyze/static-graph.cjs +831 -0
  40. package/dist/analyze/static-graph.d.cts +102 -0
  41. package/dist/analyze/static-graph.d.ts +103 -0
  42. package/dist/analyze/static-graph.d.ts.map +1 -0
  43. package/dist/analyze/static-graph.js +871 -0
  44. package/dist/analyze/static-graph.mjs +813 -0
  45. package/dist/babel-I6BUWUCU.mjs +636 -0
  46. package/dist/chunk-3AICWNF7.mjs +92 -0
  47. package/dist/chunk-6CWJWGE2.mjs +2170 -0
  48. package/dist/chunk-C3XPDB4Y.mjs +16 -0
  49. package/dist/chunk-GX5XV6Z7.mjs +190 -0
  50. package/dist/chunk-HXEXPWJ2.mjs +999 -0
  51. package/dist/chunk-NU3W67UZ.mjs +584 -0
  52. package/dist/chunk-SKAVY75W.mjs +11 -0
  53. package/dist/codegen/backend.cjs +18 -0
  54. package/dist/codegen/backend.d.cts +35 -0
  55. package/dist/codegen/backend.d.ts +36 -0
  56. package/dist/codegen/backend.d.ts.map +1 -0
  57. package/dist/codegen/backend.js +1 -0
  58. package/dist/codegen/backend.mjs +0 -0
  59. package/dist/codegen/backends/imperative.cjs +577 -0
  60. package/dist/codegen/backends/imperative.d.cts +11 -0
  61. package/dist/codegen/backends/imperative.d.ts +12 -0
  62. package/dist/codegen/backends/imperative.d.ts.map +1 -0
  63. package/dist/codegen/backends/imperative.js +362 -0
  64. package/dist/codegen/backends/imperative.mjs +554 -0
  65. package/dist/codegen/contract.cjs +52 -0
  66. package/dist/codegen/contract.d.cts +24 -0
  67. package/dist/codegen/contract.d.ts +25 -0
  68. package/dist/codegen/contract.d.ts.map +1 -0
  69. package/dist/codegen/contract.js +30 -0
  70. package/dist/codegen/contract.mjs +31 -0
  71. package/dist/codegen/partial-template.cjs +176 -0
  72. package/dist/codegen/partial-template.d.cts +61 -0
  73. package/dist/codegen/partial-template.d.ts +62 -0
  74. package/dist/codegen/partial-template.d.ts.map +1 -0
  75. package/dist/codegen/partial-template.js +0 -0
  76. package/dist/codegen/partial-template.mjs +153 -0
  77. package/dist/codegen/serialize-static.cjs +125 -0
  78. package/dist/codegen/serialize-static.d.cts +38 -0
  79. package/dist/codegen/serialize-static.d.ts +39 -0
  80. package/dist/codegen/serialize-static.d.ts.map +1 -0
  81. package/dist/codegen/serialize-static.js +165 -0
  82. package/dist/codegen/serialize-static.mjs +104 -0
  83. package/dist/frontend/babel/build-ir-lit.cjs +1933 -0
  84. package/dist/frontend/babel/build-ir-lit.d.cts +26 -0
  85. package/dist/frontend/babel/build-ir-lit.d.ts +27 -0
  86. package/dist/frontend/babel/build-ir-lit.d.ts.map +1 -0
  87. package/dist/frontend/babel/build-ir-lit.js +13 -0
  88. package/dist/frontend/babel/build-ir-lit.mjs +1902 -0
  89. package/dist/frontend/babel/build-ir.cjs +1948 -0
  90. package/dist/frontend/babel/build-ir.d.cts +35 -0
  91. package/dist/frontend/babel/build-ir.d.ts +36 -0
  92. package/dist/frontend/babel/build-ir.d.ts.map +1 -0
  93. package/dist/frontend/babel/build-ir.js +124 -0
  94. package/dist/frontend/babel/build-ir.mjs +1919 -0
  95. package/dist/frontend/babel/index.cjs +2610 -0
  96. package/dist/frontend/babel/index.d.cts +33 -0
  97. package/dist/frontend/babel/index.d.ts +34 -0
  98. package/dist/frontend/babel/index.d.ts.map +1 -0
  99. package/dist/frontend/babel/index.js +65 -0
  100. package/dist/frontend/babel/index.mjs +2580 -0
  101. package/dist/frontend/babel/lower-template.cjs +1931 -0
  102. package/dist/frontend/babel/lower-template.d.cts +23 -0
  103. package/dist/frontend/babel/lower-template.d.ts +24 -0
  104. package/dist/frontend/babel/lower-template.d.ts.map +1 -0
  105. package/dist/frontend/babel/lower-template.js +64 -0
  106. package/dist/frontend/babel/lower-template.mjs +1902 -0
  107. package/dist/frontend/babel/plugin.cjs +2556 -0
  108. package/dist/frontend/babel/plugin.d.cts +95 -0
  109. package/dist/frontend/babel/plugin.d.ts +96 -0
  110. package/dist/frontend/babel/plugin.d.ts.map +1 -0
  111. package/dist/frontend/babel/plugin.js +523 -0
  112. package/dist/frontend/babel/plugin.mjs +2527 -0
  113. package/dist/frontend/babel/server-functions.cjs +110 -0
  114. package/dist/frontend/babel/server-functions.d.cts +10 -0
  115. package/dist/frontend/babel/server-functions.d.ts +11 -0
  116. package/dist/frontend/babel/server-functions.d.ts.map +1 -0
  117. package/dist/frontend/babel/server-functions.js +81 -0
  118. package/dist/frontend/babel/server-functions.mjs +89 -0
  119. package/dist/frontend/babel/types.cjs +18 -0
  120. package/dist/frontend/babel/types.d.cts +33 -0
  121. package/dist/frontend/babel/types.d.ts +34 -0
  122. package/dist/frontend/babel/types.d.ts.map +1 -0
  123. package/dist/frontend/babel/types.js +1 -0
  124. package/dist/frontend/babel/types.mjs +0 -0
  125. package/dist/frontend/types.cjs +18 -0
  126. package/dist/frontend/types.d.cts +25 -0
  127. package/dist/frontend/types.d.ts +26 -0
  128. package/dist/frontend/types.d.ts.map +1 -0
  129. package/dist/frontend/types.js +1 -0
  130. package/dist/frontend/types.mjs +0 -0
  131. package/dist/frontend/vocabulary.cjs +98 -0
  132. package/dist/frontend/vocabulary.d.cts +79 -0
  133. package/dist/frontend/vocabulary.d.ts +80 -0
  134. package/dist/frontend/vocabulary.d.ts.map +1 -0
  135. package/dist/frontend/vocabulary.js +124 -0
  136. package/dist/frontend/vocabulary.mjs +77 -0
  137. package/dist/index.cjs +1957 -0
  138. package/dist/index.d.cts +27 -0
  139. package/dist/index.d.ts +28 -0
  140. package/dist/index.d.ts.map +1 -0
  141. package/dist/index.js +38 -0
  142. package/dist/index.mjs +1949 -0
  143. package/dist/integrations.cjs +5705 -0
  144. package/dist/integrations.d.cts +215 -0
  145. package/dist/integrations.d.ts +216 -0
  146. package/dist/integrations.d.ts.map +1 -0
  147. package/dist/integrations.js +566 -0
  148. package/dist/integrations.mjs +810 -0
  149. package/dist/ir/nodes.cjs +18 -0
  150. package/dist/ir/nodes.d.cts +168 -0
  151. package/dist/ir/nodes.d.ts +169 -0
  152. package/dist/ir/nodes.d.ts.map +1 -0
  153. package/dist/ir/nodes.js +1 -0
  154. package/dist/ir/nodes.mjs +0 -0
  155. package/dist/lower/compile-template.cjs +1670 -0
  156. package/dist/lower/compile-template.d.cts +82 -0
  157. package/dist/lower/compile-template.d.ts +83 -0
  158. package/dist/lower/compile-template.d.ts.map +1 -0
  159. package/dist/lower/compile-template.js +79 -0
  160. package/dist/lower/compile-template.mjs +1662 -0
  161. package/dist/lower/entities.cjs +288 -0
  162. package/dist/lower/entities.d.cts +1 -0
  163. package/dist/lower/entities.d.ts +2 -0
  164. package/dist/lower/entities.d.ts.map +1 -0
  165. package/dist/lower/entities.js +54 -0
  166. package/dist/lower/entities.mjs +267 -0
  167. package/dist/lower/jsx.cjs +1101 -0
  168. package/dist/lower/jsx.d.cts +33 -0
  169. package/dist/lower/jsx.d.ts +34 -0
  170. package/dist/lower/jsx.d.ts.map +1 -0
  171. package/dist/lower/jsx.js +414 -0
  172. package/dist/lower/jsx.mjs +1078 -0
  173. package/dist/lower/template.cjs +1354 -0
  174. package/dist/lower/template.d.cts +53 -0
  175. package/dist/lower/template.d.ts +54 -0
  176. package/dist/lower/template.d.ts.map +1 -0
  177. package/dist/lower/template.js +542 -0
  178. package/dist/lower/template.mjs +1335 -0
  179. package/dist/lower/text.cjs +42 -0
  180. package/dist/lower/text.d.cts +10 -0
  181. package/dist/lower/text.d.ts +11 -0
  182. package/dist/lower/text.d.ts.map +1 -0
  183. package/dist/lower/text.js +31 -0
  184. package/dist/lower/text.mjs +21 -0
  185. package/dist/optimize/analyze-static.cjs +112 -0
  186. package/dist/optimize/analyze-static.d.cts +39 -0
  187. package/dist/optimize/analyze-static.d.ts +40 -0
  188. package/dist/optimize/analyze-static.d.ts.map +1 -0
  189. package/dist/optimize/analyze-static.js +131 -0
  190. package/dist/optimize/analyze-static.mjs +91 -0
  191. package/dist/optimize/collapse-strategies.cjs +90 -0
  192. package/dist/optimize/collapse-strategies.d.cts +30 -0
  193. package/dist/optimize/collapse-strategies.d.ts +31 -0
  194. package/dist/optimize/collapse-strategies.d.ts.map +1 -0
  195. package/dist/optimize/collapse-strategies.js +33 -0
  196. package/dist/optimize/collapse-strategies.mjs +67 -0
  197. package/dist/options.cjs +33 -0
  198. package/dist/options.d.cts +39 -0
  199. package/dist/options.d.ts +40 -0
  200. package/dist/options.d.ts.map +1 -0
  201. package/dist/options.js +8 -0
  202. package/dist/options.mjs +12 -0
  203. package/dist/resolve/builtins.cjs +73 -0
  204. package/dist/resolve/builtins.d.cts +68 -0
  205. package/dist/resolve/builtins.d.ts +69 -0
  206. package/dist/resolve/builtins.d.ts.map +1 -0
  207. package/dist/resolve/builtins.js +64 -0
  208. package/dist/resolve/builtins.mjs +53 -0
  209. package/dist/resolve/component-globals.cjs +272 -0
  210. package/dist/resolve/component-globals.d.cts +88 -0
  211. package/dist/resolve/component-globals.d.ts +89 -0
  212. package/dist/resolve/component-globals.d.ts.map +1 -0
  213. package/dist/resolve/component-globals.js +160 -0
  214. package/dist/resolve/component-globals.mjs +249 -0
  215. package/dist/resolve/component-resolver.cjs +80 -0
  216. package/dist/resolve/component-resolver.d.cts +68 -0
  217. package/dist/resolve/component-resolver.d.ts +69 -0
  218. package/dist/resolve/component-resolver.d.ts.map +1 -0
  219. package/dist/resolve/component-resolver.js +95 -0
  220. package/dist/resolve/component-resolver.mjs +59 -0
  221. package/dist/resolve/load-directive.cjs +93 -0
  222. package/dist/resolve/load-directive.d.cts +53 -0
  223. package/dist/resolve/load-directive.d.ts +54 -0
  224. package/dist/resolve/load-directive.d.ts.map +1 -0
  225. package/dist/resolve/load-directive.js +93 -0
  226. package/dist/resolve/load-directive.mjs +72 -0
  227. package/dist/resolve/resolve-ir.cjs +108 -0
  228. package/dist/resolve/resolve-ir.d.cts +53 -0
  229. package/dist/resolve/resolve-ir.d.ts +54 -0
  230. package/dist/resolve/resolve-ir.d.ts.map +1 -0
  231. package/dist/resolve/resolve-ir.js +58 -0
  232. package/dist/resolve/resolve-ir.mjs +85 -0
  233. package/dist/resolve/write-globals.cjs +383 -0
  234. package/dist/resolve/write-globals.d.cts +36 -0
  235. package/dist/resolve/write-globals.d.ts +37 -0
  236. package/dist/resolve/write-globals.d.ts.map +1 -0
  237. package/dist/resolve/write-globals.js +169 -0
  238. package/dist/resolve/write-globals.mjs +362 -0
  239. package/dist/server-fns-VZLHMQTC.mjs +79 -0
  240. package/dist/server-functions-UAZKOLZW.mjs +82 -0
  241. package/dist/transform/bindings.cjs +71 -0
  242. package/dist/transform/bindings.d.cts +16 -0
  243. package/dist/transform/bindings.d.ts +17 -0
  244. package/dist/transform/bindings.d.ts.map +1 -0
  245. package/dist/transform/bindings.js +69 -0
  246. package/dist/transform/bindings.mjs +50 -0
  247. package/dist/transform/index.cjs +3837 -0
  248. package/dist/transform/index.d.cts +15 -0
  249. package/dist/transform/index.d.ts +16 -0
  250. package/dist/transform/index.d.ts.map +1 -0
  251. package/dist/transform/index.js +12 -0
  252. package/dist/transform/index.mjs +4882 -0
  253. package/dist/transform/intrinsics.cjs +261 -0
  254. package/dist/transform/intrinsics.d.cts +33 -0
  255. package/dist/transform/intrinsics.d.ts +34 -0
  256. package/dist/transform/intrinsics.d.ts.map +1 -0
  257. package/dist/transform/intrinsics.js +120 -0
  258. package/dist/transform/intrinsics.mjs +238 -0
  259. package/dist/transform/props.cjs +441 -0
  260. package/dist/transform/props.d.cts +45 -0
  261. package/dist/transform/props.d.ts +46 -0
  262. package/dist/transform/props.d.ts.map +1 -0
  263. package/dist/transform/props.js +221 -0
  264. package/dist/transform/props.mjs +1487 -0
  265. package/dist/transform/server-fn-id.cjs +35 -0
  266. package/dist/transform/server-fn-id.d.cts +9 -0
  267. package/dist/transform/server-fn-id.d.ts +10 -0
  268. package/dist/transform/server-fn-id.d.ts.map +1 -0
  269. package/dist/transform/server-fn-id.js +18 -0
  270. package/dist/transform/server-fn-id.mjs +14 -0
  271. package/dist/transform/server-fns.cjs +114 -0
  272. package/dist/transform/server-fns.d.cts +12 -0
  273. package/dist/transform/server-fns.d.ts +13 -0
  274. package/dist/transform/server-fns.d.ts.map +1 -0
  275. package/dist/transform/server-fns.js +94 -0
  276. package/dist/transform/server-fns.mjs +1160 -0
  277. package/dist/transform/source-locations.cjs +393 -0
  278. package/dist/transform/source-locations.d.cts +48 -0
  279. package/dist/transform/source-locations.d.ts +49 -0
  280. package/dist/transform/source-locations.d.ts.map +1 -0
  281. package/dist/transform/source-locations.js +303 -0
  282. package/dist/transform/source-locations.mjs +370 -0
  283. package/dist/transform/styles.cjs +606 -0
  284. package/dist/transform/styles.d.cts +237 -0
  285. package/dist/transform/styles.d.ts +238 -0
  286. package/dist/transform/styles.d.ts.map +1 -0
  287. package/dist/transform/styles.js +743 -0
  288. package/dist/transform/styles.mjs +671 -0
  289. package/dist/transform/templates.cjs +3806 -0
  290. package/dist/transform/templates.d.cts +82 -0
  291. package/dist/transform/templates.d.ts +83 -0
  292. package/dist/transform/templates.d.ts.map +1 -0
  293. package/dist/transform/templates.js +613 -0
  294. package/dist/transform/templates.mjs +4852 -0
  295. package/dist/transform-3W45L3EA.mjs +951 -0
  296. package/dist/tsconfig.lib.tsbuildinfo +1 -0
  297. package/dist/vite-styles.cjs +223 -0
  298. package/dist/vite-styles.d.cts +68 -0
  299. package/dist/vite-styles.d.ts +69 -0
  300. package/dist/vite-styles.d.ts.map +1 -0
  301. package/dist/vite-styles.js +241 -0
  302. package/dist/vite-styles.mjs +214 -0
  303. package/package.json +141 -0
@@ -0,0 +1,743 @@
1
+ /**
2
+ * `<style>` and `<style scoped>` in a component.
3
+ *
4
+ * The compiler owns which component a style belongs to and the scoping; what the CSS means
5
+ * (`@apply`, utilities, variants, theme values, nesting) is the CSS engine's, reached through
6
+ * the `process` function the host passes in, the same engine and context the project's own CSS
7
+ * goes through. The host gets the processed CSS back and decides where it goes; the element
8
+ * itself leaves the template.
9
+ *
10
+ * Scoping marks every element the component renders with `data-fx-s="<id>"` at compile time
11
+ * (part of the static template, so client renders, SSR and hydration all carry it) and adds
12
+ * `[data-fx-s="<id>"]` to the last compound of each selector.
13
+ */
14
+ import { encode } from '@jridgewell/sourcemap-codec';
15
+ export const SCOPE_ATTR = 'data-fx-s';
16
+ const FUNCTIONS = new Set(['FunctionDeclaration', 'FunctionExpression', 'ArrowFunctionExpression', 'ObjectMethod', 'ClassMethod']);
17
+ /** Finds the style blocks of a module and compiles them. Without `options`, nothing happens. */
18
+ export function collectStyles(program, sourceName, options,
19
+ /** Template tags by name (`html`, `$html`), and the `css` tags a module may use unimported (`$css`). */
20
+ tags = { html: new Map([['html', 'html']]) },
21
+ /** The module as the host knows it, for source maps that point into it. */
22
+ module) {
23
+ const plan = {
24
+ scopes: [], templateOwners: new Map(), drop: new Set(), styles: [], diagnostics: [], edits: [], literals: [], references: [],
25
+ shadowClasses: new Map(),
26
+ };
27
+ if (!options)
28
+ return plan;
29
+ const literalsOf = findLiterals(program, options.cssModules ?? ['@fluixi/core', '@fluixi/dom'], plan, tags.css ?? []);
30
+ plan.names = literalsOf;
31
+ // A class method's class, for telling whether a render belongs to a shadow-DOM element.
32
+ const classOf = new Map();
33
+ const shadowOf = (owner) => {
34
+ const cls = classOf.get(owner);
35
+ return cls ? plan.shadowClasses.get(cls) : undefined;
36
+ };
37
+ const resolved = new Map();
38
+ // A `css`` value's nodes: each static piece processed on its own, interpolated values put
39
+ // in between, in order. Composition happens on the AST, so the cascade is the written one,
40
+ // and interpolation can only stand between rules.
41
+ const piecesToNodes = (quasis, expressions, at, stack) => {
42
+ const out = [];
43
+ for (let i = 0; i < quasis.length; i++) {
44
+ const text = (quasis[i].value.cooked ?? quasis[i].value.raw);
45
+ if (text.trim()) {
46
+ try {
47
+ // The engine's positions count from the piece; the piece starts where its quasi does.
48
+ const start = quasis[i].loc?.start;
49
+ out.push(...options.process(text, sourceName).map((n) => (start ? shiftLoc(n, sourceName, start) : n)));
50
+ }
51
+ catch (error) {
52
+ plan.diagnostics.push({ ...at, message: `CSS could not be processed: ${error.message}` });
53
+ return null;
54
+ }
55
+ }
56
+ const expr = expressions[i];
57
+ if (!expr)
58
+ continue;
59
+ const value = expr.type === 'Identifier' ? resolveLiteral(expr.name, at, stack) : undefined;
60
+ if (value === undefined) {
61
+ plan.diagnostics.push({
62
+ ...at,
63
+ message: 'Only css`` values can be interpolated into styles, and only by name: ${base}. Dynamic values go through custom properties (style:--x={...} and var(--x)).',
64
+ });
65
+ return null;
66
+ }
67
+ if (value === null)
68
+ return null;
69
+ out.push(...value);
70
+ }
71
+ return out;
72
+ };
73
+ /** A literal's nodes; `undefined` when the name is not a style value at all. */
74
+ function resolveLiteral(name, at, stack) {
75
+ const imported = literalsOf.imports.get(name);
76
+ if (imported) {
77
+ const nodes = options?.imported?.get(`${imported.source}#${imported.name}`);
78
+ // Positions in a module the build named stay, for the map; any other is dropped.
79
+ if (nodes)
80
+ return nodes.map((n) => keepLocIn(n, options?.importedModules));
81
+ plan.references.push({ name: imported.name, source: imported.source, ...at });
82
+ // Without `imported` the host has not looked yet; with it, it looked and found nothing.
83
+ plan.diagnostics.push({
84
+ ...at,
85
+ message: options?.imported
86
+ ? `${name} from ${imported.source} is not a css\`\` value the build could find.`
87
+ : `${name} comes from ${imported.source}: style values from another module are resolved by the build.`,
88
+ });
89
+ return null;
90
+ }
91
+ const literal = literalsOf.literals.get(name);
92
+ if (!literal)
93
+ return undefined;
94
+ if (stack.includes(name)) {
95
+ plan.diagnostics.push({ ...at, message: `css\`\` values include each other: ${[...stack, name].join(' → ')}.` });
96
+ return null;
97
+ }
98
+ if (!resolved.has(name)) {
99
+ resolved.set(name, piecesToNodes(literal.quasi.quasis, literal.quasi.expressions, at, [...stack, name]));
100
+ }
101
+ return resolved.get(name);
102
+ }
103
+ for (const [name, literal] of literalsOf.literals) {
104
+ const at = { line: literal.loc?.start.line ?? 0, column: literal.loc?.start.column ?? 0 };
105
+ const nodes = resolveLiteral(name, at, []);
106
+ const id = hash(`${sourceName}:css:${name}`);
107
+ plan.edits.push({ start: literal.start, end: literal.end, code: `({ $fxStyle: ${JSON.stringify(id)} })` });
108
+ if (nodes)
109
+ plan.literals.push({ id, name, css: printStyle(nodes, options.minify), nodes });
110
+ }
111
+ const scopeOf = new Map();
112
+ const names = new Map();
113
+ // `const Card = () => …`: the component's name is the variable's.
114
+ const named = new Map();
115
+ const visit = (node, owners) => {
116
+ if (!node || typeof node !== 'object')
117
+ return;
118
+ if (node.type === 'VariableDeclarator' && node.id.type === 'Identifier' && node.init && FUNCTIONS.has(node.init.type)) {
119
+ named.set(node.init, node.id.name);
120
+ }
121
+ // A custom element's `render()` belongs to the class: the element is the component.
122
+ if ((node.type === 'ClassDeclaration' || node.type === 'ClassExpression') && node.id) {
123
+ for (const member of node.body.body)
124
+ if (member.type === 'ClassMethod')
125
+ named.set(member, node.id.name);
126
+ }
127
+ if (node.type === 'ClassDeclaration' || node.type === 'ClassExpression') {
128
+ for (const member of node.body.body)
129
+ if (member.type === 'ClassMethod')
130
+ classOf.set(member, node);
131
+ const shadow = staticMember(node, 'shadow');
132
+ if (shadow?.value && !(shadow.value.type === 'BooleanLiteral' && shadow.value.value === false)) {
133
+ plan.shadowClasses.set(node, { node, styles: staticMember(node, 'styles'), indexes: [] });
134
+ }
135
+ }
136
+ if (node.type === 'TaggedTemplateExpression' && node.tag.type === 'Identifier' && tags.html.get(node.tag.name) === 'html') {
137
+ const text = node.quasi.quasis.map((q) => q.value.raw).join('');
138
+ if (/<style[\s>]/.test(text)) {
139
+ const at = { line: node.loc?.start.line ?? 0, column: node.loc?.start.column ?? 0 };
140
+ const owner = owners[0];
141
+ if (!owner)
142
+ plan.diagnostics.push({ ...at, message: '<style> has to be written inside a component.' });
143
+ else {
144
+ const id = idFor(owner);
145
+ const shadow = shadowOf(owner);
146
+ plan.templateOwners.set(node.start, { id, component: functionName(owner, named) });
147
+ // The blocks are compiled here, from the template's own pieces, so `${base}` resolves
148
+ // as it does in JSX; the template compile only takes the elements out.
149
+ for (const block of templateBlocks(node.quasi))
150
+ compileBlock(block, block.scoped, owner, at);
151
+ }
152
+ }
153
+ }
154
+ const inner = FUNCTIONS.has(node.type) ? [...owners, node] : owners;
155
+ if (node.type === 'JSXElement' && isStyle(node)) {
156
+ handle(node, owners);
157
+ return;
158
+ }
159
+ for (const key of Object.keys(node)) {
160
+ if (key === 'loc' || key === 'leadingComments' || key === 'trailingComments' || key === 'innerComments')
161
+ continue;
162
+ const value = node[key];
163
+ if (Array.isArray(value))
164
+ for (const v of value)
165
+ visit(v, inner);
166
+ else if (value && typeof value === 'object' && 'type' in value)
167
+ visit(value, inner);
168
+ }
169
+ };
170
+ const handle = (node, owners) => {
171
+ const at = { line: node.loc?.start.line ?? 0, column: node.loc?.start.column ?? 0 };
172
+ const pieces = blockPieces(node);
173
+ if (pieces === null) {
174
+ plan.diagnostics.push({
175
+ ...at,
176
+ message: '<style> needs its CSS as one template literal, <style>{`...`}</style>: JSX reads a bare `{` as an expression.',
177
+ });
178
+ return;
179
+ }
180
+ // The component is the outermost function around the block: inner callbacks (a list's
181
+ // render function) render the same component's elements.
182
+ const owner = owners[0];
183
+ if (!owner) {
184
+ plan.diagnostics.push({ ...at, message: '<style> has to be written inside a component.' });
185
+ return;
186
+ }
187
+ compileBlock(pieces, isScoped(node), owner, at);
188
+ plan.drop.add(node.start);
189
+ };
190
+ const compileBlock = (pieces, scoped, owner, at) => {
191
+ const component = functionName(owner, named);
192
+ const id = idFor(owner);
193
+ const processed = piecesToNodes(pieces.quasis, pieces.expressions, at, []);
194
+ if (!processed)
195
+ return;
196
+ let nodes = processed;
197
+ const shadow = shadowOf(owner);
198
+ // Everything in the block, composed values included, takes the one scope. A shadow root
199
+ // needs none: its styles do not reach out, and the page's do not reach in.
200
+ if (scoped && !shadow) {
201
+ if (!plan.scopes.some((s) => s.value === id))
202
+ plan.scopes.push({ start: owner.start, end: owner.end, value: id });
203
+ nodes = scopeNodes(nodes, id, (message) => plan.diagnostics.push({ ...at, message }));
204
+ }
205
+ const printed = module
206
+ ? printStyleWithMap(nodes, options.minify, sourceName, module, options.importedModules)
207
+ : { css: printStyle(nodes, options.minify) };
208
+ plan.styles.push({ id, scoped: scoped && !shadow, component, ...printed, ...(shadow ? { shadow: true } : {}), ...at });
209
+ if (shadow)
210
+ shadow.indexes.push(plan.styles.length - 1);
211
+ };
212
+ // One id per component: every block it has, scoped or not, JSX or template, shares it.
213
+ function idFor(owner) {
214
+ let id = scopeOf.get(owner);
215
+ if (!id) {
216
+ const component = functionName(owner, named);
217
+ const seen = names.get(component) ?? 0;
218
+ names.set(component, seen + 1);
219
+ id = hash(`${sourceName}:${component}${seen ? ':' + seen : ''}`);
220
+ scopeOf.set(owner, id);
221
+ }
222
+ return id;
223
+ }
224
+ visit(program, []);
225
+ return plan;
226
+ }
227
+ /**
228
+ * The template form: after lowering, a `<style>` is an element with raw text. It is taken out,
229
+ * compiled like a JSX block, and the template's other elements get the scope.
230
+ */
231
+ export function applyTemplateStyles(ir, t) {
232
+ const walk = (node) => {
233
+ const children = node.children;
234
+ if (children) {
235
+ for (let i = children.length - 1; i >= 0; i--) {
236
+ const child = children[i];
237
+ if (child.kind === 'element' && child.tag === 'style' && t.owner)
238
+ children.splice(i, 1);
239
+ else
240
+ walk(child);
241
+ }
242
+ }
243
+ if (t.scope && node.kind === 'element' && node.tag !== 'style' && node.props && !node.props.some((p) => p.name === SCOPE_ATTR)) {
244
+ node.props.unshift({ name: SCOPE_ATTR, kind: 'attr', literal: t.scope });
245
+ }
246
+ };
247
+ walk(ir);
248
+ }
249
+ function staticMember(cls, name) {
250
+ return cls.body.body.find((m) => m.type === 'ClassProperty' && m.static && ((m.key.type === 'Identifier' && m.key.name === name) || (m.key.type === 'StringLiteral' && m.key.value === name)));
251
+ }
252
+ /**
253
+ * A shadow-DOM element's styles: once every block is compiled, each class's blocks and the
254
+ * `css`` values named in its `static styles` become `?inline` imports of their processed CSS
255
+ * (the text `static styles` takes), and the class's `static styles` lists them.
256
+ */
257
+ /**
258
+ * Where a component's style blocks and css`` values are served: next to the component, a path
259
+ * ending in `.css`. Every CSS tool in the bundler then sees CSS, and none sees TSX: Vite 8
260
+ * matches its transforms on the path without the query, so `card.tsx?…` would read as a .tsx.
261
+ * `?inline` (Vite's own) asks for the CSS as a string, for a shadow root.
262
+ */
263
+ export const styleIds = {
264
+ block: (owner, index) => `${owner}.fx-${index}.css`,
265
+ inline: (owner, index) => `${owner}.fx-${index}.css?inline`,
266
+ literal: (owner, name) => `${owner}.fx-literal-${name}.css?inline`,
267
+ };
268
+ export function finishShadowStyles(plan, code, moduleId) {
269
+ const edits = [];
270
+ const imports = [];
271
+ let next = 0;
272
+ const importOf = (specifier) => {
273
+ const local = `__fxShadow${next++}`;
274
+ imports.push(`import ${local} from ${JSON.stringify(specifier)};\n`);
275
+ return local;
276
+ };
277
+ for (const shadow of plan.shadowClasses.values()) {
278
+ const blocks = shadow.indexes.map((i) => importOf(styleIds.inline(moduleId, i)));
279
+ let value;
280
+ const prop = shadow.styles;
281
+ if (prop?.value) {
282
+ // `css`` values named in it become their CSS; anything else is left as written.
283
+ const start = prop.value.start;
284
+ let text = code.slice(start, prop.value.end);
285
+ const replacements = [];
286
+ walkIdentifiers(prop.value, (id) => {
287
+ const local = plan.names?.literals.has(id.name)
288
+ ? importOf(styleIds.literal(moduleId, id.name))
289
+ : plan.names?.imports.has(id.name) && !/\.css(\?|$)/.test(plan.names.imports.get(id.name).source)
290
+ ? importOf(styleIds.literal(plan.names.imports.get(id.name).source, plan.names.imports.get(id.name).name))
291
+ : undefined;
292
+ if (local)
293
+ replacements.push({ at: id.start - start, length: id.name.length, with: local });
294
+ });
295
+ for (const r of replacements.sort((a, b) => b.at - a.at))
296
+ text = text.slice(0, r.at) + r.with + text.slice(r.at + r.length);
297
+ value = text;
298
+ }
299
+ if (!blocks.length && value === undefined)
300
+ continue;
301
+ if (prop?.value) {
302
+ const merged = blocks.length ? `[${value}, ${blocks.join(', ')}]` : value;
303
+ edits.push({ start: prop.value.start, end: prop.value.end, code: merged });
304
+ }
305
+ else if (blocks.length) {
306
+ const open = shadow.node.body.start + 1;
307
+ edits.push({ start: open, end: open, code: ` static styles = [${blocks.join(', ')}];` });
308
+ }
309
+ }
310
+ if (imports.length)
311
+ edits.push({ start: 0, end: 0, code: imports.join('') });
312
+ return edits;
313
+ }
314
+ function walkIdentifiers(node, visit) {
315
+ if (!node || typeof node !== 'object')
316
+ return;
317
+ if (node.type === 'Identifier')
318
+ return visit(node);
319
+ if (node.type === 'MemberExpression')
320
+ return walkIdentifiers(node.object, visit);
321
+ if (node.type === 'ObjectProperty')
322
+ return walkIdentifiers(node.value, visit);
323
+ for (const key of Object.keys(node)) {
324
+ if (key === 'loc')
325
+ continue;
326
+ const value = node[key];
327
+ if (Array.isArray(value))
328
+ for (const v of value)
329
+ walkIdentifiers(v, visit);
330
+ else if (value && typeof value === 'object' && 'type' in value)
331
+ walkIdentifiers(value, visit);
332
+ }
333
+ }
334
+ function isStyle(node) {
335
+ const name = node.openingElement.name;
336
+ return name.type === 'JSXIdentifier' && name.name === 'style';
337
+ }
338
+ function isScoped(node) {
339
+ return node.openingElement.attributes.some((a) => a.type === 'JSXAttribute' && a.name.type === 'JSXIdentifier' && a.name.name === 'scoped');
340
+ }
341
+ /** The block's template pieces, a string counting as one piece; `null` when it is anything else. */
342
+ /**
343
+ * The `<style>` blocks of an html`` template, as pieces of its quasis: the CSS between the
344
+ * tags, with the `${…}` that stand in it. Each piece keeps the position it starts at.
345
+ */
346
+ function templateBlocks(quasi) {
347
+ const blocks = [];
348
+ let open = null;
349
+ quasi.quasis.forEach((q, i) => {
350
+ const raw = q.value.raw;
351
+ let from = 0;
352
+ while (from <= raw.length) {
353
+ if (!open) {
354
+ const tag = /<style\b([^>]*)>/g;
355
+ tag.lastIndex = from;
356
+ const m = tag.exec(raw);
357
+ if (!m)
358
+ break;
359
+ open = { quasis: [], expressions: [], scoped: /\bscoped\b/.test(m[1]) };
360
+ from = m.index + m[0].length;
361
+ }
362
+ const close = raw.indexOf('</style', from);
363
+ open.quasis.push(slicePiece(q, raw, from, close === -1 ? raw.length : close));
364
+ if (close === -1)
365
+ break;
366
+ blocks.push(open);
367
+ open = null;
368
+ from = close;
369
+ }
370
+ const expr = quasi.expressions[i];
371
+ if (open && expr)
372
+ open.expressions.push(expr);
373
+ });
374
+ return blocks;
375
+ }
376
+ function slicePiece(q, raw, from, to) {
377
+ const text = raw.slice(from, to);
378
+ const start = q.loc?.start;
379
+ if (!start)
380
+ return { type: 'TemplateElement', value: { raw: text, cooked: text } };
381
+ const before = raw.slice(0, from).split('\n');
382
+ const line = start.line + before.length - 1;
383
+ const column = before.length > 1 ? before[before.length - 1].length : start.column + from;
384
+ return { type: 'TemplateElement', value: { raw: text, cooked: text }, loc: { start: { line, column } } };
385
+ }
386
+ function blockPieces(node) {
387
+ const meaningful = node.children.filter((c) => !(c.type === 'JSXText' && !c.value.trim()));
388
+ if (meaningful.length === 0)
389
+ return { quasis: [], expressions: [] };
390
+ if (meaningful.length !== 1)
391
+ return null;
392
+ const only = meaningful[0];
393
+ if (only.type !== 'JSXExpressionContainer')
394
+ return null;
395
+ const expr = only.expression;
396
+ if (expr.type === 'StringLiteral')
397
+ return { quasis: [{ type: 'TemplateElement', value: { raw: expr.value, cooked: expr.value } }], expressions: [] };
398
+ if (expr.type === 'TemplateLiteral')
399
+ return { quasis: expr.quasis, expressions: expr.expressions };
400
+ return null;
401
+ }
402
+ /**
403
+ * The module's `css` binding and its `css`` declarations. The import is rewritten without
404
+ * `css`: every use is compiled away, and the engine has no business in a browser bundle.
405
+ */
406
+ function findLiterals(program, modules, plan, intrinsic) {
407
+ const literals = new Map();
408
+ // Local name → where it comes from and the export it is (`import { base as b }`: b → base).
409
+ const imports = new Map();
410
+ const tags = new Set(intrinsic);
411
+ for (const statement of program.body ?? []) {
412
+ if (statement.type !== 'ImportDeclaration')
413
+ continue;
414
+ const source = statement.source.value;
415
+ const specifiers = statement.specifiers;
416
+ for (const sp of specifiers) {
417
+ if (sp.type === 'ImportSpecifier')
418
+ imports.set(sp.local.name, { source, name: sp.imported.name ?? sp.imported.value });
419
+ }
420
+ if (!modules.includes(source))
421
+ continue;
422
+ const css = specifiers.find((sp) => sp.type === 'ImportSpecifier' && (sp.imported.name ?? sp.imported.value) === 'css');
423
+ if (!css)
424
+ continue;
425
+ const local = css.local.name;
426
+ tags.add(local);
427
+ imports.delete(local);
428
+ plan.edits.push({ start: statement.start, end: statement.end, code: importWithout(statement, css) });
429
+ }
430
+ // A component that only composes imported values has no `css` import of its own: its
431
+ // imports still name where those values come from.
432
+ if (tags.size === 0)
433
+ return { literals, imports };
434
+ const visit = (node) => {
435
+ if (!node || typeof node !== 'object')
436
+ return;
437
+ if (node.type === 'VariableDeclarator' && node.id.type === 'Identifier' && node.init?.type === 'TaggedTemplateExpression' && node.init.tag.type === 'Identifier' && tags.has(node.init.tag.name)) {
438
+ literals.set(node.id.name, node.init);
439
+ }
440
+ for (const key of Object.keys(node)) {
441
+ if (key === 'loc')
442
+ continue;
443
+ const value = node[key];
444
+ if (Array.isArray(value))
445
+ for (const v of value)
446
+ visit(v);
447
+ else if (value && typeof value === 'object' && 'type' in value)
448
+ visit(value);
449
+ }
450
+ };
451
+ visit(program);
452
+ return { literals, imports };
453
+ }
454
+ function importWithout(statement, removed) {
455
+ const rest = statement.specifiers.filter((sp) => sp !== removed);
456
+ const source = JSON.stringify(statement.source.value);
457
+ if (rest.length === 0)
458
+ return '';
459
+ const def = rest.find((sp) => sp.type === 'ImportDefaultSpecifier');
460
+ const ns = rest.find((sp) => sp.type === 'ImportNamespaceSpecifier');
461
+ const named = rest.filter((sp) => sp.type === 'ImportSpecifier').map((sp) => {
462
+ const imported = sp.imported.name ?? JSON.stringify(sp.imported.value);
463
+ return imported === sp.local.name ? imported : `${imported} as ${sp.local.name}`;
464
+ });
465
+ const parts = [def?.local.name, ns ? `* as ${ns.local.name}` : undefined, named.length ? `{ ${named.join(', ')} }` : undefined].filter(Boolean);
466
+ return `import ${parts.join(', ')} from ${source};`;
467
+ }
468
+ function functionName(fn, named) {
469
+ if ((fn.type === 'FunctionDeclaration' || fn.type === 'FunctionExpression') && fn.id)
470
+ return fn.id.name;
471
+ return named.get(fn) ?? 'anonymous';
472
+ }
473
+ /** FNV-1a, 32 bits, base 36: short, stable for the same file and component everywhere. */
474
+ export function hash(text) {
475
+ let h = 0x811c9dc5;
476
+ for (let i = 0; i < text.length; i++) {
477
+ h ^= text.charCodeAt(i);
478
+ h = Math.imul(h, 0x01000193);
479
+ }
480
+ return (h >>> 0).toString(36);
481
+ }
482
+ // ─── Scoping ─────────────────────────────────────────────────────────────────
483
+ // Selectors of these at-rules are not element selectors (`from`, `50%`) or there are none.
484
+ const OPAQUE = /(^|-)keyframes$|^font-face$|^property$|^counter-style$|^page$|^font-feature-values$/;
485
+ /** Adds the scope to every selector, through grouping at-rules; keyframes and the like are left. */
486
+ export function scopeNodes(nodes, id, warn = () => { }) {
487
+ return nodes.map((node) => {
488
+ if (node.kind === 'rule')
489
+ return { ...node, selector: scopeSelector(node.selector, id, warn) };
490
+ if (node.kind === 'at-rule' && !OPAQUE.test(node.name))
491
+ return { ...node, nodes: scopeNodes(node.nodes, id, warn) };
492
+ return node;
493
+ });
494
+ }
495
+ /** Scopes a selector list: each complex selector gets the scope on its last compound. */
496
+ export function scopeSelector(selector, id, warn = () => { }) {
497
+ return splitTop(selector, ',')
498
+ .map((complex) => scopeComplex(complex.trim(), `[${SCOPE_ATTR}="${id}"]`, warn))
499
+ .join(', ');
500
+ }
501
+ function scopeComplex(selector, attr, warn) {
502
+ if (/:host\b|::slotted\(/.test(selector)) {
503
+ warn(`\`${selector}\` only means something in a shadow root; in a light-DOM component it is left as written.`);
504
+ return selector;
505
+ }
506
+ const parts = compounds(selector);
507
+ // `:deep(x)` scopes what comes before it and leaves `x` free; `:global(x)` is never scoped.
508
+ const deep = parts.findIndex((p) => p.text.startsWith(':deep('));
509
+ if (deep !== -1) {
510
+ const inner = unwrap(parts[deep].text, ':deep(');
511
+ const before = parts.slice(0, deep);
512
+ if (before.length === 0)
513
+ return `${attr} ${inner}`;
514
+ const scopedBefore = scopeAt(before, before.length - 1, attr);
515
+ return `${join(scopedBefore)} ${inner}`;
516
+ }
517
+ let target = -1;
518
+ for (let i = parts.length - 1; i >= 0; i--) {
519
+ if (!parts[i].text.startsWith(':global(')) {
520
+ target = i;
521
+ break;
522
+ }
523
+ }
524
+ const out = target === -1 ? parts : scopeAt(parts, target, attr);
525
+ return join(out.map((p) => (p.text.startsWith(':global(') ? { ...p, text: unwrap(p.text, ':global(') } : p)));
526
+ }
527
+ function scopeAt(parts, index, attr) {
528
+ return parts.map((p, i) => (i === index ? { ...p, text: insertAttr(p.text, attr) } : p));
529
+ }
530
+ /** Puts the attribute before the compound's pseudo-elements and pseudo-classes: `a[s]:hover::before`. */
531
+ function insertAttr(compound, attr) {
532
+ let depth = 0;
533
+ let quote = '';
534
+ for (let i = 0; i < compound.length; i++) {
535
+ const c = compound[i];
536
+ if (quote) {
537
+ if (c === '\\')
538
+ i++;
539
+ else if (c === quote)
540
+ quote = '';
541
+ continue;
542
+ }
543
+ if (c === '\\') {
544
+ i++;
545
+ continue;
546
+ }
547
+ if (c === '"' || c === "'")
548
+ quote = c;
549
+ else if (c === '(' || c === '[')
550
+ depth++;
551
+ else if (c === ')' || c === ']')
552
+ depth--;
553
+ else if (c === ':' && depth === 0 && i > 0)
554
+ return compound.slice(0, i) + attr + compound.slice(i);
555
+ }
556
+ return compound + attr;
557
+ }
558
+ function compounds(selector) {
559
+ const out = [];
560
+ let depth = 0;
561
+ let quote = '';
562
+ let current = '';
563
+ let combinator = '';
564
+ const push = () => {
565
+ if (current.trim())
566
+ out.push({ combinator: out.length ? combinator || ' ' : '', text: current.trim() });
567
+ current = '';
568
+ combinator = '';
569
+ };
570
+ for (let i = 0; i < selector.length; i++) {
571
+ const c = selector[i];
572
+ if (quote) {
573
+ current += c;
574
+ if (c === '\\')
575
+ current += selector[++i] ?? '';
576
+ else if (c === quote)
577
+ quote = '';
578
+ continue;
579
+ }
580
+ if (c === '\\') {
581
+ current += c + (selector[++i] ?? '');
582
+ continue;
583
+ }
584
+ if (c === '"' || c === "'")
585
+ quote = c;
586
+ if (c === '(' || c === '[')
587
+ depth++;
588
+ if (c === ')' || c === ']')
589
+ depth--;
590
+ if (depth === 0 && (c === '>' || c === '+' || c === '~')) {
591
+ push();
592
+ combinator = c;
593
+ continue;
594
+ }
595
+ if (depth === 0 && /\s/.test(c)) {
596
+ if (current.trim()) {
597
+ const keep = combinator;
598
+ push();
599
+ combinator = keep;
600
+ }
601
+ continue;
602
+ }
603
+ current += c;
604
+ }
605
+ push();
606
+ return out;
607
+ }
608
+ function join(parts) {
609
+ return parts.map((p, i) => (i === 0 ? p.text : p.combinator === ' ' ? ` ${p.text}` : ` ${p.combinator} ${p.text}`)).join('');
610
+ }
611
+ function unwrap(text, prefix) {
612
+ return text.slice(prefix.length, text.lastIndexOf(')')).trim() + text.slice(text.lastIndexOf(')') + 1);
613
+ }
614
+ function splitTop(selector, separator) {
615
+ const parts = [];
616
+ let depth = 0;
617
+ let quote = '';
618
+ let start = 0;
619
+ for (let i = 0; i < selector.length; i++) {
620
+ const c = selector[i];
621
+ if (quote) {
622
+ if (c === '\\')
623
+ i++;
624
+ else if (c === quote)
625
+ quote = '';
626
+ }
627
+ else if (c === '"' || c === "'")
628
+ quote = c;
629
+ else if (c === '\\')
630
+ i++;
631
+ else if (c === '(' || c === '[')
632
+ depth++;
633
+ else if (c === ')' || c === ']')
634
+ depth--;
635
+ else if (c === separator && depth === 0) {
636
+ parts.push(selector.slice(start, i));
637
+ start = i + 1;
638
+ }
639
+ }
640
+ parts.push(selector.slice(start));
641
+ return parts.filter((p) => p.trim());
642
+ }
643
+ // ─── Printing ────────────────────────────────────────────────────────────────
644
+ function shiftLoc(node, source, start) {
645
+ const loc = node.loc && node.loc.source === source
646
+ ? { source, line: start.line + node.loc.line - 1, column: node.loc.line === 1 ? start.column + node.loc.column : node.loc.column }
647
+ : node.loc;
648
+ if (node.kind === 'rule' || node.kind === 'at-rule')
649
+ return { ...node, loc, nodes: node.nodes.map((n) => shiftLoc(n, source, start)) };
650
+ return { ...node, loc };
651
+ }
652
+ function keepLocIn(node, modules) {
653
+ const keep = node.loc !== undefined && modules?.has(node.loc.source) === true;
654
+ const { loc, ...rest } = node;
655
+ const kept = keep ? { ...rest, loc } : rest;
656
+ if (kept.kind === 'rule' || kept.kind === 'at-rule')
657
+ return { ...kept, nodes: kept.nodes.map((n) => keepLocIn(n, modules)) };
658
+ return kept;
659
+ }
660
+ /**
661
+ * Prints like `printStyle`, with a map from each rule and declaration back to where it was
662
+ * written in the module: the browser's devtools then show the `.tsx` line, not the generated CSS.
663
+ */
664
+ export function printStyleWithMap(nodes, minify, sourceName, module,
665
+ /** Other modules rules came from (composed css`` values), by the name their positions carry. */
666
+ others) {
667
+ const sources = [module];
668
+ const index = new Map([[sourceName, 0]]);
669
+ const sourceOf = (name) => {
670
+ if (index.has(name))
671
+ return index.get(name);
672
+ const other = others?.get(name);
673
+ if (!other)
674
+ return undefined;
675
+ index.set(name, sources.push(other) - 1);
676
+ return index.get(name);
677
+ };
678
+ const lines = [[]];
679
+ let css = '';
680
+ let column = 0;
681
+ const emit = (text) => {
682
+ for (const ch of text) {
683
+ css += ch;
684
+ if (ch === '\n') {
685
+ lines.push([]);
686
+ column = 0;
687
+ }
688
+ else
689
+ column++;
690
+ }
691
+ };
692
+ const mark = (loc) => {
693
+ const at = loc ? sourceOf(loc.source) : undefined;
694
+ if (loc && at !== undefined)
695
+ lines[lines.length - 1].push([column, at, loc.line - 1, loc.column]);
696
+ };
697
+ const write = (node, depth) => {
698
+ const pad = minify ? '' : ' '.repeat(depth);
699
+ const nl = minify ? '' : '\n';
700
+ const sp = minify ? '' : ' ';
701
+ emit(pad);
702
+ mark(node.loc);
703
+ if (node.kind === 'declaration') {
704
+ emit(`${node.property}:${sp}${node.value}${node.important ? `${sp}!important` : ''};${nl}`);
705
+ }
706
+ else if (node.kind === 'raw') {
707
+ emit(`${node.text}${nl}`);
708
+ }
709
+ else {
710
+ emit(`${node.kind === 'rule' ? node.selector : `@${node.name}${node.params ? ' ' + node.params : ''}`}${sp}{${nl}`);
711
+ for (const child of node.nodes)
712
+ write(child, depth + 1);
713
+ emit(`${pad}}${nl}`);
714
+ }
715
+ };
716
+ for (const node of nodes)
717
+ write(node, 0);
718
+ return { css, map: { version: 3, sources: sources.map((s) => s.id), sourcesContent: sources.map((s) => s.code), names: [], mappings: encode(lines) } };
719
+ }
720
+ export function printStyle(nodes, minify = false) {
721
+ const out = [];
722
+ const write = (node, depth) => {
723
+ const pad = minify ? '' : ' '.repeat(depth);
724
+ const nl = minify ? '' : '\n';
725
+ const sp = minify ? '' : ' ';
726
+ if (node.kind === 'declaration') {
727
+ out.push(`${pad}${node.property}:${sp}${node.value}${node.important ? `${sp}!important` : ''};${nl}`);
728
+ }
729
+ else if (node.kind === 'raw') {
730
+ out.push(`${pad}${node.text}${nl}`);
731
+ }
732
+ else {
733
+ const header = node.kind === 'rule' ? node.selector : `@${node.name}${node.params ? ' ' + node.params : ''}`;
734
+ out.push(`${pad}${header}${sp}{${nl}`);
735
+ for (const child of node.nodes)
736
+ write(child, depth + 1);
737
+ out.push(`${pad}}${nl}`);
738
+ }
739
+ };
740
+ for (const node of nodes)
741
+ write(node, 0);
742
+ return out.join('');
743
+ }