@poveste/plugin-vue 0.14.0 → 0.16.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.
Files changed (68) hide show
  1. package/README.md +2 -2
  2. package/components.d.ts +4 -0
  3. package/dist/bundled/client/app/MountStory.js +8 -3
  4. package/dist/bundled/client/app/RenderStory.js +15 -9
  5. package/dist/bundled/client/app/Story.js +76 -62
  6. package/dist/bundled/client/app/Variant.js +48 -42
  7. package/dist/bundled/client/app/context.js +5 -0
  8. package/dist/bundled/client/app/global-components.js +11 -10
  9. package/dist/bundled/client/app/host.js +2 -2
  10. package/dist/bundled/client/app/render-context.js +7 -7
  11. package/dist/bundled/client/app/util.js +36 -26
  12. package/dist/bundled/client/client.js +4 -4
  13. package/dist/bundled/client/codegen.js +79 -60
  14. package/dist/bundled/client/context.js +20 -0
  15. package/dist/bundled/client/server/Story.js +28 -25
  16. package/dist/bundled/client/server/Variant.js +13 -16
  17. package/dist/bundled/client/server/context.js +5 -0
  18. package/dist/bundled/client/server/run.js +29 -29
  19. package/dist/client/app/MountStory.d.ts +12 -3
  20. package/dist/client/app/RenderStory.d.ts +1 -1
  21. package/dist/client/app/Story.d.ts +10 -7
  22. package/dist/client/app/Variant.d.ts +14 -13
  23. package/dist/client/app/context.d.ts +9 -0
  24. package/dist/client/app/render-context.d.ts +16 -1
  25. package/dist/client/app/util.d.ts +38 -3
  26. package/dist/client/codegen.d.ts +29 -0
  27. package/dist/client/context.d.ts +40 -0
  28. package/dist/client/server/Story.d.ts +17 -17
  29. package/dist/client/server/Variant.d.ts +10 -10
  30. package/dist/client/server/context.d.ts +7 -0
  31. package/dist/commands/generate-story.client.js +4 -4
  32. package/dist/commands/generate-story.server.js +2 -2
  33. package/dist/helpers.d.ts +2 -2
  34. package/dist/index.node.js +2 -0
  35. package/dist/util/list-components.d.ts +1 -1
  36. package/dist/util/list-components.js +63 -6
  37. package/dist/util/list-components.spec.d.ts +1 -0
  38. package/dist/util/list-components.spec.js +46 -0
  39. package/package.json +17 -16
  40. package/src/client/__tests__/codegen-attrs.spec.ts +149 -0
  41. package/src/client/__tests__/context.spec.ts +50 -0
  42. package/src/client/app/MountStory.ts +11 -1
  43. package/src/client/app/RenderStory.ts +6 -1
  44. package/src/client/app/RouterLinkStub.ts +1 -1
  45. package/src/client/app/Story.ts +85 -39
  46. package/src/client/app/Variant.ts +35 -27
  47. package/src/client/app/__tests__/preview-variants.spec.ts +76 -0
  48. package/src/client/app/__tests__/state-sync.spec.ts +113 -2
  49. package/src/client/app/__tests__/writable-binding.spec.ts +39 -0
  50. package/src/client/app/auto-props.ts +2 -2
  51. package/src/client/app/context.ts +17 -0
  52. package/src/client/app/global-components.ts +20 -14
  53. package/src/client/app/host.ts +9 -6
  54. package/src/client/app/render-context.ts +25 -5
  55. package/src/client/app/util.ts +104 -9
  56. package/src/client/codegen.ts +81 -29
  57. package/src/client/context.ts +66 -0
  58. package/src/client/server/Story.ts +16 -10
  59. package/src/client/server/Variant.ts +13 -14
  60. package/src/client/server/__tests__/nesting-errors.spec.ts +48 -0
  61. package/src/client/server/context.ts +18 -0
  62. package/src/client/server/run.ts +11 -7
  63. package/src/commands/generate-story.client.ts +4 -4
  64. package/src/commands/generate-story.server.ts +2 -2
  65. package/src/helpers.ts +2 -2
  66. package/src/index.node.ts +2 -0
  67. package/src/util/list-components.spec.ts +54 -0
  68. package/src/util/list-components.ts +68 -6
@@ -1,17 +1,52 @@
1
+ import type { ComponentInternalInstance } from 'vue';
2
+ /**
3
+ * A value Vue has marked raw is carried by reference rather than rebuilt.
4
+ *
5
+ * Both sides of this bridge live in one realm, so the reference is the useful
6
+ * thing to hand over: the baseline then holds the same identity the next pass
7
+ * reads, `isEquivalent` settles it by `Object.is`, and nothing walks whatever
8
+ * is behind it. Rebuilding it was ten of the twenty traversals a keystroke
9
+ * cost (#957).
10
+ *
11
+ * The bridge that leaves this realm cannot do the same — see `toRawDeep` in
12
+ * `poveste-app`, where the mark does not survive the crossing and the key is
13
+ * dropped instead.
14
+ */
1
15
  /**
2
16
  * Using external/user Vue
3
17
  */
4
- export declare function toRawDeep(val: any, seen?: WeakMap<WeakKey, any>): any;
18
+ export declare function toRawDeep(val: unknown, seen?: WeakMap<WeakKey, any>): any;
5
19
  /**
6
20
  * Using bundled Vue
7
21
  */
8
- export declare function _toRawDeep(val: any, seen?: WeakMap<WeakKey, any>): any;
22
+ export declare function _toRawDeep(val: unknown, seen?: WeakMap<WeakKey, any>): any;
9
23
  /**
10
24
  * Synchronize states between the bundled and external/user versions of Vue
11
25
  * @param bundledState Reactive state created with the bundled Vue
12
26
  * @param externalState Reactive state created with the external/user Vue
13
27
  * @param omit Keys neither side may learn from the other
14
28
  */
15
- export declare function syncStateBundledAndExternal(bundledState: any, externalState: any, omit?: string[]): {
29
+ export declare function syncStateBundledAndExternal(bundledState: Record<string, any>, externalState: Record<string, any>, omit?: string[]): {
16
30
  stop(): void;
17
31
  };
32
+ /** The component being set up. Throws outside `setup`, where Vue returns null. */
33
+ /**
34
+ * Whether a `<script setup>` binding can be story state a control drives.
35
+ *
36
+ * A readonly ref cannot: the write-back is refused, so the two sides of the
37
+ * bridge never agree on it and the sync re-walks forever (#959). `useTemplateRef`
38
+ * returns one — in dev builds only, which is why a built book is quiet and the
39
+ * mode story authors work in is not.
40
+ *
41
+ * It has to be asked of the ref rather than of what the ref holds. The guard
42
+ * beside this one tests the value, and a value test cannot classify a template
43
+ * ref at all: at setup time it holds `null`, and what it will hold later is not
44
+ * knowable from here. Readonly-ness is a property of the ref itself and is
45
+ * settled by the time the binding is registered.
46
+ *
47
+ * A `computed` is caught by the same rule and for the same reason — it is a
48
+ * derived value, and a control that cannot write is not a control. Before this
49
+ * it appeared in the panel and warned when written.
50
+ */
51
+ export declare function isWritableBinding(value: unknown): boolean;
52
+ export declare function useInstance(name: string): ComponentInternalInstance;
@@ -1,4 +1,33 @@
1
1
  import type { Variant } from '@poveste/shared';
2
2
  import type { VNode } from 'vue';
3
3
  export declare function generateSourceCode(variant: Variant): Promise<string>;
4
+ /**
5
+ * How to delimit an attribute whose value is arbitrary code.
6
+ *
7
+ * The source pane shows template source a reader copies, so the code has to
8
+ * survive as written. The pass this replaces escaped `'` for a JavaScript
9
+ * string and rewrote `"` into `'`, and the consumer is neither — it is an
10
+ * attribute delimited by `"`. Both halves reached the reader: a handler written
11
+ * `() => alert("hi")` was shown as `() => alert('hi')`, and one written
12
+ * `() => alert('hi')` came out with visible backslashes, which reads as a bug
13
+ * in the reader's own code rather than as our rendering.
14
+ *
15
+ * The order made it worse. Every `'` the rewrite introduced arrived after the
16
+ * escaping pass, so an authored quote was escaped and a manufactured one was
17
+ * not. A backslash was never escaped at all, which is what CodeQL flagged as
18
+ * `js/incomplete-sanitization`: `() => alert('it\'s')` went in carrying one
19
+ * and came out carrying four.
20
+ *
21
+ * So nothing is escaped for a string context. Code containing `"` takes the
22
+ * other delimiter, the way someone writing the template by hand would. Code
23
+ * carrying both quote characters has no free delimiter, so whichever it takes
24
+ * is escaped inside it — and the one appearing less often wins, because every
25
+ * escape is a character the author did not write. That is `&#39;` as often as
26
+ * `&quot;`: the repository's own `get-name` fixture holds two doubles and one
27
+ * single, so the single is the cheaper one there (#602).
28
+ */
29
+ export declare function delimitAttr(lines: string[]): {
30
+ quote: string;
31
+ lines: string[];
32
+ };
4
33
  export declare function getTagName(vnode: VNode): any;
@@ -0,0 +1,40 @@
1
+ /**
2
+ * A context keyed by a symbol, with its provide and its inject in one place.
3
+ *
4
+ * Six of these used to be string keys carrying `any`, and two of the six were
5
+ * the same string meaning two different things in two realms (#981). A symbol
6
+ * cannot collide and the type travels with it.
7
+ *
8
+ * `inject` and `injectOptional` are separate functions rather than one call with a
9
+ * default, because "nobody provided this" and "this is allowed to be absent"
10
+ * are different questions that used to arrive as the same `undefined` — and the
11
+ * first one is what an author hits when they nest a component wrongly.
12
+ *
13
+ * Reka's `createContext` is this shape and is already a dependency of the
14
+ * controls package. It is not one of this package's, and this is fifteen lines,
15
+ * so it is written here rather than taking a dependency for it.
16
+ */
17
+ export interface Context<T> {
18
+ provide: (value: T) => void;
19
+ /** Throws, naming the provider, when nothing provided it. */
20
+ inject: (consumer: string) => T;
21
+ /** `null` when nothing provided it, which the caller is expected to handle. */
22
+ injectOptional: () => T | null;
23
+ }
24
+ /**
25
+ * `description` is what a symbol shows in a stack; `provider` is the component
26
+ * a reader has to go and add, and is the only part of the error they can act on.
27
+ *
28
+ * The key comes from the global registry rather than being minted here, because
29
+ * this module is evaluated more than once. A collection worker's module graph is
30
+ * invalidated while a story is mid-run, so `provide` and `inject` can each hold
31
+ * their own instance of this file — a plain `Symbol()` then differs between them
32
+ * and the injection misses, which reads as a `<Variant>` outside its `<Story>`.
33
+ * Every description here is already unique, so the registry cannot re-collide
34
+ * the way the string keys in #981 did.
35
+ *
36
+ * Absence is read as `null` rather than `undefined` so that a provider passing
37
+ * `undefined` on purpose is still a provider. None does today, and this is the
38
+ * cheaper of the two mistakes to have made.
39
+ */
40
+ export declare function createContext<T>(description: string, provider: string): Context<T>;
@@ -3,27 +3,27 @@ import type { PropType } from 'vue';
3
3
  declare const _default: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
4
4
  title: {
5
5
  type: StringConstructor;
6
- default: any;
6
+ default: undefined;
7
7
  };
8
8
  id: {
9
9
  type: StringConstructor;
10
- default: any;
10
+ default: undefined;
11
11
  };
12
12
  group: {
13
13
  type: StringConstructor;
14
- default: any;
14
+ default: undefined;
15
15
  };
16
16
  layout: {
17
17
  type: PropType<ServerStory["layout"]>;
18
- default: any;
18
+ default: undefined;
19
19
  };
20
20
  icon: {
21
21
  type: StringConstructor;
22
- default: any;
22
+ default: undefined;
23
23
  };
24
24
  iconColor: {
25
25
  type: StringConstructor;
26
- default: any;
26
+ default: undefined;
27
27
  };
28
28
  docsOnly: {
29
29
  type: BooleanConstructor;
@@ -31,34 +31,34 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
31
31
  };
32
32
  meta: {
33
33
  type: PropType<ServerStory["meta"]>;
34
- default: any;
34
+ default: undefined;
35
35
  };
36
36
  }>, {
37
37
  story: ServerStory;
38
38
  }, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
39
39
  title: {
40
40
  type: StringConstructor;
41
- default: any;
41
+ default: undefined;
42
42
  };
43
43
  id: {
44
44
  type: StringConstructor;
45
- default: any;
45
+ default: undefined;
46
46
  };
47
47
  group: {
48
48
  type: StringConstructor;
49
- default: any;
49
+ default: undefined;
50
50
  };
51
51
  layout: {
52
52
  type: PropType<ServerStory["layout"]>;
53
- default: any;
53
+ default: undefined;
54
54
  };
55
55
  icon: {
56
56
  type: StringConstructor;
57
- default: any;
57
+ default: undefined;
58
58
  };
59
59
  iconColor: {
60
60
  type: StringConstructor;
61
- default: any;
61
+ default: undefined;
62
62
  };
63
63
  docsOnly: {
64
64
  type: BooleanConstructor;
@@ -66,14 +66,14 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
66
66
  };
67
67
  meta: {
68
68
  type: PropType<ServerStory["meta"]>;
69
- default: any;
69
+ default: undefined;
70
70
  };
71
71
  }>> & Readonly<{}>, {
72
- meta: import("poveste").StoryMeta;
73
- title: string;
72
+ meta: import("poveste").StoryMeta | undefined;
74
73
  id: string;
74
+ title: string;
75
75
  group: string;
76
- layout: import("poveste").StoryLayout;
76
+ layout: import("poveste").StoryLayout | undefined;
77
77
  icon: string;
78
78
  iconColor: string;
79
79
  docsOnly: boolean;
@@ -7,19 +7,19 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
7
7
  };
8
8
  id: {
9
9
  type: StringConstructor;
10
- default: any;
10
+ default: undefined;
11
11
  };
12
12
  icon: {
13
13
  type: StringConstructor;
14
- default: any;
14
+ default: undefined;
15
15
  };
16
16
  iconColor: {
17
17
  type: StringConstructor;
18
- default: any;
18
+ default: undefined;
19
19
  };
20
20
  meta: {
21
21
  type: PropType<ServerVariant["meta"]>;
22
- default: any;
22
+ default: undefined;
23
23
  };
24
24
  }>, void, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
25
25
  title: {
@@ -28,24 +28,24 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
28
28
  };
29
29
  id: {
30
30
  type: StringConstructor;
31
- default: any;
31
+ default: undefined;
32
32
  };
33
33
  icon: {
34
34
  type: StringConstructor;
35
- default: any;
35
+ default: undefined;
36
36
  };
37
37
  iconColor: {
38
38
  type: StringConstructor;
39
- default: any;
39
+ default: undefined;
40
40
  };
41
41
  meta: {
42
42
  type: PropType<ServerVariant["meta"]>;
43
- default: any;
43
+ default: undefined;
44
44
  };
45
45
  }>> & Readonly<{}>, {
46
- meta: any;
47
- title: string;
46
+ meta: import("poveste").VariantMeta | undefined;
48
47
  id: string;
48
+ title: string;
49
49
  icon: string;
50
50
  iconColor: string;
51
51
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
@@ -0,0 +1,7 @@
1
+ import type { ServerStory, ServerStoryFile, ServerVariant } from '@poveste/shared';
2
+ /** The file being collected, provided by `run.ts` rather than by a component. */
3
+ export declare const storyFileContext: import("../context.js").Context<ServerStoryFile>;
4
+ /** Optional: a `<Story>` collected outside a run has nowhere to report to. */
5
+ export declare const addStoryContext: import("../context.js").Context<(story: ServerStory) => void>;
6
+ export declare const serverStoryContext: import("../context.js").Context<ServerStory>;
7
+ export declare const addVariantContext: import("../context.js").Context<(variant: ServerVariant) => void>;
@@ -14,13 +14,13 @@ export default {
14
14
  label: 'File name',
15
15
  type: 'text',
16
16
  required: true,
17
- defaultValue: answers => answers.component?.replace(/[^/]+\/([^/]+)\.vue$/, '$1.story.vue'),
17
+ defaultValue: answers => answers['component']?.replace(/[^/]+\/([^/]+)\.vue$/, '$1.story.vue'),
18
18
  },
19
19
  ],
20
20
  clientAction: (params) => {
21
- const index = params.component.lastIndexOf('/');
22
- const dirname = params.component.substring(0, index + 1);
23
- const file = `${dirname}${params.fileName}`;
21
+ const index = params['component'].lastIndexOf('/');
22
+ const dirname = params['component'].substring(0, index + 1);
23
+ const file = `${dirname}${params['fileName']}`;
24
24
  const storyId = kebabCase(file.toLowerCase());
25
25
  openStory(storyId);
26
26
  },
@@ -7,11 +7,11 @@ export default {
7
7
  icon: 'https://vuejs.org/logo.svg',
8
8
  searchText: 'generate create',
9
9
  async serverAction(params) {
10
- const targetFile = path.join(path.dirname(params.component), params.fileName);
10
+ const targetFile = path.join(path.dirname(params['component']), params['fileName']);
11
11
  if (fs.existsSync(targetFile)) {
12
12
  throw new Error(`File ${targetFile} already exists`);
13
13
  }
14
- const { component, componentName, isTs } = await getComponentInfo(params.component);
14
+ const { component, componentName, isTs } = await getComponentInfo(params['component']);
15
15
  const content = `<script setup${isTs ? ' lang="ts"' : ''}>
16
16
  import ${componentName} from './${component}'
17
17
  </script>
package/dist/helpers.d.ts CHANGED
@@ -2,8 +2,8 @@ import type { Story, Variant } from '@poveste/shared';
2
2
  import type { App, Component } from 'vue';
3
3
  export interface Vue3StorySetupApi {
4
4
  app: App;
5
- story?: Story;
6
- variant?: Variant;
5
+ story?: Story | undefined;
6
+ variant?: Variant | undefined;
7
7
  addWrapper: (wrapper: Component) => void;
8
8
  }
9
9
  export type Vue3StorySetupHandler = (api: Vue3StorySetupApi) => Promise<void> | void;
@@ -27,6 +27,7 @@ export function HstVue() {
27
27
  if (this.meta.poveste?.isCollecting && id.endsWith('.vue')) {
28
28
  return `const _stubComponent = (name) => ['Story','Variant'].some(validName => name.toLowerCase() === validName.toLowerCase()) ? _resolveComponent(name) : ({ render: () => null });${code?.replaceAll('_resolveComponent(', '_stubComponent(') ?? ''}`;
29
29
  }
30
+ return undefined;
30
31
  },
31
32
  },
32
33
  ],
@@ -49,6 +50,7 @@ export function HstVue() {
49
50
  return listComponentFiles(api.payload.search, api.getConfig().storyMatch);
50
51
  }
51
52
  }
53
+ return undefined;
52
54
  },
53
55
  };
54
56
  }
@@ -1 +1 @@
1
- export declare function listComponentFiles(search?: string, ignore?: string[], limit?: number): Promise<string[]>;
1
+ export declare function listComponentFiles(search?: string, ignoredPatterns?: string[], limit?: number, cwd?: string): Promise<string[]>;
@@ -1,12 +1,69 @@
1
- import { globby } from 'globby';
2
- export async function listComponentFiles(search = '', ignore = [], limit = 10) {
3
- let files = await globby('**/*.vue', {
4
- gitignore: true,
1
+ import { existsSync, readFileSync } from 'node:fs';
2
+ import { dirname, join, relative, resolve, sep } from 'node:path';
3
+ import ignore from 'ignore';
4
+ import { glob } from 'tinyglobby';
5
+ function toPosix(path) {
6
+ return path.split(sep).join('/');
7
+ }
8
+ /**
9
+ * Whether a file under `cwd` is git-ignored, the way globby's `gitignore: true`
10
+ * decided it: every `.gitignore` from the repository root down, each pattern
11
+ * relative to its own file. tinyglobby reads none of them (#839).
12
+ */
13
+ async function gitIgnoredFilter(cwd) {
14
+ let root = cwd;
15
+ while (!existsSync(join(root, '.git'))) {
16
+ const parent = dirname(root);
17
+ if (parent === root) {
18
+ root = cwd;
19
+ break;
20
+ }
21
+ root = parent;
22
+ }
23
+ const ancestors = [];
24
+ for (let dir = cwd; dir !== root;) {
25
+ dir = dirname(dir);
26
+ ancestors.unshift(join(dir, '.gitignore'));
27
+ }
28
+ // Shallow files first, so a nested `.gitignore` can override its parent.
29
+ const nested = (await glob('**/.gitignore', { cwd, absolute: true, dot: true, ignore: ['**/node_modules/**', '**/.git/**'] }))
30
+ .sort((a, b) => a.split('/').length - b.split('/').length || a.localeCompare(b));
31
+ const rules = ignore();
32
+ for (const file of [...ancestors, ...nested]) {
33
+ if (!existsSync(file)) {
34
+ continue;
35
+ }
36
+ const base = toPosix(relative(root, dirname(file)));
37
+ for (const raw of readFileSync(file, 'utf8').split(/\r?\n/)) {
38
+ const line = raw.trimEnd();
39
+ if (!line || line.startsWith('#')) {
40
+ continue;
41
+ }
42
+ const negated = line.startsWith('!');
43
+ let pattern = negated ? line.slice(1) : line;
44
+ if (base) {
45
+ // A pattern with a slash before its end is anchored to its own directory;
46
+ // one without matches at any depth below it.
47
+ const anchored = pattern.replace(/\/$/, '').includes('/');
48
+ pattern = anchored ? `${base}/${pattern.replace(/^\//, '')}` : `${base}/**/${pattern}`;
49
+ }
50
+ rules.add(negated ? `!${pattern}` : pattern);
51
+ }
52
+ }
53
+ return (file) => {
54
+ const path = toPosix(relative(root, resolve(cwd, file)));
55
+ return !path.startsWith('..') && rules.ignores(path);
56
+ };
57
+ }
58
+ export async function listComponentFiles(search = '', ignoredPatterns = [], limit = 10, cwd = process.cwd()) {
59
+ const isIgnored = await gitIgnoredFilter(cwd);
60
+ let files = (await glob('**/*.vue', {
61
+ cwd,
5
62
  ignore: [
6
63
  'node_modules',
7
- ...ignore,
64
+ ...ignoredPatterns,
8
65
  ],
9
- });
66
+ })).filter(file => !isIgnored(file));
10
67
  if (search) {
11
68
  const searchText = search.toLowerCase();
12
69
  files = files.filter(file => file.toLowerCase().includes(searchText));
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,46 @@
1
+ import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from 'node:fs';
2
+ import { tmpdir } from 'node:os';
3
+ import { dirname, join } from 'node:path';
4
+ import { afterEach, describe, expect, it } from 'vitest';
5
+ import { listComponentFiles } from './list-components.js';
6
+ const roots = [];
7
+ function tree(files) {
8
+ const root = mkdtempSync(join(tmpdir(), 'list-components-'));
9
+ roots.push(root);
10
+ for (const [path, content] of Object.entries(files)) {
11
+ mkdirSync(dirname(join(root, path)), { recursive: true });
12
+ writeFileSync(join(root, path), content);
13
+ }
14
+ return root;
15
+ }
16
+ afterEach(() => {
17
+ for (const root of roots.splice(0)) {
18
+ rmSync(root, { recursive: true, force: true });
19
+ }
20
+ });
21
+ // Listing honoured .gitignore through globby's `gitignore: true`, and tinyglobby
22
+ // has no such option, so the filtering is ours now (#839).
23
+ describe('listComponentFiles', () => {
24
+ it('leaves out components git ignores, from the root .gitignore and a nested one', async () => {
25
+ const root = tree({
26
+ '.git/HEAD': 'ref: refs/heads/main\n',
27
+ '.gitignore': 'generated/\n',
28
+ 'app/.gitignore': 'scratch/*\n!scratch/Kept.vue\n',
29
+ 'app/src/Button.vue': '',
30
+ 'app/src/generated/Output.vue': '',
31
+ 'app/scratch/Draft.vue': '',
32
+ 'app/scratch/Kept.vue': '',
33
+ });
34
+ const files = await listComponentFiles('', [], 10, join(root, 'app'));
35
+ expect(files.sort()).toEqual(['scratch/Kept.vue', 'src/Button.vue']);
36
+ });
37
+ it('still skips node_modules and the patterns it is given', async () => {
38
+ const root = tree({
39
+ '.git/HEAD': 'ref: refs/heads/main\n',
40
+ 'src/Button.vue': '',
41
+ 'src/Button.story.vue': '',
42
+ 'node_modules/pkg/Dep.vue': '',
43
+ });
44
+ expect(await listComponentFiles('', ['**/*.story.vue'], 10, root)).toEqual(['src/Button.vue']);
45
+ });
46
+ });
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@poveste/plugin-vue",
3
3
  "type": "module",
4
- "version": "0.14.0",
4
+ "version": "0.16.0",
5
5
  "description": "Poveste plugin for Vue.js support",
6
6
  "author": {
7
7
  "name": "Sorin Gitlan",
@@ -67,29 +67,30 @@
67
67
  "src"
68
68
  ],
69
69
  "engines": {
70
- "node": "^22.22.2 || ^24.15.0 || >=26.0.0"
70
+ "node": ">=22.22.2"
71
71
  },
72
72
  "peerDependencies": {
73
- "poveste": "^0.14.0",
74
- "vue": "^3.5.26"
73
+ "poveste": "^0.16.0",
74
+ "vue": "^3.5.43"
75
75
  },
76
76
  "dependencies": {
77
- "@poveste/controls": "^0.14.0",
78
- "@poveste/shared": "^0.14.0",
79
- "@poveste/vendors": "^0.14.0",
77
+ "@poveste/controls": "^0.16.0",
78
+ "@poveste/shared": "^0.16.0",
79
+ "@poveste/vendors": "^0.16.0",
80
80
  "change-case": "^5.4.4",
81
- "globby": "^14.0.2",
81
+ "ignore": "^7.0.10",
82
82
  "launch-editor": "^2.9.1",
83
- "pathe": "^1.1.2"
83
+ "pathe": "^2.0.3",
84
+ "tinyglobby": "^0.2.17"
84
85
  },
85
86
  "devDependencies": {
86
- "@types/node": "^22.10.1",
87
- "concurrently": "^9.1.0",
88
- "poveste": "0.14.0",
89
- "typescript": "5.6.3",
90
- "vite": "^8.2.0",
91
- "vitest": "^5.0.0",
92
- "vue": "^3.5.26"
87
+ "@types/node": "^26.6.3",
88
+ "concurrently": "^10.0.5",
89
+ "poveste": "0.16.0",
90
+ "typescript": "6.0.3",
91
+ "vite": "^8.3.1",
92
+ "vitest": "^5.0.2",
93
+ "vue": "^3.5.43"
93
94
  },
94
95
  "scripts": {
95
96
  "build": "rimraf dist && vite build && tsc -d -P tsconfig.build.json && pnpm run build:types",