storybook-addon-md 0.2.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,25 @@
1
1
  # storybook-addon-md
2
2
 
3
+ ## 0.4.0
4
+
5
+ ### Minor Changes
6
+
7
+ - df081eb: Respect `docs.defaultName`, use leading H1s as standalone titles, and add `tagFields` and the `storybook-addon-md/node` parsing API. Markdown pages retain props, examples, and original manifest source.
8
+
9
+ Migration: update attached links from `--markdown` to `--docs` (or the configured name), enable Autodocs in preview-level tags, and render the supplied `heading` in custom layouts. MCP component IDs are unchanged.
10
+
11
+ ## 0.3.0
12
+
13
+ ### Minor Changes
14
+
15
+ - 209fe53: Add opt-in documentation manifests with original Markdown, frontmatter summaries, and live updates for standalone and attached docs. Enable `manifests: true` to use [Storybook 10.6.0 manifests](https://storybook.js.org/docs/ai/manifests) and [@storybook/addon-mcp](https://storybook.js.org/docs/ai/mcp/overview) without a custom preset.
16
+
17
+ See the [setup guide](https://github.com/ruijdacd/storybook-addon-md#documentation-manifests-and-mcp) and [examples with and without MCP](https://github.com/ruijdacd/storybook-addon-md#examples-and-contributing).
18
+
19
+ ### Patch Changes
20
+
21
+ - a94853e: Use rem values for default Markdown styles so they scale with the root font size. Add `--sbmd-monospace-font-family` to customize inline code and code blocks, with Storybook’s monospace theme font as the default. See the [CSS variable reference](https://github.com/ruijdacd/storybook-addon-md/blob/main/STYLING.md).
22
+
3
23
  ## 0.2.0
4
24
 
5
25
  ### Minor Changes
package/README.md CHANGED
@@ -61,7 +61,19 @@ Use buttons to trigger actions.
61
61
  - Confirm a choice.
62
62
  ```
63
63
 
64
- The component gets a **Markdown** Docs entry with the content, status and tag chips, examples, and props. Existing stories and Autodocs remain available.
64
+ The component gets one **Docs** entry with Markdown, status and tag chips, examples, and automatic props. The name follows Storybook's `docs.defaultName`, falling back to `Docs`.
65
+
66
+ Enable Autodocs at project level in `.storybook/preview.ts`:
67
+
68
+ ```ts
69
+ export default {
70
+ tags: ['autodocs'],
71
+ };
72
+ ```
73
+
74
+ Storybook 10.6.0 replaces project-level Autodocs with the attached Markdown page. Components without Markdown keep ordinary Autodocs. Use `tags: ['!autodocs']` on components that should not have automatic docs. Component-only or story-only `autodocs` tags conflict with attached MDX in this Storybook version; move the enabling tag to the preview. Native props and examples on Markdown pages do not require an `autodocs` tag.
75
+
76
+ Authored MDX keeps its title and explicit `name`. Additional attached MDX pages can use a distinct name such as `<Meta of={ButtonStories} name="Design notes" />`. An authored page using the default docs name for the same component conflicts with the addon page: keep the authored page and exclude that component's Markdown from `patterns` (or remove its association). The addon does not overwrite authored pages.
65
77
 
66
78
  The sibling convention supports `.stories.tsx`, `.stories.ts`, `.stories.jsx`, and `.stories.js`. To associate a different file, or share a document across components, set `stories` relative to the Markdown file:
67
79
 
@@ -89,34 +101,118 @@ Write ordinary Markdown here.
89
101
 
90
102
  Without a title, `docs/Introduction.md` appears at `Documentation/docs/Introduction`.
91
103
 
104
+ A leading Markdown H1 supplies the visible title, including inline formatting. Otherwise the final segment of `title` is shown. Both `# Heading` and Setext H1 syntax work; a later H1 is ordinary content. Sidebar placement and IDs always use the configured or inferred sidebar title. The original file and manifest content remain unchanged.
105
+
92
106
  ### Frontmatter
93
107
 
94
108
  YAML frontmatter is optional. Use lowercase field names.
95
109
 
96
- | Field | Meaning |
97
- | ------------ | -------------------------------------------------- |
98
- | `title` | Sidebar location for standalone pages. |
99
- | `stories` | Relative story-file path or array of paths. |
100
- | `tags` | Array of labels rendered as chips below the title. |
101
- | `status` | A chip with its value preserved in `data-status`. |
102
- | Other fields | Preserved as metadata for custom presentation. |
110
+ | Field | Meaning |
111
+ | ------------- | --------------------------------------------------- |
112
+ | `title` | Sidebar location for standalone pages. |
113
+ | `stories` | Relative story-file path or array of paths. |
114
+ | `tags` | Array of labels rendered as chips below the title. |
115
+ | `description` | Optional string summary in documentation manifests. |
116
+ | `status` | A chip with its value preserved in `data-status`. |
117
+ | Other fields | Preserved as metadata for custom presentation. |
103
118
 
104
119
  Invalid frontmatter, missing or ambiguous story references, and missing local assets produce source-specific errors.
105
120
 
106
121
  ## Configuration
107
122
 
108
- | Option | Default | Purpose |
109
- | -------------- | ------------------------------ | ------------------------------------------------------------- |
110
- | `patterns` | Required | Markdown globs; prefix with `!` to exclude files. |
111
- | `root` | `..` | Project folder, resolved from the Storybook config directory. |
112
- | `generatedDir` | `storybook-markdown-generated` | Disposable output folder under the working directory. |
113
- | `stylesheet` | None | Custom stylesheet path. |
114
- | `presentation` | None | Module exporting `Layout` and/or `MarkdownRenderer`. |
123
+ | Option | Default | Purpose |
124
+ | -------------- | ------------------------------ | --------------------------------------------------------------- |
125
+ | `patterns` | Required | Markdown globs; prefix with `!` to exclude files. |
126
+ | `root` | `..` | Project folder, resolved from the Storybook config directory. |
127
+ | `generatedDir` | `storybook-markdown-generated` | Disposable output folder under the working directory. |
128
+ | `stylesheet` | None | Custom stylesheet path. |
129
+ | `manifests` | `false` | Include original Markdown in Storybook documentation manifests. |
130
+ | `tagFields` | `[]` | Additional frontmatter fields displayed as tags. |
131
+ | `presentation` | None | Module exporting `Layout` and/or `MarkdownRenderer`. |
115
132
 
116
133
  Globs and customization paths start from your project folder (the parent of `.storybook` by default). Keep the config and local files inside that folder. Restart Storybook after changing options.
117
134
 
118
135
  `generatedDir` must be a visible folder name using letters, digits, hyphens, or underscores. Hidden folders, nested paths, `node_modules`, and `storybook-static` are unsupported. Ignore the folder in Git; the addon manages its contents.
119
136
 
137
+ ### Docs names and metadata tags
138
+
139
+ ```ts
140
+ const config: StorybookConfig = {
141
+ framework: '@storybook/react-vite',
142
+ docs: { defaultName: 'Reference' },
143
+ stories: ['../src/**/*.stories.@(ts|tsx|js|jsx)', '../docs/**/*.mdx'],
144
+ addons: [
145
+ '@storybook/addon-docs',
146
+ {
147
+ name: 'storybook-addon-md',
148
+ options: {
149
+ patterns: ['src/**/*.md', 'docs/**/*.md'],
150
+ tagFields: ['category', 'subcategory'],
151
+ },
152
+ },
153
+ ],
154
+ };
155
+ ```
156
+
157
+ `tagFields` adds string values and string array items from those fields to the existing tags. Missing fields, blank strings, and non-string values are ignored. Labels are deduplicated by exact value across documents, tags, configured fields, and status; status takes precedence and retains its original `data-status`. Metadata is not modified. Consumers can remove adapters that only copied these fields into `tags`.
158
+
159
+ ### Node parsing and CI checks
160
+
161
+ Use the Node-only `storybook-addon-md/node` export. It shares discovery's parser and story resolution without loading Storybook or browser code:
162
+
163
+ ```ts
164
+ import { readMarkdown, parseMarkdown, resolveStoryAssociations } from 'storybook-addon-md/node';
165
+
166
+ const root = process.cwd();
167
+ const document = await readMarkdown('src/Button.metadata.md', root);
168
+
169
+ if (!document.body.includes('## When to use')) {
170
+ throw new Error(`${document.file}: missing When to use section`);
171
+ }
172
+
173
+ const parsed = parseMarkdown('---\ntags: [Actions]\n---\n## Overview', 'virtual.md');
174
+ const stories = await resolveStoryAssociations(document.file, document.metadata, root);
175
+ ```
176
+
177
+ `readMarkdown(file, root)` accepts a root-relative or absolute `.md` path and returns `{ file, original, body, metadata, stories }`. `file` and resolved `stories` are absolute paths. `original` is the complete unchanged source; `body` excludes frontmatter and normalizes BOM/CRLF just as discovery does.
178
+
179
+ `parseMarkdown(text, source)` returns `{ body, metadata }` and validates YAML, lowercase keys, title, tags, status, and story-reference value shapes. `source` labels errors. `resolveStoryAssociations(file, metadata, root)` takes parsed metadata and absolute paths, checks relative references, the four supported story extensions, file existence and root boundaries, and missing or ambiguous `.metadata.md` siblings. Explicit references take precedence. These functions throw source-specific errors; consumers can add their own template checks using `body` and metadata.
180
+
181
+ This is not a separate validation framework. These functions do not check local assets, duplicate sidebar titles, or whether stories match the consuming Storybook's globs; discovery/build still performs the relevant integration checks. Filesystem dependencies are confined to Node entry points, never the runtime export.
182
+
183
+ ## Documentation manifests and MCP
184
+
185
+ Manifest support is opt-in. Set `manifests: true` in this addon's options and enable Storybook's `features.componentsManifest`:
186
+
187
+ ```ts
188
+ const config: StorybookConfig = {
189
+ framework: '@storybook/react-vite',
190
+ features: { componentsManifest: true },
191
+ stories: ['../src/**/*.stories.@(ts|tsx|js|jsx)'],
192
+ addons: [
193
+ '@storybook/addon-docs',
194
+ '@storybook/addon-mcp',
195
+ {
196
+ name: 'storybook-addon-md',
197
+ options: {
198
+ patterns: ['src/**/*.md', 'docs/**/*.md'],
199
+ manifests: true,
200
+ },
201
+ },
202
+ ],
203
+ };
204
+ ```
205
+
206
+ Use MCP's `docs-list` to find IDs, then `docs-show` with a component ID (for attached guidance) or standalone documentation ID.
207
+
208
+ For MCP access, install `@storybook/addon-mcp@10.6.0` and connect your MCP client to `http://localhost:6006/mcp`. Its Get Documentation tool is named `docs-show` in 10.6.0. Omit that addon if you only need JSON manifests. It is not a dependency of `storybook-addon-md`.
209
+
210
+ With Storybook and React Vite **10.6.0**, standalone Markdown appears in `/manifests/docs.json`, and attached Markdown appears in the component's `docs` in `/manifests/components.json`. Both development and static builds include the complete original source, including frontmatter. Development updates use the existing file watcher. Shared documents appear under each associated component; multiple documents on one page are joined in discovery order with two newlines. String `description` values supply optional summaries.
211
+
212
+ Keep this addon after `@storybook/addon-docs`. Consumers can remove custom manifest presets that supplied Markdown content after enabling this option. Unrelated MDX, Autodocs, and other manifest fields are preserved. Storybook's manifest tag filtering still applies.
213
+
214
+ This integration uses Storybook 10.6.0's experimental preset hook and inline (v0) manifests. Other Storybook versions and `features.experimentalDocgenServer` service-backed manifests are unsupported. Markdown links and assets remain as authored in manifest content. See [Storybook manifests](https://storybook.js.org/docs/ai/manifests) for the upstream feature.
215
+
120
216
  ## Styling
121
217
 
122
218
  Set `stylesheet: '.storybook/markdown.css'` to override the defaults:
@@ -139,17 +235,25 @@ See [Styling](STYLING.md) for all variables, status colors, theme switching, and
139
235
  - Links to `.md` files open the original source, not a rendered Docs page. Use a Storybook URL such as `/?path=/docs/guides-introduction--docs` for page navigation.
140
236
  - Braces and JSX-like text are treated as content. Raw HTML renders as text by default.
141
237
  - Set Storybook’s `parameters.options.storySort` for explicit sidebar ordering. See the [example preview](https://github.com/ruijdacd/storybook-addon-md/blob/main/example/.storybook/preview.ts).
142
- - The attached Docs entry name **Markdown** is reserved. Multiple development Storybooks sharing one config directory are unsupported.
238
+ - Multiple development Storybooks sharing one config directory are unsupported.
143
239
 
144
- ## Example and contributing
240
+ ## Examples and contributing
145
241
 
146
- Run the included Storybook with **Nub 0.7.5** and **Node 24**:
242
+ Install dependencies with **Nub 0.7.5** and **Node 24.11+**:
147
243
 
148
244
  ```sh
149
245
  nub install
150
- nub run storybook
151
246
  ```
152
247
 
248
+ Choose either example. They share stories, Markdown, and styling, with separate Storybook configurations. The MCP example sets `docs.defaultName: 'Reference'` to exercise custom docs names:
249
+
250
+ | Example | Configuration | Run | Build |
251
+ | ----------- | ------------------------------------- | ------------------------------ | ----------------------------- |
252
+ | Without MCP | [Default](example/.storybook/main.ts) | `nub run storybook` (6006) | `nub run build-storybook` |
253
+ | With MCP | [MCP](example/.storybook-mcp/main.ts) | `nub run storybook:mcp` (6007) | `nub run build-storybook:mcp` |
254
+
255
+ The MCP example enables `manifests: true` and `@storybook/addon-mcp`. Connect your MCP client to `http://localhost:6007/mcp`. Static builds write to `storybook-static/` and `storybook-static-mcp/`, respectively. MCP is a development dependency for the example only; normal addon usage does not require it.
256
+
153
257
  Browse **Guides → Introduction**, **Components → Button**, and **Components → Toggle** for standalone, attached, and shared docs with system light/dark styling.
154
258
 
155
259
  See [Contributing](CONTRIBUTING.md) for tests and releases, or [open an issue](https://github.com/ruijdacd/storybook-addon-md/issues).
package/STYLING.md CHANGED
@@ -4,105 +4,109 @@ Set these variables on `.storybook-addon-md-page` in the file configured by `sty
4
4
 
5
5
  ```css
6
6
  .storybook-addon-md-page {
7
- --sbmd-font-size: 16px;
8
- --sbmd-h2-size: 26px;
9
- --sbmd-paragraph-spacing: 20px;
10
- --sbmd-quote-border: 3px solid currentColor;
11
- --sbmd-quote-radius: 8px;
12
- --sbmd-table-cell-padding: 12px 16px;
13
- --sbmd-tag-radius: 6px;
7
+ --sbmd-font-size: 1rem;
8
+ --sbmd-monospace-font-family: 'JetBrains Mono', monospace;
9
+ --sbmd-h2-size: 1.625rem;
10
+ --sbmd-paragraph-spacing: 1.25rem;
11
+ --sbmd-quote-border: 0.1875rem solid currentColor;
12
+ --sbmd-quote-radius: 0.5rem;
13
+ --sbmd-table-cell-padding: 0.75rem 1rem;
14
+ --sbmd-tag-radius: 0.375rem;
14
15
  }
15
16
  ```
16
17
 
18
+ Default lengths use `rem`, preserving their original sizes at a 16px root font size and scaling with the document root font size. Set `--sbmd-monospace-font-family` to customize inline code and fenced code blocks; it defaults to Storybook’s monospace theme font.
19
+
17
20
  Variables accept normal CSS values for the property listed below, including `clamp()`, `calc()`, and references to your own theme variables. Border variables accept full border shorthands. Heading margins set space above the heading; title margin sets space below it. Paragraph spacing also applies to lists. Tag margin sets space below the chip list.
18
21
 
19
22
  Use your theme selector to override colors in dark mode. The [complete example](https://github.com/ruijdacd/storybook-addon-md/blob/main/example/.storybook/markdown.css) maps the addon variables to Tailwind v4 theme variables. Its `light-dark()` colors follow the system preference.
20
23
 
21
- | Variable | CSS property |
22
- | --------------------------------- | --------------------------- |
23
- | `--sbmd-background` | `background` |
24
- | `--sbmd-checkbox-color` | `accent-color` |
25
- | `--sbmd-checkbox-gap` | `margin-inline-end` |
26
- | `--sbmd-code-border` | `border` |
27
- | `--sbmd-code-padding` | `padding` |
28
- | `--sbmd-code-radius` | `border-radius` |
29
- | `--sbmd-color` | `color` |
30
- | `--sbmd-font-family` | `font-family` |
31
- | `--sbmd-font-size` | `font-size` |
32
- | `--sbmd-h1-size` | `font-size` |
33
- | `--sbmd-h2-border` | `border-bottom` |
34
- | `--sbmd-h2-letter-spacing` | `letter-spacing` |
35
- | `--sbmd-h2-margin` | `margin-top` |
36
- | `--sbmd-h2-padding` | `padding-bottom` |
37
- | `--sbmd-h2-size` | `font-size` |
38
- | `--sbmd-h3-letter-spacing` | `letter-spacing` |
39
- | `--sbmd-h3-margin` | `margin-top` |
40
- | `--sbmd-h3-size` | `font-size` |
41
- | `--sbmd-h4-size` | `font-size` |
42
- | `--sbmd-h5-size` | `font-size` |
43
- | `--sbmd-h6-size` | `font-size` |
44
- | `--sbmd-heading-color` | `color` |
45
- | `--sbmd-heading-font-family` | `font-family` |
46
- | `--sbmd-heading-line-height` | `line-height` |
47
- | `--sbmd-heading-weight` | `font-weight` |
48
- | `--sbmd-image-border` | `border` |
49
- | `--sbmd-image-margin` | `margin-block` |
50
- | `--sbmd-image-radius` | `border-radius` |
51
- | `--sbmd-inline-code-background` | `background` |
52
- | `--sbmd-inline-code-border` | `border` |
53
- | `--sbmd-inline-code-color` | `color` |
54
- | `--sbmd-inline-code-padding` | `padding` |
55
- | `--sbmd-inline-code-radius` | `border-radius` |
56
- | `--sbmd-inline-code-size` | `font-size` |
57
- | `--sbmd-line-height` | `line-height` |
58
- | `--sbmd-link-color` | `color` |
59
- | `--sbmd-link-decoration` | `text-decoration` |
60
- | `--sbmd-link-focus-offset` | `outline-offset` |
61
- | `--sbmd-link-focus-outline` | `outline` |
62
- | `--sbmd-link-hover-thickness` | `text-decoration-thickness` |
63
- | `--sbmd-link-radius` | `border-radius` |
64
- | `--sbmd-link-thickness` | `text-decoration-thickness` |
65
- | `--sbmd-link-underline-offset` | `text-underline-offset` |
66
- | `--sbmd-list-item-spacing` | `margin-top` |
67
- | `--sbmd-list-marker-color` | `color` |
68
- | `--sbmd-max-width` | `max-width` |
69
- | `--sbmd-page-border` | `border` |
70
- | `--sbmd-page-padding` | `padding` |
71
- | `--sbmd-page-radius` | `border-radius` |
72
- | `--sbmd-paragraph-spacing` | `margin-block` |
73
- | `--sbmd-quote-background` | `background` |
74
- | `--sbmd-quote-border` | `border-inline-start` |
75
- | `--sbmd-quote-margin` | `margin` |
76
- | `--sbmd-quote-padding` | `padding` |
77
- | `--sbmd-quote-radius` | `border-radius` |
78
- | `--sbmd-rule-color` | `background` |
79
- | `--sbmd-rule-height` | `height` |
80
- | `--sbmd-rule-margin` | `margin-block` |
81
- | `--sbmd-table-align` | `text-align` |
82
- | `--sbmd-table-background` | `background` |
83
- | `--sbmd-table-border` | `border` |
84
- | `--sbmd-table-cell-padding` | `padding` |
85
- | `--sbmd-table-heading-background` | `background` |
86
- | `--sbmd-table-heading-weight` | `font-weight` |
87
- | `--sbmd-table-margin` | `margin-block` |
88
- | `--sbmd-table-stripe-background` | `background` |
89
- | `--sbmd-tag-background` | `background` |
90
- | `--sbmd-tag-border` | `border` |
91
- | `--sbmd-tag-color` | `color` |
92
- | `--sbmd-tag-font-size` | `font-size` |
93
- | `--sbmd-tag-font-weight` | `font-weight` |
94
- | `--sbmd-tag-gap` | `gap` |
95
- | `--sbmd-tag-line-height` | `line-height` |
96
- | `--sbmd-tag-padding` | `padding` |
97
- | `--sbmd-tag-radius` | `border-radius` |
98
- | `--sbmd-title-letter-spacing` | `letter-spacing` |
99
- | `--sbmd-title-line-height` | `line-height` |
100
- | `--sbmd-title-margin` | `margin-bottom` |
101
- | `--sbmd-title-size` | `font-size` |
24
+ | Variable | CSS property |
25
+ | --------------------------------- | ----------------------------- |
26
+ | `--sbmd-background` | `background` |
27
+ | `--sbmd-checkbox-color` | `accent-color` |
28
+ | `--sbmd-checkbox-gap` | `margin-inline-end` |
29
+ | `--sbmd-code-border` | `border` |
30
+ | `--sbmd-code-padding` | `padding` |
31
+ | `--sbmd-code-radius` | `border-radius` |
32
+ | `--sbmd-color` | `color` |
33
+ | `--sbmd-font-family` | `font-family` |
34
+ | `--sbmd-font-size` | `font-size` |
35
+ | `--sbmd-h1-size` | `font-size` |
36
+ | `--sbmd-h2-border` | `border-bottom` |
37
+ | `--sbmd-h2-letter-spacing` | `letter-spacing` |
38
+ | `--sbmd-h2-margin` | `margin-top` |
39
+ | `--sbmd-h2-padding` | `padding-bottom` |
40
+ | `--sbmd-h2-size` | `font-size` |
41
+ | `--sbmd-h3-letter-spacing` | `letter-spacing` |
42
+ | `--sbmd-h3-margin` | `margin-top` |
43
+ | `--sbmd-h3-size` | `font-size` |
44
+ | `--sbmd-h4-size` | `font-size` |
45
+ | `--sbmd-h5-size` | `font-size` |
46
+ | `--sbmd-h6-size` | `font-size` |
47
+ | `--sbmd-heading-color` | `color` |
48
+ | `--sbmd-heading-font-family` | `font-family` |
49
+ | `--sbmd-heading-line-height` | `line-height` |
50
+ | `--sbmd-heading-weight` | `font-weight` |
51
+ | `--sbmd-image-border` | `border` |
52
+ | `--sbmd-image-margin` | `margin-block` |
53
+ | `--sbmd-image-radius` | `border-radius` |
54
+ | `--sbmd-inline-code-background` | `background` |
55
+ | `--sbmd-inline-code-border` | `border` |
56
+ | `--sbmd-inline-code-color` | `color` |
57
+ | `--sbmd-inline-code-padding` | `padding` |
58
+ | `--sbmd-inline-code-radius` | `border-radius` |
59
+ | `--sbmd-inline-code-size` | `font-size` |
60
+ | `--sbmd-line-height` | `line-height` |
61
+ | `--sbmd-link-color` | `color` |
62
+ | `--sbmd-link-decoration` | `text-decoration` |
63
+ | `--sbmd-link-focus-offset` | `outline-offset` |
64
+ | `--sbmd-link-focus-outline` | `outline` |
65
+ | `--sbmd-link-hover-thickness` | `text-decoration-thickness` |
66
+ | `--sbmd-link-radius` | `border-radius` |
67
+ | `--sbmd-link-thickness` | `text-decoration-thickness` |
68
+ | `--sbmd-link-underline-offset` | `text-underline-offset` |
69
+ | `--sbmd-list-item-spacing` | `margin-top` |
70
+ | `--sbmd-list-marker-color` | `color` |
71
+ | `--sbmd-monospace-font-family` | `font-family` (Markdown code) |
72
+ | `--sbmd-max-width` | `max-width` |
73
+ | `--sbmd-page-border` | `border` |
74
+ | `--sbmd-page-padding` | `padding` |
75
+ | `--sbmd-page-radius` | `border-radius` |
76
+ | `--sbmd-paragraph-spacing` | `margin-block` |
77
+ | `--sbmd-quote-background` | `background` |
78
+ | `--sbmd-quote-border` | `border-inline-start` |
79
+ | `--sbmd-quote-margin` | `margin` |
80
+ | `--sbmd-quote-padding` | `padding` |
81
+ | `--sbmd-quote-radius` | `border-radius` |
82
+ | `--sbmd-rule-color` | `background` |
83
+ | `--sbmd-rule-height` | `height` |
84
+ | `--sbmd-rule-margin` | `margin-block` |
85
+ | `--sbmd-table-align` | `text-align` |
86
+ | `--sbmd-table-background` | `background` |
87
+ | `--sbmd-table-border` | `border` |
88
+ | `--sbmd-table-cell-padding` | `padding` |
89
+ | `--sbmd-table-heading-background` | `background` |
90
+ | `--sbmd-table-heading-weight` | `font-weight` |
91
+ | `--sbmd-table-margin` | `margin-block` |
92
+ | `--sbmd-table-stripe-background` | `background` |
93
+ | `--sbmd-tag-background` | `background` |
94
+ | `--sbmd-tag-border` | `border` |
95
+ | `--sbmd-tag-color` | `color` |
96
+ | `--sbmd-tag-font-size` | `font-size` |
97
+ | `--sbmd-tag-font-weight` | `font-weight` |
98
+ | `--sbmd-tag-gap` | `gap` |
99
+ | `--sbmd-tag-line-height` | `line-height` |
100
+ | `--sbmd-tag-padding` | `padding` |
101
+ | `--sbmd-tag-radius` | `border-radius` |
102
+ | `--sbmd-title-letter-spacing` | `letter-spacing` |
103
+ | `--sbmd-title-line-height` | `line-height` |
104
+ | `--sbmd-title-margin` | `margin-bottom` |
105
+ | `--sbmd-title-size` | `font-size` |
102
106
 
103
107
  Status chips have `data-status` set to the original frontmatter value. Override `--sbmd-tag-*` on selectors such as `.storybook-addon-md-tag[data-status="stable" i]` to assign a status-specific appearance.
104
108
 
105
- These styles target Markdown content and its title/chips. Story canvases, props controls, and syntax highlighting still use Storybook’s theme. Custom renderers can use the shared styles when they produce matching HTML elements; custom layouts own any additional structure. Internal `--sbmd-native-*` variables carry Storybook theme values and are not customization hooks.
109
+ These styles target Markdown content and its title/chips. Story canvases, props controls, and syntax-highlighting colors still use Storybook’s theme. Custom renderers can use the shared styles when they produce matching HTML elements; custom layouts own any additional structure. Internal `--sbmd-native-*` variables carry Storybook theme values and are not customization hooks.
106
110
 
107
111
  ## Customization
108
112
 
@@ -114,11 +118,12 @@ Set `stylesheet: '.storybook/markdown.css'` in the addon options, then define yo
114
118
 
115
119
  ```css
116
120
  .storybook-addon-md-page {
117
- --sbmd-font-size: 16px;
121
+ --sbmd-font-size: 1rem;
122
+ --sbmd-monospace-font-family: 'JetBrains Mono', monospace;
118
123
  --sbmd-line-height: 1.8;
119
124
  --sbmd-heading-color: currentColor;
120
- --sbmd-tag-radius: 6px;
121
- --sbmd-tag-border: 1px solid currentColor;
125
+ --sbmd-tag-radius: 0.375rem;
126
+ --sbmd-tag-border: 0.0625rem solid currentColor;
122
127
  }
123
128
  ```
124
129
 
@@ -136,7 +141,7 @@ Status chips share the tag variables. Use `data-status` to map values to your th
136
141
  .storybook-addon-md-tag[data-status='stable' i] {
137
142
  --sbmd-tag-color: light-dark(#1a7f37, #3fb950);
138
143
  --sbmd-tag-background: light-dark(#dafbe1, #12261e);
139
- --sbmd-tag-border: 1px solid currentColor;
144
+ --sbmd-tag-border: 0.0625rem solid currentColor;
140
145
  }
141
146
  ```
142
147
 
@@ -173,9 +178,9 @@ export function MarkdownRenderer(document: MarkdownDocument) {
173
178
  }
174
179
  ```
175
180
 
176
- `MarkdownRenderer` receives `{ markdown, metadata, source }`: processed Markdown with resolved asset URLs, preserved frontmatter, and the source path relative to the project folder.
181
+ `MarkdownRenderer` receives `{ markdown, metadata, source, heading? }`: processed Markdown with resolved asset URLs, preserved frontmatter, and the source path relative to the project folder.
177
182
 
178
- `Layout` receives `{ documents, title, attached, children, examples }`. Render `children` and `examples` to keep documentation and native example/props blocks. `examples` is `null` for standalone pages. `title` contains the standalone sidebar title and is empty for attached pages; `DefaultLayout` uses Storybook’s `Title` block for those.
183
+ `Layout` receives `{ documents, title, attached, children, examples, heading, tagFields }`. A standalone leading H1 is extracted in the default pipeline and supplied as the rendered `heading` node; render it instead of your fallback title. The remaining Markdown is supplied through `children`, while source files and manifests stay intact. `tagFields` lists configured metadata fields for tag display. Render `children` and `examples` to keep documentation and native example/props blocks. `examples` is `null` for standalone pages. `title` contains the standalone sidebar title and is empty for attached pages; `DefaultLayout` uses Storybook’s `Title` block for those.
179
184
 
180
185
  Customization paths are relative to the project folder and must stay inside it. Missing files produce source-specific errors. Styling and presentation are independent options.
181
186
 
@@ -0,0 +1,44 @@
1
+ import { t as MarkdownOptions } from "./index-BzM0tjFM.js";
2
+ //#region src/content.d.ts
3
+ interface ContentOptions extends MarkdownOptions {
4
+ root: string;
5
+ output: string;
6
+ docsName?: string;
7
+ }
8
+ interface Frontmatter extends Record<string, unknown> {
9
+ title?: string;
10
+ stories?: string | string[];
11
+ tags?: string[];
12
+ status?: string;
13
+ }
14
+ type DiscoveredDocument = Awaited<ReturnType<typeof discover>>[number];
15
+ declare function parseMarkdown(text: string, source: string): {
16
+ body: string;
17
+ metadata: Frontmatter;
18
+ };
19
+ declare function resolveStoryAssociations(file: string, metadata: Frontmatter, root: string): Promise<string[]>;
20
+ declare function discover({ root, patterns, output }: ContentOptions): Promise<{
21
+ markdown: string;
22
+ assets: {
23
+ file: string;
24
+ suffix: string;
25
+ token: string;
26
+ }[];
27
+ heading: string | undefined;
28
+ file: string;
29
+ original: string;
30
+ body: string;
31
+ source: string;
32
+ title: string;
33
+ metadata: Frontmatter;
34
+ stories: string[];
35
+ }[]>;
36
+ declare function readMarkdown(file: string, root: string): Promise<{
37
+ file: string;
38
+ original: string;
39
+ body: string;
40
+ metadata: Frontmatter;
41
+ stories: string[];
42
+ }>;
43
+ //#endregion
44
+ export { readMarkdown as a, parseMarkdown as i, DiscoveredDocument as n, resolveStoryAssociations as o, Frontmatter as r, ContentOptions as t };