@poveste/plugin-svelte 0.18.3 → 0.19.0

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.
@@ -0,0 +1,3 @@
1
+ # Third-party notices
2
+
3
+ @poveste/plugin-svelte bundles no third-party code into its `dist`.
@@ -1 +1 @@
1
- import{addStoryContext as e,addVariantContext as t,collectStoryContext as n,storyFileContext as r}from"../contexts.js";import"svelte/internal/disclose-version";import"svelte/internal/flags/legacy";import*as i from"svelte/internal/client";function a(a,o){i.push(o,!1);let s=i.prop(o,`title`,8,null),c=i.prop(o,`id`,8,null),l=i.prop(o,`group`,8,null),u=i.prop(o,`layout`,8,null),d=i.prop(o,`icon`,8,null),f=i.prop(o,`iconColor`,8,null),p=i.prop(o,`docsOnly`,8,!1),m=i.prop(o,`autoPropsDisabled`,8,null),h=i.prop(o,`initState`,8,null),g=e.getOptional(),_=r.getOptional(),v=c()??_?.id,y=s()??_?.fileName;if(!v||y===void 0)throw Error("[poveste] a <Story> collected outside a story file needs an `id` and a `title`");let b={id:v,title:y,group:l(),layout:u(),icon:d(),iconColor:f(),docsOnly:p(),autoPropsDisabled:m(),variants:[]};g?.(b);let x=h()?h()():{};n.set(b),t.set(e=>{b.variants.push(e)}),i.init();var S=i.comment(),C=i.first_child(S);i.slot(C,o,`default`,{get state(){return x}},null),i.append(a,S),i.pop()}export{a as default};
1
+ import{addStoryContext as e,addVariantContext as t,collectStoryContext as n,storyFileContext as r}from"../contexts.js";import"svelte/internal/disclose-version";import"svelte/internal/flags/legacy";import*as i from"svelte/internal/client";function a(a,o){i.push(o,!1);let s=i.prop(o,`title`,8,null),c=i.prop(o,`id`,8,null),l=i.prop(o,`group`,8,null),u=i.prop(o,`layout`,8,null),d=i.prop(o,`icon`,8,null),f=i.prop(o,`iconColor`,8,null),p=i.prop(o,`docsOnly`,8,!1),m=i.prop(o,`autoPropsDisabled`,8,null),h=i.prop(o,`initState`,8,null),g=i.prop(o,`meta`,8,null),_=e.getOptional(),v=r.getOptional(),y=c()??v?.id,b=s()??v?.fileName;if(!y||b===void 0)throw Error("[poveste] a <Story> collected outside a story file needs an `id` and a `title`");let x={id:y,title:b,group:l(),layout:u(),icon:d(),iconColor:f(),docsOnly:p(),autoPropsDisabled:m(),...g()?{meta:g()}:{},variants:[]};_?.(x);let S=h()?h()():{};n.set(x),t.set(e=>{x.variants.push(e)}),i.init();var C=i.comment(),w=i.first_child(C);i.slot(w,o,`default`,{get state(){return S}},null),i.append(a,C),i.pop()}export{a as default};
@@ -10,6 +10,7 @@
10
10
  export let docsOnly = false
11
11
  export let autoPropsDisabled = null
12
12
  export let initState = null
13
+ export let meta = null
13
14
 
14
15
  const addStory = addStoryContext.getOptional()
15
16
  const file = storyFileContext.getOptional()
@@ -36,6 +37,8 @@
36
37
  // only to an implicit variant (#466). Left undefined when unset, or the
37
38
  // collector's `??=` merge could never apply `defaultStoryProps`.
38
39
  autoPropsDisabled,
40
+ // Was dropped: a story's `meta.storyOptions` did nothing in a Svelte book (#1206).
41
+ ...meta ? { meta } : {},
39
42
  variants: [],
40
43
  }
41
44
 
@@ -1 +1 @@
1
- import{addVariantContext as e,collectStoryContext as t}from"../contexts.js";import"svelte/internal/disclose-version";import"svelte/internal/flags/legacy";import*as n from"svelte/internal/client";function r(r,i){n.push(i,!1);let a=n.prop(i,`title`,8,`untitled`),o=n.prop(i,`id`,8,null),s=n.prop(i,`icon`,8,null),c=n.prop(i,`iconColor`,8,null),l=n.prop(i,`autoPropsDisabled`,8,!1);n.prop(i,`initState`,8,null);let u=t.get(`<Variant>`);e.get(`<Variant>`)({id:o()??`${u.id}-${u.variants.length}`,title:a(),icon:s(),iconColor:c(),autoPropsDisabled:l()}),n.init(),n.pop()}export{r as default};
1
+ import{addVariantContext as e,collectStoryContext as t}from"../contexts.js";import"svelte/internal/disclose-version";import"svelte/internal/flags/legacy";import*as n from"svelte/internal/client";function r(r,i){n.push(i,!1);let a=n.prop(i,`title`,8,`untitled`),o=n.prop(i,`id`,8,null),s=n.prop(i,`icon`,8,null),c=n.prop(i,`iconColor`,8,null),l=n.prop(i,`autoPropsDisabled`,8,!1);n.prop(i,`initState`,8,null);let u=n.prop(i,`meta`,8,null),d=t.get(`<Variant>`);e.get(`<Variant>`)({id:o()??`${d.id}-${d.variants.length}`,title:a(),icon:s(),iconColor:c(),autoPropsDisabled:l(),...u()?{meta:u()}:{}}),n.init(),n.pop()}export{r as default};
@@ -13,6 +13,7 @@
13
13
  // (the compiler's suggestion) would make passing one an error.
14
14
  // svelte-ignore export_let_unused
15
15
  export let initState = null
16
+ export let meta = null
16
17
 
17
18
  // Asked for before anything reads them, so a missing `<Story>` is reported
18
19
  // once and the same way whether or not the variant carries an `id`. Reading
@@ -27,6 +28,8 @@
27
28
  icon,
28
29
  iconColor,
29
30
  autoPropsDisabled,
31
+ // Was dropped, as a story's was (#1260).
32
+ ...meta ? { meta } : {},
30
33
  }
31
34
 
32
35
  addVariant(variant)
@@ -0,0 +1,15 @@
1
+ /**
2
+ * The `Hst` a story is collected with.
3
+ *
4
+ * Collection reads a story's structure, so `Story` and `Variant` are the two
5
+ * members that do anything. A story can still hold a builtin control in its
6
+ * default slot, which collection renders to find the variants: every other
7
+ * capitalised member is a component that renders nothing. With two members and
8
+ * no more, `<Hst.Select>` there was `undefined(...)`, and one story stopped the
9
+ * book's build (#925).
10
+ *
11
+ * Any name, not the list of controls: importing `@poveste/controls` here would
12
+ * load every control into the collection worker to learn their names. A name
13
+ * that is no control is caught where the story renders, in that story alone.
14
+ */
15
+ export declare function collectHst(): Record<string, unknown>;
@@ -0,0 +1 @@
1
+ import e from"../client/Stub.js";import t from"./Story.svelte";import n from"./Variant.svelte";function r(){return new Proxy({Story:t,Variant:n},{get:(t,n)=>t[n]??(typeof n==`string`&&/^[A-Z]/.test(n)?e:void 0)})}export{r as collectHst};
@@ -1 +1 @@
1
- import{addStoryContext as e,storyFileContext as t}from"../contexts.js";import{callSetupFunctions as n,mountSvelteComponent as r}from"../util/svelte.js";import i from"./Story.svelte";import a from"./Variant.svelte";import*as o from"virtual:$poveste-generated-global-setup";import*as s from"virtual:$poveste-setup";import{tick as c}from"svelte";async function l({file:l,el:u,storyData:d}){let{default:f}=await import(/* @vite-ignore */l.moduleId),p=await r(f,{target:u,props:{Hst:{Story:i,Variant:a}},context:new Map([[e.key,e=>{d.push(e)}],[t.key,l]])},`client`),m={app:p.app,story:void 0,variant:void 0};if(await n(o,s,m),await c(),!d[0]){p.destroy();return}d[0].variants.length||d[0].variants.push({id:`_default`,title:`default`}),p.destroy()}export{l as run};
1
+ import{addStoryContext as e,storyFileContext as t}from"../contexts.js";import{callSetupFunctions as n,mountSvelteComponent as r}from"../util/svelte.js";import{collectHst as i}from"./hst.js";import*as a from"virtual:$poveste-generated-global-setup";import*as o from"virtual:$poveste-setup";import{tick as s}from"svelte";async function c({file:c,el:l,storyData:u}){let{default:d}=await import(/* @vite-ignore */c.moduleId),f=await r(d,{target:l,props:{Hst:i()},context:new Map([[e.key,e=>{u.push(e)}],[t.key,c]])},`client`),p={app:f.app,story:void 0,variant:void 0};if(await n(a,o,p),await s(),!u[0]){f.destroy();return}u[0].variants.length||u[0].variants.push({id:`_default`,title:`default`}),f.destroy()}export{c as run};
package/dist/helpers.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import type { HstControlOption } from '@poveste/controls';
2
- import type { Story, StoryProps, Variant, VariantProps } from '@poveste/shared';
2
+ import type { Story, StoryMeta, StoryProps, Variant, VariantMeta, VariantProps } from '@poveste/shared';
3
3
  import type { Component, Snippet } from 'svelte';
4
4
  export interface SvelteStorySetupApi {
5
5
  app: any;
@@ -44,8 +44,12 @@ type WithState<P> = Omit<P, 'source'> & {
44
44
  source?: string | ((state: StoryState) => string);
45
45
  };
46
46
  export interface Hst {
47
- Story: Component<WithState<WithChildren<StoryProps>>>;
48
- Variant: Component<WithState<WithChildren<VariantProps>>>;
47
+ Story: Component<WithState<WithChildren<StoryProps>> & {
48
+ meta?: StoryMeta;
49
+ }>;
50
+ Variant: Component<WithState<WithChildren<VariantProps>> & {
51
+ meta?: VariantMeta;
52
+ }>;
49
53
  Button: Component<WithChildren<Record<string, any>>>;
50
54
  ButtonGroup: Component<{
51
55
  value?: string;
@@ -88,7 +92,7 @@ export interface Hst {
88
92
  }>;
89
93
  Radio: Component<{
90
94
  value?: string;
91
- options: HstControlOption[];
95
+ options: Record<string, string> | (string | HstControlOption)[];
92
96
  title?: string;
93
97
  }>;
94
98
  Color: Component<{
@@ -1,9 +1,7 @@
1
1
  import { readFile } from 'node:fs/promises';
2
2
  import { transformStoryAutoProps } from './auto-props.js';
3
3
  import { extractPropDefs } from './props.js';
4
- // Cheaper than a parse, and unlike a filename pattern it cannot go blind when a
5
- // project narrows `storyMatch`.
6
- const RENDERS_A_STORY = '<Hst.Story';
4
+ import { isSvelteStory } from './story-source.js';
7
5
  const IMPORTS_A_COMPONENT = /from\s*['"][^'"]*\.svelte['"]/;
8
6
  /** Runs before `vite-plugin-svelte`: after it compiles there is nothing left to rewrite (#233). */
9
7
  export function svelteAutoProps() {
@@ -11,7 +9,7 @@ export function svelteAutoProps() {
11
9
  name: 'poveste:svelte-auto-props',
12
10
  enforce: 'pre',
13
11
  async transform(code, id) {
14
- if (!id.replace(/\?.*$/s, '').endsWith('.svelte') || !code.includes(RENDERS_A_STORY) || !IMPORTS_A_COMPONENT.test(code)) {
12
+ if (!isSvelteStory(id, code) || !IMPORTS_A_COMPONENT.test(code)) {
15
13
  return undefined;
16
14
  }
17
15
  const result = await transformStoryAutoProps(code, async (specifier) => {
@@ -6,6 +6,11 @@
6
6
  * `kit.files.assets`, and poveste drops that plugin through `viteIgnorePlugins`
7
7
  * — so a book served none of a Kit project's `static/`, in dev or in the build
8
8
  * (#463). This restores the one value that went with it.
9
+ *
10
+ * Kit 2 only. Kit 3 sets `publicDir` from a plugin poveste keeps, out of the
11
+ * `files.assets` given to `sveltekit()`. Answering `static` here as well put
12
+ * that in the config poveste resolves, and a `theme.favicon` in a custom assets
13
+ * directory was reported missing (#1212).
9
14
  */
10
15
  export declare function svelteKitAssetsDir(cwd: string): Promise<string | undefined>;
11
16
  export declare function declaresKit(cwd: string): boolean;
@@ -1,4 +1,5 @@
1
1
  import { existsSync, readFileSync } from 'node:fs';
2
+ import { createRequire } from 'node:module';
2
3
  import { pathToFileURL } from 'node:url';
3
4
  import { isAbsolute, join } from 'pathe';
4
5
  /**
@@ -9,9 +10,14 @@ import { isAbsolute, join } from 'pathe';
9
10
  * `kit.files.assets`, and poveste drops that plugin through `viteIgnorePlugins`
10
11
  * — so a book served none of a Kit project's `static/`, in dev or in the build
11
12
  * (#463). This restores the one value that went with it.
13
+ *
14
+ * Kit 2 only. Kit 3 sets `publicDir` from a plugin poveste keeps, out of the
15
+ * `files.assets` given to `sveltekit()`. Answering `static` here as well put
16
+ * that in the config poveste resolves, and a `theme.favicon` in a custom assets
17
+ * directory was reported missing (#1212).
12
18
  */
13
19
  export async function svelteKitAssetsDir(cwd) {
14
- if (!declaresKit(cwd)) {
20
+ if (!declaresKit(cwd) || installedKitMajor(cwd) >= 3) {
15
21
  return undefined;
16
22
  }
17
23
  const assets = await configuredAssetsDir(cwd) ?? 'static';
@@ -31,6 +37,16 @@ export function declaresKit(cwd) {
31
37
  return false;
32
38
  }
33
39
  }
40
+ // 0 when Kit is declared and not installed, which leaves the Kit 2 answer.
41
+ function installedKitMajor(cwd) {
42
+ try {
43
+ const manifestPath = createRequire(join(cwd, 'package.json')).resolve('@sveltejs/kit/package.json');
44
+ return Number.parseInt(JSON.parse(readFileSync(manifestPath, 'utf8')).version) || 0;
45
+ }
46
+ catch {
47
+ return 0;
48
+ }
49
+ }
34
50
  // Kit reads this from `svelte.config.js` and defaults it to `static`. Reading it
35
51
  // rather than assuming the default is what makes a project that moved its assets
36
52
  // work; a config that will not load is not this plugin's failure to report, so
@@ -6,5 +6,8 @@
6
6
  *
7
7
  * Returns why it could not run, for the caller to report; a failed sync is the
8
8
  * project's to fix, and the book may still start without it.
9
+ *
10
+ * Bounded, because it blocks startup: a Kit config that never settles kept
11
+ * `spawnSync` waiting with nothing printed, and the book never started (#1211).
9
12
  */
10
- export declare function syncSvelteKit(cwd: string): string | undefined;
13
+ export declare function syncSvelteKit(cwd: string, timeoutMs?: number): string | undefined;
@@ -12,8 +12,11 @@ import { declaresKit } from './kit-assets.js';
12
12
  *
13
13
  * Returns why it could not run, for the caller to report; a failed sync is the
14
14
  * project's to fix, and the book may still start without it.
15
+ *
16
+ * Bounded, because it blocks startup: a Kit config that never settles kept
17
+ * `spawnSync` waiting with nothing printed, and the book never started (#1211).
15
18
  */
16
- export function syncSvelteKit(cwd) {
19
+ export function syncSvelteKit(cwd, timeoutMs = 60_000) {
17
20
  if (!declaresKit(cwd)) {
18
21
  return undefined;
19
22
  }
@@ -26,6 +29,9 @@ export function syncSvelteKit(cwd) {
26
29
  catch {
27
30
  return '@sveltejs/kit is declared but could not be resolved from the project';
28
31
  }
29
- const result = spawnSync(process.execPath, [cli, 'sync'], { cwd, encoding: 'utf8' });
32
+ const result = spawnSync(process.execPath, [cli, 'sync'], { cwd, encoding: 'utf8', timeout: timeoutMs });
33
+ if (Reflect.get(result.error ?? {}, 'code') === 'ETIMEDOUT') {
34
+ return `\`svelte-kit sync\` in ${cwd} did not finish within ${timeoutMs / 1000}s and was stopped. A Kit or Vite config that never settles does this, and it would hang \`vite dev\` the same way`;
35
+ }
30
36
  return result.status === 0 ? undefined : (result.stderr || result.error?.message || `exited with ${result.status}`).trim();
31
37
  }
@@ -1,8 +1,9 @@
1
1
  export declare function disableStoryComponentHmr(): {
2
2
  name: string;
3
3
  apply: "serve";
4
- handleHotUpdate({ file, server }: {
4
+ handleHotUpdate({ file, read, server }: {
5
5
  file: string;
6
+ read: () => string | Promise<string>;
6
7
  server: {
7
8
  ws: {
8
9
  send: (payload: {
@@ -10,7 +11,7 @@ export declare function disableStoryComponentHmr(): {
10
11
  }) => void;
11
12
  };
12
13
  };
13
- }): never[] | undefined;
14
+ }): Promise<never[] | undefined>;
14
15
  configResolved(config: {
15
16
  readonly plugins: readonly unknown[];
16
17
  }): void;
@@ -1,4 +1,4 @@
1
- const storyFileRE = /\.story\.svelte$/;
1
+ import { isSvelteStory } from './story-source.js';
2
2
  export function disableStoryComponentHmr() {
3
3
  return {
4
4
  name: 'poveste:svelte-story-hmr',
@@ -6,8 +6,8 @@ export function disableStoryComponentHmr() {
6
6
  // With component HMR off, nothing in the sandbox takes the updated story module:
7
7
  // the edit was collected and never shown until a manual reload (#1178). A reload
8
8
  // shows it, as for Solid, at the cost of whatever was set in the panel.
9
- handleHotUpdate({ file, server }) {
10
- if (!storyFileRE.test(file)) {
9
+ async handleHotUpdate({ file, read, server }) {
10
+ if (!file.endsWith('.svelte') || !isSvelteStory(file, await read())) {
11
11
  return undefined;
12
12
  }
13
13
  server.ws.send({ type: 'full-reload' });
@@ -25,7 +25,7 @@ export function disableStoryComponentHmr() {
25
25
  const originalDynamicCompileOptions = options.dynamicCompileOptions;
26
26
  options.dynamicCompileOptions = async (data) => {
27
27
  const result = await originalDynamicCompileOptions?.(data);
28
- if (!storyFileRE.test(data.filename)) {
28
+ if (!isSvelteStory(data.filename, data.code)) {
29
29
  return result;
30
30
  }
31
31
  return {
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Whether a module is a Svelte story, by what it renders.
3
+ *
4
+ * Not by its name: `storyMatch` is the book's to narrow or replace, so
5
+ * `src/stories/Button.svelte` is a story where the config says so, and a
6
+ * `.story.svelte` pattern here does not follow it (#472, #474). Cheaper than a
7
+ * parse, and one predicate for both Vite plugins that need to know.
8
+ */
9
+ export declare function isSvelteStory(id: string, code: string): boolean;
@@ -0,0 +1,12 @@
1
+ const RENDERS_A_STORY = '<Hst.Story';
2
+ /**
3
+ * Whether a module is a Svelte story, by what it renders.
4
+ *
5
+ * Not by its name: `storyMatch` is the book's to narrow or replace, so
6
+ * `src/stories/Button.svelte` is a story where the config says so, and a
7
+ * `.story.svelte` pattern here does not follow it (#472, #474). Cheaper than a
8
+ * parse, and one predicate for both Vite plugins that need to know.
9
+ */
10
+ export function isSvelteStory(id, code) {
11
+ return id.replace(/\?.*$/s, '').endsWith('.svelte') && code.includes(RENDERS_A_STORY);
12
+ }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@poveste/plugin-svelte",
3
3
  "type": "module",
4
- "version": "0.18.3",
4
+ "version": "0.19.0",
5
5
  "description": "Poveste plugin for Svelte 5 and SvelteKit support",
6
6
  "author": {
7
7
  "name": "Sorin Gitlan",
@@ -46,7 +46,11 @@
46
46
  "types": "./dist/client/auto-props.d.ts",
47
47
  "default": "./dist/client/auto-props.js"
48
48
  },
49
- ".": "./dist/index.node.js",
49
+ ".": {
50
+ "types": "./dist/index.node.d.ts",
51
+ "node": "./dist/index.node.js",
52
+ "default": "./dist/index.js"
53
+ },
50
54
  "./*": "./*"
51
55
  },
52
56
  "main": "./dist/index.node.js",
@@ -65,7 +69,7 @@
65
69
  "peerDependencies": {
66
70
  "@sveltejs/kit": "^2.53.0 || ^3.0.0",
67
71
  "@sveltejs/vite-plugin-svelte": "^7.3.0",
68
- "poveste": "^0.18.3",
72
+ "poveste": "^0.19.0",
69
73
  "svelte": "^5.46.4"
70
74
  },
71
75
  "peerDependenciesMeta": {
@@ -74,9 +78,9 @@
74
78
  }
75
79
  },
76
80
  "dependencies": {
77
- "@poveste/controls": "^0.18.3",
78
- "@poveste/shared": "^0.18.3",
79
- "@poveste/vendors": "^0.18.3",
81
+ "@poveste/controls": "^0.19.0",
82
+ "@poveste/shared": "^0.19.0",
83
+ "@poveste/vendors": "^0.19.0",
80
84
  "change-case": "^5.4.4",
81
85
  "ignore": "^7.0.10",
82
86
  "launch-editor": "^2.9.1",
@@ -89,7 +93,7 @@
89
93
  "concurrently": "^10.0.5",
90
94
  "fs-extra": "^11.4.1",
91
95
  "jsdom": "^30.1.1",
92
- "poveste": "0.18.3",
96
+ "poveste": "0.19.0",
93
97
  "svelte": "5.57.1",
94
98
  "svelte-preprocess": "^6.0.5",
95
99
  "typescript": "6.0.3",