poveste 0.2.1 → 0.3.1

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 (38) hide show
  1. package/dist/node/build.js +0 -3
  2. package/dist/node/builtin-plugins/tailwind-tokens.d.ts +6 -1
  3. package/dist/node/builtin-plugins/tailwind-tokens.d.ts.map +1 -1
  4. package/dist/node/builtin-plugins/tailwind-tokens.js +169 -33
  5. package/dist/node/builtin-plugins/vanilla-support/MountStory.d.ts +3 -3
  6. package/dist/node/builtin-plugins/vanilla-support/RenderStory.d.ts +5 -5
  7. package/dist/node/collect/index.d.ts.map +1 -1
  8. package/dist/node/collect/index.js +1 -3
  9. package/dist/node/config.d.ts +2 -18
  10. package/dist/node/config.d.ts.map +1 -1
  11. package/dist/node/config.js +3 -0
  12. package/dist/node/dom/env.d.ts.map +1 -1
  13. package/dist/node/dom/env.js +10 -6
  14. package/dist/node/index.d.ts +0 -7
  15. package/dist/node/index.d.ts.map +1 -1
  16. package/dist/node/markdown.d.ts.map +1 -1
  17. package/dist/node/markdown.js +21 -3
  18. package/dist/node/stories.js +1 -1
  19. package/dist/node/style-isolation/entry-css-merger.d.ts.map +1 -1
  20. package/dist/node/style-isolation/entry-css-merger.js +8 -7
  21. package/dist/node/style-isolation/transforms.js +32 -8
  22. package/dist/node/vite.js +1 -1
  23. package/package.json +10 -12
  24. package/src/node/__tests__/dom-env.spec.ts +19 -1
  25. package/src/node/build.ts +2 -6
  26. package/src/node/builtin-plugins/tailwind-tokens.ts +190 -34
  27. package/src/node/collect/index.ts +1 -3
  28. package/src/node/config.ts +3 -0
  29. package/src/node/dom/env.ts +10 -6
  30. package/src/node/index.ts +0 -8
  31. package/src/node/markdown.ts +25 -3
  32. package/src/node/stories.ts +1 -1
  33. package/src/node/style-isolation/__tests__/entry-css-merger.spec.ts +37 -18
  34. package/src/node/style-isolation/__tests__/transforms.spec.ts +46 -8
  35. package/src/node/style-isolation/entry-css-merger.ts +10 -9
  36. package/src/node/style-isolation/transforms.ts +36 -7
  37. package/src/node/vite.ts +4 -4
  38. package/tsconfig.json +1 -1
@@ -241,6 +241,3 @@ async function writeFile(fileName, content, ctx) {
241
241
  function generateScriptLinks(prefetchScripts, rel, ctx) {
242
242
  return prefetchScripts.map(s => `<link rel="${rel}" href="${ctx.resolvedViteConfig.base}${s}" as="script" crossOrigin="anonymous">`).join('');
243
243
  }
244
- function generateStyleLinks(styleFiles, rel, ctx) {
245
- return styleFiles.map(s => `<link rel="${rel}" href="${ctx.resolvedViteConfig.base}${s}" as="style">`).join('');
246
- }
@@ -1,6 +1,11 @@
1
1
  import type { Plugin } from '@poveste/shared';
2
2
  export interface TailwindTokensOptions {
3
- configFile?: string;
3
+ /**
4
+ * Path to the CSS entrypoint that imports Tailwind and declares `@theme`.
5
+ * Tailwind v4 is CSS-first, so the design tokens are read from CSS rather
6
+ * than from a JS config. Auto-detected when omitted.
7
+ */
8
+ cssFile?: string;
4
9
  }
5
10
  export declare function tailwindTokens(options?: TailwindTokensOptions): Plugin;
6
11
  //# sourceMappingURL=tailwind-tokens.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"tailwind-tokens.d.ts","sourceRoot":"","sources":["../../../src/node/builtin-plugins/tailwind-tokens.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAiB,MAAM,iBAAiB,CAAA;AAI5D,MAAM,WAAW,qBAAqB;IACpC,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB;AAED,wBAAgB,cAAc,CAAC,OAAO,GAAE,qBAA0B,GAAG,MAAM,CA2E1E"}
1
+ {"version":3,"file":"tailwind-tokens.d.ts","sourceRoot":"","sources":["../../../src/node/builtin-plugins/tailwind-tokens.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAiB,MAAM,iBAAiB,CAAA;AAI5D,MAAM,WAAW,qBAAqB;IACpC;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;AAqBD,wBAAgB,cAAc,CAAC,OAAO,GAAE,qBAA0B,GAAG,MAAM,CAgE1E"}
@@ -1,27 +1,34 @@
1
1
  import { findUp } from '../util/find-up.js';
2
2
  import { getInjectedImport } from '../util/vendors.js';
3
+ const CSS_ENTRY_CANDIDATES = [
4
+ 'src/style.css',
5
+ 'src/styles.css',
6
+ 'src/main.css',
7
+ 'src/index.css',
8
+ 'src/app.css',
9
+ 'src/assets/main.css',
10
+ 'src/assets/style.css',
11
+ 'src/assets/css/main.css',
12
+ // Nuxt conventions
13
+ 'app/assets/css/main.css',
14
+ 'assets/css/main.css',
15
+ // Next.js conventions
16
+ 'styles/globals.css',
17
+ 'app/globals.css',
18
+ 'style.css',
19
+ 'styles.css',
20
+ ];
3
21
  export function tailwindTokens(options = {}) {
4
- const tailwindConfigFile = options.configFile ?? findUp(process.cwd(), [
5
- 'tailwind.config.js',
6
- 'tailwind.config.cjs',
7
- 'tailwind.config.mjs',
8
- 'tailwind.config.ts',
9
- 'tailwind-config.js',
10
- 'tailwind-config.cjs',
11
- 'tailwind-config.mjs',
12
- 'tailwind-config.ts',
13
- ]);
22
+ const tailwindCssFile = options.cssFile ?? findUp(process.cwd(), CSS_ENTRY_CANDIDATES);
14
23
  async function generate(api) {
15
24
  try {
16
25
  await api.fs.ensureDir(api.pluginTempDir);
17
26
  await api.fs.emptyDir(api.pluginTempDir);
18
27
  api.moduleLoader.clearCache();
19
28
  await api.fs.writeFile(api.path.resolve(api.pluginTempDir, 'style.css'), css);
20
- const tailwindConfig = await api.moduleLoader.loadModule(tailwindConfigFile);
21
- const { default: resolveConfig } = await import('tailwindcss/resolveConfig.js');
22
- const resolvedTailwindConfig = resolveConfig(tailwindConfig.default ?? tailwindConfig);
29
+ const theme = await loadTailwindTheme(api, tailwindCssFile);
23
30
  const storyFile = api.path.resolve(api.pluginTempDir, 'Tailwind.story.js');
24
- await api.fs.writeFile(storyFile, storyTemplate(resolvedTailwindConfig));
31
+ await api.fs.writeFile(storyFile, storyTemplate({ theme }));
25
32
  api.addStoryFile(storyFile);
26
33
  }
27
34
  catch (e) {
@@ -31,7 +38,7 @@ export function tailwindTokens(options = {}) {
31
38
  return {
32
39
  name: 'builtin:tailwind-tokens',
33
40
  config(config) {
34
- if (tailwindConfigFile) {
41
+ if (tailwindCssFile) {
35
42
  // Add 'design-system' group
36
43
  if (!config.tree) {
37
44
  config.tree = {};
@@ -55,8 +62,8 @@ export function tailwindTokens(options = {}) {
55
62
  }
56
63
  },
57
64
  onDev(api, onCleanup) {
58
- if (tailwindConfigFile) {
59
- const watcher = api.watcher.watch(tailwindConfigFile)
65
+ if (tailwindCssFile) {
66
+ const watcher = api.watcher.watch(tailwindCssFile)
60
67
  .on('change', () => generate(api))
61
68
  .on('add', () => generate(api));
62
69
  onCleanup(() => {
@@ -65,12 +72,141 @@ export function tailwindTokens(options = {}) {
65
72
  }
66
73
  },
67
74
  async onBuild(api) {
68
- if (tailwindConfigFile) {
75
+ if (tailwindCssFile) {
69
76
  await generate(api);
70
77
  }
71
78
  },
72
79
  };
73
80
  }
81
+ /**
82
+ * Tailwind v4 keeps its theme as flat CSS custom properties rather than a
83
+ * resolved JS config (`resolveConfig` is gone). Load the design system from the
84
+ * project's CSS entrypoint and reshape its variables into the grouped structure
85
+ * the story template renders.
86
+ */
87
+ /**
88
+ * Resolve a stylesheet referenced from CSS. A bare package specifier resolves
89
+ * to the JS entry, so its `style` field is used instead — that is how
90
+ * `@import 'tailwindcss'` reaches `tailwindcss/index.css`.
91
+ */
92
+ async function resolveStylesheet(api, id, importBase) {
93
+ const { createRequire } = await import('node:module');
94
+ const require = createRequire(`${importBase}/`);
95
+ if (id.startsWith('.')) {
96
+ return api.path.resolve(importBase, id);
97
+ }
98
+ if (id.endsWith('.css')) {
99
+ return require.resolve(id);
100
+ }
101
+ const packageJsonPath = require.resolve(`${id}/package.json`);
102
+ const packageJson = JSON.parse(await api.fs.readFile(packageJsonPath, 'utf8'));
103
+ return api.path.resolve(api.path.dirname(packageJsonPath), packageJson.style ?? 'index.css');
104
+ }
105
+ async function loadTailwindTheme(api, cssFile) {
106
+ const { __unstable__loadDesignSystem } = await import('tailwindcss');
107
+ const base = api.path.dirname(cssFile);
108
+ const designSystem = await __unstable__loadDesignSystem(await api.fs.readFile(cssFile, 'utf8'), {
109
+ base,
110
+ loadStylesheet: async (id, importBase) => {
111
+ const resolved = await resolveStylesheet(api, id, importBase);
112
+ return {
113
+ path: resolved,
114
+ base: api.path.dirname(resolved),
115
+ content: await api.fs.readFile(resolved, 'utf8'),
116
+ };
117
+ },
118
+ });
119
+ const vars = new Map([...designSystem.theme.entries()].map(([key, entry]) => [key, entry.value]));
120
+ /** All values in a `--namespace-*` group, keyed by their remainder. */
121
+ function group(namespace, exclude) {
122
+ const out = {};
123
+ const prefix = `${namespace}-`;
124
+ for (const [key, value] of vars) {
125
+ if (!key.startsWith(prefix))
126
+ continue;
127
+ if (exclude?.test(key))
128
+ continue;
129
+ out[key.slice(prefix.length)] = value;
130
+ }
131
+ return out;
132
+ }
133
+ /** Colours are rendered as shade sets: `red-500` -> `{ red: { 500: … } }`. */
134
+ function colors() {
135
+ const out = {};
136
+ for (const [key, value] of Object.entries(group('--color'))) {
137
+ const match = key.match(/^(.*)-(\d+)$/);
138
+ if (match) {
139
+ out[match[1]] ??= {};
140
+ out[match[1]][match[2]] = value;
141
+ }
142
+ else {
143
+ out[key] = value;
144
+ }
145
+ }
146
+ return out;
147
+ }
148
+ // v4 generates the spacing scale on demand from a single `--spacing` base,
149
+ // so the conventional steps are reconstructed here for display.
150
+ const SPACING_STEPS = [0, 0.5, 1, 1.5, 2, 2.5, 3, 3.5, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60, 64, 72, 80, 96];
151
+ function spacing() {
152
+ const unit = vars.get('--spacing') ?? '0.25rem';
153
+ // Multiply out rather than emitting `calc(0.25rem * 4)`, so the story shows
154
+ // the resolved length the way the v3 resolved config did.
155
+ const [, rawAmount, cssUnit] = unit.trim().match(/^([\d.]+)([a-z%]*)$/i) ?? [];
156
+ const amount = Number(rawAmount);
157
+ const out = {};
158
+ for (const step of SPACING_STEPS) {
159
+ if (step === 0) {
160
+ out['0'] = '0px';
161
+ }
162
+ else {
163
+ out[String(step)] = Number.isFinite(amount)
164
+ ? `${Number((amount * step).toFixed(4))}${cssUnit}`
165
+ : `calc(${unit} * ${step})`;
166
+ }
167
+ }
168
+ return out;
169
+ }
170
+ // Fractions and keywords have no theme variables in v4 — they are static
171
+ // utilities — but they belong in the sizing scales the story lists.
172
+ const SIZING_EXTRAS = {
173
+ 'auto': 'auto',
174
+ 'full': '100%',
175
+ 'min': 'min-content',
176
+ 'max': 'max-content',
177
+ 'fit': 'fit-content',
178
+ 'px': '1px',
179
+ '1/2': '50%',
180
+ '1/3': '33.333333%',
181
+ '2/3': '66.666667%',
182
+ '1/4': '25%',
183
+ '3/4': '75%',
184
+ '1/5': '20%',
185
+ '2/5': '40%',
186
+ '3/5': '60%',
187
+ '4/5': '80%',
188
+ };
189
+ const palette = colors();
190
+ const scale = spacing();
191
+ return {
192
+ backgroundColor: palette,
193
+ textColor: palette,
194
+ borderColor: palette,
195
+ padding: scale,
196
+ margin: scale,
197
+ width: { ...scale, ...SIZING_EXTRAS, screen: '100vw' },
198
+ height: { ...scale, ...SIZING_EXTRAS, screen: '100vh' },
199
+ fontSize: group('--text', /--line-height$|--letter-spacing$|--font-weight$/),
200
+ fontWeight: group('--font-weight'),
201
+ fontFamily: group('--font', /^--font-weight-/),
202
+ letterSpacing: group('--tracking'),
203
+ lineHeight: group('--leading'),
204
+ dropShadow: group('--drop-shadow'),
205
+ borderRadius: group('--radius'),
206
+ // v4 has no border-width namespace; these are the built-in static utilities.
207
+ borderWidth: { DEFAULT: '1px', 0: '0px', 2: '2px', 4: '4px', 8: '8px' },
208
+ };
209
+ }
74
210
  function storyTemplate(tailwindConfig) {
75
211
  return `
76
212
  import 'poveste-style'
@@ -122,7 +258,7 @@ export default {
122
258
  onMount: (api) => mountApp(api, () => Object.entries(config.theme.backgroundColor).map(([key, shades]) => h(HstColorShades, {
123
259
  key,
124
260
  shades: typeof shades === 'object' ? shades : { DEFAULT: shades },
125
- getName: shade => (config.prefix ?? '') + (shade === 'DEFAULT' ? \`bg-\${key}\` : \`bg-\${key}-\${shade}\`),
261
+ getName: shade => '' + (shade === 'DEFAULT' ? \`bg-\${key}\` : \`bg-\${key}-\${shade}\`),
126
262
  search: search.value,
127
263
  }, ({ color}) => h('div', {
128
264
  class: '__pvt-shade',
@@ -145,7 +281,7 @@ export default {
145
281
  onMount: (api) => mountApp(api, () => Object.entries(config.theme.textColor).map(([key, shades]) => h(HstColorShades, {
146
282
  key,
147
283
  shades: typeof shades === 'object' ? shades : { DEFAULT: shades },
148
- getName: shade => (config.prefix ?? '') + (shade === 'DEFAULT' ? \`text-\${key}\` : \`text-\${key}-\${shade}\`),
284
+ getName: shade => '' + (shade === 'DEFAULT' ? \`text-\${key}\` : \`text-\${key}-\${shade}\`),
149
285
  search: search.value,
150
286
  }, ({ color}) => h('div', {
151
287
  class: '__pvt-shade __pvt-text',
@@ -168,7 +304,7 @@ export default {
168
304
  onMount: (api) => mountApp(api, () => Object.entries(config.theme.borderColor).map(([key, shades]) => h(HstColorShades, {
169
305
  key,
170
306
  shades: typeof shades === 'object' ? shades : { DEFAULT: shades },
171
- getName: shade => (config.prefix ?? '') + (shade === 'DEFAULT' ? \`border-\${key}\` : \`border-\${key}-\${shade}\`),
307
+ getName: shade => '' + (shade === 'DEFAULT' ? \`border-\${key}\` : \`border-\${key}-\${shade}\`),
172
308
  search: search.value,
173
309
  }, ({ color}) => h('div', {
174
310
  class: '__pvt-shade __pvt-border',
@@ -190,7 +326,7 @@ export default {
190
326
  icon: 'carbon:area',
191
327
  onMount: (api) => mountApp(api, () => h(HstTokenList, {
192
328
  tokens: config.theme.padding,
193
- getName: key => \`\${config.prefix ?? ''}p-\${key}\`,
329
+ getName: key => \`p-\${key}\`,
194
330
  }, ({ token }) => h('div', {
195
331
  class: '__pvt-padding',
196
332
  style: {
@@ -208,7 +344,7 @@ export default {
208
344
  icon: 'carbon:area',
209
345
  onMount: (api) => mountApp(api, () => h(HstTokenList, {
210
346
  tokens: config.theme.margin,
211
- getName: key => \`\${config.prefix ?? ''}m-\${key}\`,
347
+ getName: key => \`m-\${key}\`,
212
348
  }, ({ token }) => h('div', {
213
349
  class: '__pvt-margin',
214
350
  }, [
@@ -226,7 +362,7 @@ export default {
226
362
  icon: 'carbon:text-font',
227
363
  onMount: (api) => mountApp(api, () => h(HstTokenList, {
228
364
  tokens: config.theme.fontSize,
229
- getName: key => \`\${config.prefix ?? ''}text-\${key}\`,
365
+ getName: key => \`text-\${key}\`,
230
366
  }, ({ token }) => h('div', {
231
367
  class: '__pvt-truncate',
232
368
  style: {
@@ -249,7 +385,7 @@ export default {
249
385
  icon: 'carbon:text-font',
250
386
  onMount: (api) => mountApp(api, () => h(HstTokenList, {
251
387
  tokens: config.theme.fontWeight,
252
- getName: key => \`\${config.prefix ?? ''}font-\${key}\`,
388
+ getName: key => \`font-\${key}\`,
253
389
  }, ({ token }) => h('div', {
254
390
  class: '__pvt-truncate',
255
391
  style: {
@@ -278,7 +414,7 @@ export default {
278
414
  icon: 'carbon:text-font',
279
415
  onMount: (api) => mountApp(api, () => h(HstTokenList, {
280
416
  tokens: config.theme.fontFamily,
281
- getName: key => \`\${config.prefix ?? ''}font-\${key}\`,
417
+ getName: key => \`font-\${key}\`,
282
418
  }, ({ token }) => h('div', {
283
419
  class: '__pvt-truncate',
284
420
  style: {
@@ -307,7 +443,7 @@ export default {
307
443
  icon: 'carbon:text-font',
308
444
  onMount: (api) => mountApp(api, () => h(HstTokenList, {
309
445
  tokens: config.theme.letterSpacing,
310
- getName: key => \`\${config.prefix ?? ''}tracking-\${key}\`,
446
+ getName: key => \`tracking-\${key}\`,
311
447
  }, ({ token }) => h('div', {
312
448
  class: '__pvt-truncate',
313
449
  style: {
@@ -336,7 +472,7 @@ export default {
336
472
  icon: 'carbon:text-font',
337
473
  onMount: (api) => mountApp(api, () => h(HstTokenList, {
338
474
  tokens: config.theme.lineHeight,
339
- getName: key => \`\${config.prefix ?? ''}leading-\${key}\`,
475
+ getName: key => \`leading-\${key}\`,
340
476
  }, ({ token }) => h('div', {
341
477
  style: {
342
478
  lineHeight: token.value,
@@ -358,7 +494,7 @@ export default {
358
494
  icon: 'carbon:shape-except',
359
495
  onMount: (api) => mountApp(api, () => h(HstTokenGrid, {
360
496
  tokens: config.theme.dropShadow,
361
- getName: key => (config.prefix ?? '') + (key === 'DEFAULT' ? 'drop-shadow' : \`drop-shadow-\${key}\`),
497
+ getName: key => '' + (key === 'DEFAULT' ? 'drop-shadow' : \`drop-shadow-\${key}\`),
362
498
  colSize: 180,
363
499
  }, ({ token }) => h('div', {
364
500
  class: '__pvt-drop-shadow',
@@ -373,7 +509,7 @@ export default {
373
509
  icon: 'carbon:condition-wait-point',
374
510
  onMount: (api) => mountApp(api, () => h(HstTokenGrid, {
375
511
  tokens: config.theme.borderRadius,
376
- getName: key => (config.prefix ?? '') + (key === 'DEFAULT' ? 'rounded' : \`rounded-\${key}\`),
512
+ getName: key => '' + (key === 'DEFAULT' ? 'rounded' : \`rounded-\${key}\`),
377
513
  colSize: 180,
378
514
  }, ({ token }) => h('div', {
379
515
  class: '__pvt-border-radius',
@@ -388,7 +524,7 @@ export default {
388
524
  icon: 'carbon:checkbox',
389
525
  onMount: (api) => mountApp(api, () => h(HstTokenGrid, {
390
526
  tokens: config.theme.borderWidth,
391
- getName: key => (config.prefix ?? '') + (key === 'DEFAULT' ? 'border' : \`border-\${key}\`),
527
+ getName: key => '' + (key === 'DEFAULT' ? 'border' : \`border-\${key}\`),
392
528
  colSize: 180,
393
529
  }, ({ token }) => h('div', {
394
530
  class: '__pvt-border-width',
@@ -403,7 +539,7 @@ export default {
403
539
  icon: 'carbon:pan-horizontal',
404
540
  onMount: (api) => mountApp(api, () => h(HstTokenList, {
405
541
  tokens: config.theme.width,
406
- getName: key => (config.prefix ?? '') + (key === 'DEFAULT' ? 'w' : \`w-\${key}\`),
542
+ getName: key => '' + (key === 'DEFAULT' ? 'w' : \`w-\${key}\`),
407
543
  }, ({ token }) => h('div', {
408
544
  class: '__pvt-width',
409
545
  }, [
@@ -421,7 +557,7 @@ export default {
421
557
  icon: 'carbon:pan-vertical',
422
558
  onMount: (api) => mountApp(api, () => h(HstTokenList, {
423
559
  tokens: config.theme.height,
424
- getName: key => (config.prefix ?? '') + (key === 'DEFAULT' ? 'h' : \`h-\${key}\`),
560
+ getName: key => '' + (key === 'DEFAULT' ? 'h' : \`h-\${key}\`),
425
561
  }, ({ token }) => h('div', {
426
562
  class: '__pvt-height',
427
563
  style: {
@@ -1,15 +1,15 @@
1
1
  import type { Story } from '@poveste/shared';
2
2
  import type { PropType as _PropType } from '@poveste/vendors/vue';
3
- declare const _default: import("@vue/runtime-core").DefineComponent<import("@vue/runtime-core").ExtractPropTypes<{
3
+ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
4
4
  story: {
5
5
  type: _PropType<Story>;
6
6
  required: true;
7
7
  };
8
- }>, void, {}, {}, {}, import("@vue/runtime-core").ComponentOptionsMixin, import("@vue/runtime-core").ComponentOptionsMixin, {}, string, import("@vue/runtime-core").PublicProps, Readonly<import("@vue/runtime-core").ExtractPropTypes<{
8
+ }>, void, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
9
9
  story: {
10
10
  type: _PropType<Story>;
11
11
  required: true;
12
12
  };
13
- }>> & Readonly<{}>, {}, {}, {}, {}, string, import("@vue/runtime-core").ComponentProvideOptions, true, {}, any>;
13
+ }>> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
14
14
  export default _default;
15
15
  //# sourceMappingURL=MountStory.d.ts.map
@@ -1,6 +1,6 @@
1
1
  import type { Story, Variant } from '@poveste/shared';
2
2
  import type { PropType as _PropType } from '@poveste/vendors/vue';
3
- declare const _default: import("@vue/runtime-core").DefineComponent<import("@vue/runtime-core").ExtractPropTypes<{
3
+ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
4
4
  variant: {
5
5
  type: _PropType<Variant>;
6
6
  required: true;
@@ -14,10 +14,10 @@ declare const _default: import("@vue/runtime-core").DefineComponent<import("@vue
14
14
  default: string;
15
15
  };
16
16
  }>, {
17
- sandbox: import("@vue/reactivity").Ref<HTMLDivElement, HTMLDivElement>;
18
- }, {}, {}, {}, import("@vue/runtime-core").ComponentOptionsMixin, import("@vue/runtime-core").ComponentOptionsMixin, {
17
+ sandbox: import("vue").Ref<HTMLDivElement, HTMLDivElement>;
18
+ }, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
19
19
  ready: () => true;
20
- }, string, import("@vue/runtime-core").PublicProps, Readonly<import("@vue/runtime-core").ExtractPropTypes<{
20
+ }, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
21
21
  variant: {
22
22
  type: _PropType<Variant>;
23
23
  required: true;
@@ -34,6 +34,6 @@ declare const _default: import("@vue/runtime-core").DefineComponent<import("@vue
34
34
  onReady?: () => any;
35
35
  }>, {
36
36
  slotName: string;
37
- }, {}, {}, {}, string, import("@vue/runtime-core").ComponentProvideOptions, true, {}, any>;
37
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
38
38
  export default _default;
39
39
  //# sourceMappingURL=RenderStory.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/node/collect/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AACtD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,MAAM,CAAA;AAEzC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAA;AAa5C,MAAM,WAAW,wBAAwB;IACvC,MAAM,EAAE,aAAa,CAAA;IACrB,UAAU,CAAC,EAAE,aAAa,CAAA;IAC1B,MAAM,CAAC,EAAE,OAAO,CAAA;CACjB;AAED,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,wBAAwB,EAAE,GAAG,EAAE,OAAO;;kCAgFpC,eAAe;;EA+D3D"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/node/collect/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AACtD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,MAAM,CAAA;AAEzC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAA;AAa5C,MAAM,WAAW,wBAAwB;IACvC,MAAM,EAAE,aAAa,CAAA;IACrB,UAAU,CAAC,EAAE,aAAa,CAAA;IAC1B,MAAM,CAAC,EAAE,OAAO,CAAA;CACjB;AAED,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,wBAAwB,EAAE,GAAG,EAAE,OAAO;;kCAgFpC,eAAe;;EA6D3D"}
@@ -100,9 +100,7 @@ export function useCollectStories(options, ctx) {
100
100
  // Default props
101
101
  if (ctx.config.defaultStoryProps) {
102
102
  for (const key in ctx.config.defaultStoryProps) {
103
- if (finalData[key] == null) {
104
- finalData[key] = ctx.config.defaultStoryProps[key];
105
- }
103
+ finalData[key] ??= ctx.config.defaultStoryProps[key];
106
104
  }
107
105
  }
108
106
  if (!finalData.layout) {
@@ -4,24 +4,8 @@ export declare function getDefaultConfig(): PovesteConfig;
4
4
  export declare const configFileNames: string[];
5
5
  export declare function resolveConfigFile(cwd?: string, configFile?: string): string;
6
6
  export declare function loadConfigFile(configFile: string): Promise<Partial<PovesteConfig>>;
7
- export declare const mergeBuildConfig: <Source extends {
8
- [x: string]: any;
9
- [x: number]: any;
10
- [x: symbol]: any;
11
- }, Defaults extends Array<{
12
- [x: string]: any;
13
- [x: number]: any;
14
- [x: symbol]: any;
15
- } | (number | boolean | any[] | Record<never, any>)>>(source: Source, ...defaults: Defaults) => import("defu").Defu<Source, Defaults>;
16
- export declare const mergeConfig: <Source extends {
17
- [x: string]: any;
18
- [x: number]: any;
19
- [x: symbol]: any;
20
- }, Defaults extends Array<{
21
- [x: string]: any;
22
- [x: number]: any;
23
- [x: symbol]: any;
24
- } | (number | boolean | any[] | Record<never, any>)>>(source: Source, ...defaults: Defaults) => import("defu").Defu<Source, Defaults>;
7
+ export declare const mergeBuildConfig: import("defu").DefuFn;
8
+ export declare const mergeConfig: import("defu").DefuFn;
25
9
  export declare function resolveConfig(cwd: string, mode: ConfigMode, configFile: string): Promise<PovesteConfig>;
26
10
  export declare function processConfig(ctx: Context): Promise<void>;
27
11
  export declare function defineConfig(config: Partial<PovesteConfig>): Partial<PovesteConfig>;
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/node/config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,UAAU,EAEV,aAAa,EAEd,MAAM,iBAAiB,CAAA;AACxB,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AAkB3C,wBAAgB,gBAAgB,IAAI,aAAa,CA4HhD;AAED,eAAO,MAAM,eAAe,UAU3B,CAAA;AAED,wBAAgB,iBAAiB,CAAC,GAAG,GAAE,MAAsB,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,MAAM,CAQ1F;AAED,wBAAsB,cAAc,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC,CAexF;AAED,eAAO,MAAM,gBAAgB;;;;;;;;qIAK3B,CAAA;AAEF,eAAO,MAAM,WAAW;;;;;;;;qIA8DtB,CAAA;AAEF,wBAAsB,aAAa,CAAC,GAAG,EAAE,MAAsB,EAAE,IAAI,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CAa7H;AA2BD,wBAAsB,aAAa,CAAC,GAAG,EAAE,OAAO,iBAoE/C;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE,OAAO,CAAC,aAAa,CAAC,0BAE1D;AAED,OAAO,QAAQ,MAAM,CAAC;IACpB,UAAU,UAAU;QAClB;;WAEG;QACH,OAAO,CAAC,EAAE,OAAO,CAAC,aAAa,CAAC,CAAA;QAChC;;WAEG;QACH,QAAQ,CAAC,EAAE,OAAO,CAAC,aAAa,CAAC,CAAA;KAClC;CACF"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/node/config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,UAAU,EAEV,aAAa,EAEd,MAAM,iBAAiB,CAAA;AACxB,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AAkB3C,wBAAgB,gBAAgB,IAAI,aAAa,CA4HhD;AAED,eAAO,MAAM,eAAe,UAU3B,CAAA;AAED,wBAAgB,iBAAiB,CAAC,GAAG,GAAE,MAAsB,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,MAAM,CAQ1F;AAED,wBAAsB,cAAc,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC,CAexF;AAED,eAAO,MAAM,gBAAgB,uBAK3B,CAAA;AAEF,eAAO,MAAM,WAAW,uBA8DtB,CAAA;AAEF,wBAAsB,aAAa,CAAC,GAAG,EAAE,MAAsB,EAAE,IAAI,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CAgB7H;AA2BD,wBAAsB,aAAa,CAAC,GAAG,EAAE,OAAO,iBAoE/C;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE,OAAO,CAAC,aAAa,CAAC,0BAE1D;AAED,OAAO,QAAQ,MAAM,CAAC;IACpB,UAAU,UAAU;QAClB;;WAEG;QACH,OAAO,CAAC,EAAE,OAAO,CAAC,aAAa,CAAC,CAAA;QAChC;;WAEG;QACH,QAAQ,CAAC,EAAE,OAAO,CAAC,aAAa,CAAC,CAAA;KAClC;CACF"}
@@ -238,6 +238,9 @@ export async function resolveConfig(cwd = process.cwd(), mode, configFile) {
238
238
  result = await loadConfigFile(resolvedConfigFile);
239
239
  }
240
240
  const viteConfig = await resolveViteConfig({}, 'serve');
241
+ // The `histoire` key is our own deprecation, and reading it is the whole
242
+ // point — it is what makes poveste drop-in for an existing histoire config.
243
+ // eslint-disable-next-line ts/no-deprecated
241
244
  const vitePovesteConfig = (viteConfig.poveste ?? viteConfig.histoire ?? {});
242
245
  const preUserConfig = mergeConfig(result, vitePovesteConfig);
243
246
  const processedDefaultConfig = await processDefaultConfig(getDefaultConfig(), preUserConfig, mode, cwd);
@@ -1 +1 @@
1
- {"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../../../src/node/dom/env.ts"],"names":[],"mappings":"AA+BA,wBAAgB,YAAY;;;EAqD3B"}
1
+ {"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../../../src/node/dom/env.ts"],"names":[],"mappings":"AAmCA,wBAAgB,YAAY;;;EAqD3B"}
@@ -3,12 +3,16 @@ import { populateGlobal } from './util.js';
3
3
  // jsdom error types — not exported by jsdom.
4
4
  const JSDOM_ERROR_CSS_PARSING = 'css-parsing';
5
5
  const JSDOM_ERROR_UNHANDLED_EXCEPTION = 'unhandled-exception';
6
- // Directives JSDOM's CSS parser doesn't know — Tailwind v4's `@theme` is the
7
- // common one — make it emit a jsdomError per stylesheet, so collecting stories
8
- // from a Tailwind app prints "Could not parse CSS stylesheet" over and over.
9
- // The parser recovers on its own and keeps the valid rules, so the message is
10
- // pure noise: drop css-parsing errors, mirror jsdom's default forwardTo for
11
- // the rest.
6
+ // CSS jsdom's parser can't make sense of makes it emit a jsdomError per
7
+ // stylesheet, so collecting stories from an app with such a stylesheet prints
8
+ // "Could not parse CSS stylesheet" over and over. The parser recovers on its
9
+ // own and keeps the valid rules, so the message is pure noise: drop
10
+ // css-parsing errors, mirror jsdom's default forwardTo for the rest.
11
+ //
12
+ // jsdom 28 moved to css-tree, which recovers browser-style and stays quiet for
13
+ // most of what jsdom 27 complained about — Tailwind v4's `@theme`, unknown
14
+ // at-rules, unterminated strings. It still reports some inputs (an
15
+ // unparseable selector, for one), so this stays.
12
16
  function createVirtualConsole() {
13
17
  if (!console || !globalThis.console)
14
18
  return undefined;
@@ -2,11 +2,4 @@ export { defaultColors } from './colors.js';
2
2
  export * from './config.js';
3
3
  export * from './plugin.js';
4
4
  export * from '@poveste/shared';
5
- declare module 'rollup' {
6
- interface PluginContextMeta {
7
- poveste: {
8
- isCollecting: boolean;
9
- };
10
- }
11
- }
12
5
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/node/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAC3C,cAAc,aAAa,CAAA;AAC3B,cAAc,aAAa,CAAA;AAC3B,cAAc,iBAAiB,CAAA;AAE/B,OAAO,QAAQ,QAAQ,CAAC;IACtB,UAAU,iBAAiB;QACzB,OAAO,EAAE;YACP,YAAY,EAAE,OAAO,CAAA;SACtB,CAAA;KACF;CACF"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/node/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAC3C,cAAc,aAAa,CAAA;AAC3B,cAAc,aAAa,CAAA;AAC3B,cAAc,iBAAiB,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"markdown.d.ts","sourceRoot":"","sources":["../../src/node/markdown.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,IAAI,UAAU,EAAE,MAAM,MAAM,CAAA;AAChD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AAK3C,OAAO,UAAU,MAAM,aAAa,CAAA;AAapC,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,OAAO,QAE1D;AAQD,wBAAsB,sBAAsB,CAAC,GAAG,EAAE,OAAO,uBAsExD;AAaD,wBAAsB,qBAAqB,CAAC,GAAG,EAAE,OAAO,8BAqBvD;AAED,wBAAsB,0BAA0B,CAAC,GAAG,EAAE,OAAO;;GAgI5D;AAED,MAAM,MAAM,oBAAoB,GAAG,UAAU,CAAC,OAAO,0BAA0B,CAAC,CAAA"}
1
+ {"version":3,"file":"markdown.d.ts","sourceRoot":"","sources":["../../src/node/markdown.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,IAAI,UAAU,EAAE,MAAM,MAAM,CAAA;AAChD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AAK3C,OAAO,UAAU,MAAM,aAAa,CAAA;AAapC,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,OAAO,QAE1D;AAyBD,wBAAsB,sBAAsB,CAAC,GAAG,EAAE,OAAO,uBA0ExD;AAaD,wBAAsB,qBAAqB,CAAC,GAAG,EAAE,OAAO,8BAqBvD;AAED,wBAAsB,0BAA0B,CAAC,GAAG,EAAE,OAAO;;GAgI5D;AAED,MAAM,MAAM,oBAAoB,GAAG,UAAU,CAAC,OAAO,0BAA0B,CAAC,CAAA"}
@@ -21,13 +21,31 @@ function notifyMarkdownListChange() {
21
21
  handler();
22
22
  }
23
23
  }
24
- export async function createMarkdownRenderer(ctx) {
25
- const highlighter = await createHighlighter({
24
+ /**
25
+ * Shared between the markdown Vite plugin and the markdown file watcher, which
26
+ * both build a renderer — a `poveste build` reaches this three times. The
27
+ * themes and langs are constant, and each instance eagerly loads every bundled
28
+ * grammar, so the duplicates are pure waste.
29
+ */
30
+ let highlighterPromise;
31
+ function getHighlighter() {
32
+ highlighterPromise ??= createHighlighter({
26
33
  themes: ['github-dark'],
27
34
  langs: Object.keys(bundledLanguages), // not ideal but markdown-it does not provide async highlight
28
35
  });
36
+ return highlighterPromise;
37
+ }
38
+ export async function createMarkdownRenderer(ctx) {
39
+ const highlighter = await getHighlighter();
29
40
  const md = new MarkdownIt({
30
- highlight: (code, lang) => `<div class="ptw-relative ptw-not-prose __poveste-code __histoire-code"><div class="ptw-absolute ptw-top-0 ptw-right-0 ptw-text-xs ptw-text-white/40">${lang}</div>${highlighter.codeToHtml(code, { theme: 'github-dark', lang })}</div>`,
41
+ /*
42
+ * Unprefixed utilities: the `ptw-` prefix went away with Tailwind v4, and
43
+ * `not-prose` in particular is matched by the typography plugin's own
44
+ * `[class~="not-prose"]` selector, so a prefixed spelling silently opts the
45
+ * block back *into* prose. These classes are generated because main.pcss
46
+ * `@source`s this file — v4 auto-detection only scans the app package.
47
+ */
48
+ highlight: (code, lang) => `<div class="relative not-prose __poveste-code __histoire-code"><div class="absolute top-0 right-0 text-xs text-white/40">${lang}</div>${highlighter.codeToHtml(code, { theme: 'github-dark', lang })}</div>`,
31
49
  linkify: true,
32
50
  html: true,
33
51
  breaks: false,
@@ -58,7 +58,7 @@ export async function watchStories(newContext) {
58
58
  watcher
59
59
  .on('add', (file) => {
60
60
  const storyFile = addStory(file);
61
- setTimeout(() => notifyStoryChange(storyFile), 100); // Delay in case file renaming fired Add event before Unlink event
61
+ setTimeout(notifyStoryChange, 100, storyFile); // Delay in case file renaming fired Add event before Unlink event
62
62
  })
63
63
  .on('unlink', (file) => {
64
64
  removeStory(file);
@@ -1 +1 @@
1
- {"version":3,"file":"entry-css-merger.d.ts","sourceRoot":"","sources":["../../../src/node/style-isolation/entry-css-merger.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,IAAI,UAAU,EAAE,MAAM,MAAM,CAAA;AAKhD,MAAM,WAAW,qBAAqB;IACpC,aAAa,EAAE,OAAO,CAAA;IACtB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,aAAa,CAAC,EAAE,MAAM,CAAA;CACvB;AAED,wBAAgB,oBAAoB,CAAC,IAAI,GAAE,qBAAgD,GAAG,UAAU,CA4FvG;AAMD,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAsBxE"}
1
+ {"version":3,"file":"entry-css-merger.d.ts","sourceRoot":"","sources":["../../../src/node/style-isolation/entry-css-merger.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,IAAI,UAAU,EAAE,MAAM,MAAM,CAAA;AAKhD,MAAM,WAAW,qBAAqB;IACpC,aAAa,EAAE,OAAO,CAAA;IACtB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,aAAa,CAAC,EAAE,MAAM,CAAA;CACvB;AAED,wBAAgB,oBAAoB,CAAC,IAAI,GAAE,qBAAgD,GAAG,UAAU,CA8FvG;AAMD,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAsBxE"}
@@ -43,6 +43,7 @@ export function entryCssMergerPlugin(opts = { isolateStyles: false }) {
43
43
  collectChunkCss(fileName, chunk.name, cssAssetUsedBy);
44
44
  }
45
45
  const mergedByEntry = new Map();
46
+ const mergedCssAssets = [];
46
47
  for (const [cssName, entries] of cssAssetUsedBy) {
47
48
  const asset = bundle[cssName];
48
49
  if (!asset || asset.type !== 'asset')
@@ -55,6 +56,12 @@ export function entryCssMergerPlugin(opts = { isolateStyles: false }) {
55
56
  list.push(source);
56
57
  mergedByEntry.set(entryName, list);
57
58
  }
59
+ mergedCssAssets.push(cssName);
60
+ }
61
+ // Rolldown ignores assignment to `bundle` in generateBundle, so the merged
62
+ // files are added with this.emitFile. The now-merged per-chunk CSS assets
63
+ // are dropped so they don't ship as unscoped, orphaned duplicates.
64
+ for (const cssName of mergedCssAssets) {
58
65
  delete bundle[cssName];
59
66
  }
60
67
  for (const [entryName, sources] of mergedByEntry) {
@@ -63,13 +70,7 @@ export function entryCssMergerPlugin(opts = { isolateStyles: false }) {
63
70
  const finalSource = entryName === mainEntryName && opts.isolateStyles
64
71
  ? wrapMarkedUserCss(merged, scopeRoot)
65
72
  : stripMarkers(merged);
66
- bundle[fileName] = {
67
- type: 'asset',
68
- fileName,
69
- name: fileName,
70
- source: finalSource,
71
- needsCodeReference: false,
72
- };
73
+ this.emitFile({ type: 'asset', fileName, source: finalSource });
73
74
  }
74
75
  // Re-point CSS metadata: entries claim their own merged file; non-entry
75
76
  // chunks (vendor, route splits) drop their importedCss because the