From 11d4396a62108c2ac69de2b3a5f6acf2ddb4057d Mon Sep 17 00:00:00 2001 From: chakAs3 Date: Tue, 20 Jun 2023 15:39:11 +0400 Subject: [PATCH 1/2] fix source decorator reactivity --- .../renderers/vue/src/docs/sourceDecorator.ts | 63 ++++++++++--------- 1 file changed, 35 insertions(+), 28 deletions(-) diff --git a/code/renderers/vue/src/docs/sourceDecorator.ts b/code/renderers/vue/src/docs/sourceDecorator.ts index 24c4fe3c4ddb..48e66b2ba75e 100644 --- a/code/renderers/vue/src/docs/sourceDecorator.ts +++ b/code/renderers/vue/src/docs/sourceDecorator.ts @@ -1,10 +1,10 @@ /* eslint-disable no-underscore-dangle */ /* eslint no-underscore-dangle: ["error", { "allow": ["_vnode"] }] */ -import { addons } from '@storybook/preview-api'; +import { addons, useEffect } from '@storybook/preview-api'; import { logger } from '@storybook/client-logger'; import { SourceType, SNIPPET_RENDERED } from '@storybook/docs-tools'; -import type { ComponentOptions } from 'vue'; +import { h, type ComponentOptions, ref, watch } from 'vue'; import type Vue from 'vue'; import type { StoryContext } from '../types'; @@ -24,46 +24,53 @@ export const skipSourceRender = (context: StoryContext) => { export const sourceDecorator = (storyFn: any, context: StoryContext) => { const story = storyFn(); + const source = ref(undefined); // See ../react/jsxDecorator.tsx - if (skipSourceRender(context)) { + const skip = skipSourceRender(context); + if (skip) { return story; } const channel = addons.getChannel(); + watch( + () => source, + () => { + if (!skip) { + channel.emit(SNIPPET_RENDERED, (context || {}).id, ``); + } + }, + { immediate: true, deep: true } + ); const storyComponent = getStoryComponent(story.options.STORYBOOK_WRAPS); + const generateSource = (vueInstance: Vue) => { + 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 consistent-return + return vnodeToString(storyNode._vnode); + } catch (e) { + logger.warn(`Failed to generate dynamic story source: ${e}`); + } + // eslint-disable-next-line consistent-return + return undefined; + }; 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. + updated() { + source.value = 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}`); - } + source.value = generateSource(this); }, template: '', } as ComponentOptions & ThisType; From f6b3735ef07a472aa67dca3e400335f45cabbb36 Mon Sep 17 00:00:00 2001 From: chakAs3 Date: Tue, 20 Jun 2023 16:16:39 +0400 Subject: [PATCH 2/2] add reactivity to source decorator ( vue2 ) --- .../renderers/vue/src/docs/sourceDecorator.ts | 34 ++++++++----------- 1 file changed, 14 insertions(+), 20 deletions(-) diff --git a/code/renderers/vue/src/docs/sourceDecorator.ts b/code/renderers/vue/src/docs/sourceDecorator.ts index 48e66b2ba75e..becc96802860 100644 --- a/code/renderers/vue/src/docs/sourceDecorator.ts +++ b/code/renderers/vue/src/docs/sourceDecorator.ts @@ -1,10 +1,10 @@ /* eslint-disable no-underscore-dangle */ /* eslint no-underscore-dangle: ["error", { "allow": ["_vnode"] }] */ -import { addons, useEffect } from '@storybook/preview-api'; +import { addons } from '@storybook/preview-api'; import { logger } from '@storybook/client-logger'; import { SourceType, SNIPPET_RENDERED } from '@storybook/docs-tools'; -import { h, type ComponentOptions, ref, watch } from 'vue'; +import { type ComponentOptions } from 'vue'; import type Vue from 'vue'; import type { StoryContext } from '../types'; @@ -24,7 +24,7 @@ export const skipSourceRender = (context: StoryContext) => { export const sourceDecorator = (storyFn: any, context: StoryContext) => { const story = storyFn(); - const source = ref(undefined); + const source = ''; // See ../react/jsxDecorator.tsx const skip = skipSourceRender(context); @@ -33,18 +33,9 @@ export const sourceDecorator = (storyFn: any, context: StoryContext) => { } const channel = addons.getChannel(); - watch( - () => source, - () => { - if (!skip) { - channel.emit(SNIPPET_RENDERED, (context || {}).id, ``); - } - }, - { immediate: true, deep: true } - ); const storyComponent = getStoryComponent(story.options.STORYBOOK_WRAPS); - const generateSource = (vueInstance: Vue) => { + const generateSource = (vueInstance: any) => { try { // console.log('updateSource():', vueInstance.$vnode); const storyNode = lookupStoryInstance(vueInstance, storyComponent); @@ -52,25 +43,28 @@ export const sourceDecorator = (storyFn: any, context: StoryContext) => { logger.warn(`Failed to find story component in the rendered tree: ${storyComponent}`); return; } - - // eslint-disable-next-line consistent-return - return vnodeToString(storyNode._vnode); + // eslint-disable-next-line no-param-reassign + vueInstance.source = vnodeToString(storyNode._vnode); } catch (e) { logger.warn(`Failed to generate dynamic story source: ${e}`); } - // eslint-disable-next-line consistent-return - return undefined; }; return { components: { Story: story, }, + data() { + return { source }; + }, updated() { - source.value = generateSource(this); + generateSource(this); }, mounted() { - source.value = generateSource(this); + this.$watch('source', (val) => + channel.emit(SNIPPET_RENDERED, context.id, ``, 'vue') + ); + generateSource(this); }, template: '', } as ComponentOptions & ThisType;