Skip to content

Commit 4cfcb6d

Browse files
committed
πŸ§‘β€πŸ’» Make headings processing opt-in
1 parent 5e2ffc0 commit 4cfcb6d

File tree

3 files changed

+32
-6
lines changed

3 files changed

+32
-6
lines changed

β€ŽREADME.mdβ€Ž

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ Use Markdoc defaults out of the box or configure Markdoc schema to your needs.
1616
- [Relative imports](#relative-imports)
1717
- [Preprocessor Options](#preprocessor-options)
1818
- [Functions](#functions)
19+
- [Heading IDs](#heading-ids)
1920
- [Nodes](#nodes)
2021
- [Partials](#partials)
2122
- [Tags](#tags)
@@ -270,6 +271,7 @@ const config = {
270271
| `components` | string | `"$lib/components"` | Svelte components directory for custom nodes and tags |
271272
| `extensions` | string[] | `[".mdoc", ".md"]` | Files to process with Markdoc |
272273
| `functions` | Config['functions'] | - | [Functions config](#functions) |
274+
| `headingIds` | boolean | `false` | Add IDs to headings without them and include them in export |
273275
| `layout` | string | - | Default layout for all processed Markdown files |
274276
| `linkify` | boolean | `false` | Auto-convert bare URLs to links |
275277
| `nodes` | Config['nodes'] | - | [Nodes config](#nodes) |
@@ -313,6 +315,16 @@ title: Hello World
313315
This is a {% uppercase(markdown) %} file that is processed by `markdoc-svelte`.
314316
```
315317

318+
### Heading IDs
319+
320+
If you want to build a table of contents for a page or just have links to specific headings, set `headingIds` to `true.
321+
You can add your own IDs in the original file with [annotations](https://markdoc.dev/docs/syntax#annotations)
322+
or they are generated automatically.
323+
Each heading element in the generated HTML has an `id` attribute you can use to link to directly.
324+
325+
Each page then also exports a `headings` property: a list of all headings with their text, level, and ID.
326+
Use the list to generate a [table of contents](#page-table-of-contents).
327+
316328
### Nodes
317329

318330
[Nodes](https://markdoc.dev/docs/nodes) are elements built into Markdown from the CommonMark specification.
@@ -525,16 +537,16 @@ See the example [custom node](#nodes).
525537

526538
### Page table of contents
527539

528-
Each proccessed page automatically exports a `headings` property with all headings on the page and IDs for each.
529-
Add IDs with [annotations](https://markdoc.dev/docs/syntax#annotations) or they are generated automatically.
540+
When you have the [`headingIds` option](#heading-ids) set to `true`,
541+
each proccessed page automatically exports a `headings` property with all headings on the page and IDs for each.
530542
Use this list to generate a table of contents for the page, as in the following example:
531543

532544
```svelte
533545
<script lang="ts">
534546
let { data } = $props();
535547
const { frontmatter, headings } = data.page;
536548
537-
// Filter only h1 and h2 headings
549+
// Include only h1 and h2 headings
538550
const filteredHeadings = headings?.filter((heading) => heading.level <= 2) ?? [];
539551
</script>
540552

β€Žsrc/main.tsβ€Ž

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ const validOptionKeys: (keyof Options)[] = [
2323
"components",
2424
"extensions",
2525
"functions",
26+
"headingIds",
2627
"layout",
2728
"linkify",
2829
"nodes",
@@ -67,6 +68,7 @@ export const markdocPreprocess = (options: Options = {}): PreprocessorGroup => {
6768
const componentsPath = options.components || "$lib/components";
6869
const layoutPath = options.layout;
6970
const allowComments = options.comments ?? true;
71+
const processHeadings = options.headingIds ?? false;
7072
const linkify = options.linkify ?? false;
7173
const typographer = options.typographer ?? false;
7274
const validationLevel = options.validationLevel || "error";
@@ -144,8 +146,13 @@ export const markdocPreprocess = (options: Options = {}): PreprocessorGroup => {
144146
const fullConfig: Config = {
145147
// Start with base config loaded from the schema directory
146148
// Explicitly set options overwrite the base config
147-
// For example, this processor's heading comes first so it's overwritten
148-
nodes: { heading, ...configFromSchema.nodes, ...nodes },
149+
// For example, if processing headings,
150+
// This processor's heading comes first so it's overwritten
151+
nodes: {
152+
...(processHeadings ? { heading } : {}), // Only include if passed as option
153+
...configFromSchema.nodes,
154+
...nodes,
155+
},
149156
tags: { ...configFromSchema.tags, ...tags },
150157
functions: { ...configFromSchema.functions, ...functions },
151158
partials: { ...partialsFromSchema, ...partialsFromPartials },
@@ -166,7 +173,9 @@ export const markdocPreprocess = (options: Options = {}): PreprocessorGroup => {
166173
const transformedContent = await Markdoc.transform(ast, fullConfig);
167174

168175
// --- Collect headings from transformed content ---
169-
const headings = collectHeadings(transformedContent);
176+
const headings = processHeadings
177+
? collectHeadings(transformedContent)
178+
: [];
170179

171180
// Render Markdoc AST to Svelte
172181
const svelteContent = render(transformedContent);

β€Žsrc/types.tsβ€Ž

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,11 @@ export interface Options {
3939
* @default undefined
4040
*/
4141
functions?: Config["functions"];
42+
/**
43+
* Whether to add IDs to all headings and generate and export a list of headings.
44+
* @default false
45+
*/
46+
headingIds?: boolean;
4247
/**
4348
* Specify a Svelte component to use as a layout for the Markdoc file.
4449
* Use import paths and aliases that Svelte can resolve.

0 commit comments

Comments
Β (0)