Skip to content

Commit c419c88

Browse files
committed
feat: on this page subsections
1 parent 3ac1105 commit c419c88

File tree

3 files changed

+54
-22
lines changed

3 files changed

+54
-22
lines changed

apps/svelte.dev/src/routes/docs/[topic]/[...path]/OnThisPage.svelte

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
1010
afterNavigate(() => {
1111
current = location.hash.slice(1);
12-
headings = content.querySelectorAll('h2');
12+
headings = content.querySelectorAll('h2, h3');
1313
update(); // Ensure active link is set correctly on navigation
1414
});
1515
@@ -58,8 +58,24 @@
5858

5959
{#each document.sections as section}
6060
<li>
61-
<a href="#{section.slug}" class:active={current === section.slug}>{@html section.title}</a
62-
>
61+
<a href="#{section.slug}" class:active={current === section.slug}>
62+
{@html section.title}
63+
</a>
64+
65+
{#if section.subsections.length > 0}
66+
<ul
67+
data-active={current === section.slug ||
68+
section.subsections.some((subsection) => subsection.slug === current)}
69+
>
70+
{#each section.subsections as subsection}
71+
<li>
72+
<a href="#{subsection.slug}" class:active={current === subsection.slug}>
73+
{@html subsection.title}
74+
</a>
75+
</li>
76+
{/each}
77+
</ul>
78+
{/if}
6379
</li>
6480
{/each}
6581
</ul>
@@ -76,6 +92,10 @@
7692
font: var(--sk-font-body-small);
7793
}
7894
95+
li ul {
96+
margin: 0 0 0 1.6rem;
97+
}
98+
7999
/* Only show the title link if it's in the sidebar */
80100
li:first-child {
81101
display: none;
@@ -228,6 +248,14 @@
228248
display: list-item;
229249
}
230250
251+
li ul {
252+
display: none;
253+
}
254+
255+
li ul[data-active='true'] {
256+
display: block;
257+
}
258+
231259
a.active {
232260
color: var(--sk-fg-1);
233261
text-decoration: underline;

packages/site-kit/src/lib/server/content/index.ts

Lines changed: 22 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { extract_frontmatter, is_in_code_block, slugify, smart_quotes } from '../../markdown/utils';
2-
import type { Document } from '../../types';
2+
import type { Document, Section } from '../../types';
33

44
export async function create_index(
55
documents: Record<string, string>,
@@ -32,24 +32,27 @@ export async function create_index(
3232
'<code>$1</code>'
3333
);
3434

35-
const sections = Array.from(body.matchAll(/^##\s+(.*)$/gm)).reduce(
36-
(arr, match) => {
37-
if (is_in_code_block(body, match.index || 0)) return arr;
38-
const title = smart_quotes(match[1])
39-
// replace < and > inside code spans
40-
.replace(/`(.+?)`/g, (_, contents) =>
41-
contents.replace(/</g, '&lt;').replace(/>/g, '&gt;')
42-
)
43-
// turn e.g. `class:_name_` into `class:<em>name</em>`
44-
.replace(/_(.+)_/g, (_, contents) => `<em>${contents}</em>`);
45-
46-
const slug = slugify(title);
47-
48-
arr.push({ slug, title });
49-
return arr;
50-
},
51-
[] as Array<{ slug: string; title: string }>
52-
);
35+
const sections = Array.from(body.matchAll(/^#{2,3}\s+(.*)$/gm)).reduce((arr, match) => {
36+
if (is_in_code_block(body, match.index || 0)) return arr;
37+
const title = smart_quotes(match[1])
38+
// replace < and > inside code spans
39+
.replace(/`(.+?)`/g, (_, contents) => contents.replace(/</g, '&lt;').replace(/>/g, '&gt;'))
40+
// turn e.g. `class:_name_` into `class:<em>name</em>`
41+
.replace(/_(.+)_/g, (_, contents) => `<em>${contents}</em>`);
42+
43+
const slug = slugify(title);
44+
45+
if (match[0].startsWith('###')) {
46+
const section = arr.at(-1);
47+
if (section) {
48+
section.subsections.push({ slug: `${section.slug}-${slug}`, title });
49+
}
50+
} else {
51+
arr.push({ slug, title, subsections: [] });
52+
}
53+
54+
return arr;
55+
}, [] as Array<Section>);
5356

5457
content[slug] = {
5558
slug,

packages/site-kit/src/lib/types.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ export interface DocumentSummary {
4444
export interface Section {
4545
slug: string;
4646
title: string;
47+
subsections: Omit<Section, 'subsections'>[];
4748
}
4849

4950
export interface BannerData {

0 commit comments

Comments
 (0)