Angular: Report what a snippet could not resolve - #35798
Draft
valentinpalkovic wants to merge 8 commits into
Draft
Angular: Report what a snippet could not resolve#35798valentinpalkovic wants to merge 8 commits into
valentinpalkovic wants to merge 8 commits into
Conversation
Contributor
|
This was referenced Aug 7, 2026
valentinpalkovic
force-pushed
the
valentin/angular-story-docs-3-warning
branch
from
August 7, 2026 16:40
8ab3bd3 to
ce7d9ad
Compare
valentinpalkovic
force-pushed
the
valentin/angular-story-docs-2-story-shapes
branch
from
August 7, 2026 16:43
056d892 to
a431b81
Compare
valentinpalkovic
force-pushed
the
valentin/angular-story-docs-3-warning
branch
from
August 7, 2026 16:43
ce7d9ad to
c0429f9
Compare
valentinpalkovic
force-pushed
the
valentin/angular-story-docs-2-story-shapes
branch
from
August 7, 2026 16:49
a431b81 to
23fdf78
Compare
valentinpalkovic
force-pushed
the
valentin/angular-story-docs-3-warning
branch
3 times, most recently
from
August 7, 2026 17:09
ce9df5d to
d9dbeea
Compare
This was referenced Aug 7, 2026
valentinpalkovic
force-pushed
the
valentin/angular-story-docs-2-story-shapes
branch
from
August 8, 2026 05:27
740865a to
e46f5c9
Compare
Server-side snippets are built by reading the story file, not by running it, so some things cannot be resolved: args merged in through a spread, a template held in an imported const, a `render` that points at a function declared elsewhere. The snippet that comes out is still useful, but until now nothing said it was partial. A story that fell back now carries a `warning` naming the source text this pass could not read, alongside the snippet it produced anyway. The note is data on the story rather than a comment inside the markup, so a consumer that renders the snippet is not left with a stray comment and one that reads it can act on it. `warning` always comes with a `snippet`; `error` continues to mean there is no snippet at all.
valentinpalkovic
force-pushed
the
valentin/angular-story-docs-3-warning
branch
from
August 8, 2026 05:42
f3061fa to
3d41670
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Note
Third of four Angular story-docs slices, stacked on #35797 (which now sits on #35807 -> #35808 -> #35805). First producer of the
warningfield added in #35794.What I did
Angular story snippets are built on the server by reading the story file, not by running it. Some things cannot be read that way: args merged in through a spread, a template held in an imported const, a
renderthat points at a function declared elsewhere. The snippet that comes out is still useful, but nothing marked it as partial, so a consumer had no way to tell an incomplete example from a complete one.Every story left incomplete now carries a
warningnaming the source text this pass could not read, next to the snippet it produced anyway.What changes in the output
The same story file, built before and after this change:
Before, the two stories are indistinguishable:
{ "example-button--spread-args": { "id": "example-button--spread-args", "name": "Spread Args", "snippet": "<sb-button [label]=\"'meta'\" [count]=\"1\" (clicked)=\"clicked($event)\"></sb-button>" }, "example-button--plain": { "id": "example-button--plain", "name": "Plain", "snippet": "<sb-button [label]=\"'meta'\" [count]=\"2\" (clicked)=\"clicked($event)\"></sb-button>" } }After, the partial one says so and the complete one is left alone:
{ "example-button--spread-args": { "id": "example-button--spread-args", "name": "Spread Args", "snippet": "<sb-button [label]=\"'meta'\" [count]=\"1\" (clicked)=\"clicked($event)\"></sb-button>", "warning": "Incomplete snippet: `...sharedArgs` could not be resolved statically." }, "example-button--plain": { "id": "example-button--plain", "name": "Plain", "snippet": "<sb-button [label]=\"'meta'\" [count]=\"2\" (clicked)=\"clicked($event)\"></sb-button>" } }labelin the first snippet is the meta's value, notsharedArgs's. The snippet itself is byte-identical in both runs; only the note next to it is new.Why a field and not a comment in the snippet
The obvious alternative is to write it into the markup:
That pushes the problem onto every consumer. The Docs Source block renders it as a stray comment, an agent reading the manifest has to parse it back out, and a story whose snippet is not HTML has no comment syntax to hide it in.
warningalways comes with asnippet.errorcontinues to mean there is no snippet at all.What counts as unresolvable
A spread at the config level hides args just as invisibly as one inside
args, so both are checked, along with computed keys and object methods:This runs over the meta's config and the story's own, so a spread written once in the meta is reported on every story it leaves incomplete.
A
templateorrenderthat could not be read as markup is reported the same way, which is what stops the silent fallback introduced in #35797 from being silent. Markup is looked for in three places in order (the story's owntemplate/render, the object a CSF2 function story returns, then the meta's), and only one of them produces the result, so the warning names that one: it always points at the markup that would have been used.One deliberate exception: a component with no selector renders as
<ng-container *ngComponentOutlet="X">, which shows no args at all, so naming the args that could not be read would say nothing about what is missing from it. Those snippets carry no warning.yarn vitest run --project "@storybook/angular-vite" code/frameworks/angular-vite/src/docgen/story-docs-build.test.tsyarn vitest run code/core/src/core-server/utils/manifestsWhat a bad run looks like
With the producer removed and the tests kept,
yarn vitest run --project "@storybook/angular-vite" code/frameworks/angular-vite/src/docgen/story-docs-build.test.tsprints:Checklist for Contributors
Testing
The changes in this PR are covered in the following automated tests:
Manual testing
yarn task sandbox --template angular-vite/docgen-server-ts --start-from auto. That template is the Angular sandbox withexperimentalDocgenServerandcomponentsManifestalready on.yarn build-storybook).storybook-static/manifests/components.json, find the component, and follow itsstories$refintostorybook-static/services/core/story-docs/<component-id>.json.Spreadstory carries awarningnaming...shared, and itssnippetcontains no HTML comment. The other stories in the same file carry nowarning.Documentation
Checklist for Maintainers
When this PR is ready for testing, make sure to add
ci:normal,ci:mergedorci:dailyGH label to it to run a specific set of sandboxes. The particular set of sandboxes can be found incode/lib/cli-storybook/src/sandbox-templates.tsDeclare whether manual QA will be needed for this PR during the next release, through
qa:neededorqa:skipMake sure this PR contains one of the labels below:
Available labels
bug: Internal changes that fixes incorrect behavior.maintenance: User-facing maintenance tasks.dependencies: Upgrading (sometimes downgrading) dependencies.build: Internal-facing build tooling & test updates. Will not show up in release changelog.cleanup: Minor cleanup style change. Will not show up in release changelog.documentation: Documentation only changes. Will not show up in release changelog.feature request: Introducing a new feature.BREAKING CHANGE: Changes that break compatibility in some way with current major version.other: Changes that don't fit in the above categories.