-
Notifications
You must be signed in to change notification settings - Fork 27
Expand file tree
/
Copy path_app.tsx
More file actions
111 lines (95 loc) · 3.25 KB
/
_app.tsx
File metadata and controls
111 lines (95 loc) · 3.25 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
import { AppProps } from 'next/app';
import { slugifyWithCounter } from '@sindresorhus/slugify';
import 'focus-visible';
import {
AnalyticsProvider,
NavigationProvider,
LandingPageMeta,
Header,
Footer,
LandingPageLayout as Layout,
} from '@devfile-web/core';
import '../styles/tailwind.css';
import type { MarkdocNextJsPageProps } from '@markdoc/next.js';
import type { RenderableTreeNodes, Tag } from '@markdoc/markdoc';
import type { TableOfContents } from '@devfile-web/core';
import type { DocsNavigation } from '@devfile-web/docs';
import { useRouter } from 'next/router';
import { docsNavigation, headerNavigation, footerNavigation } from '../navigation';
const analyticsConfig = {
writeKey: process.env.NEXT_PUBLIC_ANALYTICS_WRITE_KEY,
client: 'landing-page',
};
function getNodeText(node: Tag): string {
let text = '';
for (const child of node.children ?? []) {
text += typeof child === 'string' ? child : getNodeText(child);
}
return text;
}
function collectHeadings(
nodes: RenderableTreeNodes,
slugify = slugifyWithCounter(),
): TableOfContents[] {
const sections: TableOfContents[] = [];
if (!Array.isArray(nodes)) return sections;
for (const node of nodes) {
if (typeof node !== 'string') {
if (node.name === 'h2' || node.name === 'h3') {
const title = getNodeText(node);
if (title) {
const id = slugify(title);
node.attributes.id = id;
if (node.name === 'h3') {
if (!sections[sections.length - 1]) {
throw new Error('Cannot add `h3` to table of contents without a preceding `h2`');
}
sections[sections.length - 1].children.push({
...node.attributes,
title,
});
} else {
sections.push({ ...node.attributes, title, children: [] });
}
}
}
sections.push(...collectHeadings(node.children ?? [], slugify));
}
}
return sections;
}
function LandingPage({ Component, pageProps }: AppProps): JSX.Element {
const { markdoc } = pageProps as MarkdocNextJsPageProps;
const router = useRouter();
const title = (markdoc?.frontmatter.title as string) ?? '';
let pageTitle: string;
let description: string;
if (router.asPath.includes('/docs')) {
pageTitle =
(markdoc?.frontmatter.pageTitle as string) ||
`${(markdoc?.frontmatter.title as string) ?? ''} - Docs`;
description = (markdoc?.frontmatter.description as string) ?? '';
}
const tableOfContents = markdoc?.content ? collectHeadings(markdoc.content) : [];
return (
<AnalyticsProvider {...analyticsConfig}>
<NavigationProvider
headerNavigation={headerNavigation}
footerNavigation={footerNavigation}
docsNavigation={docsNavigation as DocsNavigation}
>
<div className="flex h-screen min-w-[300px] flex-col justify-between">
<LandingPageMeta title={pageTitle} description={description} />
<div className="grow">
<Header />
<Layout title={title} tableOfContents={tableOfContents}>
<Component {...pageProps} />
</Layout>
</div>
<Footer />
</div>
</NavigationProvider>
</AnalyticsProvider>
);
}
export default LandingPage;