diff --git a/code/renderers/vue/src/docs/sourceDecorator.ts b/code/renderers/vue/src/docs/sourceDecorator.ts index 24c4fe3c4ddb..becc96802860 100644 --- a/code/renderers/vue/src/docs/sourceDecorator.ts +++ b/code/renderers/vue/src/docs/sourceDecorator.ts @@ -4,7 +4,7 @@ import { addons } from '@storybook/preview-api'; import { logger } from '@storybook/client-logger'; import { SourceType, SNIPPET_RENDERED } from '@storybook/docs-tools'; -import type { ComponentOptions } from 'vue'; +import { type ComponentOptions } from 'vue'; import type Vue from 'vue'; import type { StoryContext } from '../types'; @@ -24,46 +24,47 @@ export const skipSourceRender = (context: StoryContext) => { export const sourceDecorator = (storyFn: any, context: StoryContext) => { const story = storyFn(); + const source = ''; // See ../react/jsxDecorator.tsx - if (skipSourceRender(context)) { + const skip = skipSourceRender(context); + if (skip) { return story; } const channel = addons.getChannel(); const storyComponent = getStoryComponent(story.options.STORYBOOK_WRAPS); + const generateSource = (vueInstance: any) => { + try { + // console.log('updateSource():', vueInstance.$vnode); + const storyNode = lookupStoryInstance(vueInstance, storyComponent); + if (!storyNode) { + logger.warn(`Failed to find story component in the rendered tree: ${storyComponent}`); + return; + } + // eslint-disable-next-line no-param-reassign + vueInstance.source = vnodeToString(storyNode._vnode); + } catch (e) { + logger.warn(`Failed to generate dynamic story source: ${e}`); + } + }; return { components: { Story: story, }, - // We need to wait until the wrapper component to be mounted so Vue runtime - // struct VNode tree. We get `this._vnode == null` if switch to `created` - // lifecycle hook. + data() { + return { source }; + }, + updated() { + generateSource(this); + }, mounted() { - // Theoretically this does not happens but we need to check it. - // @ts-expect-error TS says it is called $vnode - if (!this._vnode) { - return; - } - - try { - const storyNode = lookupStoryInstance(this, storyComponent); - - // @ts-expect-error TS says it is called $vnode - const code = vnodeToString(storyNode._vnode); - - const { id, unmappedArgs } = context; - channel.emit(SNIPPET_RENDERED, { - id, - args: unmappedArgs, - source: ``, - format: 'vue', - }); - } catch (e) { - logger.warn(`Failed to generate dynamic story source: ${e}`); - } + this.$watch('source', (val) => + channel.emit(SNIPPET_RENDERED, context.id, ``, 'vue') + ); + generateSource(this); }, template: '', } as ComponentOptions & ThisType;