@typestyles/build-runner 0.0.0-unstable.0df89fa2fae4 → 0.0.0-unstable.0f8b0f95f8de

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.
package/README.md CHANGED
@@ -164,7 +164,7 @@ Parses a file for typestyles registration calls. Returns `{ keys, prefixes }` fo
164
164
  import { extractNamespaces } from '@typestyles/build-runner';
165
165
 
166
166
  const { prefixes } = extractNamespaces(source);
167
- // styles.component('button', ...) → prefixes includes '.button-'
167
+ // recipe({ name: 'button', ... }) → prefixes includes '.button-'
168
168
  ```
169
169
 
170
170
  ### `reportDuplicateNamespaces(map, fileId, prefixes, reporter)`
package/dist/index.cjs CHANGED
@@ -21,6 +21,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
21
21
  var index_exports = {};
22
22
  __export(index_exports, {
23
23
  DEFAULT_EXTRACT_MODULE_CANDIDATES: () => DEFAULT_EXTRACT_MODULE_CANDIDATES,
24
+ DEFAULT_REGISTERED_COMPONENTS_MODULE_BASES: () => DEFAULT_REGISTERED_COMPONENTS_MODULE_BASES,
24
25
  TYPESTYLES_IMPORT_RE: () => TYPESTYLES_IMPORT_RE,
25
26
  VerifyTypestylesBuildError: () => VerifyTypestylesBuildError,
26
27
  buildManifestV2: () => buildManifestV2,
@@ -28,6 +29,7 @@ __export(index_exports, {
28
29
  createModuleLoader: () => createModuleLoader,
29
30
  discoverDefaultExtractModules: () => discoverDefaultExtractModules,
30
31
  discoverNextAppRoutes: () => discoverNextAppRoutes,
32
+ discoverRegisteredComponentsModule: () => discoverRegisteredComponentsModule,
31
33
  extractNamespaces: () => extractNamespaces,
32
34
  getRouteCss: () => getRouteCss,
33
35
  isManifestV2: () => isManifestV2,
@@ -60,6 +62,12 @@ var DISCOVERY_EXTENSIONS = [".ts", ".tsx", ".js", ".mjs"];
60
62
  var DEFAULT_EXTRACT_MODULE_CANDIDATES = DEFAULT_EXTRACT_MODULE_BASES.map(
61
63
  (base) => `${base}.ts`
62
64
  );
65
+ var DEFAULT_REGISTERED_COMPONENTS_MODULE_BASES = [
66
+ "src/themeable-refs",
67
+ "src/typestyles/themeable-refs",
68
+ "src/typestyles-registry",
69
+ "styles/themeable-refs"
70
+ ];
63
71
  function discoverDefaultExtractModules(root) {
64
72
  const absRoot = (0, import_node_path.resolve)(root);
65
73
  for (const base of DEFAULT_EXTRACT_MODULE_BASES) {
@@ -72,15 +80,187 @@ function discoverDefaultExtractModules(root) {
72
80
  }
73
81
  return [];
74
82
  }
83
+ function discoverRegisteredComponentsModule(root) {
84
+ const absRoot = (0, import_node_path.resolve)(root);
85
+ for (const base of DEFAULT_REGISTERED_COMPONENTS_MODULE_BASES) {
86
+ for (const ext of DISCOVERY_EXTENSIONS) {
87
+ const rel = `${base}${ext}`;
88
+ if ((0, import_node_fs.existsSync)((0, import_node_path.resolve)(absRoot, rel))) {
89
+ return rel.replace(/\\/g, "/");
90
+ }
91
+ }
92
+ }
93
+ return void 0;
94
+ }
75
95
 
76
96
  // src/namespaces.ts
77
- var STYLES_COMPONENT_RE = /styles\.component\(\s*['"]([^'"]+)['"]/g;
78
- var STYLES_CLASS_RE = /styles\.class\(\s*['"]([^'"]+)['"]/g;
97
+ var STYLES_COMPONENT_CALL_RE = /(?:styles\.component|(?<![\w.])recipe)\s*\(/g;
98
+ var STYLES_CLASS_RE = /(?:styles\.class|(?<![\w.])style)\(\s*['"]([^'"]+)['"]/g;
79
99
  var TOKENS_CREATE_RE = /tokens\.create\(\s*['"]([^'"]+)['"]/g;
80
- var CREATE_THEME_RE = /(?:tokens\.)?createTheme\(\s*['"]([^'"]+)['"]/g;
100
+ var CREATE_THEME_CALL_RE = /(?:tokens\.)?createTheme\s*\(/g;
81
101
  var KEYFRAMES_CREATE_RE = /keyframes\.create\(\s*['"]([^'"]+)['"]/g;
82
- var GLOBAL_STYLE_RE = /global\.style\(\s*['"]([^'"]+)['"]/g;
102
+ var GLOBAL_STYLE_RE = /global\.(?:rule|style)\(\s*['"]([^'"]+)['"]/g;
83
103
  var GLOBAL_FONT_FACE_RE = /global\.fontFace\(\s*['"]([^'"]+)['"]/g;
104
+ var CREATE_THEME_ARG_SCAN = 4e3;
105
+ function codeSpanMask(code) {
106
+ const mask = new Uint8Array(code.length);
107
+ let i = 0;
108
+ const mark = (from, to) => {
109
+ const end = Math.min(to, code.length);
110
+ for (let j = from; j < end; j++) mask[j] = 1;
111
+ };
112
+ const skipString = (quote) => {
113
+ const start = i;
114
+ i += 1;
115
+ while (i < code.length) {
116
+ if (code[i] === "\\") {
117
+ i += 2;
118
+ continue;
119
+ }
120
+ if (code[i] === quote) {
121
+ i += 1;
122
+ break;
123
+ }
124
+ i += 1;
125
+ }
126
+ mark(start, i);
127
+ };
128
+ const scanExpression = () => {
129
+ let depth = 0;
130
+ while (i < code.length) {
131
+ const c = code[i];
132
+ const next = code[i + 1];
133
+ if (c === "/" && next === "/") {
134
+ const start = i;
135
+ i += 2;
136
+ while (i < code.length && code[i] !== "\n") i += 1;
137
+ mark(start, i);
138
+ continue;
139
+ }
140
+ if (c === "/" && next === "*") {
141
+ const start = i;
142
+ i += 2;
143
+ while (i < code.length && !(code[i] === "*" && code[i + 1] === "/")) i += 1;
144
+ if (i < code.length) i += 2;
145
+ mark(start, i);
146
+ continue;
147
+ }
148
+ if (c === '"' || c === "'") {
149
+ skipString(c);
150
+ continue;
151
+ }
152
+ if (c === "`") {
153
+ scanTemplate();
154
+ continue;
155
+ }
156
+ if (c === "{") {
157
+ depth += 1;
158
+ i += 1;
159
+ continue;
160
+ }
161
+ if (c === "}") {
162
+ i += 1;
163
+ if (depth === 0) return;
164
+ depth -= 1;
165
+ continue;
166
+ }
167
+ i += 1;
168
+ }
169
+ };
170
+ const scanTemplate = () => {
171
+ const open = i;
172
+ i += 1;
173
+ let staticFrom = open;
174
+ while (i < code.length) {
175
+ if (code[i] === "\\") {
176
+ i += 2;
177
+ continue;
178
+ }
179
+ if (code[i] === "`") {
180
+ i += 1;
181
+ mark(staticFrom, i);
182
+ return;
183
+ }
184
+ if (code[i] === "$" && code[i + 1] === "{") {
185
+ mark(staticFrom, i);
186
+ i += 2;
187
+ scanExpression();
188
+ staticFrom = i;
189
+ continue;
190
+ }
191
+ i += 1;
192
+ }
193
+ mark(staticFrom, i);
194
+ };
195
+ while (i < code.length) {
196
+ const c = code[i];
197
+ const next = code[i + 1];
198
+ if (c === "/" && next === "/") {
199
+ const start = i;
200
+ i += 2;
201
+ while (i < code.length && code[i] !== "\n") i += 1;
202
+ mark(start, i);
203
+ continue;
204
+ }
205
+ if (c === "/" && next === "*") {
206
+ const start = i;
207
+ i += 2;
208
+ while (i < code.length && !(code[i] === "*" && code[i + 1] === "/")) i += 1;
209
+ if (i < code.length) i += 2;
210
+ mark(start, i);
211
+ continue;
212
+ }
213
+ if (c === '"' || c === "'") {
214
+ skipString(c);
215
+ continue;
216
+ }
217
+ if (c === "`") {
218
+ scanTemplate();
219
+ continue;
220
+ }
221
+ i += 1;
222
+ }
223
+ return mask;
224
+ }
225
+ function isStaticNamespace(name) {
226
+ return !name.includes("$") && !name.includes("{") && !name.includes("}");
227
+ }
228
+ function extractRecipeNames(code, mask) {
229
+ const names = [];
230
+ for (const match of code.matchAll(STYLES_COMPONENT_CALL_RE)) {
231
+ const index = match.index ?? 0;
232
+ if (mask[index]) continue;
233
+ const start = index + match[0].length;
234
+ const args = code.slice(start, start + CREATE_THEME_ARG_SCAN);
235
+ const positional = args.match(/^\s*['"]([^'"]+)['"]/);
236
+ if (positional) {
237
+ if (isStaticNamespace(positional[1])) names.push(positional[1]);
238
+ continue;
239
+ }
240
+ if (!/^\s*\{/.test(args)) continue;
241
+ const named = args.match(/\bname\s*:\s*['"]([^'"]+)['"]/);
242
+ if (named && isStaticNamespace(named[1])) names.push(named[1]);
243
+ }
244
+ return names;
245
+ }
246
+ function extractCreateThemeNames(code, mask) {
247
+ const names = [];
248
+ for (const match of code.matchAll(CREATE_THEME_CALL_RE)) {
249
+ const index = match.index ?? 0;
250
+ if (mask[index]) continue;
251
+ const start = index + match[0].length;
252
+ const args = code.slice(start, start + CREATE_THEME_ARG_SCAN);
253
+ const positional = args.match(/^\s*['"]([^'"]+)['"]/);
254
+ if (positional) {
255
+ if (isStaticNamespace(positional[1])) names.push(positional[1]);
256
+ continue;
257
+ }
258
+ if (!/^\s*\{/.test(args)) continue;
259
+ const named = args.match(/\bname\s*:\s*['"]([^'"]+)['"]/);
260
+ if (named && isStaticNamespace(named[1])) names.push(named[1]);
261
+ }
262
+ return names;
263
+ }
84
264
  var OVERRIDE_HMR_EXPORT_NAMES = /* @__PURE__ */ new Set(["createDesignTheme", "overrideComponent"]);
85
265
  var TYPESTYLES_IMPORT_RE = /(?:from\s+|import\s+|require\s*\(\s*)['"]typestyles['"]/;
86
266
  function stripCommentsForHmrScan(code) {
@@ -113,7 +293,7 @@ function collectOverrideHmrCallTargets(code) {
113
293
  }
114
294
  function moduleNeedsOverrideHmr(code) {
115
295
  const scan = stripCommentsForHmrScan(code);
116
- if (/\bstyles\.override\s*\(/.test(scan)) return true;
296
+ if (/\b(?:styles\.)?override\s*\(/.test(scan)) return true;
117
297
  const { locals, namespaces } = collectOverrideHmrCallTargets(scan);
118
298
  for (const name of locals) {
119
299
  if (new RegExp(`\\b${name}\\s*\\(`).test(scan)) return true;
@@ -128,25 +308,32 @@ function moduleNeedsOverrideHmr(code) {
128
308
  function extractNamespaces(code) {
129
309
  const keys = [];
130
310
  const prefixes = [];
131
- for (const match of code.matchAll(STYLES_COMPONENT_RE)) {
132
- prefixes.push(`.${match[1]}-`);
311
+ const mask = codeSpanMask(code);
312
+ const inCode = (index) => index !== void 0 && mask[index] === 0;
313
+ for (const name of extractRecipeNames(code, mask)) {
314
+ prefixes.push(`.${name}-`);
133
315
  }
134
316
  for (const match of code.matchAll(STYLES_CLASS_RE)) {
317
+ if (!inCode(match.index) || !isStaticNamespace(match[1])) continue;
135
318
  prefixes.push(`.${match[1]}-`);
136
319
  }
137
320
  for (const match of code.matchAll(TOKENS_CREATE_RE)) {
321
+ if (!inCode(match.index) || !isStaticNamespace(match[1])) continue;
138
322
  keys.push(`tokens:${match[1]}`);
139
323
  }
140
- for (const match of code.matchAll(CREATE_THEME_RE)) {
141
- keys.push(`theme:${match[1]}`);
324
+ for (const themeName of extractCreateThemeNames(code, mask)) {
325
+ keys.push(`theme:${themeName}`);
142
326
  }
143
327
  for (const match of code.matchAll(KEYFRAMES_CREATE_RE)) {
328
+ if (!inCode(match.index) || !isStaticNamespace(match[1])) continue;
144
329
  keys.push(`keyframes:${match[1]}`);
145
330
  }
146
331
  for (const match of code.matchAll(GLOBAL_STYLE_RE)) {
332
+ if (!inCode(match.index)) continue;
147
333
  prefixes.push(match[1]);
148
334
  }
149
335
  for (const match of code.matchAll(GLOBAL_FONT_FACE_RE)) {
336
+ if (!inCode(match.index)) continue;
150
337
  prefixes.push(`font-face:${match[1]}`);
151
338
  }
152
339
  return { keys, prefixes };
@@ -167,10 +354,20 @@ function reportDuplicateNamespaces(moduleNamespaces, id, prefixes, reporter) {
167
354
 
168
355
  // src/resolve-extract.ts
169
356
  function resolveExtractModules(root, extract) {
357
+ let modules;
170
358
  if (extract?.modules !== void 0) {
171
- return extract.modules;
359
+ modules = [...extract.modules];
360
+ } else {
361
+ modules = discoverDefaultExtractModules(root);
362
+ }
363
+ let registeredModule = extract?.registeredComponentsModule;
364
+ if (!registeredModule && extract?.include === "allRegisteredComponents") {
365
+ registeredModule = discoverRegisteredComponentsModule(root);
366
+ }
367
+ if (registeredModule && !modules.includes(registeredModule)) {
368
+ modules.push(registeredModule);
172
369
  }
173
- return discoverDefaultExtractModules(root);
370
+ return modules;
174
371
  }
175
372
  function resolveExtractMode(explicitMode, resolvedModules) {
176
373
  return explicitMode ?? (resolvedModules.length > 0 ? "build" : "runtime");
@@ -468,10 +665,11 @@ async function traceTypestylesModules(root, entryFiles) {
468
665
  }
469
666
  return [...traced].sort();
470
667
  }
668
+ var moduleLoadNonce = 0;
471
669
  function createModuleLoader(root, modulePath) {
472
670
  const abs = (0, import_node_path4.resolve)(root, modulePath);
473
671
  const href = (0, import_node_url.pathToFileURL)(abs).href;
474
- return () => import(href);
672
+ return () => import(`${href}?typestyles-extract=${++moduleLoadNonce}`);
475
673
  }
476
674
 
477
675
  // src/route-css.ts
@@ -647,6 +845,7 @@ ${result.stderr || result.stdout || "unknown error"}`
647
845
  // Annotate the CommonJS export names for ESM import in node:
648
846
  0 && (module.exports = {
649
847
  DEFAULT_EXTRACT_MODULE_CANDIDATES,
848
+ DEFAULT_REGISTERED_COMPONENTS_MODULE_BASES,
650
849
  TYPESTYLES_IMPORT_RE,
651
850
  VerifyTypestylesBuildError,
652
851
  buildManifestV2,
@@ -654,6 +853,7 @@ ${result.stderr || result.stdout || "unknown error"}`
654
853
  createModuleLoader,
655
854
  discoverDefaultExtractModules,
656
855
  discoverNextAppRoutes,
856
+ discoverRegisteredComponentsModule,
657
857
  extractNamespaces,
658
858
  getRouteCss,
659
859
  isManifestV2,
package/dist/index.d.cts CHANGED
@@ -3,11 +3,22 @@
3
3
  * Shared by bundler integrations and `@typestyles/next/build`.
4
4
  */
5
5
  declare const DEFAULT_EXTRACT_MODULE_CANDIDATES: readonly string[];
6
+ /**
7
+ * Side-effect modules that import every recipe and export `getRegisteredComponentRefs(styles)`.
8
+ * Used when `extract.include` is `"allRegisteredComponents"`.
9
+ */
10
+ declare const DEFAULT_REGISTERED_COMPONENTS_MODULE_BASES: readonly ["src/themeable-refs", "src/typestyles/themeable-refs", "src/typestyles-registry", "styles/themeable-refs"];
6
11
  /**
7
12
  * Resolve the default extraction module when the user did not pass explicit `modules`.
8
13
  * Returns at most one path using `/` separators, relative to `root`.
9
14
  */
10
15
  declare function discoverDefaultExtractModules(root: string): string[];
16
+ /**
17
+ * Convention registry module for `extract.include: 'allRegisteredComponents'`.
18
+ * The file should import all recipe modules and
19
+ * export `getRegisteredComponentRefs(styles)` from your `createTypeStyles` entry.
20
+ */
21
+ declare function discoverRegisteredComponentsModule(root: string): string | undefined;
11
22
 
12
23
  declare const TYPESTYLES_IMPORT_RE: RegExp;
13
24
  /**
@@ -48,6 +59,19 @@ interface TypestylesExtractOptions {
48
59
  * Output CSS filename. Defaults to `typestyles.css`.
49
60
  */
50
61
  fileName?: string;
62
+ /**
63
+ * Additional module that re-exports {@link getRegisteredComponentRefs} (or an
64
+ * equivalent object of every themeable recipe handle) so extract bundles retain
65
+ * full design-system CSS without a hand-maintained registry object.
66
+ */
67
+ registeredComponentsModule?: string;
68
+ /**
69
+ * When `"allRegisteredComponents"`, appends a convention registry module if present
70
+ * ({@link discoverRegisteredComponentsModule}) or {@link registeredComponentsModule}
71
+ * when set. That file must side-effect-import every recipe and reference
72
+ * `getRegisteredComponentRefs(styles)` — the extract entry alone is not enough.
73
+ */
74
+ include?: 'allRegisteredComponents';
51
75
  }
52
76
  /**
53
77
  * Resolve extraction modules from explicit config or convention entry discovery.
@@ -143,7 +167,7 @@ declare function discoverNextAppRoutes(root: string, appDir?: string): NextAppRo
143
167
  * Paths are relative to `root` with `/` separators.
144
168
  */
145
169
  declare function traceTypestylesModules(root: string, entryFiles: string[]): Promise<string[]>;
146
- /** Load a traced module for style extraction. */
170
+ /** Load a traced module for style extraction (cache-busted so re-runs re-register styles). */
147
171
  declare function createModuleLoader(root: string, modulePath: string): () => Promise<unknown>;
148
172
 
149
173
  interface CollectRouteCssOptions {
@@ -203,4 +227,4 @@ interface RunTypestylesBuildOptions {
203
227
  */
204
228
  declare function runTypestylesBuild({ root, modules, }: RunTypestylesBuildOptions): Promise<string>;
205
229
 
206
- export { type CollectRouteCssOptions, type CollectRouteCssResult, DEFAULT_EXTRACT_MODULE_CANDIDATES, type DuplicateNamespaceReporter, type GetRouteCssOptions, type NextAppRoute, type RunTypestylesBuildOptions, TYPESTYLES_IMPORT_RE, type TypestylesExtractManifest, type TypestylesExtractManifestV1, type TypestylesExtractManifestV2, type TypestylesExtractOptions, type TypestylesIntegrationMode, type TypestylesRouteCssEntry, VerifyTypestylesBuildError, type VerifyTypestylesBuildOptions, type VerifyTypestylesBuildResult, buildManifestV2, collectAndWriteRouteCss, createModuleLoader, discoverDefaultExtractModules, discoverNextAppRoutes, extractNamespaces, getRouteCss, isManifestV2, moduleNeedsOverrideHmr, normalizeRoutePath, pageRelPathToRoutePath, readCssFile, readTypestylesManifest, reportDuplicateNamespaces, resolveExtractMode, resolveExtractModules, runTypestylesBuild, traceTypestylesModules, verifyTypestylesBuild };
230
+ export { type CollectRouteCssOptions, type CollectRouteCssResult, DEFAULT_EXTRACT_MODULE_CANDIDATES, DEFAULT_REGISTERED_COMPONENTS_MODULE_BASES, type DuplicateNamespaceReporter, type GetRouteCssOptions, type NextAppRoute, type RunTypestylesBuildOptions, TYPESTYLES_IMPORT_RE, type TypestylesExtractManifest, type TypestylesExtractManifestV1, type TypestylesExtractManifestV2, type TypestylesExtractOptions, type TypestylesIntegrationMode, type TypestylesRouteCssEntry, VerifyTypestylesBuildError, type VerifyTypestylesBuildOptions, type VerifyTypestylesBuildResult, buildManifestV2, collectAndWriteRouteCss, createModuleLoader, discoverDefaultExtractModules, discoverNextAppRoutes, discoverRegisteredComponentsModule, extractNamespaces, getRouteCss, isManifestV2, moduleNeedsOverrideHmr, normalizeRoutePath, pageRelPathToRoutePath, readCssFile, readTypestylesManifest, reportDuplicateNamespaces, resolveExtractMode, resolveExtractModules, runTypestylesBuild, traceTypestylesModules, verifyTypestylesBuild };
package/dist/index.d.ts CHANGED
@@ -3,11 +3,22 @@
3
3
  * Shared by bundler integrations and `@typestyles/next/build`.
4
4
  */
5
5
  declare const DEFAULT_EXTRACT_MODULE_CANDIDATES: readonly string[];
6
+ /**
7
+ * Side-effect modules that import every recipe and export `getRegisteredComponentRefs(styles)`.
8
+ * Used when `extract.include` is `"allRegisteredComponents"`.
9
+ */
10
+ declare const DEFAULT_REGISTERED_COMPONENTS_MODULE_BASES: readonly ["src/themeable-refs", "src/typestyles/themeable-refs", "src/typestyles-registry", "styles/themeable-refs"];
6
11
  /**
7
12
  * Resolve the default extraction module when the user did not pass explicit `modules`.
8
13
  * Returns at most one path using `/` separators, relative to `root`.
9
14
  */
10
15
  declare function discoverDefaultExtractModules(root: string): string[];
16
+ /**
17
+ * Convention registry module for `extract.include: 'allRegisteredComponents'`.
18
+ * The file should import all recipe modules and
19
+ * export `getRegisteredComponentRefs(styles)` from your `createTypeStyles` entry.
20
+ */
21
+ declare function discoverRegisteredComponentsModule(root: string): string | undefined;
11
22
 
12
23
  declare const TYPESTYLES_IMPORT_RE: RegExp;
13
24
  /**
@@ -48,6 +59,19 @@ interface TypestylesExtractOptions {
48
59
  * Output CSS filename. Defaults to `typestyles.css`.
49
60
  */
50
61
  fileName?: string;
62
+ /**
63
+ * Additional module that re-exports {@link getRegisteredComponentRefs} (or an
64
+ * equivalent object of every themeable recipe handle) so extract bundles retain
65
+ * full design-system CSS without a hand-maintained registry object.
66
+ */
67
+ registeredComponentsModule?: string;
68
+ /**
69
+ * When `"allRegisteredComponents"`, appends a convention registry module if present
70
+ * ({@link discoverRegisteredComponentsModule}) or {@link registeredComponentsModule}
71
+ * when set. That file must side-effect-import every recipe and reference
72
+ * `getRegisteredComponentRefs(styles)` — the extract entry alone is not enough.
73
+ */
74
+ include?: 'allRegisteredComponents';
51
75
  }
52
76
  /**
53
77
  * Resolve extraction modules from explicit config or convention entry discovery.
@@ -143,7 +167,7 @@ declare function discoverNextAppRoutes(root: string, appDir?: string): NextAppRo
143
167
  * Paths are relative to `root` with `/` separators.
144
168
  */
145
169
  declare function traceTypestylesModules(root: string, entryFiles: string[]): Promise<string[]>;
146
- /** Load a traced module for style extraction. */
170
+ /** Load a traced module for style extraction (cache-busted so re-runs re-register styles). */
147
171
  declare function createModuleLoader(root: string, modulePath: string): () => Promise<unknown>;
148
172
 
149
173
  interface CollectRouteCssOptions {
@@ -203,4 +227,4 @@ interface RunTypestylesBuildOptions {
203
227
  */
204
228
  declare function runTypestylesBuild({ root, modules, }: RunTypestylesBuildOptions): Promise<string>;
205
229
 
206
- export { type CollectRouteCssOptions, type CollectRouteCssResult, DEFAULT_EXTRACT_MODULE_CANDIDATES, type DuplicateNamespaceReporter, type GetRouteCssOptions, type NextAppRoute, type RunTypestylesBuildOptions, TYPESTYLES_IMPORT_RE, type TypestylesExtractManifest, type TypestylesExtractManifestV1, type TypestylesExtractManifestV2, type TypestylesExtractOptions, type TypestylesIntegrationMode, type TypestylesRouteCssEntry, VerifyTypestylesBuildError, type VerifyTypestylesBuildOptions, type VerifyTypestylesBuildResult, buildManifestV2, collectAndWriteRouteCss, createModuleLoader, discoverDefaultExtractModules, discoverNextAppRoutes, extractNamespaces, getRouteCss, isManifestV2, moduleNeedsOverrideHmr, normalizeRoutePath, pageRelPathToRoutePath, readCssFile, readTypestylesManifest, reportDuplicateNamespaces, resolveExtractMode, resolveExtractModules, runTypestylesBuild, traceTypestylesModules, verifyTypestylesBuild };
230
+ export { type CollectRouteCssOptions, type CollectRouteCssResult, DEFAULT_EXTRACT_MODULE_CANDIDATES, DEFAULT_REGISTERED_COMPONENTS_MODULE_BASES, type DuplicateNamespaceReporter, type GetRouteCssOptions, type NextAppRoute, type RunTypestylesBuildOptions, TYPESTYLES_IMPORT_RE, type TypestylesExtractManifest, type TypestylesExtractManifestV1, type TypestylesExtractManifestV2, type TypestylesExtractOptions, type TypestylesIntegrationMode, type TypestylesRouteCssEntry, VerifyTypestylesBuildError, type VerifyTypestylesBuildOptions, type VerifyTypestylesBuildResult, buildManifestV2, collectAndWriteRouteCss, createModuleLoader, discoverDefaultExtractModules, discoverNextAppRoutes, discoverRegisteredComponentsModule, extractNamespaces, getRouteCss, isManifestV2, moduleNeedsOverrideHmr, normalizeRoutePath, pageRelPathToRoutePath, readCssFile, readTypestylesManifest, reportDuplicateNamespaces, resolveExtractMode, resolveExtractModules, runTypestylesBuild, traceTypestylesModules, verifyTypestylesBuild };
package/dist/index.js CHANGED
@@ -13,6 +13,12 @@ var DISCOVERY_EXTENSIONS = [".ts", ".tsx", ".js", ".mjs"];
13
13
  var DEFAULT_EXTRACT_MODULE_CANDIDATES = DEFAULT_EXTRACT_MODULE_BASES.map(
14
14
  (base) => `${base}.ts`
15
15
  );
16
+ var DEFAULT_REGISTERED_COMPONENTS_MODULE_BASES = [
17
+ "src/themeable-refs",
18
+ "src/typestyles/themeable-refs",
19
+ "src/typestyles-registry",
20
+ "styles/themeable-refs"
21
+ ];
16
22
  function discoverDefaultExtractModules(root) {
17
23
  const absRoot = resolvePath(root);
18
24
  for (const base of DEFAULT_EXTRACT_MODULE_BASES) {
@@ -25,15 +31,187 @@ function discoverDefaultExtractModules(root) {
25
31
  }
26
32
  return [];
27
33
  }
34
+ function discoverRegisteredComponentsModule(root) {
35
+ const absRoot = resolvePath(root);
36
+ for (const base of DEFAULT_REGISTERED_COMPONENTS_MODULE_BASES) {
37
+ for (const ext of DISCOVERY_EXTENSIONS) {
38
+ const rel = `${base}${ext}`;
39
+ if (existsSync(resolvePath(absRoot, rel))) {
40
+ return rel.replace(/\\/g, "/");
41
+ }
42
+ }
43
+ }
44
+ return void 0;
45
+ }
28
46
 
29
47
  // src/namespaces.ts
30
- var STYLES_COMPONENT_RE = /styles\.component\(\s*['"]([^'"]+)['"]/g;
31
- var STYLES_CLASS_RE = /styles\.class\(\s*['"]([^'"]+)['"]/g;
48
+ var STYLES_COMPONENT_CALL_RE = /(?:styles\.component|(?<![\w.])recipe)\s*\(/g;
49
+ var STYLES_CLASS_RE = /(?:styles\.class|(?<![\w.])style)\(\s*['"]([^'"]+)['"]/g;
32
50
  var TOKENS_CREATE_RE = /tokens\.create\(\s*['"]([^'"]+)['"]/g;
33
- var CREATE_THEME_RE = /(?:tokens\.)?createTheme\(\s*['"]([^'"]+)['"]/g;
51
+ var CREATE_THEME_CALL_RE = /(?:tokens\.)?createTheme\s*\(/g;
34
52
  var KEYFRAMES_CREATE_RE = /keyframes\.create\(\s*['"]([^'"]+)['"]/g;
35
- var GLOBAL_STYLE_RE = /global\.style\(\s*['"]([^'"]+)['"]/g;
53
+ var GLOBAL_STYLE_RE = /global\.(?:rule|style)\(\s*['"]([^'"]+)['"]/g;
36
54
  var GLOBAL_FONT_FACE_RE = /global\.fontFace\(\s*['"]([^'"]+)['"]/g;
55
+ var CREATE_THEME_ARG_SCAN = 4e3;
56
+ function codeSpanMask(code) {
57
+ const mask = new Uint8Array(code.length);
58
+ let i = 0;
59
+ const mark = (from, to) => {
60
+ const end = Math.min(to, code.length);
61
+ for (let j = from; j < end; j++) mask[j] = 1;
62
+ };
63
+ const skipString = (quote) => {
64
+ const start = i;
65
+ i += 1;
66
+ while (i < code.length) {
67
+ if (code[i] === "\\") {
68
+ i += 2;
69
+ continue;
70
+ }
71
+ if (code[i] === quote) {
72
+ i += 1;
73
+ break;
74
+ }
75
+ i += 1;
76
+ }
77
+ mark(start, i);
78
+ };
79
+ const scanExpression = () => {
80
+ let depth = 0;
81
+ while (i < code.length) {
82
+ const c = code[i];
83
+ const next = code[i + 1];
84
+ if (c === "/" && next === "/") {
85
+ const start = i;
86
+ i += 2;
87
+ while (i < code.length && code[i] !== "\n") i += 1;
88
+ mark(start, i);
89
+ continue;
90
+ }
91
+ if (c === "/" && next === "*") {
92
+ const start = i;
93
+ i += 2;
94
+ while (i < code.length && !(code[i] === "*" && code[i + 1] === "/")) i += 1;
95
+ if (i < code.length) i += 2;
96
+ mark(start, i);
97
+ continue;
98
+ }
99
+ if (c === '"' || c === "'") {
100
+ skipString(c);
101
+ continue;
102
+ }
103
+ if (c === "`") {
104
+ scanTemplate();
105
+ continue;
106
+ }
107
+ if (c === "{") {
108
+ depth += 1;
109
+ i += 1;
110
+ continue;
111
+ }
112
+ if (c === "}") {
113
+ i += 1;
114
+ if (depth === 0) return;
115
+ depth -= 1;
116
+ continue;
117
+ }
118
+ i += 1;
119
+ }
120
+ };
121
+ const scanTemplate = () => {
122
+ const open = i;
123
+ i += 1;
124
+ let staticFrom = open;
125
+ while (i < code.length) {
126
+ if (code[i] === "\\") {
127
+ i += 2;
128
+ continue;
129
+ }
130
+ if (code[i] === "`") {
131
+ i += 1;
132
+ mark(staticFrom, i);
133
+ return;
134
+ }
135
+ if (code[i] === "$" && code[i + 1] === "{") {
136
+ mark(staticFrom, i);
137
+ i += 2;
138
+ scanExpression();
139
+ staticFrom = i;
140
+ continue;
141
+ }
142
+ i += 1;
143
+ }
144
+ mark(staticFrom, i);
145
+ };
146
+ while (i < code.length) {
147
+ const c = code[i];
148
+ const next = code[i + 1];
149
+ if (c === "/" && next === "/") {
150
+ const start = i;
151
+ i += 2;
152
+ while (i < code.length && code[i] !== "\n") i += 1;
153
+ mark(start, i);
154
+ continue;
155
+ }
156
+ if (c === "/" && next === "*") {
157
+ const start = i;
158
+ i += 2;
159
+ while (i < code.length && !(code[i] === "*" && code[i + 1] === "/")) i += 1;
160
+ if (i < code.length) i += 2;
161
+ mark(start, i);
162
+ continue;
163
+ }
164
+ if (c === '"' || c === "'") {
165
+ skipString(c);
166
+ continue;
167
+ }
168
+ if (c === "`") {
169
+ scanTemplate();
170
+ continue;
171
+ }
172
+ i += 1;
173
+ }
174
+ return mask;
175
+ }
176
+ function isStaticNamespace(name) {
177
+ return !name.includes("$") && !name.includes("{") && !name.includes("}");
178
+ }
179
+ function extractRecipeNames(code, mask) {
180
+ const names = [];
181
+ for (const match of code.matchAll(STYLES_COMPONENT_CALL_RE)) {
182
+ const index = match.index ?? 0;
183
+ if (mask[index]) continue;
184
+ const start = index + match[0].length;
185
+ const args = code.slice(start, start + CREATE_THEME_ARG_SCAN);
186
+ const positional = args.match(/^\s*['"]([^'"]+)['"]/);
187
+ if (positional) {
188
+ if (isStaticNamespace(positional[1])) names.push(positional[1]);
189
+ continue;
190
+ }
191
+ if (!/^\s*\{/.test(args)) continue;
192
+ const named = args.match(/\bname\s*:\s*['"]([^'"]+)['"]/);
193
+ if (named && isStaticNamespace(named[1])) names.push(named[1]);
194
+ }
195
+ return names;
196
+ }
197
+ function extractCreateThemeNames(code, mask) {
198
+ const names = [];
199
+ for (const match of code.matchAll(CREATE_THEME_CALL_RE)) {
200
+ const index = match.index ?? 0;
201
+ if (mask[index]) continue;
202
+ const start = index + match[0].length;
203
+ const args = code.slice(start, start + CREATE_THEME_ARG_SCAN);
204
+ const positional = args.match(/^\s*['"]([^'"]+)['"]/);
205
+ if (positional) {
206
+ if (isStaticNamespace(positional[1])) names.push(positional[1]);
207
+ continue;
208
+ }
209
+ if (!/^\s*\{/.test(args)) continue;
210
+ const named = args.match(/\bname\s*:\s*['"]([^'"]+)['"]/);
211
+ if (named && isStaticNamespace(named[1])) names.push(named[1]);
212
+ }
213
+ return names;
214
+ }
37
215
  var OVERRIDE_HMR_EXPORT_NAMES = /* @__PURE__ */ new Set(["createDesignTheme", "overrideComponent"]);
38
216
  var TYPESTYLES_IMPORT_RE = /(?:from\s+|import\s+|require\s*\(\s*)['"]typestyles['"]/;
39
217
  function stripCommentsForHmrScan(code) {
@@ -66,7 +244,7 @@ function collectOverrideHmrCallTargets(code) {
66
244
  }
67
245
  function moduleNeedsOverrideHmr(code) {
68
246
  const scan = stripCommentsForHmrScan(code);
69
- if (/\bstyles\.override\s*\(/.test(scan)) return true;
247
+ if (/\b(?:styles\.)?override\s*\(/.test(scan)) return true;
70
248
  const { locals, namespaces } = collectOverrideHmrCallTargets(scan);
71
249
  for (const name of locals) {
72
250
  if (new RegExp(`\\b${name}\\s*\\(`).test(scan)) return true;
@@ -81,25 +259,32 @@ function moduleNeedsOverrideHmr(code) {
81
259
  function extractNamespaces(code) {
82
260
  const keys = [];
83
261
  const prefixes = [];
84
- for (const match of code.matchAll(STYLES_COMPONENT_RE)) {
85
- prefixes.push(`.${match[1]}-`);
262
+ const mask = codeSpanMask(code);
263
+ const inCode = (index) => index !== void 0 && mask[index] === 0;
264
+ for (const name of extractRecipeNames(code, mask)) {
265
+ prefixes.push(`.${name}-`);
86
266
  }
87
267
  for (const match of code.matchAll(STYLES_CLASS_RE)) {
268
+ if (!inCode(match.index) || !isStaticNamespace(match[1])) continue;
88
269
  prefixes.push(`.${match[1]}-`);
89
270
  }
90
271
  for (const match of code.matchAll(TOKENS_CREATE_RE)) {
272
+ if (!inCode(match.index) || !isStaticNamespace(match[1])) continue;
91
273
  keys.push(`tokens:${match[1]}`);
92
274
  }
93
- for (const match of code.matchAll(CREATE_THEME_RE)) {
94
- keys.push(`theme:${match[1]}`);
275
+ for (const themeName of extractCreateThemeNames(code, mask)) {
276
+ keys.push(`theme:${themeName}`);
95
277
  }
96
278
  for (const match of code.matchAll(KEYFRAMES_CREATE_RE)) {
279
+ if (!inCode(match.index) || !isStaticNamespace(match[1])) continue;
97
280
  keys.push(`keyframes:${match[1]}`);
98
281
  }
99
282
  for (const match of code.matchAll(GLOBAL_STYLE_RE)) {
283
+ if (!inCode(match.index)) continue;
100
284
  prefixes.push(match[1]);
101
285
  }
102
286
  for (const match of code.matchAll(GLOBAL_FONT_FACE_RE)) {
287
+ if (!inCode(match.index)) continue;
103
288
  prefixes.push(`font-face:${match[1]}`);
104
289
  }
105
290
  return { keys, prefixes };
@@ -120,10 +305,20 @@ function reportDuplicateNamespaces(moduleNamespaces, id, prefixes, reporter) {
120
305
 
121
306
  // src/resolve-extract.ts
122
307
  function resolveExtractModules(root, extract) {
308
+ let modules;
123
309
  if (extract?.modules !== void 0) {
124
- return extract.modules;
310
+ modules = [...extract.modules];
311
+ } else {
312
+ modules = discoverDefaultExtractModules(root);
313
+ }
314
+ let registeredModule = extract?.registeredComponentsModule;
315
+ if (!registeredModule && extract?.include === "allRegisteredComponents") {
316
+ registeredModule = discoverRegisteredComponentsModule(root);
317
+ }
318
+ if (registeredModule && !modules.includes(registeredModule)) {
319
+ modules.push(registeredModule);
125
320
  }
126
- return discoverDefaultExtractModules(root);
321
+ return modules;
127
322
  }
128
323
  function resolveExtractMode(explicitMode, resolvedModules) {
129
324
  return explicitMode ?? (resolvedModules.length > 0 ? "build" : "runtime");
@@ -421,10 +616,11 @@ async function traceTypestylesModules(root, entryFiles) {
421
616
  }
422
617
  return [...traced].sort();
423
618
  }
619
+ var moduleLoadNonce = 0;
424
620
  function createModuleLoader(root, modulePath) {
425
621
  const abs = resolve3(root, modulePath);
426
622
  const href = pathToFileURL(abs).href;
427
- return () => import(href);
623
+ return () => import(`${href}?typestyles-extract=${++moduleLoadNonce}`);
428
624
  }
429
625
 
430
626
  // src/route-css.ts
@@ -599,6 +795,7 @@ ${result.stderr || result.stdout || "unknown error"}`
599
795
  }
600
796
  export {
601
797
  DEFAULT_EXTRACT_MODULE_CANDIDATES,
798
+ DEFAULT_REGISTERED_COMPONENTS_MODULE_BASES,
602
799
  TYPESTYLES_IMPORT_RE,
603
800
  VerifyTypestylesBuildError,
604
801
  buildManifestV2,
@@ -606,6 +803,7 @@ export {
606
803
  createModuleLoader,
607
804
  discoverDefaultExtractModules,
608
805
  discoverNextAppRoutes,
806
+ discoverRegisteredComponentsModule,
609
807
  extractNamespaces,
610
808
  getRouteCss,
611
809
  isManifestV2,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@typestyles/build-runner",
3
- "version": "0.0.0-unstable.0df89fa2fae4",
3
+ "version": "0.0.0-unstable.0f8b0f95f8de",
4
4
  "description": "Shared module execution utilities for typestyles build integrations",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -29,7 +29,7 @@
29
29
  "eslint": "^9.39.2",
30
30
  "tsup": "^8.0.0",
31
31
  "typescript": "^5.4.0",
32
- "typestyles": "0.0.0-unstable.0df89fa2fae4",
32
+ "typestyles": "0.0.0-unstable.0f8b0f95f8de",
33
33
  "vitest": "^3.0.0"
34
34
  },
35
35
  "license": "Apache-2.0",