Skip to content

Commit a0c5e8c

Browse files
committed
♻️ Generalize slugging for headings
1 parent 8b5c29f commit a0c5e8c

File tree

2 files changed

+28
-12
lines changed

2 files changed

+28
-12
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -579,7 +579,7 @@ export const load = async () => {
579579
slug: module.slug,
580580
frontmatter: module.frontmatter,
581581
};
582-
})
582+
}),
583583
);
584584
return { content };
585585
};

src/headings.ts

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
import type { RenderableTreeNode, Tag } from "@markdoc/markdoc";
1+
import { Tag } from "@markdoc/markdoc";
2+
import type { RenderableTreeNode } from "@markdoc/markdoc";
23
import slugify from "slugify";
34

45
export interface Heading {
@@ -16,6 +17,26 @@ export interface Heading {
1617
id?: string;
1718
}
1819

20+
const getTextContent = (children: RenderableTreeNode[]): string => {
21+
return children.reduce((text: string, child): string => {
22+
if (typeof child === "string" || typeof child === "number") {
23+
return text + child;
24+
} else if (typeof child === "object" && Tag.isTag(child)) {
25+
return text + getTextContent(child.children);
26+
}
27+
return text;
28+
}, "");
29+
};
30+
31+
const getSlug = (tag: Tag): string => {
32+
if (tag.attributes.id && typeof tag.attributes.id === "string") {
33+
return tag.attributes.id;
34+
}
35+
return slugify(getTextContent(tag.children), {
36+
lower: true,
37+
strict: true,
38+
}) as string;
39+
};
1940
/**
2041
* Recursively collects all heading nodes from a Markdoc AST
2142
* @param node - The Markdoc AST node to process
@@ -37,16 +58,11 @@ export function collectHeadings(
3758
if (typeof node === "object" && node !== null && "name" in node) {
3859
const tag = node as Tag;
3960
if (tag.name.match(/^h\d$/)) {
40-
const title = tag.children[0];
41-
if (typeof title === "string") {
42-
sections.push({
43-
level: parseInt(tag.name[1]),
44-
title,
45-
id:
46-
(tag.attributes.id as string) ||
47-
(slugify(title, { lower: true, strict: true }) as string),
48-
});
49-
}
61+
sections.push({
62+
level: parseInt(tag.name[1]),
63+
title: getTextContent(tag.children),
64+
id: getSlug(tag),
65+
});
5066
}
5167

5268
// Handle node children

0 commit comments

Comments
 (0)