From 7c85a39e0de2365af376612bc2710898858964d0 Mon Sep 17 00:00:00 2001 From: Jonathan Carle Date: Fri, 2 Aug 2024 11:30:25 +0200 Subject: [PATCH 1/3] extend vue3 sourceDecorator to support v-bind and nested keys --- .../vue3/src/docs/sourceDecorator.test.ts | 12 ++- .../vue3/src/docs/sourceDecorator.ts | 84 +++++++++++++++---- 2 files changed, 77 insertions(+), 19 deletions(-) diff --git a/code/renderers/vue3/src/docs/sourceDecorator.test.ts b/code/renderers/vue3/src/docs/sourceDecorator.test.ts index 4f92bcd9cb27..764ba403cf3a 100644 --- a/code/renderers/vue3/src/docs/sourceDecorator.test.ts +++ b/code/renderers/vue3/src/docs/sourceDecorator.test.ts @@ -150,16 +150,20 @@ test('should generate source code for slots with bindings', () => { type TestBindings = { foo: string; bar?: number; + boo: { + mimeType: string; + }; }; const slots = { - a: ({ foo, bar }: TestBindings) => `Slot with bindings ${foo} and ${bar}`, - b: ({ foo }: TestBindings) => h('a', { href: foo, target: foo }, `Test link: ${foo}`), + a: ({ foo, bar, boo }: TestBindings) => `Slot with bindings ${foo}, ${bar} and ${boo.mimeType}`, + b: ({ foo, boo }: TestBindings) => + h('a', { href: foo, target: foo, type: boo.mimeType, ...boo }, `Test link: ${foo}`), }; - const expectedCode = ` + const expectedCode = ` -`; +`; const actualCode = generateSlotSourceCode(slots, Object.keys(slots), { imports: {}, diff --git a/code/renderers/vue3/src/docs/sourceDecorator.ts b/code/renderers/vue3/src/docs/sourceDecorator.ts index 764aacf91fe7..375db1b3a4c4 100644 --- a/code/renderers/vue3/src/docs/sourceDecorator.ts +++ b/code/renderers/vue3/src/docs/sourceDecorator.ts @@ -23,6 +23,20 @@ export type SourceCodeGeneratorContext = { imports: Record>; }; +/** + * Used to get the tracking data from the proxy. + * A symbol is unique, so when using it as a key it can't be accidentally accessed. + */ +const TRACKING_SYMBOL = Symbol('DEEP_ACCESS_SYMBOL'); + +type TrackingProxy = { + [TRACKING_SYMBOL]: true; + toString: () => string; +}; + +const isProxy = (obj: unknown): obj is TrackingProxy => + !!(obj && typeof obj === 'object' && TRACKING_SYMBOL in obj); + /** * Decorator to generate Vue source code for stories. */ @@ -208,6 +222,10 @@ export const generatePropsSourceCode = ( if (slotNames.includes(propName)) return; if (value == undefined) return; // do not render undefined/null values + if (isProxy(value)) { + value = value.toString(); + } + switch (typeof value) { case 'string': if (value === '') return; // do not render empty strings @@ -249,7 +267,7 @@ export const generatePropsSourceCode = ( case 'object': { properties.push({ name: propName, - value: formatObject(value), + value: formatObject(value ?? {}), // to follow Vue best practices, complex values like object and arrays are // usually placed inside the