Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Vue: Replace vue-docgen-api with Volar vue-component-meta #22285

Merged
merged 203 commits into from
Feb 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
203 commits
Select commit Hold shift + click to select a range
fecc165
add component meta 1.5.4 + tests
chakAs3 Apr 27, 2023
1744729
upgrade vue-component-meta
chakAs3 Apr 27, 2023
ee87fb7
remoe "vue-docgen-loader"
chakAs3 Apr 27, 2023
2d155af
run yarn to update deps
chakAs3 Apr 27, 2023
50f37e4
Merge branch 'chaks/fix-sandbox-nx-deps' into chaks/vue-component-meta
chakAs3 May 8, 2023
c15f27a
add some logs
chakAs3 May 9, 2023
8f47cb1
add all type of components + tests
chakAs3 May 15, 2023
23e0ab7
remove the undefined string from event descriptions
chakAs3 May 15, 2023
c730333
Merge branch 'next' into chaks/vue-component-meta
chakAs3 May 15, 2023
dd02f17
refactory extractArgTypes vue3
chakAs3 May 18, 2023
d4c34ef
refactory stories for vue-component meta
chakAs3 May 18, 2023
5f2f547
add unity tests for extractArgTypes
chakAs3 May 18, 2023
291ec4c
refactory component meta plugin
chakAs3 May 18, 2023
bfb8bd9
Merge branch 'next' into chaks/vue-component-meta
chakAs3 May 18, 2023
7c18b7b
refactory export function
chakAs3 May 18, 2023
a37d65d
refactory for better types
chakAs3 May 19, 2023
4e87c9c
remove vue-component-meta from main project, keep it only in packag…
chakAs3 May 19, 2023
975ddd7
revert back nx version update for darwin
chakAs3 May 19, 2023
815f0e9
add vue3 meta-component support
chakAs3 May 19, 2023
9a7cf88
Merge branch 'next' into chaks/vue-component-meta
chakAs3 May 22, 2023
b306138
refactory to pass type check
chakAs3 May 22, 2023
c84d8f8
Merge branch 'next' into chaks/vue-component-meta
chakAs3 May 22, 2023
045b450
update vue-component-meta
chakAs3 May 22, 2023
c781baa
fix type check for addon docs
chakAs3 May 22, 2023
e8870a0
Merge branch 'next' into chaks/vue-component-meta
chakAs3 May 22, 2023
8f5f871
refactory for type check
chakAs3 May 24, 2023
5cd3604
Merge branch 'next' into chaks/vue-component-meta
chakAs3 May 24, 2023
3c26a03
revert to next
chakAs3 May 24, 2023
c377d73
Merge branch 'next' into chaks/vue-component-meta
chakAs3 May 24, 2023
29fce71
update vue component meta
chakAs3 May 24, 2023
3fd9b33
Merge branch 'next' into chaks/vue-component-meta
chakAs3 May 24, 2023
9c7a13d
fix type checking errors
chakAs3 May 24, 2023
acf6c26
Merge branch 'next' into chaks/vue-component-meta
chakAs3 May 27, 2023
b05339a
Merge branch 'next' into chaks/vue-component-meta
chakAs3 May 28, 2023
184e71d
new defineComponent API, passing setup function as param
chakAs3 May 29, 2023
f47be75
reset vue-component-meta to stable version
chakAs3 May 29, 2023
52fe01c
i remove the Omit cause i don't see the purpose of it
chakAs3 May 29, 2023
d566404
add vue 3.3.0 peerDeps
chakAs3 May 29, 2023
52bc921
fix type check
chakAs3 May 29, 2023
729fe65
fix type check
chakAs3 May 29, 2023
e1ad917
fix webpack vue sandbox deps
chakAs3 May 30, 2023
2ba5cf7
disable controls for exposed and events and fix Record type control
chakAs3 May 30, 2023
c221ff7
update the unit test
chakAs3 May 30, 2023
80456d7
add meta load for vue on webpack
chakAs3 May 31, 2023
ade42a3
Merge branch 'next' into chaks/vue-component-meta
chakAs3 Jun 2, 2023
a3b474b
revert back webpack
chakAs3 Jun 2, 2023
3457d60
Merge branch 'next' into chaks/vue-component-meta
chakAs3 Jun 2, 2023
330ff55
lockfile chnge
chakAs3 Jun 2, 2023
693381b
remove meta-loader for later
chakAs3 Jun 2, 2023
9cee347
update vue-component-meta to fix typescript peerDeps
chakAs3 Jun 2, 2023
3992919
Merge branch 'next' into chaks/vue-component-meta
chakAs3 Jun 2, 2023
42c907d
add typescript to deps
chakAs3 Jun 2, 2023
bfad9fc
remove display nested props info for now
chakAs3 Jun 2, 2023
fe0c4ec
fix unit-test and update vue-jest
chakAs3 Jun 3, 2023
addf64d
remove nested type info dispay on vue2 for now
chakAs3 Jun 3, 2023
7e4c4c9
Merge branch 'next' into chaks/vue-component-meta
chakAs3 Jun 3, 2023
27455c9
add typescript as peerDeps, required by vue-component-meta
chakAs3 Jun 3, 2023
a8e39e7
add typescript peerDeps for @storybook/vue
chakAs3 Jun 3, 2023
8db7905
fix typeName index
chakAs3 Jun 3, 2023
bad08e7
set defaut control for boolean
chakAs3 Jun 3, 2023
3892050
add description to test component
chakAs3 Jun 4, 2023
f413b93
fix story template invalide event
chakAs3 Jun 4, 2023
1f99b2d
refactory and cleanup
chakAs3 Jun 4, 2023
91c807c
fix vue2 deps
chakAs3 Jun 4, 2023
c2404bb
add onClick to argTypes to pass to e2e test
chakAs3 Jun 4, 2023
da10cff
fix test story args type
chakAs3 Jun 4, 2023
ffc29d8
fix onClick action log cli
chakAs3 Jun 4, 2023
7c98b8d
add more get control info
chakAs3 Jun 5, 2023
226400c
Merge branch 'next' into chaks/vue-component-meta
chakAs3 Jun 5, 2023
9a2b924
unit test changes
chakAs3 Jun 5, 2023
fd3a600
add extra type union prop in test story
chakAs3 Jun 5, 2023
0600ec7
add emits to component in order to expose the event
chakAs3 Jun 5, 2023
d52a733
Merge branch 'next' into chaks/vue-component-meta
chakAs3 Jun 6, 2023
7a96d9c
lockfile after install
chakAs3 Jun 6, 2023
4015a93
optional control.disable to match tests
chakAs3 Jun 6, 2023
f0f2336
add emits events
chakAs3 Jun 6, 2023
cdd6dcf
use consistent event attributes, remove unused code
chakAs3 Jun 7, 2023
64a9c4f
add description to example cli
chakAs3 Jun 7, 2023
52446b5
Merge branch 'next' into chaks/vue-component-meta
chakAs3 Jun 7, 2023
e08af56
Merge branch 'next' into chaks/vue-component-meta
chakAs3 Jun 7, 2023
4ef7b67
Merge branch 'next' into chaks/vue-component-meta
chakAs3 Jun 8, 2023
985d90d
vue tools version
chakAs3 Jun 8, 2023
b859b35
vue version
chakAs3 Jun 8, 2023
49323a3
Merge branch 'next' into chaks/vue-component-meta
chakAs3 Jun 8, 2023
45858bc
normalize the cli template. update vue2 deps
chakAs3 Jun 9, 2023
abeecca
Merge branch 'next' into chaks/vue-component-meta
chakAs3 Jun 13, 2023
9ef0eab
Merge branch 'next' into chaks/vue-component-meta
chakAs3 Jun 16, 2023
28f2f31
update meta-component to get new api type
chakAs3 Jun 16, 2023
2059de1
ajust cli template for types
chakAs3 Jun 17, 2023
881db6c
Merge branch 'next' into chaks/vue-component-meta
chakAs3 Jun 17, 2023
a4aed06
update vue-componen-meta
chakAs3 Jun 19, 2023
de3f548
adapt vue 2 to emits events
chakAs3 Jun 19, 2023
b0b8d8e
Merge branch 'next' into chaks/vue-component-meta
chakAs3 Jun 20, 2023
5bfdd33
remove unecessary deps
chakAs3 Jun 20, 2023
4305146
fix sub packages
chakAs3 Jun 20, 2023
411944c
set vue-template-compiler as devDep
chakAs3 Jun 20, 2023
367f0c0
fix out of project deps for vue-cli sandbox
chakAs3 Jun 20, 2023
4bb564b
fix type issue after api changes
chakAs3 Jun 20, 2023
1f4889b
Merge branch 'next' into chaks/vue-component-meta
chakAs3 Jun 20, 2023
0b71dcc
fix typo removed a line
chakAs3 Jun 20, 2023
7554510
clean up cli template code
chakAs3 Jun 21, 2023
a225ce5
Merge branch 'next' into chaks/vue-component-meta
chakAs3 Jun 21, 2023
8547960
Merge branch 'chaks/fix-ts-deps-react' into chaks/vue-component-meta
chakAs3 Jun 21, 2023
7e19547
Merge branch 'next' into chaks/vue-component-meta
chakAs3 Jun 21, 2023
26a79b3
Merge branch 'chaks/fix-ts-deps-react' into chaks/vue-component-meta
chakAs3 Jun 21, 2023
85b1741
Merge branch 'next' into chaks/vue-component-meta
chakAs3 Jun 21, 2023
f4adf08
generate yarn to fix unit-tests
chakAs3 Jun 21, 2023
74ec395
fix deps on vue3
chakAs3 Jun 21, 2023
209fe54
move vue-component-type-helpers to devDeps
chakAs3 Jun 21, 2023
f954f2c
no need to redeclare __STORYBOOK_ADDONS_CHANNEL__
chakAs3 Jun 21, 2023
6be4d3b
Merge branch 'chaks/vue-move-type-helpers-deps' into chaks/vue-compon…
chakAs3 Jun 21, 2023
3bd8831
move deps to right type
chakAs3 Jun 22, 2023
8c7afa0
Merge branch 'chaks/vue-move-type-helpers-deps' into chaks/vue-compon…
chakAs3 Jun 22, 2023
7f822b0
fix deps and cleanup
chakAs3 Jun 22, 2023
0b64013
generate lockfile
chakAs3 Jun 22, 2023
224deb2
Merge branch 'chaks/fix-ts-deps-react' into chaks/vue-move-type-helpe…
chakAs3 Jun 22, 2023
5a63650
Merge branch 'chaks/vue-move-type-helpers-deps' into chaks/vue-compon…
chakAs3 Jun 22, 2023
ac232dc
Merge branch 'chaks/fix-ts-deps-react' into chaks/vue-component-meta
chakAs3 Jun 22, 2023
72b8137
Merge branch 'next' into chaks/vue-component-meta
chakAs3 Jun 22, 2023
2940ff7
provide vue/compiler-core
chakAs3 Jun 22, 2023
953698c
update vue-component-meta & ajust extractArgTypes
chakAs3 Jul 2, 2023
dc6fd47
Merge branch 'next' into chaks/vue-component-meta
chakAs3 Jul 2, 2023
d0eddb6
update deps vue
chakAs3 Jul 2, 2023
35dfb9a
use getProjectRoot + add tsx,jsx
chakAs3 Jul 2, 2023
d76391e
add support JSX,expertName components,class & function
chakAs3 Jul 2, 2023
4ba2231
set es target 2021
chakAs3 Jul 2, 2023
56314ce
safe using component type
chakAs3 Jul 3, 2023
0586d82
refactory & update unit-tests
chakAs3 Jul 3, 2023
787edd3
add support for jsx & named export component
chakAs3 Jul 5, 2023
d27c4dc
refactor and cleanup fix some egdes
chakAs3 Jul 5, 2023
edce7aa
add tests stories for ts named export
chakAs3 Jul 5, 2023
cde0696
move typescript to peerDep
chakAs3 Jul 5, 2023
babd3a4
Merge branch 'next' into chaks/vue-component-meta
chakAs3 Jul 5, 2023
08bc358
generate lockfile
chakAs3 Jul 5, 2023
774f22f
use no ts typechecker
chakAs3 Jul 5, 2023
9726aa4
fix undefined type
chakAs3 Jul 5, 2023
1f28986
Merge branch 'next' into chaks/vue-component-meta
chakAs3 Jul 7, 2023
0f5eeab
Merge branch 'next' into chaks/vue-component-meta
chakAs3 Jul 9, 2023
9e65b62
generate lockfile
chakAs3 Jul 9, 2023
e7cab9e
Merge remote-tracking branch 'origin/next' into chaks/vue-component-meta
kasperpeulen Jul 25, 2023
2b90791
Merge remote-tracking branch 'origin/next' into chaks/vue-component-meta
kasperpeulen Jul 25, 2023
bdd08f4
Fix yarn.lock
kasperpeulen Jul 25, 2023
81eb09e
Don't change target in tsconfig.json
kasperpeulen Jul 25, 2023
035010c
Move vue-component-type-helpers to normal deps
kasperpeulen Jul 25, 2023
d07bfc5
Merge branch 'next' into chaks/vue-component-meta
kasperpeulen Jul 26, 2023
60b8540
Merge branch 'next' of https://github.com/storybookjs/storybook into …
chakAs3 Sep 11, 2023
41d2be4
upgrade component-meta
chakAs3 Sep 15, 2023
8fe06a9
Merge branch 'next' of https://github.com/storybookjs/storybook into …
chakAs3 Sep 15, 2023
93a3790
update deps and exclude stories files from check
chakAs3 Sep 23, 2023
f535efd
fix type check
chakAs3 Sep 23, 2023
02fd3c1
Merge branch 'next' of https://github.com/storybookjs/storybook into …
chakAs3 Sep 23, 2023
e0a27ca
Merge branch 'next' of https://github.com/storybookjs/storybook into …
chakAs3 Oct 3, 2023
f618233
Merge branch 'next' into chaks/vue-component-meta
yannbf Oct 3, 2023
bc68613
Merge branch 'next' into chaks/vue-component-meta
chakAs3 Oct 3, 2023
1ea44ac
Merge branch 'chaks/vue-component-meta' of https://github.com/storybo…
chakAs3 Oct 7, 2023
c00d17a
Merge branch next into chaks/vue-component-meta
chakAs3 Jan 27, 2024
800bb4f
refactory & cleanup to fix long time merge
chakAs3 Jan 27, 2024
b3d1020
refactory
chakAs3 Jan 27, 2024
f467388
refactory & cleanup
chakAs3 Jan 27, 2024
9b9cd5d
Merge branch 'next' into chaks/vue-component-meta
chakAs3 Jan 28, 2024
75e2ca9
Merge branch 'next' into chaks/vue-component-meta
chakAs3 Jan 28, 2024
337c0f6
fix linting
chakAs3 Jan 28, 2024
170ed94
Merge branch 'chaks/vue-component-meta' of https://github.com/storybo…
chakAs3 Jan 28, 2024
8d74d95
replace jest with vitest
chakAs3 Jan 28, 2024
70cd79a
Merge branch 'next' into chaks/vue-component-meta
chakAs3 Jan 29, 2024
f4b8636
added find-package-json
chakAs3 Jan 29, 2024
5198b6a
fix imports
chakAs3 Jan 29, 2024
b19dc7d
cleanup logs
chakAs3 Jan 29, 2024
d60d546
fix deps + types
chakAs3 Jan 30, 2024
81cc6a1
Merge branch 'next' into chaks/vue-component-meta
chakAs3 Feb 12, 2024
6d7087d
Merge branch 'next' into chaks/vue-component-meta
larsrickert Feb 16, 2024
6000c7c
remove unwanted exposed slots/events
larsrickert Feb 16, 2024
6566d07
remove unnecessary schema
larsrickert Feb 16, 2024
9fae623
use project tsconfig for meta checker
larsrickert Feb 16, 2024
63ec7a0
fix error for non-vue component exports from .ts files
larsrickert Feb 16, 2024
75732a3
use fallback checker if no tsconfig.json exists
larsrickert Feb 16, 2024
9b57d80
fix check CI
larsrickert Feb 17, 2024
87d007d
add temp workaround for missing Volar event descriptions
larsrickert Feb 17, 2024
226bf21
fix ReferenceError for re-exports
larsrickert Feb 18, 2024
96c64cc
fix typo
larsrickert Feb 18, 2024
80bb204
remove unused extends
larsrickert Feb 18, 2024
624ddff
extract code to "createChecker" method
larsrickert Feb 18, 2024
d8e8640
Update code/frameworks/vue3-vite/src/plugins/vue-component-meta.ts
larsrickert Feb 18, 2024
59743ea
Merge branch 'next' into chaks/vue-component-meta
chakAs3 Feb 18, 2024
f79c7cc
fix lint error
larsrickert Feb 18, 2024
5832537
add temporary workaround for tsconfig with references
larsrickert Feb 19, 2024
c202721
prevent reference errors
larsrickert Feb 19, 2024
21557c1
remove ts from runtime code
larsrickert Feb 19, 2024
95acca3
add missing error handling
larsrickert Feb 19, 2024
79c8078
Merge branch 'next' into chaks/vue-component-meta
larsrickert Feb 19, 2024
d5e7fdb
style: update code formatting
larsrickert Feb 19, 2024
dd85701
update exclude filter
larsrickert Feb 20, 2024
07702dd
support both "vue-docgen-api" and "volar"
larsrickert Feb 22, 2024
e3a1d4a
rename "docgen-api" to "vue-docgen-api"
larsrickert Feb 22, 2024
e047e7b
rename "docgen-api" to "vue-docgen-api"
larsrickert Feb 22, 2024
e6c0cc3
use real framework options
larsrickert Feb 22, 2024
cd4fd8c
Merge branch 'next' into chaks/vue-component-meta
larsrickert Feb 22, 2024
4b6f889
Merge branch 'next' into chaks/vue-component-meta
chakAs3 Feb 22, 2024
3ab790c
fix: update arg types extractor
larsrickert Feb 23, 2024
b47da2b
Merge branch 'next' into chaks/vue-component-meta
kasperpeulen Feb 23, 2024
ae87a4a
fix tests
larsrickert Feb 23, 2024
388e29c
Merge branch 'chaks/vue-component-meta' of https://github.com/storybo…
larsrickert Feb 23, 2024
f910dcc
rename docgen option "volar" to "vue-component-meta"
larsrickert Feb 23, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion code/frameworks/vue3-vite/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,14 @@
"@storybook/builder-vite": "workspace:*",
"@storybook/core-server": "workspace:*",
"@storybook/vue3": "workspace:*",
"find-package-json": "^1.2.0",
"magic-string": "^0.30.0",
"vue-docgen-api": "^4.40.0"
"typescript": "^5.0.0",
"vue-component-meta": "^1.8.27",
"vue-docgen-api": "^4.75.1"
},
"devDependencies": {
"@types/find-package-json": "^1.2.6",
"@types/node": "^18.0.0",
"typescript": "^5.3.2",
"vite": "^4.0.0"
Expand Down
253 changes: 253 additions & 0 deletions code/frameworks/vue3-vite/src/plugins/vue-component-meta.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,253 @@
import findPackageJson from 'find-package-json';
import fs from 'fs/promises';
import MagicString from 'magic-string';
import path from 'path';
import type { PluginOption } from 'vite';
import {
TypeMeta,
createComponentMetaChecker,
createComponentMetaCheckerByJsonConfig,
type ComponentMeta,
type MetaCheckerOptions,
} from 'vue-component-meta';
import { parseMulti } from 'vue-docgen-api';

type MetaSource = {
exportName: string;
displayName: string;
sourceFiles: string;
} & ComponentMeta &
MetaCheckerOptions['schema'];

export async function vueComponentMeta(): Promise<PluginOption> {
const { createFilter } = await import('vite');

// exclude stories, virtual modules and storybook internals
const exclude =
/\.stories\.(ts|tsx|js|jsx)$|^\/virtual:|^\/sb-preview\/|\.storybook\/.*\.(ts|js)$/;
const include = /\.(vue|ts|js|tsx|jsx)$/;
const filter = createFilter(include, exclude);

const checker = await createChecker();

return {
name: 'storybook:vue-component-meta-plugin',
async transform(src, id) {
if (!filter(id)) return undefined;

try {
const exportNames = checker.getExportNames(id);
let componentsMeta = exportNames.map((name) => checker.getComponentMeta(id, name));
componentsMeta = await applyTempFixForEventDescriptions(id, componentsMeta);

const metaSources: MetaSource[] = [];

componentsMeta.forEach((meta, index) => {
// filter out empty meta
const isEmpty =
!meta.props.length && !meta.events.length && !meta.slots.length && !meta.exposed.length;
if (isEmpty || meta.type === TypeMeta.Unknown) return;

const exportName = exportNames[index];

const exposed =
// the meta also includes duplicated entries in the "exposed" array with "on"
// prefix (e.g. onClick instead of click), so we need to filter them out here
meta.exposed
.filter((expose) => {
let nameWithoutOnPrefix = expose.name;

if (nameWithoutOnPrefix.startsWith('on')) {
nameWithoutOnPrefix = lowercaseFirstLetter(expose.name.replace('on', ''));
}

const hasEvent = meta.events.find((event) => event.name === nameWithoutOnPrefix);
return !hasEvent;
})
// remove unwanted duplicated "$slots" expose
.filter((expose) => {
if (expose.name === '$slots') {
const slotNames = meta.slots.map((slot) => slot.name);
return !slotNames.every((slotName) => expose.type.includes(slotName));
}
return true;
});

metaSources.push({
exportName,
displayName: exportName === 'default' ? getFilenameWithoutExtension(id) : exportName,
...meta,
exposed,
sourceFiles: id,
});
});

// if there is no component meta, return undefined
if (metaSources.length === 0) return undefined;

const s = new MagicString(src);

metaSources.forEach((meta) => {
const isDefaultExport = meta.exportName === 'default';
const name = isDefaultExport ? '_sfc_main' : meta.exportName;

// we can only add the "__docgenInfo" to variables that are actually defined in the current file
// so e.g. re-exports like "export { default as MyComponent } from './MyComponent.vue'" must be ignored
// to prevent runtime errors
if (new RegExp(`export {.*${name}.*}`).test(src)) {
return;
}

if (!id.endsWith('.vue') && isDefaultExport) {
// we can not add the __docgenInfo if the component is default exported directly
// so we need to safe it to a variable instead and export default it instead
s.replace('export default ', 'const _sfc_main = ');
s.append('\nexport default _sfc_main;');
}

s.append(`\n;${name}.__docgenInfo = ${JSON.stringify(meta)}`);
});

return {
code: s.toString(),
map: s.generateMap({ hires: true, source: id }),
};
} catch (e) {
return undefined;
}
},
};
}

/**
* Creates the vue-component-meta checker to use for extracting component meta/docs.
*/
async function createChecker() {
const checkerOptions: MetaCheckerOptions = {
forceUseTs: true,
noDeclarations: true,
printer: { newLine: 1 },
};

const projectRoot = getProjectRoot();
const projectTsConfigPath = path.join(projectRoot, 'tsconfig.json');

const defaultChecker = createComponentMetaCheckerByJsonConfig(
projectRoot,
{ include: ['**/*'] },
checkerOptions
);

// prefer the tsconfig.json file of the project to support alias resolution etc.
if (await fileExists(projectTsConfigPath)) {
larsrickert marked this conversation as resolved.
Show resolved Hide resolved
// tsconfig that uses references is currently not supported by vue-component-meta
// see: https://github.com/vuejs/language-tools/issues/3896
// so we return the no-tsconfig defaultChecker if tsconfig references are found
// remove this workaround once the above issue is fixed
const references = await getTsConfigReferences(projectTsConfigPath);
if (references.length > 0) {
// TODO: paths/aliases are not resolvable, find workaround for this
return defaultChecker;
}
return createComponentMetaChecker(projectTsConfigPath, checkerOptions);
}

return defaultChecker;
}

/**
* Gets the absolute path to the project root.
*/
function getProjectRoot() {
const projectRoot = findPackageJson().next().value?.path ?? '';

const currentFileDir = path.dirname(__filename);
const relativePathToProjectRoot = path.relative(currentFileDir, projectRoot);

return path.resolve(currentFileDir, relativePathToProjectRoot);
}

/**
* Gets the filename without file extension.
*/
function getFilenameWithoutExtension(filename: string) {
return path.parse(filename).name;
}

/**
* Lowercases the first letter.
*/
function lowercaseFirstLetter(string: string) {
return string.charAt(0).toLowerCase() + string.slice(1);
}

/**
* Checks whether the given file path exists.
*/
async function fileExists(fullPath: string) {
try {
await fs.stat(fullPath);
return true;
} catch {
return false;
}
}

/**
* Applies a temporary workaround/fix for missing event descriptions because
* Volar is currently not able to extract them.
* Will modify the events of the passed meta.
* Performance note: Based on some quick tests, calling "parseMulti" only takes a few milliseconds (8-20ms)
* so it should not decrease performance that much. Especially because it is only execute if the component actually
* has events.
*
* Check status of this Volar issue: https://github.com/vuejs/language-tools/issues/3893
* and update/remove this workaround once Volar supports it:
* - delete this function
* - uninstall vue-docgen-api dependency
*/
async function applyTempFixForEventDescriptions(filename: string, componentMeta: ComponentMeta[]) {
// do not apply temp fix if no events exist for performance reasons
const hasEvents = componentMeta.some((meta) => meta.events.length);
if (!hasEvents) return componentMeta;

try {
const parsedComponentDocs = await parseMulti(filename);

// add event descriptions to the existing Volar meta if available
componentMeta.map((meta, index) => {
const eventsWithDescription = parsedComponentDocs[index].events;
if (!meta.events.length || !eventsWithDescription?.length) return meta;

meta.events = meta.events.map((event) => {
const description = eventsWithDescription.find((i) => i.name === event.name)?.description;
if (description) {
(event as typeof event & { description: string }).description = description;
}
return event;
});

return meta;
});
} catch {
// noop
}

return componentMeta;
}

/**
* Gets a list of tsconfig references for the given tsconfig path.
* This is only needed for the temporary workaround/fix for:
* https://github.com/vuejs/language-tools/issues/3896
*/
async function getTsConfigReferences(tsConfigPath: string) {
try {
const content = JSON.parse(await fs.readFile(tsConfigPath, 'utf-8'));
if (!('references' in content) || !Array.isArray(content.references)) return [];
return content.references as unknown[];
} catch {
// invalid project tsconfig
return [];
}
}
14 changes: 7 additions & 7 deletions code/frameworks/vue3-vite/src/plugins/vue-docgen.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
import { parse } from 'vue-docgen-api';
import type { PluginOption } from 'vite';
import MagicString from 'magic-string';
import type { PluginOption } from 'vite';
import { parse } from 'vue-docgen-api';

export async function vueDocgen(): Promise<PluginOption> {
const include = /\.(vue)$/;
const { createFilter } = await import('vite');

const include = /\.(vue)$/;
const filter = createFilter(include);

return {
name: 'storybook:vue-docgen-plugin',

async transform(src: string, id: string) {
async transform(src, id) {
if (!filter(id)) return undefined;

const metaData = await parse(id);
const metaSource = JSON.stringify(metaData);

const s = new MagicString(src);
s.append(`;_sfc_main.__docgenInfo = ${metaSource}`);
s.append(`;_sfc_main.__docgenInfo = ${JSON.stringify(metaData)}`);

return {
code: s.toString(),
Expand Down
21 changes: 16 additions & 5 deletions code/frameworks/vue3-vite/src/preset.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import type { PresetProperty } from '@storybook/types';
import type { PluginOption } from 'vite';
import { dirname, join } from 'path';
import type { StorybookConfig } from './types';
import type { PluginOption } from 'vite';
import { vueComponentMeta } from './plugins/vue-component-meta';
import { vueDocgen } from './plugins/vue-docgen';
import type { FrameworkOptions, StorybookConfig } from './types';

const getAbsolutePath = <I extends string>(input: I): I =>
dirname(require.resolve(join(input, 'package.json'))) as any;
Expand All @@ -12,11 +13,21 @@ export const core: PresetProperty<'core'> = {
renderer: getAbsolutePath('@storybook/vue3'),
};

export const viteFinal: StorybookConfig['viteFinal'] = async (config, { presets }) => {
export const viteFinal: StorybookConfig['viteFinal'] = async (config, options) => {
const plugins: PluginOption[] = [];

// Add docgen plugin
plugins.push(await vueDocgen());
const framework = await options.presets.apply('framework');
const frameworkOptions: FrameworkOptions =
typeof framework === 'string' ? {} : framework.options ?? {};

const docgenPlugin = frameworkOptions.docgen ?? 'vue-docgen-api';

// add docgen plugin depending on framework option
if (docgenPlugin === 'vue-component-meta') {
plugins.push(await vueComponentMeta());
} else {
plugins.push(await vueDocgen());
}

const { mergeConfig } = await import('vite');
return mergeConfig(config, {
Expand Down
11 changes: 10 additions & 1 deletion code/frameworks/vue3-vite/src/types.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,20 @@
import type { BuilderOptions, StorybookConfigVite } from '@storybook/builder-vite';
import type { StorybookConfig as StorybookConfigBase } from '@storybook/types';
import type { StorybookConfigVite, BuilderOptions } from '@storybook/builder-vite';

type FrameworkName = '@storybook/vue3-vite';
type BuilderName = '@storybook/builder-vite';

export type FrameworkOptions = {
builder?: BuilderOptions;
/**
* Plugin to use for generation docs for component props, events, slots and exposes.
* Since Storybook 8, the official vue plugin "vue-component-meta" (Volar) can be used which supports
* more complex types, better type docs, support for js(x)/ts(x) components and more.
*
* "vue-component-meta" will become the new default in the future and "vue-docgen-api" will be removed.
* @default "vue-docgen-api"
*/
docgen?: 'vue-docgen-api' | 'vue-component-meta';
};

type StorybookConfigFramework = {
Expand Down
Loading
Loading