@fluixi/compiler 1.0.0-alpha.94 → 1.0.0-alpha.96

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 (60) hide show
  1. package/LICENSE +1 -1
  2. package/dist/analyze/static-graph.cjs +1 -1
  3. package/dist/analyze/static-graph.mjs +1 -1
  4. package/dist/{babel-RJFQVFJW.mjs → babel-YG5PQAMX.mjs} +4 -4
  5. package/dist/{chunk-ZR2QHTEX.mjs → chunk-JHBI26FW.mjs} +6 -4
  6. package/dist/{chunk-DP2QDWWH.mjs → chunk-JJ4ZAZKY.mjs} +1 -1
  7. package/dist/{chunk-HCCBEJEZ.mjs → chunk-L6WBOEIO.mjs} +1 -1
  8. package/dist/{chunk-HIZU7WI2.mjs → chunk-UVH2BMMY.mjs} +1 -1
  9. package/dist/chunk-VX2OBUMB.mjs +92 -0
  10. package/dist/{chunk-E2RWTIYE.mjs → chunk-X735CULF.mjs} +4 -89
  11. package/dist/chunk-ZPEHDBCH.mjs +584 -0
  12. package/dist/codegen/backends/imperative.cjs +4 -2
  13. package/dist/codegen/backends/imperative.d.ts.map +1 -1
  14. package/dist/codegen/backends/imperative.js +9 -2
  15. package/dist/codegen/backends/imperative.mjs +4 -2
  16. package/dist/frontend/babel/build-ir-lit.cjs +4 -2
  17. package/dist/frontend/babel/build-ir-lit.mjs +4 -2
  18. package/dist/frontend/babel/build-ir.cjs +4 -2
  19. package/dist/frontend/babel/build-ir.mjs +4 -2
  20. package/dist/frontend/babel/index.cjs +5 -3
  21. package/dist/frontend/babel/index.mjs +5 -3
  22. package/dist/frontend/babel/lower-template.cjs +4 -2
  23. package/dist/frontend/babel/lower-template.mjs +4 -2
  24. package/dist/frontend/babel/plugin.cjs +4 -2
  25. package/dist/frontend/babel/plugin.mjs +4 -2
  26. package/dist/index.cjs +5 -3
  27. package/dist/index.mjs +5 -3
  28. package/dist/integrations.cjs +3330 -3269
  29. package/dist/integrations.d.ts.map +1 -1
  30. package/dist/integrations.js +19 -8
  31. package/dist/integrations.mjs +85 -40
  32. package/dist/lower/compile-template.cjs +5 -3
  33. package/dist/lower/compile-template.mjs +5 -3
  34. package/dist/lower/jsx.cjs +4 -2
  35. package/dist/lower/jsx.mjs +4 -2
  36. package/dist/lower/template.cjs +4 -2
  37. package/dist/lower/template.mjs +4 -2
  38. package/dist/resolve/builtins.cjs +1 -1
  39. package/dist/resolve/builtins.mjs +1 -1
  40. package/dist/{server-fns-JLSTKWPS.mjs → server-fns-PZEOON2D.mjs} +5 -4
  41. package/dist/{server-functions-BGY3RD4R.mjs → server-functions-JNSQMA63.mjs} +3 -3
  42. package/dist/transform/index.cjs +35 -16
  43. package/dist/transform/index.mjs +35 -16
  44. package/dist/transform/styles.cjs +31 -13
  45. package/dist/transform/styles.d.cts +27 -1
  46. package/dist/transform/styles.d.ts +27 -1
  47. package/dist/transform/styles.d.ts.map +1 -1
  48. package/dist/transform/styles.js +45 -16
  49. package/dist/transform/styles.mjs +31 -13
  50. package/dist/transform/templates.cjs +34 -15
  51. package/dist/transform/templates.mjs +34 -15
  52. package/dist/{transform-GBP6Y4UI.mjs → transform-UODP37VJ.mjs} +12 -563
  53. package/dist/tsconfig.lib.tsbuildinfo +1 -1
  54. package/dist/vite-styles.cjs +66 -23
  55. package/dist/vite-styles.d.cts +16 -7
  56. package/dist/vite-styles.d.ts +16 -7
  57. package/dist/vite-styles.d.ts.map +1 -1
  58. package/dist/vite-styles.js +68 -25
  59. package/dist/vite-styles.mjs +78 -23
  60. package/package.json +4 -4
@@ -9,12 +9,29 @@
9
9
  */
10
10
  import { existsSync, readFileSync } from 'node:fs';
11
11
  import { basename, dirname, extname, join, relative } from 'node:path';
12
- // A page stylesheet, or (`&inline`, Vite's own flag) a shadow root's CSS as a string; and a
13
- // css`` value's CSS for a shadow class's `static styles`.
14
- const STYLE_ID = /\?fx-style&index=(\d+)(?:&inline)?&lang\.css$/;
15
- const LITERAL_ID = /\?fx-literal=([\w$]+)&inline&lang\.css$/;
12
+ import { styleIds } from './transform/styles.js';
13
+ // A page stylesheet, or (`?inline`, Vite's own flag) a shadow root's CSS as a string; and a
14
+ // css`` value's CSS for a shadow class's `static styles`. The owner is what comes before.
15
+ const STYLE_ID = /\.fx-(\d+)\.css(?:\?inline)?$/;
16
+ const LITERAL_ID = /\.fx-literal-([\w$]+)\.css\?inline$/;
17
+ const SUFFIX = /\.fx-(?:\d+|literal-[\w$]+)\.css(?:\?inline)?$/;
16
18
  /** The id a component's n-th style block is served under: a CSS request Vite treats as such. */
17
- export const styleId = (file, index) => `${file}?fx-style&index=${index}&lang.css`;
19
+ export const styleId = styleIds.block;
20
+ /** The source name the first positioned node carries: the module a value was written in. */
21
+ function firstLoc(nodes) {
22
+ for (const node of nodes) {
23
+ if (node.loc)
24
+ return node.loc.source;
25
+ if ((node.kind === 'rule' || node.kind === 'at-rule') && node.nodes.length) {
26
+ const inner = firstLoc(node.nodes);
27
+ if (inner)
28
+ return inner;
29
+ }
30
+ }
31
+ return undefined;
32
+ }
33
+ /** The component a style id belongs to, as written in the id. */
34
+ const ownerOf = (id) => id.slice(0, id.search(SUFFIX));
18
35
  // The same loader @fluixi-ui/tokens ships beside each slice: one <link>, added once.
19
36
  const loader = (name) => `const href = new URL(${JSON.stringify(`./${name}`)}, import.meta.url).href;
20
37
  if (typeof document !== 'undefined' && !document.querySelector(\`link[data-fx-css="\${href}"]\`)) {
@@ -39,7 +56,7 @@ export function createComponentStyles(compile) {
39
56
  // The CSS of each module's blocks, with the source it came from, for `load` and for telling
40
57
  // what changed.
41
58
  const cache = new Map();
42
- const resolveReference = async (ref, importer, ctx, seen) => {
59
+ const resolveReference = async (ref, importer, ctx, seen, modules) => {
43
60
  const resolved = await ctx.resolve?.(ref.source, importer);
44
61
  if (!resolved)
45
62
  return null;
@@ -57,16 +74,23 @@ export function createComponentStyles(compile) {
57
74
  let result = compile(code, file, styles);
58
75
  // A value that composes values from further away: those first.
59
76
  if (result?.styleReferences?.length) {
60
- const imported = await resolveAll(result.styleReferences, file, ctx, new Set([...seen, file]));
61
- result = compile(code, file, { ...styles, imported });
77
+ const imported = await resolveAll(result.styleReferences, file, ctx, new Set([...seen, file]), modules);
78
+ result = compile(code, file, { ...styles, imported, importedModules: modules });
62
79
  }
63
80
  const literal = result?.styleLiterals?.find((l) => l.name === ref.name);
64
- return literal ? styles.process(literal.css, file) : null;
81
+ if (!literal)
82
+ return null;
83
+ // Its rules as written, positions in its own module, which the composing block's map names.
84
+ const nodes = literal.nodes ?? styles.process(literal.css, file);
85
+ const named = firstLoc(nodes);
86
+ if (named)
87
+ modules.set(named, { id: file, code });
88
+ return nodes;
65
89
  };
66
- const resolveAll = async (refs, importer, ctx, seen) => {
90
+ const resolveAll = async (refs, importer, ctx, seen, modules) => {
67
91
  const imported = new Map();
68
92
  for (const ref of refs) {
69
- const nodes = await resolveReference(ref, importer, ctx, seen);
93
+ const nodes = await resolveReference(ref, importer, ctx, seen, modules);
70
94
  if (nodes)
71
95
  imported.set(`${ref.source}#${ref.name}`, nodes);
72
96
  }
@@ -80,8 +104,9 @@ export function createComponentStyles(compile) {
80
104
  const styles = api.styles(file);
81
105
  let result = compile(code, file, styles);
82
106
  if (result?.styleReferences?.length) {
83
- const imported = await resolveAll(result.styleReferences, id, ctx, new Set([file]));
84
- result = compile(code, file, { ...styles, imported });
107
+ const modules = new Map();
108
+ const imported = await resolveAll(result.styleReferences, id, ctx, new Set([file]), modules);
109
+ result = compile(code, file, { ...styles, imported, importedModules: modules });
85
110
  }
86
111
  const css = (result?.styles ?? []).map((s) => s.css);
87
112
  const maps = (result?.styles ?? []).map((s) => s.map ?? null);
@@ -94,7 +119,7 @@ export function createComponentStyles(compile) {
94
119
  for (let i = 0; i < css.length; i++) {
95
120
  if (before.css[i] === css[i])
96
121
  continue;
97
- const mod = server.moduleGraph.getModuleById(styleId(id, i));
122
+ const mod = server.moduleGraph.getModuleById(styleId(file, i));
98
123
  if (mod)
99
124
  void server.reloadModule(mod);
100
125
  }
@@ -118,7 +143,7 @@ export function createComponentStyles(compile) {
118
143
  emitted.set(`${out}.js`, loader(name));
119
144
  return { ...result, code: `${result.code}\nimport ${JSON.stringify(`./${name}`)};` };
120
145
  }
121
- const imports = page.map((i) => `\nimport ${JSON.stringify(styleId(id, i))};`).join('');
146
+ const imports = page.map((i) => `\nimport ${JSON.stringify(styleId(file, i))};`).join('');
122
147
  return { ...result, code: result.code + imports };
123
148
  };
124
149
  return {
@@ -155,14 +180,32 @@ export function createComponentStyles(compile) {
155
180
  return STYLE_ID.test(id) || LITERAL_ID.test(id);
156
181
  },
157
182
  /**
158
- * A style request as the module id Vite should keep: the file's absolute path and the
159
- * query. Vite invalidates a module when the file its id names changes, so a root-relative id
160
- * (`/src/card.tsx?fx-style…`, which is how a request arrives before the component's imports
161
- * were analysed) was never invalidated, and an edited block kept its old CSS until restart.
183
+ * A style request as the module id Vite keeps: its owner's absolute path, then the suffix.
184
+ * One id per block however it was asked for (`/src/card.tsx.fx-0.css` from a page, the
185
+ * absolute path from the component), or the reload after an edit misses the copy in use.
186
+ * A css`` value imported from another module names that module relatively, as written.
187
+ */
188
+ async resolveId(id, importer, ctx) {
189
+ const at = id.search(SUFFIX);
190
+ const owner = id.slice(0, at);
191
+ if (!owner.startsWith('.'))
192
+ return fileOf(owner) + id.slice(at);
193
+ const resolved = importer ? await ctx.resolve?.(owner, importer) : null;
194
+ return resolved ? resolved.id.split('?')[0] + id.slice(at) : null;
195
+ },
196
+ /**
197
+ * The style modules of a changed file, for the update Vite sends. Their ids do not name the
198
+ * file (they end in `.css`), so Vite would not find them itself.
162
199
  */
163
- resolveId(id) {
164
- const at = id.indexOf('?');
165
- return fileOf(id.slice(0, at)) + id.slice(at);
200
+ hotModules(file, graph) {
201
+ const entry = cache.get(file);
202
+ if (!entry)
203
+ return [];
204
+ const paths = [
205
+ ...entry.css.map((_, i) => styleId(file, i)),
206
+ ...[...entry.literals.keys()].map((name) => styleIds.literal(file, name).replace(/\?inline$/, '')),
207
+ ];
208
+ return paths.flatMap((path) => [...(graph.getModulesByFile(path) ?? [])]);
166
209
  },
167
210
  compile: run,
168
211
  /**
@@ -174,7 +217,7 @@ export function createComponentStyles(compile) {
174
217
  const literal = LITERAL_ID.exec(id);
175
218
  if ((!match && !literal) || !api)
176
219
  return null;
177
- const file = id.slice(0, id.indexOf('?'));
220
+ const file = ownerOf(id);
178
221
  let source;
179
222
  try {
180
223
  source = readFileSync(fileOf(file), 'utf8');
@@ -189,10 +232,10 @@ export function createComponentStyles(compile) {
189
232
  const css = entry?.literals.get(literal[1]);
190
233
  if (css === undefined)
191
234
  throw new Error(`[fluixi] ${literal[1]} in ${file} is not a css\`\` value, so it cannot be a shadow root's styles.`);
192
- return { code: css, map: null };
235
+ return { code: css, map: null, moduleType: 'css' };
193
236
  }
194
237
  const index = Number(match[1]);
195
- return { code: entry?.css[index] ?? '', map: entry?.maps[index] ?? null };
238
+ return { code: entry?.css[index] ?? '', map: entry?.maps[index] ?? null, moduleType: 'css' };
196
239
  },
197
240
  };
198
241
  }
@@ -1,9 +1,43 @@
1
1
  // src/vite-styles.ts
2
2
  import { existsSync, readFileSync } from "node:fs";
3
3
  import { basename, dirname, extname, join, relative } from "node:path";
4
- var STYLE_ID = /\?fx-style&index=(\d+)(?:&inline)?&lang\.css$/;
5
- var LITERAL_ID = /\?fx-literal=([\w$]+)&inline&lang\.css$/;
6
- var styleId = (file, index) => `${file}?fx-style&index=${index}&lang.css`;
4
+
5
+ // ../../node_modules/.pnpm/@jridgewell+sourcemap-codec@1.6.0/node_modules/@jridgewell/sourcemap-codec/dist/sourcemap-codec.mjs
6
+ var comma = ",".charCodeAt(0);
7
+ var semicolon = ";".charCodeAt(0);
8
+ var chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
9
+ var intToChar = new Uint8Array(64);
10
+ var charToInt = new Uint8Array(128);
11
+ for (let i = 0; i < chars.length; i++) {
12
+ const c = chars.charCodeAt(i);
13
+ intToChar[i] = c;
14
+ charToInt[c] = i;
15
+ }
16
+ var bufLength = 1024 * 16;
17
+
18
+ // src/transform/styles.ts
19
+ var styleIds = {
20
+ block: (owner, index) => `${owner}.fx-${index}.css`,
21
+ inline: (owner, index) => `${owner}.fx-${index}.css?inline`,
22
+ literal: (owner, name) => `${owner}.fx-literal-${name}.css?inline`
23
+ };
24
+
25
+ // src/vite-styles.ts
26
+ var STYLE_ID = /\.fx-(\d+)\.css(?:\?inline)?$/;
27
+ var LITERAL_ID = /\.fx-literal-([\w$]+)\.css\?inline$/;
28
+ var SUFFIX = /\.fx-(?:\d+|literal-[\w$]+)\.css(?:\?inline)?$/;
29
+ var styleId = styleIds.block;
30
+ function firstLoc(nodes) {
31
+ for (const node of nodes) {
32
+ if (node.loc) return node.loc.source;
33
+ if ((node.kind === "rule" || node.kind === "at-rule") && node.nodes.length) {
34
+ const inner = firstLoc(node.nodes);
35
+ if (inner) return inner;
36
+ }
37
+ }
38
+ return void 0;
39
+ }
40
+ var ownerOf = (id) => id.slice(0, id.search(SUFFIX));
7
41
  var loader = (name) => `const href = new URL(${JSON.stringify(`./${name}`)}, import.meta.url).href;
8
42
  if (typeof document !== 'undefined' && !document.querySelector(\`link[data-fx-css="\${href}"]\`)) {
9
43
  const link = document.createElement('link');
@@ -21,7 +55,7 @@ function createComponentStyles(compile) {
21
55
  const emitted = /* @__PURE__ */ new Map();
22
56
  const fileOf = (id) => existsSync(id) ? id : join(root, id);
23
57
  const cache = /* @__PURE__ */ new Map();
24
- const resolveReference = async (ref, importer, ctx, seen) => {
58
+ const resolveReference = async (ref, importer, ctx, seen, modules) => {
25
59
  const resolved = await ctx.resolve?.(ref.source, importer);
26
60
  if (!resolved) return null;
27
61
  const file = resolved.id.split("?")[0];
@@ -35,16 +69,20 @@ function createComponentStyles(compile) {
35
69
  const styles = api.styles(file);
36
70
  let result = compile(code, file, styles);
37
71
  if (result?.styleReferences?.length) {
38
- const imported = await resolveAll(result.styleReferences, file, ctx, /* @__PURE__ */ new Set([...seen, file]));
39
- result = compile(code, file, { ...styles, imported });
72
+ const imported = await resolveAll(result.styleReferences, file, ctx, /* @__PURE__ */ new Set([...seen, file]), modules);
73
+ result = compile(code, file, { ...styles, imported, importedModules: modules });
40
74
  }
41
75
  const literal = result?.styleLiterals?.find((l) => l.name === ref.name);
42
- return literal ? styles.process(literal.css, file) : null;
76
+ if (!literal) return null;
77
+ const nodes = literal.nodes ?? styles.process(literal.css, file);
78
+ const named = firstLoc(nodes);
79
+ if (named) modules.set(named, { id: file, code });
80
+ return nodes;
43
81
  };
44
- const resolveAll = async (refs, importer, ctx, seen) => {
82
+ const resolveAll = async (refs, importer, ctx, seen, modules) => {
45
83
  const imported = /* @__PURE__ */ new Map();
46
84
  for (const ref of refs) {
47
- const nodes = await resolveReference(ref, importer, ctx, seen);
85
+ const nodes = await resolveReference(ref, importer, ctx, seen, modules);
48
86
  if (nodes) imported.set(`${ref.source}#${ref.name}`, nodes);
49
87
  }
50
88
  return imported;
@@ -54,8 +92,9 @@ function createComponentStyles(compile) {
54
92
  const styles = api.styles(file);
55
93
  let result = compile(code, file, styles);
56
94
  if (result?.styleReferences?.length) {
57
- const imported = await resolveAll(result.styleReferences, id, ctx, /* @__PURE__ */ new Set([file]));
58
- result = compile(code, file, { ...styles, imported });
95
+ const modules = /* @__PURE__ */ new Map();
96
+ const imported = await resolveAll(result.styleReferences, id, ctx, /* @__PURE__ */ new Set([file]), modules);
97
+ result = compile(code, file, { ...styles, imported, importedModules: modules });
59
98
  }
60
99
  const css = (result?.styles ?? []).map((s) => s.css);
61
100
  const maps = (result?.styles ?? []).map((s) => s.map ?? null);
@@ -65,7 +104,7 @@ function createComponentStyles(compile) {
65
104
  if (server && before) {
66
105
  for (let i = 0; i < css.length; i++) {
67
106
  if (before.css[i] === css[i]) continue;
68
- const mod = server.moduleGraph.getModuleById(styleId(id, i));
107
+ const mod = server.moduleGraph.getModuleById(styleId(file, i));
69
108
  if (mod) void server.reloadModule(mod);
70
109
  }
71
110
  }
@@ -83,7 +122,7 @@ function createComponentStyles(compile) {
83
122
  import ${JSON.stringify(`./${name}`)};` };
84
123
  }
85
124
  const imports = page.map((i) => `
86
- import ${JSON.stringify(styleId(id, i))};`).join("");
125
+ import ${JSON.stringify(styleId(file, i))};`).join("");
87
126
  return { ...result, code: result.code + imports };
88
127
  };
89
128
  return {
@@ -116,14 +155,30 @@ import ${JSON.stringify(styleId(id, i))};`).join("");
116
155
  return STYLE_ID.test(id) || LITERAL_ID.test(id);
117
156
  },
118
157
  /**
119
- * A style request as the module id Vite should keep: the file's absolute path and the
120
- * query. Vite invalidates a module when the file its id names changes, so a root-relative id
121
- * (`/src/card.tsx?fx-style…`, which is how a request arrives before the component's imports
122
- * were analysed) was never invalidated, and an edited block kept its old CSS until restart.
158
+ * A style request as the module id Vite keeps: its owner's absolute path, then the suffix.
159
+ * One id per block however it was asked for (`/src/card.tsx.fx-0.css` from a page, the
160
+ * absolute path from the component), or the reload after an edit misses the copy in use.
161
+ * A css`` value imported from another module names that module relatively, as written.
162
+ */
163
+ async resolveId(id, importer, ctx) {
164
+ const at = id.search(SUFFIX);
165
+ const owner = id.slice(0, at);
166
+ if (!owner.startsWith(".")) return fileOf(owner) + id.slice(at);
167
+ const resolved = importer ? await ctx.resolve?.(owner, importer) : null;
168
+ return resolved ? resolved.id.split("?")[0] + id.slice(at) : null;
169
+ },
170
+ /**
171
+ * The style modules of a changed file, for the update Vite sends. Their ids do not name the
172
+ * file (they end in `.css`), so Vite would not find them itself.
123
173
  */
124
- resolveId(id) {
125
- const at = id.indexOf("?");
126
- return fileOf(id.slice(0, at)) + id.slice(at);
174
+ hotModules(file, graph) {
175
+ const entry = cache.get(file);
176
+ if (!entry) return [];
177
+ const paths = [
178
+ ...entry.css.map((_, i) => styleId(file, i)),
179
+ ...[...entry.literals.keys()].map((name) => styleIds.literal(file, name).replace(/\?inline$/, ""))
180
+ ];
181
+ return paths.flatMap((path) => [...graph.getModulesByFile(path) ?? []]);
127
182
  },
128
183
  compile: run,
129
184
  /**
@@ -134,7 +189,7 @@ import ${JSON.stringify(styleId(id, i))};`).join("");
134
189
  const match = STYLE_ID.exec(id);
135
190
  const literal = LITERAL_ID.exec(id);
136
191
  if (!match && !literal || !api) return null;
137
- const file = id.slice(0, id.indexOf("?"));
192
+ const file = ownerOf(id);
138
193
  let source;
139
194
  try {
140
195
  source = readFileSync(fileOf(file), "utf8");
@@ -146,10 +201,10 @@ import ${JSON.stringify(styleId(id, i))};`).join("");
146
201
  if (literal) {
147
202
  const css = entry?.literals.get(literal[1]);
148
203
  if (css === void 0) throw new Error(`[fluixi] ${literal[1]} in ${file} is not a css\`\` value, so it cannot be a shadow root's styles.`);
149
- return { code: css, map: null };
204
+ return { code: css, map: null, moduleType: "css" };
150
205
  }
151
206
  const index = Number(match[1]);
152
- return { code: entry?.css[index] ?? "", map: entry?.maps[index] ?? null };
207
+ return { code: entry?.css[index] ?? "", map: entry?.maps[index] ?? null, moduleType: "css" };
153
208
  }
154
209
  };
155
210
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fluixi/compiler",
3
- "version": "1.0.0-alpha.94",
3
+ "version": "1.0.0-alpha.96",
4
4
  "license": "MIT",
5
5
  "author": "Ibrahima Touré",
6
6
  "repository": {
@@ -108,9 +108,9 @@
108
108
  "cross-env": "^7.0.3",
109
109
  "inquirer": "^14.0.2",
110
110
  "jsdom": "^25.0.0",
111
- "vitest": "^1.6.1",
112
- "@fluixi/dom": "1.0.0-alpha.94",
113
- "@fluixi/reactive": "1.0.0-alpha.94"
111
+ "vitest": "^5.0.3",
112
+ "@fluixi/dom": "1.0.0-alpha.96",
113
+ "@fluixi/reactive": "1.0.0-alpha.96"
114
114
  },
115
115
  "peerDependencies": {
116
116
  "@babel/core": "^7.28.5",