Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
8172258
Vue: Synthesize static story snippets from args
huang-julien Aug 6, 2026
cbc34b1
test: add snippet in generated snapshots
huang-julien Aug 7, 2026
d3366ea
chore: add comments
huang-julien Aug 8, 2026
2875084
refactor: hoist quote string into script var
huang-julien Aug 10, 2026
5e327fe
fix: Suppress snippets for render stories and classify args from argT…
huang-julien Aug 10, 2026
6619cce
fix: gen safe attributes
huang-julien Aug 10, 2026
2c2460e
fix: reject nested identifier references
huang-julien Aug 10, 2026
5698f91
fix: treat undefined args as unset
huang-julien Aug 11, 2026
7510236
fix: read CSF2 assigned story args
huang-julien Aug 11, 2026
2003598
refactor: classify arg values into a closed union
huang-julien Aug 11, 2026
c6d1358
feat: render declared listeners, function props, and static function …
huang-julien Aug 11, 2026
6221026
refactor: resolve meta object path once per story file
huang-julien Aug 11, 2026
22b6b27
refactor: name the story-docs context and hoist the snippet-possible …
huang-julien Aug 11, 2026
33545ac
test: be more precise on snippet changes
huang-julien Aug 11, 2026
c04d4de
fix: omit capturing functions and report unparsable candidates first
huang-julien Aug 11, 2026
4c6d7c1
test: update tests to be more comprehensive
huang-julien Aug 11, 2026
57898cc
chore: remove snippet parity test
huang-julien Aug 11, 2026
22d32e7
fix: hoist string slots
huang-julien Aug 12, 2026
014c4a0
chore: correctlyu indent snippets
huang-julien Aug 12, 2026
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
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,18 @@ describe('expectCurrentOrBetter', () => {
).toThrow(/changed-summary/);
});

it('reports an unparsable candidate instead of calling declared omissions stale', () => {
expect(() =>
expectCurrentOrBetter({
kind: 'snippet',
framework: 'vue3',
baseline: '<template>\n <C :severity="severity" />\n</template>',
candidate: 'not a snippet',
declaredOmissions: ['severity'],
})
).toThrow(/unparsable-candidate/);
});

it('routes snippet input to the snippet comparator', () => {
const baseline = '<sb-cmp [count]="3"></sb-cmp>';
expect(() =>
Expand Down
56 changes: 45 additions & 11 deletions code/lib/docgen-harness/src/compare/expect-current-or-better.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,22 +11,56 @@ export type ExpectCurrentOrBetterInput =
baseline: StrictArgTypes;
candidate: StrictArgTypes;
} & CompareArgTypesOptions)
| ({ kind: 'snippet' } & CompareSnippetInput);
| ({ kind: 'snippet' } & CompareSnippetInput & {
/**
* Args the candidate is expected to leave out even though the baseline represents them,
* because their source references a binding a static snippet cannot declare. The candidate
* records each one in `StoryDoc.warning`, and the runtime keeps its own snippet for readers
* who need the resolved value.
*
* Checked in both directions: an arg listed here that the candidate does represent fails, so
* the list cannot outlive the gap it documents.
*/
declaredOmissions?: readonly string[];
});

/** Throws a single error listing every violation, so a failure shows the whole gap at once. */
export function expectCurrentOrBetter(input: ExpectCurrentOrBetterInput): void {
const violations: Violation[] =
input.kind === 'argTypes'
? compareArgTypes(input.baseline, input.candidate, {
legacyBaseline: input.legacyBaseline,
strictTable: input.strictTable,
})
: compareSnippet(input);
if (violations.length > 0) {
const lines = violations.map((v) => `- [${v.kind}] ${v.arg}: ${v.message}`);
if (input.kind === 'argTypes') {
throwOnViolations(
compareArgTypes(input.baseline, input.candidate, {
legacyBaseline: input.legacyBaseline,
strictTable: input.strictTable,
})
);
return;
}

const declaredOmissions = input.declaredOmissions ?? [];
const violations = compareSnippet(input);
// An unparsable candidate leaves nothing omitted
throwOnViolations(violations.filter((v) => v.kind !== 'lost-representation'));

const omitted = new Set(violations.map((v) => v.arg));
const stale = declaredOmissions.filter((arg) => !omitted.has(arg));
if (stale.length > 0) {
// eslint-disable-next-line local-rules/no-uncategorized-errors
throw new Error(
`expectCurrentOrBetter found ${violations.length} violation(s):\n${lines.join('\n')}`
`The candidate snippet now represents ${stale.join(', ')} — remove it from declaredOmissions`
);
Comment thread
huang-julien marked this conversation as resolved.
}

throwOnViolations(violations.filter((v) => !declaredOmissions.includes(v.arg)));
}

function throwOnViolations(violations: Violation[]): void {
if (violations.length === 0) {
return;
}

const lines = violations.map((v) => `- [${v.kind}] ${v.arg}: ${v.message}`);
// eslint-disable-next-line local-rules/no-uncategorized-errors
throw new Error(
`expectCurrentOrBetter found ${violations.length} violation(s):\n${lines.join('\n')}`
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
"description": undefined,
"id": "forms-cross-file-composed-utility--props-as-written",
"name": "Props As Written",
"snippet": "<template>
<UtilityComposedProps label="Picked" />
</template>",
"summary": undefined,
},
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
"description": undefined,
"id": "forms-cross-file-extended-interface--props-as-written",
"name": "Props As Written",
"snippet": "<template>
<ExtendedInterfaceProps extra :id="7" name="Chained" />
</template>",
"summary": undefined,
},
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
"description": undefined,
"id": "forms-cross-file-imported-interface--props-as-written",
"name": "Props As Written",
"snippet": "<template>
<ImportedInterfaceProps :count="2" label="Imported" />
</template>",
"summary": undefined,
},
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
"description": undefined,
"id": "forms-cross-file-props-spread--props-as-written",
"name": "Props As Written",
"snippet": "<template>
<CrossFilePropsSpread label="Text label" :optional="false" value="hello" />
</template>",
"summary": undefined,
},
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
"description": undefined,
"id": "forms-cross-file-runtime-props--props-as-written",
"name": "Props As Written",
"snippet": "<template>
<CrossFileRuntimeProps :count="3" label="Imported" />
</template>",
"summary": undefined,
},
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
"description": undefined,
"id": "forms-cross-file-union-alias--props-as-written",
"name": "Props As Written",
"snippet": "<template>
<CrossFileUnionAlias size="small" variant="danger" />
</template>",
"summary": undefined,
},
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
"description": undefined,
"id": "forms-define-expose--props-as-written",
"name": "Props As Written",
"snippet": "<template>
<DefineExpose label="Increment" />
</template>",
"summary": undefined,
},
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
"description": undefined,
"id": "forms-define-props-destructured--props-as-written",
"name": "Props As Written",
"snippet": "<template>
<DestructuredProps label="Sized" size="large" />
</template>",
"summary": undefined,
},
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
"description": undefined,
"id": "forms-define-props-runtime-array--props-as-written",
"name": "Props As Written",
"snippet": "<template>
<RuntimeArrayProps appearance="primary" label="Go" />
</template>",
"summary": undefined,
},
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
"description": undefined,
"id": "forms-define-props-runtime-object--props-as-written",
"name": "Props As Written",
"snippet": "<template>
<RuntimeObjectProps :count="3" label="Total" />
</template>",
"summary": undefined,
},
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
"description": undefined,
"id": "forms-define-slots-with-props--props-as-written",
"name": "Props As Written",
"snippet": "<template>
<DefineSlotsWithProps disabled label="Save" />
</template>",
"summary": undefined,
},
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,15 @@
"description": undefined,
"id": "forms-events-jsdoc--with-handlers",
"name": "With Handlers",
"snippet": "<script lang="ts" setup>
const onCancel = () => {};

const onSave = () => {};
</script>

<template>
<EventsJsdoc label="Save" @cancel="onCancel" @save="onSave" />
</template>",
"summary": undefined,
},
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
"description": undefined,
"id": "forms-jsdoc-tags--props-as-written",
"name": "Props As Written",
"snippet": "<template>
<JsdocTags label="Old label" title="New title" />
</template>",
"summary": undefined,
},
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
"description": undefined,
"id": "forms-prop-slot-name-collision--icon-prop-as-written",
"name": "Icon Prop As Written",
"snippet": "<template>
<PropSlotNameCollision icon="pi pi-check" />
</template>",
"summary": undefined,
},
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,30 @@
"description": undefined,
"id": "forms-props-basic-types--props-as-written",
"name": "Props As Written",
"snippet": "<template>
<PropsBasicTypes :count="2" enabled label="Hello" />
</template>",
"summary": undefined,
},
"forms-props-basic-types--unrepresentable-args": {
"description": undefined,
"id": "forms-props-basic-types--unrepresentable-args",
"name": "Unrepresentable Args",
"snippet": "<script lang="ts" setup>
const big = BigInt('9007199254740993');

const config = { theme: 'dark', dense: true };

const formatter = (value: number) => `#${value}`;

const tags = ['alpha', 'beta'];

const token = Symbol('fixture');
</script>

<template>
<PropsBasicTypes :big="big" :config="config" :formatter="formatter" label="Formatted" :tags="tags" :token="token" />
</template>",
"summary": undefined,
},
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,13 @@
"description": undefined,
"id": "forms-props-generic--props-as-written",
"name": "Props As Written",
"snippet": "<script lang="ts" setup>
const items = ['alpha', 'beta'];
</script>

<template>
<PropsGeneric :items="items" selected="alpha" />
</template>",
"summary": undefined,
},
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,11 @@
"description": undefined,
"id": "forms-props-ts-enum--props-as-written",
"name": "Props As Written",
"snippet": "<template>
<TsEnumProps :level="1" />
</template>",
"summary": undefined,
"warning": "Omitted args that cannot be resolved statically: severity: Severity.Warning",
},
},
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
"description": undefined,
"id": "forms-props-union-enum--props-as-written",
"name": "Props As Written",
"snippet": "<template>
<PropsUnionEnum size="medium" status="ok" />
</template>",
"summary": undefined,
},
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,16 @@
"description": undefined,
"id": "forms-recursive-type--props-as-written",
"name": "Props As Written",
"snippet": "<script lang="ts" setup>
const node = {
value: 'root',
children: [{ value: 'leaf', children: [] }],
};
</script>

<template>
<RecursiveTree :node="node" />
</template>",
"summary": undefined,
},
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
"description": undefined,
"id": "forms-runtime-multi-constructor--props-as-written",
"name": "Props As Written",
"snippet": "<template>
<RuntimeMultiConstructor :width="200" />
</template>",
"summary": undefined,
},
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
"description": undefined,
"id": "forms-runtime-proptype-cast--props-as-written",
"name": "Props As Written",
"snippet": "<template>
<RuntimePropTypeCast kind="secondary" :measure="42" />
</template>",
"summary": undefined,
},
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,20 @@
"description": undefined,
"id": "forms-slots-template-only--string-child",
"name": "String Child",
"snippet": "<script lang="ts" setup>
const _default = 'Plain text content';

const header = 'Header text';
</script>

<template>
<TemplateOnlySlots>
{{ _default }}
<template #header>
{{ header }}
</template>
</TemplateOnlySlots>
</template>",
"summary": undefined,
},
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,15 @@
"description": undefined,
"id": "forms-slots--string-child",
"name": "String Child",
"snippet": "<script lang="ts" setup>
const _default = 'Plain text content';
</script>

<template>
<SlotsShowcase heading="Plain">
{{ _default }}
</SlotsShowcase>
</template>",
"summary": undefined,
},
"forms-slots--v-node-child": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
"description": undefined,
"id": "forms-type-intersection-whole--props-as-written",
"name": "Props As Written",
"snippet": "<template>
<TypeIntersectionWhole id="save-button" size="medium" />
</template>",
"summary": undefined,
},
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,13 @@
"description": undefined,
"id": "forms-type-intersection--props-as-written",
"name": "Props As Written",
"snippet": "<script lang="ts" setup>
const mixed = { label: 'Intersected', count: 2, extra: true };
</script>

<template>
<IntersectionProps :mixed="mixed" />
</template>",
"summary": undefined,
},
},
Expand Down
Loading