@poveste/plugin-vue 0.1.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.
- package/LICENSE +22 -0
- package/client.d.ts +2 -0
- package/collect.d.ts +2 -0
- package/components.d.ts +239 -0
- package/dist/bundled/client/app/MountStory.js +55 -0
- package/dist/bundled/client/app/RenderStory.js +74 -0
- package/dist/bundled/client/app/RouterLinkStub.js +40 -0
- package/dist/bundled/client/app/Story.js +112 -0
- package/dist/bundled/client/app/Variant.js +104 -0
- package/dist/bundled/client/app/auto-props.js +66 -0
- package/dist/bundled/client/app/global-components.js +81 -0
- package/dist/bundled/client/app/host.js +84 -0
- package/dist/bundled/client/app/index.js +6 -0
- package/dist/bundled/client/app/render-context.js +12 -0
- package/dist/bundled/client/app/util.js +70 -0
- package/dist/bundled/client/client.js +10 -0
- package/dist/bundled/client/codegen.js +196 -0
- package/dist/bundled/client/server/Story.js +79 -0
- package/dist/bundled/client/server/Variant.js +46 -0
- package/dist/bundled/client/server/run.js +51 -0
- package/dist/bundled/client/server/stub.js +8 -0
- package/dist/bundled/client/server.js +4 -0
- package/dist/bundled/node_modules/.pnpm/change-case@5.4.4/node_modules/change-case/dist/index.js +118 -0
- package/dist/client/app/MountStory.d.ts +16 -0
- package/dist/client/app/RenderStory.d.ts +38 -0
- package/dist/client/app/RouterLinkStub.d.ts +21 -0
- package/dist/client/app/Story.d.ts +33 -0
- package/dist/client/app/Variant.d.ts +78 -0
- package/dist/client/app/auto-props.d.ts +2 -0
- package/dist/client/app/global-components.d.ts +2 -0
- package/dist/client/app/host.d.ts +16 -0
- package/dist/client/app/index.d.ts +2 -0
- package/dist/client/app/render-context.d.ts +12 -0
- package/dist/client/app/util.d.ts +16 -0
- package/dist/client/client.d.ts +7 -0
- package/dist/client/codegen.d.ts +4 -0
- package/dist/client/server/Story.d.ts +81 -0
- package/dist/client/server/Variant.d.ts +52 -0
- package/dist/client/server/run.d.ts +2 -0
- package/dist/client/server/stub.d.ts +1 -0
- package/dist/client/server.d.ts +1 -0
- package/dist/commands/generate-story.client.d.ts +3 -0
- package/dist/commands/generate-story.client.js +27 -0
- package/dist/commands/generate-story.server.d.ts +3 -0
- package/dist/commands/generate-story.server.js +45 -0
- package/dist/helpers.d.ts +10 -0
- package/dist/helpers.js +3 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/index.node.d.ts +3 -0
- package/dist/index.node.js +54 -0
- package/dist/util/list-components.d.ts +1 -0
- package/dist/util/list-components.js +15 -0
- package/package.json +71 -0
- package/src/client/app/MountStory.ts +83 -0
- package/src/client/app/RenderStory.ts +131 -0
- package/src/client/app/RouterLinkStub.ts +48 -0
- package/src/client/app/Story.ts +209 -0
- package/src/client/app/Variant.ts +196 -0
- package/src/client/app/auto-props.ts +135 -0
- package/src/client/app/global-components.ts +131 -0
- package/src/client/app/host.ts +139 -0
- package/src/client/app/index.ts +2 -0
- package/src/client/app/render-context.ts +23 -0
- package/src/client/app/util.ts +129 -0
- package/src/client/client.ts +8 -0
- package/src/client/codegen.ts +400 -0
- package/src/client/server/Story.ts +121 -0
- package/src/client/server/Variant.ts +56 -0
- package/src/client/server/run.ts +63 -0
- package/src/client/server/stub.ts +12 -0
- package/src/client/server.ts +1 -0
- package/src/commands/generate-story.client.ts +29 -0
- package/src/commands/generate-story.server.ts +55 -0
- package/src/helpers.ts +15 -0
- package/src/index.node.ts +63 -0
- package/src/index.ts +1 -0
- package/src/util/list-components.ts +16 -0
- package/tsconfig.build.json +6 -0
- package/tsconfig.json +40 -0
- package/vite.config.ts +70 -0
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import type { ServerRunPayload } from '@poveste/shared'
|
|
2
|
+
import type { Vue3StorySetupApi, Vue3StorySetupHandler } from '../../helpers.js'
|
|
3
|
+
// @ts-expect-error virtual module id
|
|
4
|
+
import * as generatedSetup from 'virtual:$histoire-generated-global-setup'
|
|
5
|
+
// @ts-expect-error virtual module id
|
|
6
|
+
import * as setup from 'virtual:$histoire-setup'
|
|
7
|
+
import { createApp, h } from 'vue'
|
|
8
|
+
import Story from './Story'
|
|
9
|
+
import Variant from './Variant'
|
|
10
|
+
|
|
11
|
+
export async function run({ file, storyData, el }: ServerRunPayload) {
|
|
12
|
+
const { default: Comp } = await import(/* @vite-ignore */ file.moduleId)
|
|
13
|
+
|
|
14
|
+
const app = createApp({
|
|
15
|
+
provide: {
|
|
16
|
+
addStory(data) {
|
|
17
|
+
storyData.push(data)
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
render() {
|
|
21
|
+
return h(Comp, {
|
|
22
|
+
ref: 'comp',
|
|
23
|
+
data: file,
|
|
24
|
+
})
|
|
25
|
+
},
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
app.component('Story', Story)
|
|
29
|
+
|
|
30
|
+
app.component('Variant', Variant)
|
|
31
|
+
|
|
32
|
+
// Call app setups to resolve global assets such as components
|
|
33
|
+
|
|
34
|
+
const setupApi: Vue3StorySetupApi = {
|
|
35
|
+
app,
|
|
36
|
+
story: null,
|
|
37
|
+
variant: null,
|
|
38
|
+
addWrapper: () => { /* noop */ },
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
if (typeof generatedSetup?.setupVue3 === 'function') {
|
|
42
|
+
const setupFn = generatedSetup.setupVue3 as Vue3StorySetupHandler
|
|
43
|
+
await setupFn(setupApi)
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if (typeof setup?.setupVue3 === 'function') {
|
|
47
|
+
const setupFn = setup.setupVue3 as Vue3StorySetupHandler
|
|
48
|
+
await setupFn(setupApi)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
app.mount(el)
|
|
52
|
+
|
|
53
|
+
if (Comp.doc) {
|
|
54
|
+
const el = document.createElement('div')
|
|
55
|
+
el.innerHTML = Comp.doc
|
|
56
|
+
const text = el.textContent
|
|
57
|
+
storyData.forEach((s) => {
|
|
58
|
+
s.docsText = text
|
|
59
|
+
})
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
app.unmount()
|
|
63
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
const stub = { name: 'StubbedComponent', render: () => null }
|
|
2
|
+
|
|
3
|
+
export function autoStubComponents(vnodes: any[]) {
|
|
4
|
+
for (const vnode of vnodes) {
|
|
5
|
+
if (typeof vnode.type === 'object' && (vnode.type as any).name !== 'PovesteVariant') {
|
|
6
|
+
vnode.type = stub
|
|
7
|
+
}
|
|
8
|
+
if (Array.isArray(vnode.children)) {
|
|
9
|
+
autoStubComponents(vnode.children)
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './server/run.js'
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { ClientCommandOptions } from 'poveste'
|
|
2
|
+
import { kebabCase } from 'change-case'
|
|
3
|
+
import { openStory, sendEvent } from 'poveste/plugin'
|
|
4
|
+
|
|
5
|
+
export default {
|
|
6
|
+
prompts: [
|
|
7
|
+
{
|
|
8
|
+
field: 'component',
|
|
9
|
+
label: 'Choose a component',
|
|
10
|
+
type: 'select',
|
|
11
|
+
options: async search => sendEvent('listVueComponents', { search }),
|
|
12
|
+
required: true,
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
field: 'fileName',
|
|
16
|
+
label: 'File name',
|
|
17
|
+
type: 'text',
|
|
18
|
+
required: true,
|
|
19
|
+
defaultValue: answers => answers.component?.replace(/[^/]+\/([^/]+)\.vue$/, '$1.story.vue'),
|
|
20
|
+
},
|
|
21
|
+
],
|
|
22
|
+
clientAction: (params) => {
|
|
23
|
+
const index = params.component.lastIndexOf('/')
|
|
24
|
+
const dirname = params.component.substring(0, index + 1)
|
|
25
|
+
const file = `${dirname}${params.fileName}`
|
|
26
|
+
const storyId = kebabCase(file.toLowerCase())
|
|
27
|
+
openStory(storyId)
|
|
28
|
+
},
|
|
29
|
+
} as ClientCommandOptions
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import type { PluginCommand } from 'poveste'
|
|
2
|
+
import fs from 'node:fs'
|
|
3
|
+
import launchEditor from 'launch-editor'
|
|
4
|
+
import path from 'pathe'
|
|
5
|
+
|
|
6
|
+
export default {
|
|
7
|
+
id: 'histoire:plugin-vue:generate-story',
|
|
8
|
+
label: 'Generate Vue 3 story from component',
|
|
9
|
+
icon: 'https://vuejs.org/logo.svg',
|
|
10
|
+
searchText: 'generate create',
|
|
11
|
+
async serverAction(params) {
|
|
12
|
+
const targetFile = path.join(path.dirname(params.component), params.fileName)
|
|
13
|
+
|
|
14
|
+
if (fs.existsSync(targetFile)) {
|
|
15
|
+
throw new Error(`File ${targetFile} already exists`)
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const { component, componentName, isTs } = await getComponentInfo(params.component)
|
|
19
|
+
|
|
20
|
+
const content = `<script setup${isTs ? ' lang="ts"' : ''}>
|
|
21
|
+
import ${componentName} from './${component}'
|
|
22
|
+
</script>
|
|
23
|
+
|
|
24
|
+
<template>
|
|
25
|
+
<Story>
|
|
26
|
+
<Variant title="Default">
|
|
27
|
+
<${componentName} />
|
|
28
|
+
</Variant>
|
|
29
|
+
</Story>
|
|
30
|
+
</template>
|
|
31
|
+
`
|
|
32
|
+
|
|
33
|
+
await fs.promises.writeFile(targetFile, content, 'utf-8')
|
|
34
|
+
|
|
35
|
+
launchEditor(targetFile)
|
|
36
|
+
},
|
|
37
|
+
clientSetupFile: '@poveste/plugin-vue/dist/commands/generate-story.client.js',
|
|
38
|
+
} as PluginCommand
|
|
39
|
+
|
|
40
|
+
async function isComponentTs(component: string) {
|
|
41
|
+
const componentContent = await fs.promises.readFile(component, 'utf-8')
|
|
42
|
+
return componentContent.includes('lang="ts"')
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
async function getComponentInfo(file: string) {
|
|
46
|
+
const component = path.basename(file)
|
|
47
|
+
const componentName = component.replace(path.extname(component), '')
|
|
48
|
+
const isTs = await isComponentTs(file)
|
|
49
|
+
|
|
50
|
+
return {
|
|
51
|
+
component,
|
|
52
|
+
componentName,
|
|
53
|
+
isTs,
|
|
54
|
+
}
|
|
55
|
+
}
|
package/src/helpers.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { Story, Variant } from '@poveste/shared'
|
|
2
|
+
import type { App, Component } from 'vue'
|
|
3
|
+
|
|
4
|
+
export interface Vue3StorySetupApi {
|
|
5
|
+
app: App
|
|
6
|
+
story?: Story
|
|
7
|
+
variant?: Variant
|
|
8
|
+
addWrapper: (wrapper: Component) => void
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export type Vue3StorySetupHandler = (api: Vue3StorySetupApi) => Promise<void> | void
|
|
12
|
+
|
|
13
|
+
export function defineSetupVue3(handler: Vue3StorySetupHandler): Vue3StorySetupHandler {
|
|
14
|
+
return handler
|
|
15
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import type { Plugin } from 'poveste'
|
|
2
|
+
|
|
3
|
+
import generateStoryCommand from './commands/generate-story.server.js'
|
|
4
|
+
import { listComponentFiles } from './util/list-components.js'
|
|
5
|
+
|
|
6
|
+
export function HstVue(): Plugin {
|
|
7
|
+
return {
|
|
8
|
+
name: '@poveste/plugin-vue',
|
|
9
|
+
|
|
10
|
+
defaultConfig() {
|
|
11
|
+
return {
|
|
12
|
+
supportMatch: [
|
|
13
|
+
{
|
|
14
|
+
id: 'vue',
|
|
15
|
+
patterns: ['**/*.vue'],
|
|
16
|
+
pluginIds: ['vue3'],
|
|
17
|
+
},
|
|
18
|
+
],
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
|
|
22
|
+
config() {
|
|
23
|
+
return {
|
|
24
|
+
vite: {
|
|
25
|
+
plugins: [
|
|
26
|
+
{
|
|
27
|
+
name: 'histoire-plugin-vue',
|
|
28
|
+
enforce: 'post',
|
|
29
|
+
transform(code, id) {
|
|
30
|
+
// Remove vue warnings about unknown components
|
|
31
|
+
if ((this.meta as any).histoire?.isCollecting && id.endsWith('.vue')) {
|
|
32
|
+
return `const _stubComponent = (name) => ['Story','Variant'].some(validName => name.toLowerCase() === validName.toLowerCase()) ? _resolveComponent(name) : ({ render: () => null });${code?.replaceAll('_resolveComponent(', '_stubComponent(') ?? ''}`
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
],
|
|
37
|
+
},
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
|
|
41
|
+
supportPlugin: {
|
|
42
|
+
id: 'vue3',
|
|
43
|
+
moduleName: '@poveste/plugin-vue',
|
|
44
|
+
setupFn: 'setupVue3',
|
|
45
|
+
importStoriesPrepend: `import { defineAsyncComponent as defineAsyncComponentVue3 } from 'vue'`,
|
|
46
|
+
importStoryComponent: (file, index) => `const Comp${index} = defineAsyncComponentVue3(() => import(${JSON.stringify(file.moduleId)}))`,
|
|
47
|
+
},
|
|
48
|
+
|
|
49
|
+
commands: [
|
|
50
|
+
generateStoryCommand,
|
|
51
|
+
],
|
|
52
|
+
|
|
53
|
+
async onDevEvent(api) {
|
|
54
|
+
switch (api.event) {
|
|
55
|
+
case 'listVueComponents': {
|
|
56
|
+
return listComponentFiles(api.payload.search, api.getConfig().storyMatch)
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export * from './helpers.js'
|
package/src/index.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './helpers.js'
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { globby } from 'globby'
|
|
2
|
+
|
|
3
|
+
export async function listComponentFiles(search = '', ignore: string[] = [], limit = 10) {
|
|
4
|
+
let files = await globby('**/*.vue', {
|
|
5
|
+
gitignore: true,
|
|
6
|
+
ignore: [
|
|
7
|
+
'node_modules',
|
|
8
|
+
...ignore,
|
|
9
|
+
],
|
|
10
|
+
})
|
|
11
|
+
if (search) {
|
|
12
|
+
const searchText = search.toLowerCase()
|
|
13
|
+
files = files.filter(file => file.toLowerCase().includes(searchText))
|
|
14
|
+
}
|
|
15
|
+
return files.slice(0, limit)
|
|
16
|
+
}
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ESNext",
|
|
4
|
+
// Volar
|
|
5
|
+
"jsx": "preserve",
|
|
6
|
+
"lib": [
|
|
7
|
+
"ESNext",
|
|
8
|
+
"DOM"
|
|
9
|
+
],
|
|
10
|
+
"rootDir": "src",
|
|
11
|
+
"module": "ESNext",
|
|
12
|
+
"moduleResolution": "node",
|
|
13
|
+
"resolveJsonModule": true,
|
|
14
|
+
"types": [
|
|
15
|
+
"node"
|
|
16
|
+
],
|
|
17
|
+
"strictBindCallApply": true,
|
|
18
|
+
"strictFunctionTypes": true,
|
|
19
|
+
"alwaysStrict": true,
|
|
20
|
+
// Strict
|
|
21
|
+
"noImplicitAny": false,
|
|
22
|
+
"noImplicitThis": true,
|
|
23
|
+
"outDir": "dist",
|
|
24
|
+
"removeComments": false,
|
|
25
|
+
"sourceMap": false,
|
|
26
|
+
"allowSyntheticDefaultImports": true,
|
|
27
|
+
"esModuleInterop": true,
|
|
28
|
+
"skipLibCheck": true,
|
|
29
|
+
"preserveWatchOutput": true
|
|
30
|
+
},
|
|
31
|
+
"include": [
|
|
32
|
+
"src"
|
|
33
|
+
],
|
|
34
|
+
"exclude": [
|
|
35
|
+
"node_modules",
|
|
36
|
+
"generated/**/*",
|
|
37
|
+
"dist/**/*",
|
|
38
|
+
"src/**/*.spec.ts"
|
|
39
|
+
]
|
|
40
|
+
}
|
package/vite.config.ts
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import fs from 'node:fs'
|
|
2
|
+
import { globbySync } from 'globby'
|
|
3
|
+
import { defineConfig } from 'vite'
|
|
4
|
+
|
|
5
|
+
export default defineConfig({
|
|
6
|
+
plugins: [
|
|
7
|
+
{
|
|
8
|
+
name: 'histoire:preserve:import.dynamic',
|
|
9
|
+
enforce: 'pre',
|
|
10
|
+
transform(code) {
|
|
11
|
+
if (code.includes('import(')) {
|
|
12
|
+
return {
|
|
13
|
+
code: code.replace(/import\(/g, 'import__dyn('),
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
closeBundle() {
|
|
18
|
+
try {
|
|
19
|
+
const files = globbySync('./dist/**/*.js')
|
|
20
|
+
for (const file of files) {
|
|
21
|
+
const content = fs.readFileSync(file, 'utf-8')
|
|
22
|
+
if (content.includes('import__dyn')) {
|
|
23
|
+
fs.writeFileSync(file, content.replace(/import__dyn\(/g, 'import(/* @vite-ignore */'), 'utf-8')
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
catch (e) {
|
|
28
|
+
console.error(e)
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
],
|
|
33
|
+
|
|
34
|
+
build: {
|
|
35
|
+
emptyOutDir: false,
|
|
36
|
+
outDir: 'dist/bundled',
|
|
37
|
+
lib: {
|
|
38
|
+
entry: '',
|
|
39
|
+
formats: ['es'],
|
|
40
|
+
},
|
|
41
|
+
rollupOptions: {
|
|
42
|
+
external: [
|
|
43
|
+
/\$histoire/,
|
|
44
|
+
/@poveste/,
|
|
45
|
+
'vue',
|
|
46
|
+
],
|
|
47
|
+
|
|
48
|
+
input: [
|
|
49
|
+
'src/client/client.ts',
|
|
50
|
+
'src/client/server.ts',
|
|
51
|
+
],
|
|
52
|
+
|
|
53
|
+
output: {
|
|
54
|
+
// manualChunks (id) {
|
|
55
|
+
// if (id.includes('node_modules')) {
|
|
56
|
+
// return 'vendor'
|
|
57
|
+
// }
|
|
58
|
+
// },
|
|
59
|
+
entryFileNames: '[name].js',
|
|
60
|
+
chunkFileNames: '[name].js',
|
|
61
|
+
assetFileNames: '[name][extname]',
|
|
62
|
+
// hoistTransitiveImports: false,
|
|
63
|
+
preserveModules: true,
|
|
64
|
+
preserveModulesRoot: 'src',
|
|
65
|
+
},
|
|
66
|
+
treeshake: false,
|
|
67
|
+
preserveEntrySignatures: 'strict',
|
|
68
|
+
},
|
|
69
|
+
},
|
|
70
|
+
})
|