Repository navigation
Storybook: Make declared IDs the source of truth for URLs #82123
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: trunk
Are you sure you want to change the base?
Changes from all commits
d9f8880
3aa6769
8d3d307
3188a2d
a52a39d
c3574e4
e6fbe17
27c0701
ba4c9ab
d576cca
7b0c452
a68888d
592ef72
59e3f33
c768a63
e722df5
e7a37f6
7c7af36
bce4061
5a7affe
9400009
8424800
7427d66
82efa75
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,6 +1,6 @@ | ||
| import { Meta, Markdown } from '@storybook/addon-docs/blocks'; | ||
| import Readme from '../../README.md?raw'; | ||
|
|
||
| <Meta title="Design System/Theme/Introduction" /> | ||
| <Meta title="Design System/Theme/Introduction" id="design-system-theme-introduction" /> | ||
|
|
||
| <Markdown>{Readme}</Markdown> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,6 +1,6 @@ | ||
| import { Meta, Markdown } from '@storybook/addon-docs/blocks'; | ||
| import Tokens from '../../docs/tokens.md?raw'; | ||
|
|
||
| <Meta title="Design System/Tokens/Introduction" /> | ||
| <Meta title="Design System/Tokens/Introduction" id="design-system-tokens-introduction" /> | ||
|
|
||
| <Markdown>{Tokens}</Markdown> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,87 @@ | ||
| #!/usr/bin/env node | ||
| /** | ||
| * Generates a snapshot of every Storybook story and doc URL. | ||
| * | ||
| * A story's URL is its ID, and every published link, bookmark, handbook page | ||
| * and deprecation notice points at one. The snapshot records the full set so | ||
| * that losing one has to be a deliberate act rather than a side effect of a | ||
| * rename nobody looked at twice. | ||
| * | ||
| * The snapshot is regenerated in CI, which fails if an ID it used to contain | ||
| * is gone. Removing a page on purpose still works: delete it and commit the | ||
| * regenerated snapshot in the same change, where the loss is visible in the | ||
| * diff. New IDs are written without complaint. | ||
| * | ||
| * The story index is built from source, so this needs no Storybook build. | ||
| * | ||
| * Usage: node generate-story-id-snapshot.mjs | ||
| */ | ||
| import { readFile, writeFile } from 'node:fs/promises'; | ||
| import path from 'node:path'; | ||
| import { buildIndex } from 'storybook/internal/core-server'; | ||
|
|
||
| const CONFIG_DIR = path.join( import.meta.dirname, '..' ); | ||
| const SNAPSHOT_PATH = path.join( CONFIG_DIR, 'story-ids.txt' ); | ||
|
|
||
| const HEADER = | ||
| '# Auto-generated snapshot of every Storybook story and doc URL.\n' + | ||
| '# Do not edit by hand. Regenerate with `npm run storybook:story-id-snapshot`\n' + | ||
| '# and commit the result. See `storybook/README.md` for details.\n'; | ||
|
|
||
| /** | ||
| * Reads the IDs out of the committed snapshot, ignoring its header. | ||
| * | ||
| * @return {Promise<string[]>} The IDs, or an empty list if there is no | ||
| * snapshot yet. | ||
| */ | ||
| async function readSnapshot() { | ||
| try { | ||
| const raw = await readFile( SNAPSHOT_PATH, 'utf8' ); | ||
| return raw | ||
| .split( '\n' ) | ||
| .map( ( line ) => line.trim() ) | ||
| .filter( ( line ) => line && ! line.startsWith( '#' ) ); | ||
| } catch ( error ) { | ||
| if ( | ||
| /** @type {NodeJS.ErrnoException} */ ( error ).code !== 'ENOENT' | ||
| ) { | ||
| throw error; | ||
| } | ||
| return []; | ||
| } | ||
| } | ||
|
|
||
| const { entries } = await buildIndex( { configDir: CONFIG_DIR } ); | ||
| const current = Object.keys( entries ).sort(); | ||
|
|
||
| if ( current.length === 0 ) { | ||
| console.error( | ||
| 'No stories were indexed. The Storybook configuration may have changed.' | ||
| ); | ||
| process.exit( 1 ); | ||
| } | ||
|
|
||
| const committed = await readSnapshot(); | ||
| const currentIds = new Set( current ); | ||
| const committedIds = new Set( committed ); | ||
| const removed = committed.filter( ( id ) => ! currentIds.has( id ) ); | ||
| const added = current.filter( ( id ) => ! committedIds.has( id ) ); | ||
|
|
||
| await writeFile( SNAPSHOT_PATH, HEADER + current.join( '\n' ) + '\n' ); | ||
|
|
||
| if ( added.length > 0 ) { | ||
| console.log( `Added ${ added.length } story ID(s) to the snapshot.` ); | ||
| } | ||
|
|
||
| if ( removed.length > 0 ) { | ||
| console.error( | ||
| `${ removed.length } story URL(s) no longer exist:\n\n` + | ||
| removed.map( ( id ) => ` - ${ id }` ).join( '\n' ) + | ||
| `\n\nEach of these is a published URL that will start 404ing. If a story moved\n` + | ||
| `in the sidebar, give it back its original \`id\` so the URL follows it.\n` + | ||
| `Documentation for a deprecated component is usually better marked deprecated\n` + | ||
| `than deleted. If the removal is intended, commit the regenerated\n` + | ||
| `storybook/story-ids.txt so the lost URLs show up in the diff.\n` | ||
| ); | ||
| process.exitCode = 1; | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -50,6 +50,8 @@ function nameToSlug( name: string ): string { | |
|
|
||
| const meta: Meta = { | ||
| component: Icon, | ||
| // Shares its `id` and `title` with `packages/icons/src/icon/stories/index.story.tsx` | ||
| // so both files merge into one entry. Change them together. | ||
| id: 'icons-icon', | ||
| title: 'Design System/Icons/Icon', | ||
|
Comment on lines
+53
to
56
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This doesn't seem like a good pattern. Normally if we wanted to split the library story into its own file, we would just put the code (e.g. just the render function) in a separate file and import it in the main story file. Having two duplicated |
||
| tags: [ '!autodocs' ], | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.