@brillout/docpress 0.1.14 → 0.1.17
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/dist/{chunk-GBXQT242.js → chunk-ZYYJWJMY.js} +38 -13
- package/dist/chunk-ZYYJWJMY.js.map +1 -0
- package/dist/{devServer-CXZI7V2M.js → devServer-J2XJQJGT.js} +2 -5
- package/dist/{devServer-CXZI7V2M.js.map → devServer-J2XJQJGT.js.map} +1 -1
- package/dist/index.d.ts +0 -136
- package/dist/index.js +27 -484
- package/dist/index.js.map +1 -1
- package/package.json +10 -13
- package/src/MobileHeader.tsx +68 -0
- package/src/PageLayout.css +41 -0
- package/src/PageLayout.tsx +37 -0
- package/src/algolia/DocSearch.css +29 -0
- package/src/algolia/DocSearch.ts +37 -0
- package/src/autoScrollNav.ts +22 -0
- package/src/cli/devServer.ts +31 -0
- package/src/cli/index.ts +29 -0
- package/src/components/CodeBlock.tsx +22 -0
- package/src/components/DocLink.tsx +108 -0
- package/src/components/EditPageNote.tsx +18 -0
- package/src/components/HorizontalLine.tsx +20 -0
- package/src/components/ImportMeta.tsx +11 -0
- package/src/components/Info.tsx +12 -0
- package/src/components/Link.tsx +18 -0
- package/src/components/Note.tsx +31 -0
- package/src/components/P.css +8 -0
- package/src/components/P.tsx +8 -0
- package/src/components/ReadingRecommendation.tsx +53 -0
- package/src/components/RepoLink.tsx +24 -0
- package/src/components/Sponsors/companyLogos/ccoli-logo.svg +1 -0
- package/src/components/Sponsors/companyLogos/ccoli-text.svg +1 -0
- package/{dist/ccoli-CHW3TQKS.svg → src/components/Sponsors/companyLogos/ccoli.svg} +0 -0
- package/{dist/contra-WLZBOPBV.svg → src/components/Sponsors/companyLogos/contra.svg} +0 -0
- package/{dist/mfqs-2EAEE7N6.svg → src/components/Sponsors/companyLogos/mfqs.svg} +0 -0
- package/src/components/Sponsors/label.draft.svg +108 -0
- package/{dist/label-MP75CTIA.svg → src/components/Sponsors/label.svg} +0 -0
- package/{dist/medalBronze-CO4CTUR4.svg → src/components/Sponsors/medalBronze.svg} +0 -0
- package/{dist/medalGold-UP6A73FL.svg → src/components/Sponsors/medalGold.svg} +0 -0
- package/{dist/medalSilver-FAPGGOBN.svg → src/components/Sponsors/medalSilver.svg} +0 -0
- package/src/components/Sponsors.tsx +242 -0
- package/{dist → src}/components/features/FeatureList.css +7 -2
- package/src/components/features/FeatureList.tsx +114 -0
- package/{dist/chevron-R2IYJD62.svg → src/components/features/chevron.svg} +0 -0
- package/src/components/features/initFeatureList.ts +66 -0
- package/src/components/index.ts +13 -0
- package/src/config/Config.ts +30 -0
- package/src/config/getConfig.ts +18 -0
- package/src/config/resolveConfig/resolveHeading.ts +0 -0
- package/src/config/resolvePageContext.ts +157 -0
- package/{dist/Inter-Var-IOAEQULN.ttf → src/css/Inter-Var.ttf} +0 -0
- package/src/css/button.css +7 -0
- package/src/css/code/block.css +36 -0
- package/src/css/code/inline.css +27 -0
- package/src/css/code.css +20 -0
- package/src/css/colorize-on-hover.css +29 -0
- package/src/css/font.css +19 -0
- package/src/css/heading.css +25 -0
- package/src/css/index.css +11 -0
- package/src/css/link.css +17 -0
- package/src/css/note.css +26 -0
- package/src/css/reset.css +12 -0
- package/src/css/table.css +14 -0
- package/src/css/tooltip.css +11 -0
- package/src/headings.ts +200 -0
- package/{dist/changelog-IPI5F42D.svg → src/icons/changelog.svg} +0 -0
- package/{dist/discord-JD33TUSF.svg → src/icons/discord.svg} +0 -0
- package/{dist/github-P5ZSKN2N.svg → src/icons/github.svg} +0 -0
- package/{dist/heart-OINVKOXO.svg → src/icons/heart.svg} +0 -0
- package/{dist/twitter-I7DXDN3J.svg → src/icons/twitter.svg} +0 -0
- package/src/index.ts +3 -0
- package/src/installSectionUrlHashs.ts +50 -0
- package/src/markdownHeadingsVitePlugin.ts +128 -0
- package/src/navigation/Navigation-highlight.css +41 -0
- package/src/navigation/Navigation-items.css +122 -0
- package/src/navigation/Navigation-layout.css +118 -0
- package/src/navigation/Navigation.client.old.ts +303 -0
- package/src/navigation/Navigation.client.ts +19 -0
- package/src/navigation/Navigation.css +12 -0
- package/src/navigation/Navigation.tsx +228 -0
- package/src/navigation/NavigationHeader.tsx +97 -0
- package/src/navigation/navigation-fullscreen/NavigationFullscreenButton.css +32 -0
- package/src/navigation/navigation-fullscreen/NavigationFullscreenButton.tsx +44 -0
- package/{dist/chevron-K3WPYLOP.svg → src/navigation/navigation-fullscreen/chevron.svg} +0 -0
- package/{dist/close-IQXTDOHV.svg → src/navigation/navigation-fullscreen/close.svg} +0 -0
- package/src/navigation/navigation-fullscreen/initNavigationFullscreen.ts +115 -0
- package/src/parseEmojis.ts +33 -0
- package/src/renderer/_default.page.client.ts +4 -0
- package/src/renderer/_default.page.server.tsx +69 -0
- package/src/renderer/usePageContext.tsx +25 -0
- package/src/types.ts +2 -0
- package/src/utils/Emoji/Emoji.ts +216 -0
- package/src/utils/Emoji/assets.ts +9 -0
- package/{dist/compass-2RWQU3E4.svg → src/utils/Emoji/compass.svg} +0 -0
- package/{dist/engine-6Q6VSCVA.png → src/utils/Emoji/engine.png} +0 -0
- package/src/utils/Emoji/index.ts +1 -0
- package/{dist/mechanical-arm-TR7IQQMG.svg → src/utils/Emoji/mechanical-arm.svg} +0 -0
- package/src/utils/Emoji/mountain.svg +1 -0
- package/{dist/road-fork-3WZLW3HB.svg → src/utils/Emoji/road-fork.svg} +0 -0
- package/{dist/shield-CU45RG5C.svg → src/utils/Emoji/shield.svg} +0 -0
- package/{dist/typescript-ALIPKLRM.svg → src/utils/Emoji/typescript.svg} +0 -0
- package/src/utils/assert.ts +39 -0
- package/src/utils/client.ts +2 -0
- package/src/utils/crawlAllFiles.ts +17 -0
- package/src/utils/determineSectionUrlHash.ts +35 -0
- package/src/utils/filesystemPathHandling.ts +42 -0
- package/src/utils/filter.ts +12 -0
- package/src/utils/isBrowser.ts +5 -0
- package/src/utils/jsxToTextContent.ts +11 -0
- package/src/utils/objectAssign.ts +9 -0
- package/src/utils/server.ts +8 -0
- package/src/vite.config.ts +44 -0
- package/dist/chunk-7HKDCMSZ.js +0 -154
- package/dist/chunk-7HKDCMSZ.js.map +0 -1
- package/dist/chunk-G2A5MZJA.js +0 -48
- package/dist/chunk-G2A5MZJA.js.map +0 -1
- package/dist/chunk-GBXQT242.js.map +0 -1
- package/dist/chunk-JS5BGVDK.js +0 -178
- package/dist/chunk-JS5BGVDK.js.map +0 -1
- package/dist/chunk-OEVBWUR6.js +0 -92
- package/dist/chunk-OEVBWUR6.js.map +0 -1
- package/dist/chunk-TTLAZ2T2.js +0 -8
- package/dist/chunk-TTLAZ2T2.js.map +0 -1
- package/dist/cli/index.d.ts +0 -1
- package/dist/cli/index.js +0 -35
- package/dist/cli/index.js.map +0 -1
- package/dist/components/features/FeatureList.css.map +0 -1
- package/dist/components/features/FeatureList.d.ts +0 -13
- package/dist/components/features/FeatureList.js +0 -8
- package/dist/components/features/FeatureList.js.map +0 -1
- package/dist/components/features/initFeatureList.d.ts +0 -3
- package/dist/components/features/initFeatureList.js +0 -60
- package/dist/components/features/initFeatureList.js.map +0 -1
- package/dist/index.css +0 -121
- package/dist/index.css.map +0 -1
- package/dist/renderer/_default.page.client.css +0 -263
- package/dist/renderer/_default.page.client.css.map +0 -1
- package/dist/renderer/_default.page.client.d.ts +0 -1
- package/dist/renderer/_default.page.client.js +0 -180
- package/dist/renderer/_default.page.client.js.map +0 -1
- package/dist/renderer/_default.page.server.css +0 -312
- package/dist/renderer/_default.page.server.css.map +0 -1
- package/dist/renderer/_default.page.server.d.ts +0 -22
- package/dist/renderer/_default.page.server.js +0 -602
- package/dist/renderer/_default.page.server.js.map +0 -1
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import { assert, determineSectionUrlHash } from '../src/utils/server'
|
|
2
|
+
|
|
3
|
+
export { markdownHeadingsVitePlugin }
|
|
4
|
+
export type { MarkdownHeading }
|
|
5
|
+
|
|
6
|
+
type MarkdownHeading = {
|
|
7
|
+
title: string
|
|
8
|
+
id: string
|
|
9
|
+
headingLevel: number
|
|
10
|
+
titleAddendum?: string
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function markdownHeadingsVitePlugin() {
|
|
14
|
+
return {
|
|
15
|
+
name: 'mdx-headings',
|
|
16
|
+
enforce: 'pre',
|
|
17
|
+
transform: async (code: string, id: string) => {
|
|
18
|
+
if (!id.includes('.page.') || !id.endsWith('.mdx')) {
|
|
19
|
+
return
|
|
20
|
+
}
|
|
21
|
+
const codeNew = transform(code)
|
|
22
|
+
return codeNew
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function transform(code: string) {
|
|
28
|
+
const headings: MarkdownHeading[] = []
|
|
29
|
+
let isCodeBlock = false
|
|
30
|
+
let codeNew = code
|
|
31
|
+
.split('\n')
|
|
32
|
+
.map((line) => {
|
|
33
|
+
// Skip code blocks, e.g.
|
|
34
|
+
// ~~~md
|
|
35
|
+
// # Markdown Example
|
|
36
|
+
// Bla
|
|
37
|
+
// ~~~
|
|
38
|
+
if (line.startsWith('~~~') || line.startsWith('```')) {
|
|
39
|
+
isCodeBlock = !isCodeBlock
|
|
40
|
+
return line
|
|
41
|
+
}
|
|
42
|
+
if (isCodeBlock) {
|
|
43
|
+
return line
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if (line.startsWith('#')) {
|
|
47
|
+
const { id, headingLevel, title, headingHtml } = parseMarkdownHeading(line)
|
|
48
|
+
headings.push({ id, headingLevel, title })
|
|
49
|
+
return headingHtml
|
|
50
|
+
}
|
|
51
|
+
if (line.startsWith('<h')) {
|
|
52
|
+
assert(false, { line })
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return line
|
|
56
|
+
})
|
|
57
|
+
.join('\n')
|
|
58
|
+
const headingsExportCode = `export const headings = [${headings
|
|
59
|
+
.map((heading) => JSON.stringify(heading))
|
|
60
|
+
.join(', ')}];`
|
|
61
|
+
codeNew += `\n\n${headingsExportCode}\n`
|
|
62
|
+
return codeNew
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function parseMarkdownHeading(line: string): MarkdownHeading & { headingHtml: string } {
|
|
66
|
+
const [lineBegin, ...lineWords] = line.split(' ')
|
|
67
|
+
assert(lineBegin.split('#').join('') === '', { line, lineWords })
|
|
68
|
+
const headingLevel = lineBegin.length
|
|
69
|
+
|
|
70
|
+
const titleMdx = lineWords.join(' ')
|
|
71
|
+
assert(!titleMdx.startsWith(' '), { line, lineWords })
|
|
72
|
+
assert(titleMdx, { line, lineWords })
|
|
73
|
+
|
|
74
|
+
const id = determineSectionUrlHash(titleMdx)
|
|
75
|
+
const title = titleMdx
|
|
76
|
+
|
|
77
|
+
const headingHtml = `<h${headingLevel} id="${id}">${parseTitle(title)}</h${headingLevel}>`
|
|
78
|
+
|
|
79
|
+
const heading = { headingLevel, title, id, headingHtml }
|
|
80
|
+
return heading
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function parseTitle(titleMarkdown: string): string {
|
|
84
|
+
type Part = { nodeType: 'text' | 'code'; content: string }
|
|
85
|
+
const parts: Part[] = []
|
|
86
|
+
let current: Part | undefined
|
|
87
|
+
titleMarkdown.split('').forEach((letter) => {
|
|
88
|
+
if (letter === '`') {
|
|
89
|
+
if (current?.nodeType === 'code') {
|
|
90
|
+
// </code>
|
|
91
|
+
parts.push(current)
|
|
92
|
+
current = undefined
|
|
93
|
+
} else {
|
|
94
|
+
// <code>
|
|
95
|
+
if (current) {
|
|
96
|
+
parts.push(current)
|
|
97
|
+
}
|
|
98
|
+
current = { nodeType: 'code', content: '' }
|
|
99
|
+
}
|
|
100
|
+
} else {
|
|
101
|
+
if (!current) {
|
|
102
|
+
current = { nodeType: 'text', content: '' }
|
|
103
|
+
}
|
|
104
|
+
current.content += letter
|
|
105
|
+
}
|
|
106
|
+
})
|
|
107
|
+
if (current) {
|
|
108
|
+
parts.push(current)
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
const titleHtml = parts
|
|
112
|
+
.map((part) => {
|
|
113
|
+
if (part.nodeType === 'code') {
|
|
114
|
+
return `<code>${serializeText(part.content)}</code>`
|
|
115
|
+
} else {
|
|
116
|
+
assert(part.nodeType === 'text', { parts })
|
|
117
|
+
return serializeText(part.content)
|
|
118
|
+
}
|
|
119
|
+
})
|
|
120
|
+
.join('')
|
|
121
|
+
|
|
122
|
+
return titleHtml
|
|
123
|
+
|
|
124
|
+
function serializeText(text: string) {
|
|
125
|
+
const textEscaped = text.split("'").join("\\'")
|
|
126
|
+
return `{'${textEscaped}'}`
|
|
127
|
+
}
|
|
128
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/*
|
|
2
|
+
.nav-item {
|
|
3
|
+
border-top: 1px solid transparent;
|
|
4
|
+
}
|
|
5
|
+
.nav-item.is-active {
|
|
6
|
+
border-color: #eaeaea;
|
|
7
|
+
}
|
|
8
|
+
.nav-item[is-active] {
|
|
9
|
+
background-color: attr(is-active)
|
|
10
|
+
}
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
/*
|
|
14
|
+
#navigation-container:not(:hover) ::-webkit-scrollbar {
|
|
15
|
+
display: none;
|
|
16
|
+
}
|
|
17
|
+
#navigation-container ::-webkit-scrollbar-thumb {
|
|
18
|
+
opacity: 0;
|
|
19
|
+
}
|
|
20
|
+
#navigation-container ::-webkit-scrollbar-track {
|
|
21
|
+
opacity: 0;
|
|
22
|
+
}
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
/*
|
|
26
|
+
.nav-tree:not(.expanded) > .nav-tree {
|
|
27
|
+
edisplay: none;
|
|
28
|
+
background:red;
|
|
29
|
+
}
|
|
30
|
+
*/
|
|
31
|
+
/*
|
|
32
|
+
.nav-tree.expanded,
|
|
33
|
+
.nav-tree.expanded > .nav-tree {
|
|
34
|
+
display: inherit;
|
|
35
|
+
}
|
|
36
|
+
.nav-tree.expanded,
|
|
37
|
+
.nav-tree.expanded > .nav-tree {
|
|
38
|
+
display: inherit;
|
|
39
|
+
background:red;
|
|
40
|
+
}
|
|
41
|
+
*/
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
.nav-item {
|
|
2
|
+
display: block;
|
|
3
|
+
white-space: nowrap;
|
|
4
|
+
overflow-x: hidden;
|
|
5
|
+
--padding-left-global: 9px;
|
|
6
|
+
--padding-left-additional: 0px;
|
|
7
|
+
}
|
|
8
|
+
.nav-item code {
|
|
9
|
+
font-size: 0.9em;
|
|
10
|
+
}
|
|
11
|
+
.nav-item-h1 + .nav-item-h4 {
|
|
12
|
+
margin-top: -2px;
|
|
13
|
+
}
|
|
14
|
+
.nav-item-h4 {
|
|
15
|
+
margin-top: 14px;
|
|
16
|
+
margin-bottom: -1px;
|
|
17
|
+
color: #999;
|
|
18
|
+
font-size: 12px;
|
|
19
|
+
font-weight: 400;
|
|
20
|
+
letter-spacing: 0.15ch;
|
|
21
|
+
padding-left: var(--padding-left-global);
|
|
22
|
+
padding-right: 4px;
|
|
23
|
+
text-decoration: none;
|
|
24
|
+
}
|
|
25
|
+
.nav-column:first-of-type > .nav-h1-group:first-of-type > .nav-item-h1:first-of-type {
|
|
26
|
+
margin-top: 20px;
|
|
27
|
+
}
|
|
28
|
+
.nav-item-h1 {
|
|
29
|
+
margin-top: 30px;
|
|
30
|
+
font-size: 15.4px;
|
|
31
|
+
text-transform: uppercase;
|
|
32
|
+
font-weight: 600;
|
|
33
|
+
letter-spacing: 0.15ch;
|
|
34
|
+
color: var(--color-text);
|
|
35
|
+
padding: 12px 0;
|
|
36
|
+
padding-left: calc(var(--padding-left-global) - 2px);
|
|
37
|
+
padding-right: 4px;
|
|
38
|
+
text-decoration: none;
|
|
39
|
+
}
|
|
40
|
+
.nav-item-h2 {
|
|
41
|
+
text-decoration: none;
|
|
42
|
+
font-size: 14.4px;
|
|
43
|
+
font-weight: 400;
|
|
44
|
+
letter-spacing: 0.15ch;
|
|
45
|
+
color: var(--color-text);
|
|
46
|
+
padding-left: var(--padding-left-global);
|
|
47
|
+
padding-right: 0;
|
|
48
|
+
--padding: 4px;
|
|
49
|
+
padding-top: var(--padding);
|
|
50
|
+
padding-bottom: var(--padding);
|
|
51
|
+
}
|
|
52
|
+
.nav-item-h3 {
|
|
53
|
+
font-size: 12px;
|
|
54
|
+
font-weight: 400;
|
|
55
|
+
letter-spacing: 0.15ch;
|
|
56
|
+
color: var(--color-text);
|
|
57
|
+
text-decoration: none;
|
|
58
|
+
--padding: 5px;
|
|
59
|
+
|
|
60
|
+
background-color: #f9f9f9;
|
|
61
|
+
padding: var(--padding) 0;
|
|
62
|
+
padding-left: calc(var(--padding-left-global) + var(--padding-left-additional));
|
|
63
|
+
}
|
|
64
|
+
html.navigation-fullscreen .nav-item-h3 {
|
|
65
|
+
border-right: 4px solid #eee;
|
|
66
|
+
}
|
|
67
|
+
.nav-item-h3.nav-item-first-of-its-kind {
|
|
68
|
+
padding-top: calc(var(--padding) * 1.6);
|
|
69
|
+
}
|
|
70
|
+
.nav-item-h3.nav-item-last-of-its-kind {
|
|
71
|
+
padding-bottom: calc(var(--padding) * 2);
|
|
72
|
+
}
|
|
73
|
+
.nav-item-h2,
|
|
74
|
+
.nav-item-h3 {
|
|
75
|
+
position: relative;
|
|
76
|
+
}
|
|
77
|
+
/*
|
|
78
|
+
.nav-item-h2.is-active .nav-item-text{
|
|
79
|
+
background-color: var(--background-color);
|
|
80
|
+
}
|
|
81
|
+
*/
|
|
82
|
+
.nav-item-h2.is-active {
|
|
83
|
+
background-color: var(--background-color);
|
|
84
|
+
}
|
|
85
|
+
.nav-item-h3.is-active:before {
|
|
86
|
+
display: block;
|
|
87
|
+
content: '';
|
|
88
|
+
position: absolute;
|
|
89
|
+
width: 4px;
|
|
90
|
+
left: 0;
|
|
91
|
+
top: 0;
|
|
92
|
+
height: 100%;
|
|
93
|
+
background-color: var(--background-color);
|
|
94
|
+
z-index: 10;
|
|
95
|
+
}
|
|
96
|
+
.nav-item-h3.is-active-last:after {
|
|
97
|
+
display: block;
|
|
98
|
+
content: '';
|
|
99
|
+
position: absolute;
|
|
100
|
+
height: 4px;
|
|
101
|
+
left: 0;
|
|
102
|
+
bottom: 0;
|
|
103
|
+
width: 100%;
|
|
104
|
+
background-color: var(--background-color);
|
|
105
|
+
z-index: 10;
|
|
106
|
+
border-bottom-left-radius: 5px;
|
|
107
|
+
}
|
|
108
|
+
html.navigation-fullscreen .nav-item {
|
|
109
|
+
--expend-border-radius: 5px;
|
|
110
|
+
}
|
|
111
|
+
.nav-item.is-active-first {
|
|
112
|
+
border-top-left-radius: 5px;
|
|
113
|
+
border-top-right-radius: var(--expend-border-radius);
|
|
114
|
+
}
|
|
115
|
+
.nav-item.is-active-last,
|
|
116
|
+
.nav-item.is-active-last:before {
|
|
117
|
+
border-bottom-left-radius: 5px;
|
|
118
|
+
border-bottom-right-radius: var(--expend-border-radius);
|
|
119
|
+
}
|
|
120
|
+
.nav-item-h3.nav-item-parent-is-list-heading {
|
|
121
|
+
--padding-left-additional: 21px;
|
|
122
|
+
}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
:root {
|
|
2
|
+
--mobile-header-height: 60px;
|
|
3
|
+
--navigation-min-height: 300px;
|
|
4
|
+
--navigation-max-height: 350px;
|
|
5
|
+
}
|
|
6
|
+
#navigation-wrapper {
|
|
7
|
+
min-width: var(--navigation-min-height);
|
|
8
|
+
}
|
|
9
|
+
.doc-page #navigation-wrapper {
|
|
10
|
+
max-width: var(--navigation-max-height);
|
|
11
|
+
}
|
|
12
|
+
.landing-page #navigation-wrapper {
|
|
13
|
+
/* prettier-ignore */
|
|
14
|
+
max-width: min(var(--navigation-max-height), max(var(--navigation-min-height), calc(var(--navigation-min-height) + 100vw - 1240px)));
|
|
15
|
+
}
|
|
16
|
+
#navigation-container {
|
|
17
|
+
/* `position: fixed` doesn't inherit the parent's width */
|
|
18
|
+
position: sticky;
|
|
19
|
+
overflow-y: auto;
|
|
20
|
+
overscroll-behavior: contain;
|
|
21
|
+
border-right: 1px solid #eee;
|
|
22
|
+
}
|
|
23
|
+
#navigation-mask {
|
|
24
|
+
position: fixed;
|
|
25
|
+
width: 100vw;
|
|
26
|
+
height: 100vh;
|
|
27
|
+
top: 0;
|
|
28
|
+
left: 0;
|
|
29
|
+
z-index: 2;
|
|
30
|
+
}
|
|
31
|
+
/* `1140px` is the breaking point that preserves the width of code blocks. */
|
|
32
|
+
/* BEFORE EDITING THIS: also change the `1139px` value below */
|
|
33
|
+
@media screen and (min-width: 1140px) {
|
|
34
|
+
#mobile-header {
|
|
35
|
+
display: none !important;
|
|
36
|
+
}
|
|
37
|
+
#navigation-container {
|
|
38
|
+
height: 100vh;
|
|
39
|
+
top: 0;
|
|
40
|
+
}
|
|
41
|
+
#navigation-mask {
|
|
42
|
+
display: none;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
#navigation-container {
|
|
46
|
+
transition: transform 0.25s ease;
|
|
47
|
+
background: white;
|
|
48
|
+
z-index: 3;
|
|
49
|
+
}
|
|
50
|
+
#page-wrapper {
|
|
51
|
+
margin-left: calc(-1 * var(--navigation-fullscreen-button-width));
|
|
52
|
+
}
|
|
53
|
+
@media screen and (max-width: 1139px) {
|
|
54
|
+
#navigation-header-logo,
|
|
55
|
+
#docsearch {
|
|
56
|
+
display: none !important;
|
|
57
|
+
}
|
|
58
|
+
#navigation-wrapper {
|
|
59
|
+
min-width: 0px !important;
|
|
60
|
+
max-width: 0px !important;
|
|
61
|
+
}
|
|
62
|
+
#navigation-fullscreen-button {
|
|
63
|
+
display: none;
|
|
64
|
+
}
|
|
65
|
+
#page-wrapper {
|
|
66
|
+
margin-left: 0 !important;
|
|
67
|
+
}
|
|
68
|
+
#navigation-container {
|
|
69
|
+
--width: min(100vw, 350px);
|
|
70
|
+
width: var(--width);
|
|
71
|
+
left: 0;
|
|
72
|
+
height: calc(100vh - var(--mobile-header-height));
|
|
73
|
+
top: var(--mobile-header-height);
|
|
74
|
+
padding-top: 20px;
|
|
75
|
+
/* `position: sticky` doesn't seem to work on mobile */
|
|
76
|
+
position: fixed;
|
|
77
|
+
}
|
|
78
|
+
body:not(.show-menu) #navigation-container {
|
|
79
|
+
transform: translateX(calc(-1 * var(--width)));
|
|
80
|
+
}
|
|
81
|
+
body:not(.show-menu) #navigation-mask {
|
|
82
|
+
display: none;
|
|
83
|
+
}
|
|
84
|
+
#mobile-header {
|
|
85
|
+
display: inherit;
|
|
86
|
+
}
|
|
87
|
+
.doc-page h2 {
|
|
88
|
+
--padding-top: calc(var(--mobile-header-height) + 12px) !important;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
html.navigation-fullscreen #navigation-container {
|
|
93
|
+
width: 100vw;
|
|
94
|
+
height: 100vh;
|
|
95
|
+
overflow-y: scroll;
|
|
96
|
+
position: fixed;
|
|
97
|
+
top: 0;
|
|
98
|
+
left: 0;
|
|
99
|
+
background-color: white;
|
|
100
|
+
}
|
|
101
|
+
html.navigation-fullscreen #navigation-header {
|
|
102
|
+
display: none !important;
|
|
103
|
+
}
|
|
104
|
+
html.navigation-fullscreen #navigation-content {
|
|
105
|
+
display: flex;
|
|
106
|
+
margin: auto; /* A `max-width` is set by src/navigation/navigation-fullscreen/initNavigationFullscreen.ts */
|
|
107
|
+
}
|
|
108
|
+
html.navigation-fullscreen #navigation-content > .nav-column {
|
|
109
|
+
flex-grow: 1;
|
|
110
|
+
max-width: 350px;
|
|
111
|
+
}
|
|
112
|
+
html.navigation-fullscreen .nav-column > .nav-h1-group:first-child > .nav-item-h1:first-child {
|
|
113
|
+
margin-top: 0px;
|
|
114
|
+
}
|
|
115
|
+
html.navigation-fullscreen {
|
|
116
|
+
/* disable scroll of main view */
|
|
117
|
+
overflow: hidden !important;
|
|
118
|
+
}
|
|
@@ -0,0 +1,303 @@
|
|
|
1
|
+
// @ts-nocheck
|
|
2
|
+
|
|
3
|
+
import { headings as headingsCrawled } from './Docs.mdx'
|
|
4
|
+
import { assert, isBrowser } from './utils/client'
|
|
5
|
+
import { Heading } from './types'
|
|
6
|
+
const headings: Heading[] = [
|
|
7
|
+
{
|
|
8
|
+
level: 2,
|
|
9
|
+
title: 'Overview',
|
|
10
|
+
isDocumentBegin: true
|
|
11
|
+
},
|
|
12
|
+
...headingsCrawled
|
|
13
|
+
]
|
|
14
|
+
assert_headings()
|
|
15
|
+
|
|
16
|
+
export { updateSidePanelScroll }
|
|
17
|
+
|
|
18
|
+
if (isBrowser()) {
|
|
19
|
+
setTimeout(updateSidePanelScroll, 0)
|
|
20
|
+
window.addEventListener('scroll', updateSidePanelScroll, { passive: true })
|
|
21
|
+
window.addEventListener('resize', updateSidePanelScroll, { passive: true })
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function updateSidePanelScroll() {
|
|
25
|
+
const headingSectionsVisibility = getHeadingSectionsVisbility(headings)
|
|
26
|
+
setActiveHeadings(headingSectionsVisibility)
|
|
27
|
+
renderNavScrollBar(headingSectionsVisibility)
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function setActiveHeadings(headingSectionsVisibility: HeadingSectionVisibility[]) {
|
|
31
|
+
/*
|
|
32
|
+
const viewportPercentageHighest = Math.max(
|
|
33
|
+
...headingSectionsVisibility.map(({ viewportPercentage }) => viewportPercentage)
|
|
34
|
+
)
|
|
35
|
+
*/
|
|
36
|
+
const visibleHeadings = getVisibleHeadings(headingSectionsVisibility)
|
|
37
|
+
// console.log('v', visibleHeadings);
|
|
38
|
+
headingSectionsVisibility.forEach((heading) => {
|
|
39
|
+
const navItem = findNavLink(heading)
|
|
40
|
+
const isVisibile = visibleHeadings.find((visibleHeading) => {
|
|
41
|
+
if ('isDocumentBegin' in heading || 'isDocumentBegin' in visibleHeading) {
|
|
42
|
+
return 'isDocumentBegin' in heading && 'isDocumentBegin' in visibleHeading
|
|
43
|
+
} else {
|
|
44
|
+
return heading.id === visibleHeading.id
|
|
45
|
+
}
|
|
46
|
+
})
|
|
47
|
+
navItem.style.display = isVisibile ? 'inherit' : 'none'
|
|
48
|
+
/*
|
|
49
|
+
if (viewportPercentageHighest === heading.viewportPercentage) {
|
|
50
|
+
const navItem = findNavLink(heading)
|
|
51
|
+
updateNavTreeExpendedState(navItem)
|
|
52
|
+
}
|
|
53
|
+
*/
|
|
54
|
+
})
|
|
55
|
+
headingSectionsVisibility.forEach((heading) => {
|
|
56
|
+
const navItem = findNavLink(heading)
|
|
57
|
+
setNavItemBackgroundColor(navItem, heading.viewportPercentage)
|
|
58
|
+
})
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function updateNavTreeExpendedState(navItem: HTMLElement) {
|
|
62
|
+
const navItemHref = navItem.getAttribute('href')
|
|
63
|
+
assert(typeof navItemHref === 'string')
|
|
64
|
+
const selector = `a[href="${navItemHref}"]`
|
|
65
|
+
//console.log(11, selector, 2)
|
|
66
|
+
assert(document.querySelector(selector))
|
|
67
|
+
document.querySelectorAll('.nav-tree').forEach((navTree) => {
|
|
68
|
+
const isExpended = !!navTree.querySelector(selector)
|
|
69
|
+
//console.log(navTree.href, isExpended)
|
|
70
|
+
navTree.classList[isExpended ? 'add' : 'remove']('expanded')
|
|
71
|
+
})
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function setNavItemBackgroundColor(navItem: HTMLElement, viewportPercentage: number) {
|
|
75
|
+
if (viewportPercentage) {
|
|
76
|
+
assert(viewportPercentage >= 0 && viewportPercentage <= 1)
|
|
77
|
+
const backgroundColor = `rgba(0, 0, 0, ${viewportPercentage / 20})`
|
|
78
|
+
navItem.style.backgroundColor = backgroundColor
|
|
79
|
+
} else {
|
|
80
|
+
navItem.style.backgroundColor = 'transparent'
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function findNavLink(heading: Heading): HTMLElement {
|
|
85
|
+
const href = getHref(heading)
|
|
86
|
+
const navigationEl = getNavigationEl()
|
|
87
|
+
const navLinks: HTMLElement[] = Array.from(navigationEl.querySelectorAll(`a[href="${href}"]`))
|
|
88
|
+
assert(navLinks.length === 1)
|
|
89
|
+
return navLinks[0]
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
let _navigationEl: HTMLElement
|
|
93
|
+
function getNavigationEl(): HTMLElement {
|
|
94
|
+
_navigationEl = _navigationEl || document.getElementById('navigation-content')
|
|
95
|
+
assert(_navigationEl)
|
|
96
|
+
return _navigationEl
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function renderNavScrollBar(headingSectionsVisibility: HeadingSectionVisibility[]) {
|
|
100
|
+
const { headingVisibleFirst, headingVisibleLast } = getBoundaryHeading(headingSectionsVisibility)
|
|
101
|
+
assertBoundaryPosition(headingVisibleFirst.boundaryPosition)
|
|
102
|
+
assertBoundaryPosition(headingVisibleLast.boundaryPosition)
|
|
103
|
+
|
|
104
|
+
const navigationEl = getNavigationEl()
|
|
105
|
+
const getLinkNavPosition = (el: HTMLElement): number => {
|
|
106
|
+
let offsetY = el.offsetTop
|
|
107
|
+
const parentEl = el.offsetParent as HTMLElement
|
|
108
|
+
if (parentEl !== navigationEl) {
|
|
109
|
+
offsetY += getLinkNavPosition(parentEl)
|
|
110
|
+
}
|
|
111
|
+
return offsetY
|
|
112
|
+
}
|
|
113
|
+
const getOverlayPosition = ({
|
|
114
|
+
heading,
|
|
115
|
+
boundaryPosition
|
|
116
|
+
}: {
|
|
117
|
+
heading: Heading
|
|
118
|
+
boundaryPosition: number
|
|
119
|
+
}): number => {
|
|
120
|
+
const navLink = findNavLink(heading)
|
|
121
|
+
const navLinkPos = getLinkNavPosition(navLink)
|
|
122
|
+
const scrollOverlayBoundaryPos = navLinkPos + navLink.clientHeight * boundaryPosition
|
|
123
|
+
return scrollOverlayBoundaryPos
|
|
124
|
+
}
|
|
125
|
+
const overlayBegin = getOverlayPosition(headingVisibleFirst)
|
|
126
|
+
const overlayEnd = getOverlayPosition(headingVisibleLast)
|
|
127
|
+
const overlayHeight = Math.max(1, overlayEnd - overlayBegin)
|
|
128
|
+
const scrollOverlayEl = document.getElementById('scroll-overlay')!
|
|
129
|
+
scrollOverlayEl.style.top = overlayBegin + 'px'
|
|
130
|
+
scrollOverlayEl.style.height = overlayHeight + 'px'
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
function getHeadingPosition(heading: Heading): number {
|
|
134
|
+
if ('isDocumentBegin' in heading) return 0
|
|
135
|
+
const { id } = heading
|
|
136
|
+
assert(id)
|
|
137
|
+
const el = document.getElementById(id)
|
|
138
|
+
assert(el)
|
|
139
|
+
|
|
140
|
+
// `el.getBoundingClientRect()` returns position relative to viewport begin
|
|
141
|
+
// - https://stackoverflow.com/questions/5598743/finding-elements-position-relative-to-the-document
|
|
142
|
+
const headingPositionRelative = el.getBoundingClientRect().top
|
|
143
|
+
|
|
144
|
+
const scrollPosition = getScrollPosition()
|
|
145
|
+
|
|
146
|
+
// We add the viewport begin position
|
|
147
|
+
const headingPosition = headingPositionRelative + scrollPosition
|
|
148
|
+
|
|
149
|
+
return headingPosition
|
|
150
|
+
}
|
|
151
|
+
function getDocumentHeight(): number {
|
|
152
|
+
return document.body.clientHeight
|
|
153
|
+
}
|
|
154
|
+
function getViewportHeight(): number {
|
|
155
|
+
return window.innerHeight
|
|
156
|
+
}
|
|
157
|
+
function getScrollPosition(): number {
|
|
158
|
+
return window.scrollY
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
type HeadingVisible = { heading: Heading; boundaryPosition: number; viewportPercentage: number }
|
|
162
|
+
function getVisibleHeadings(headingSectionsVisibility: HeadingSectionVisibility[]): HeadingSectionVisibility[] {
|
|
163
|
+
const headings_withVisibileNavItem: Heading[] = filterHeadingsWithVisibileNavItem(headingSectionsVisibility)
|
|
164
|
+
const headingSectionsWithVisibleNavItemVisibility = getHeadingSectionsVisbility(headings_withVisibileNavItem)
|
|
165
|
+
return headingSectionsWithVisibleNavItemVisibility
|
|
166
|
+
}
|
|
167
|
+
function getBoundaryHeading(headingSectionsVisibility: HeadingSectionVisibility[]): {
|
|
168
|
+
headingVisibleFirst: HeadingVisible
|
|
169
|
+
headingVisibleLast: HeadingVisible
|
|
170
|
+
} {
|
|
171
|
+
const headingSectionsWithVisibleNavItemVisibility = getVisibleHeadings(headingSectionsVisibility)
|
|
172
|
+
const h: HeadingSectionVisibility[] = headingSectionsWithVisibleNavItemVisibility
|
|
173
|
+
const hFirst = h.find(({ screenBeginPosition }) => screenBeginPosition !== null)
|
|
174
|
+
const hLast = h.find(({ screenEndPosition }) => screenEndPosition !== null)
|
|
175
|
+
assert(hFirst)
|
|
176
|
+
assert(hLast)
|
|
177
|
+
assert(hFirst.screenBeginPosition !== null)
|
|
178
|
+
assert(hLast.screenEndPosition !== null)
|
|
179
|
+
const headingVisibleFirst = {
|
|
180
|
+
heading: hFirst,
|
|
181
|
+
boundaryPosition: hFirst.screenBeginPosition,
|
|
182
|
+
viewportPercentage: hFirst.viewportPercentage
|
|
183
|
+
}
|
|
184
|
+
const headingVisibleLast = {
|
|
185
|
+
heading: hLast,
|
|
186
|
+
boundaryPosition: hLast.screenEndPosition,
|
|
187
|
+
viewportPercentage: hLast.viewportPercentage
|
|
188
|
+
}
|
|
189
|
+
return { headingVisibleFirst, headingVisibleLast }
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
function filterHeadingsWithVisibileNavItem(headingSectionsVisibility: HeadingSectionVisibility[]): Heading[] {
|
|
193
|
+
const hs = headingSectionsVisibility
|
|
194
|
+
const viewportPercentageHighest = Math.max(...hs.map(({ viewportPercentage }) => viewportPercentage))
|
|
195
|
+
const mainHeading = hs.find((heading) => {
|
|
196
|
+
return heading.viewportPercentage === viewportPercentageHighest
|
|
197
|
+
})
|
|
198
|
+
assert(mainHeading)
|
|
199
|
+
const ancestors = getAncestors(mainHeading, hs)
|
|
200
|
+
const headings_withVisibileNavItem = hs.filter((heading) => {
|
|
201
|
+
const p = getParent(heading, hs)
|
|
202
|
+
return p === null || ancestors.includes(p)
|
|
203
|
+
})
|
|
204
|
+
return headings_withVisibileNavItem
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
function getParent(heading: Heading, headings: Heading[]): Heading | null {
|
|
208
|
+
return getAncestors(heading, headings)[0] || null
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
function getAncestors(heading: Heading, headings: Heading[]): Heading[] {
|
|
212
|
+
const headingIndex = headings.indexOf(heading)
|
|
213
|
+
assert(headingIndex >= 0)
|
|
214
|
+
const ancestors: Heading[] = []
|
|
215
|
+
let currentLevel = heading.level - 1
|
|
216
|
+
for (let i = headingIndex - 1; i >= 0; i--) {
|
|
217
|
+
const h = headings[i]
|
|
218
|
+
if (h.level === currentLevel) {
|
|
219
|
+
ancestors.push(h)
|
|
220
|
+
currentLevel--
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
assert(currentLevel === 1)
|
|
224
|
+
return ancestors
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
type HeadingSectionVisibility = Heading & {
|
|
228
|
+
viewportPercentage: number
|
|
229
|
+
screenBeginPosition: null | number
|
|
230
|
+
screenEndPosition: null | number
|
|
231
|
+
}
|
|
232
|
+
function getHeadingSectionsVisbility(headings: Heading[]): HeadingSectionVisibility[] {
|
|
233
|
+
const screenBeginPositionAbsolute = getScrollPosition()
|
|
234
|
+
const screenEndPositionAbsolute = screenBeginPositionAbsolute + getViewportHeight()
|
|
235
|
+
|
|
236
|
+
const headingSections: (HeadingSectionVisibility & { beginPosition: number; endPosition: number })[] = []
|
|
237
|
+
headings.forEach((heading, i) => {
|
|
238
|
+
const beginPosition = getHeadingPosition(heading)
|
|
239
|
+
|
|
240
|
+
const headingNext = headings[i + 1]
|
|
241
|
+
const endPosition = !headingNext ? getDocumentHeight() : getHeadingPosition(headingNext)
|
|
242
|
+
|
|
243
|
+
const sectionHeight = endPosition - beginPosition
|
|
244
|
+
assert(sectionHeight > 0)
|
|
245
|
+
|
|
246
|
+
let screenBeginPosition = null
|
|
247
|
+
if (beginPosition <= screenBeginPositionAbsolute && screenBeginPositionAbsolute <= endPosition) {
|
|
248
|
+
screenBeginPosition = (screenBeginPositionAbsolute - beginPosition) / sectionHeight
|
|
249
|
+
assert(0 <= screenBeginPosition && screenBeginPosition <= 1)
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
let screenEndPosition = null
|
|
253
|
+
if (beginPosition <= screenEndPositionAbsolute && screenEndPositionAbsolute <= endPosition) {
|
|
254
|
+
screenEndPosition = (screenEndPositionAbsolute - beginPosition) / sectionHeight
|
|
255
|
+
assert(0 <= screenEndPosition && screenEndPosition <= 1)
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
assert(beginPosition <= endPosition)
|
|
259
|
+
const getViewportPosition = (position: number) => {
|
|
260
|
+
const viewportPosition = Math.min(Math.max(position, screenBeginPositionAbsolute), screenEndPositionAbsolute)
|
|
261
|
+
assert(screenBeginPositionAbsolute <= viewportPosition && viewportPosition <= screenEndPositionAbsolute)
|
|
262
|
+
return viewportPosition
|
|
263
|
+
}
|
|
264
|
+
const viewportPositionBegin = getViewportPosition(beginPosition)
|
|
265
|
+
const viewportPositionEnd = getViewportPosition(endPosition)
|
|
266
|
+
const viewportPercentage = (viewportPositionEnd - viewportPositionBegin) / getViewportHeight()
|
|
267
|
+
|
|
268
|
+
headingSections.push({
|
|
269
|
+
...heading,
|
|
270
|
+
viewportPercentage,
|
|
271
|
+
screenBeginPosition,
|
|
272
|
+
screenEndPosition,
|
|
273
|
+
beginPosition,
|
|
274
|
+
endPosition
|
|
275
|
+
})
|
|
276
|
+
})
|
|
277
|
+
|
|
278
|
+
const viewportPercentageTotal = sum(headingSections.map(({ viewportPercentage }) => viewportPercentage))
|
|
279
|
+
const debugInfo = JSON.stringify({ headingSections, screenBeginPositionAbsolute, screenEndPositionAbsolute }, null, 2)
|
|
280
|
+
assert(viewportPercentageTotal <= 1 + 0.00001, debugInfo)
|
|
281
|
+
// assert(1 - 0.00001 <= viewportPercentageTotal && viewportPercentageTotal <= 1 + 0.00001, debugInfo)
|
|
282
|
+
assert(headingSections.filter(({ screenBeginPosition }) => screenBeginPosition !== null).length === 1, debugInfo)
|
|
283
|
+
assert(headingSections.filter(({ screenEndPosition }) => screenEndPosition !== null).length === 1, debugInfo)
|
|
284
|
+
|
|
285
|
+
return headingSections
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
function assertBoundaryPosition(boundaryPosition: number) {
|
|
289
|
+
assert(0 <= boundaryPosition && boundaryPosition <= 1)
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
function sum(numbers: number[]): number {
|
|
293
|
+
return numbers.reduce((a, b) => a + b, 0)
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
function assert_headings() {
|
|
297
|
+
const hrefs: string[] = []
|
|
298
|
+
headings.forEach((heading) => {
|
|
299
|
+
const href = getHref(heading)
|
|
300
|
+
assert(!hrefs.includes(href), href)
|
|
301
|
+
hrefs.push(href)
|
|
302
|
+
})
|
|
303
|
+
}
|