@brillout/docpress 0.1.17 → 0.2.0

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.
Files changed (144) hide show
  1. package/bin.js +3 -0
  2. package/{src/css/Inter-Var.ttf → dist/Inter-Var-IOAEQULN.ttf} +0 -0
  3. package/{src/components/Sponsors/companyLogos/ccoli.svg → dist/ccoli-CHW3TQKS.svg} +0 -0
  4. package/{src/icons/changelog.svg → dist/changelog-IPI5F42D.svg} +0 -0
  5. package/{src/navigation/navigation-fullscreen/chevron.svg → dist/chevron-K3WPYLOP.svg} +0 -0
  6. package/{src/components/features/chevron.svg → dist/chevron-R2IYJD62.svg} +0 -0
  7. package/dist/chunk-7HKDCMSZ.js +154 -0
  8. package/dist/chunk-7HKDCMSZ.js.map +1 -0
  9. package/dist/chunk-G2A5MZJA.js +48 -0
  10. package/dist/chunk-G2A5MZJA.js.map +1 -0
  11. package/dist/chunk-JS5BGVDK.js +178 -0
  12. package/dist/chunk-JS5BGVDK.js.map +1 -0
  13. package/dist/chunk-OEVBWUR6.js +92 -0
  14. package/dist/chunk-OEVBWUR6.js.map +1 -0
  15. package/dist/chunk-TTLAZ2T2.js +8 -0
  16. package/dist/chunk-TTLAZ2T2.js.map +1 -0
  17. package/dist/{chunk-ZYYJWJMY.js → chunk-XUTBTIEE.js} +15 -42
  18. package/dist/chunk-XUTBTIEE.js.map +1 -0
  19. package/dist/cli/index.d.ts +1 -0
  20. package/dist/cli/index.js +35 -0
  21. package/dist/cli/index.js.map +1 -0
  22. package/{src/navigation/navigation-fullscreen/close.svg → dist/close-IQXTDOHV.svg} +0 -0
  23. package/{src/utils/Emoji/compass.svg → dist/compass-2RWQU3E4.svg} +0 -0
  24. package/{src → dist}/components/features/FeatureList.css +2 -7
  25. package/dist/components/features/FeatureList.css.map +1 -0
  26. package/dist/components/features/FeatureList.d.ts +13 -0
  27. package/dist/components/features/FeatureList.js +8 -0
  28. package/dist/components/features/FeatureList.js.map +1 -0
  29. package/dist/components/features/initFeatureList.d.ts +3 -0
  30. package/dist/components/features/initFeatureList.js +60 -0
  31. package/dist/components/features/initFeatureList.js.map +1 -0
  32. package/{src/components/Sponsors/companyLogos/contra.svg → dist/contra-WLZBOPBV.svg} +0 -0
  33. package/dist/{devServer-J2XJQJGT.js → devServer-534L4U45.js} +5 -2
  34. package/dist/{devServer-J2XJQJGT.js.map → devServer-534L4U45.js.map} +1 -1
  35. package/{src/icons/discord.svg → dist/discord-JD33TUSF.svg} +0 -0
  36. package/{src/utils/Emoji/engine.png → dist/engine-6Q6VSCVA.png} +0 -0
  37. package/{src/icons/github.svg → dist/github-P5ZSKN2N.svg} +0 -0
  38. package/{src/icons/heart.svg → dist/heart-OINVKOXO.svg} +0 -0
  39. package/dist/index.css +121 -0
  40. package/dist/index.css.map +1 -0
  41. package/dist/index.d.ts +136 -0
  42. package/dist/index.js +484 -27
  43. package/dist/index.js.map +1 -1
  44. package/{src/components/Sponsors/label.svg → dist/label-MP75CTIA.svg} +0 -0
  45. package/{src/utils/Emoji/mechanical-arm.svg → dist/mechanical-arm-TR7IQQMG.svg} +0 -0
  46. package/{src/components/Sponsors/medalBronze.svg → dist/medalBronze-CO4CTUR4.svg} +0 -0
  47. package/{src/components/Sponsors/medalGold.svg → dist/medalGold-UP6A73FL.svg} +0 -0
  48. package/{src/components/Sponsors/medalSilver.svg → dist/medalSilver-FAPGGOBN.svg} +0 -0
  49. package/{src/components/Sponsors/companyLogos/mfqs.svg → dist/mfqs-2EAEE7N6.svg} +0 -0
  50. package/dist/renderer/_default.page.client.css +263 -0
  51. package/dist/renderer/_default.page.client.css.map +1 -0
  52. package/dist/renderer/_default.page.client.d.ts +1 -0
  53. package/dist/renderer/_default.page.client.js +180 -0
  54. package/dist/renderer/_default.page.client.js.map +1 -0
  55. package/dist/renderer/_default.page.server.css +312 -0
  56. package/dist/renderer/_default.page.server.css.map +1 -0
  57. package/dist/renderer/_default.page.server.d.ts +22 -0
  58. package/dist/renderer/_default.page.server.js +602 -0
  59. package/dist/renderer/_default.page.server.js.map +1 -0
  60. package/{src/utils/Emoji/road-fork.svg → dist/road-fork-3WZLW3HB.svg} +0 -0
  61. package/{src/utils/Emoji/shield.svg → dist/shield-CU45RG5C.svg} +0 -0
  62. package/{src/icons/twitter.svg → dist/twitter-I7DXDN3J.svg} +0 -0
  63. package/{src/utils/Emoji/typescript.svg → dist/typescript-ALIPKLRM.svg} +0 -0
  64. package/package.json +22 -13
  65. package/dist/chunk-ZYYJWJMY.js.map +0 -1
  66. package/src/MobileHeader.tsx +0 -68
  67. package/src/PageLayout.css +0 -41
  68. package/src/PageLayout.tsx +0 -37
  69. package/src/algolia/DocSearch.css +0 -29
  70. package/src/algolia/DocSearch.ts +0 -37
  71. package/src/autoScrollNav.ts +0 -22
  72. package/src/cli/devServer.ts +0 -31
  73. package/src/cli/index.ts +0 -29
  74. package/src/components/CodeBlock.tsx +0 -22
  75. package/src/components/DocLink.tsx +0 -108
  76. package/src/components/EditPageNote.tsx +0 -18
  77. package/src/components/HorizontalLine.tsx +0 -20
  78. package/src/components/ImportMeta.tsx +0 -11
  79. package/src/components/Info.tsx +0 -12
  80. package/src/components/Link.tsx +0 -18
  81. package/src/components/Note.tsx +0 -31
  82. package/src/components/P.css +0 -8
  83. package/src/components/P.tsx +0 -8
  84. package/src/components/ReadingRecommendation.tsx +0 -53
  85. package/src/components/RepoLink.tsx +0 -24
  86. package/src/components/Sponsors/companyLogos/ccoli-logo.svg +0 -1
  87. package/src/components/Sponsors/companyLogos/ccoli-text.svg +0 -1
  88. package/src/components/Sponsors/label.draft.svg +0 -108
  89. package/src/components/Sponsors.tsx +0 -242
  90. package/src/components/features/FeatureList.tsx +0 -114
  91. package/src/components/features/initFeatureList.ts +0 -66
  92. package/src/components/index.ts +0 -13
  93. package/src/config/Config.ts +0 -30
  94. package/src/config/getConfig.ts +0 -18
  95. package/src/config/resolveConfig/resolveHeading.ts +0 -0
  96. package/src/config/resolvePageContext.ts +0 -157
  97. package/src/css/button.css +0 -7
  98. package/src/css/code/block.css +0 -36
  99. package/src/css/code/inline.css +0 -27
  100. package/src/css/code.css +0 -20
  101. package/src/css/colorize-on-hover.css +0 -29
  102. package/src/css/font.css +0 -19
  103. package/src/css/heading.css +0 -25
  104. package/src/css/index.css +0 -11
  105. package/src/css/link.css +0 -17
  106. package/src/css/note.css +0 -26
  107. package/src/css/reset.css +0 -12
  108. package/src/css/table.css +0 -14
  109. package/src/css/tooltip.css +0 -11
  110. package/src/headings.ts +0 -200
  111. package/src/index.ts +0 -3
  112. package/src/installSectionUrlHashs.ts +0 -50
  113. package/src/markdownHeadingsVitePlugin.ts +0 -128
  114. package/src/navigation/Navigation-highlight.css +0 -41
  115. package/src/navigation/Navigation-items.css +0 -122
  116. package/src/navigation/Navigation-layout.css +0 -118
  117. package/src/navigation/Navigation.client.old.ts +0 -303
  118. package/src/navigation/Navigation.client.ts +0 -19
  119. package/src/navigation/Navigation.css +0 -12
  120. package/src/navigation/Navigation.tsx +0 -228
  121. package/src/navigation/NavigationHeader.tsx +0 -97
  122. package/src/navigation/navigation-fullscreen/NavigationFullscreenButton.css +0 -32
  123. package/src/navigation/navigation-fullscreen/NavigationFullscreenButton.tsx +0 -44
  124. package/src/navigation/navigation-fullscreen/initNavigationFullscreen.ts +0 -115
  125. package/src/parseEmojis.ts +0 -33
  126. package/src/renderer/_default.page.client.ts +0 -4
  127. package/src/renderer/_default.page.server.tsx +0 -69
  128. package/src/renderer/usePageContext.tsx +0 -25
  129. package/src/types.ts +0 -2
  130. package/src/utils/Emoji/Emoji.ts +0 -216
  131. package/src/utils/Emoji/assets.ts +0 -9
  132. package/src/utils/Emoji/index.ts +0 -1
  133. package/src/utils/Emoji/mountain.svg +0 -1
  134. package/src/utils/assert.ts +0 -39
  135. package/src/utils/client.ts +0 -2
  136. package/src/utils/crawlAllFiles.ts +0 -17
  137. package/src/utils/determineSectionUrlHash.ts +0 -35
  138. package/src/utils/filesystemPathHandling.ts +0 -42
  139. package/src/utils/filter.ts +0 -12
  140. package/src/utils/isBrowser.ts +0 -5
  141. package/src/utils/jsxToTextContent.ts +0 -11
  142. package/src/utils/objectAssign.ts +0 -9
  143. package/src/utils/server.ts +0 -8
  144. package/src/vite.config.ts +0 -44
@@ -1,27 +0,0 @@
1
- code {
2
- padding: 2px 5px;
3
- }
4
-
5
- /*
6
- * Line breaks in `<code>`:
7
- * - Avoid them on desktop
8
- * - Allow them on mobile
9
- * - Allo them for `<code long>`
10
- */
11
- code {
12
- display: inline-block;
13
- }
14
- @media screen and (max-width: 500px) {
15
- code {
16
- word-break: break-word;
17
- display: inline;
18
- }
19
- }
20
- .inline-code-break code {
21
- display: inline;
22
- word-break: break-word;
23
- }
24
- code.long {
25
- word-break: break-word;
26
- display: inline;
27
- }
package/src/css/code.css DELETED
@@ -1,20 +0,0 @@
1
- @import './code/inline.css';
2
- @import './code/block.css';
3
-
4
- code {
5
- /*
6
- background-color: #f4f4f4;
7
- 0.043137255 = 1 - (#f4 / #ff)
8
- */
9
- background-color: rgba(0, 0, 0, 0.043137255);
10
- border-radius: 4px;
11
- }
12
-
13
- /* Inline */
14
- code {
15
- font-size: 1.1em;
16
- }
17
- /* Block */
18
- pre > code {
19
- font-size: 1em;
20
- }
@@ -1,29 +0,0 @@
1
- .colorize-on-hover,
2
- .colorize-on-hover [class^='decolorize-'],
3
- .colorize-on-hover [class*=' decolorize-'] {
4
- transition: filter 0.3s ease-in-out;
5
- }
6
- .colorize-on-hover:hover,
7
- .colorize-on-hover:hover [class^='decolorize-'],
8
- .colorize-on-hover:hover [class*=' decolorize-'] {
9
- filter: grayscale(0) opacity(1) !important;
10
- }
11
-
12
- .decolorize-7 {
13
- filter: grayscale(1) opacity(0.7);
14
- }
15
- .decolorize-6 {
16
- filter: grayscale(1) opacity(0.6);
17
- }
18
- .decolorize-5 {
19
- filter: grayscale(1) opacity(0.5);
20
- }
21
- .decolorize-4 {
22
- filter: grayscale(1) opacity(0.4);
23
- }
24
-
25
- /*
26
- * Twitter opacity(0.7): #ababab > #868686
27
- * == Following computation does NOT work ==
28
- * Discord opacity(0.7): #6c6c6c > (0.7 * (#fff - #ababab) = #868686 = x * (#fff - #6c6c6c) <=> x = 0.7 * ((#fff - #ababab) / (#fff - #6c6c6c)) = 0.7 * ((255 - 171) / (255 - 108)) = 0.4)
29
- */
package/src/css/font.css DELETED
@@ -1,19 +0,0 @@
1
- body {
2
- font-family: 'Inter';
3
- }
4
- button {
5
- font-family: inherit;
6
- }
7
- body {
8
- --color-text: #323d48;
9
- color: var(--color-text);
10
- line-height: 1.5;
11
- }
12
-
13
- @font-face {
14
- font-family: 'Inter';
15
- font-weight: 100 900;
16
- font-stretch: 75% 125%;
17
- font-style: oblique 0deg 12deg;
18
- src: url('./Inter-Var.ttf') format('truetype-variations');
19
- }
@@ -1,25 +0,0 @@
1
- .doc-page h2 {
2
- margin-top: 50px;
3
- margin-bottom: 16px;
4
- }
5
- .doc-page h2[id] {
6
- cursor: pointer;
7
- position: relative;
8
- padding-left: 20px;
9
- margin-left: -20px;
10
- }
11
- .doc-page h2[id]:hover::before {
12
- content: '#';
13
- position: absolute;
14
- left: calc(-1 * (0.75em - 20px));
15
- color: #aaa;
16
- }
17
-
18
- .doc-page h1 + h2 {
19
- margin-top: 0;
20
- }
21
-
22
- .doc-page h4 {
23
- margin-top: 32px;
24
- margin-bottom: 16px;
25
- }
package/src/css/index.css DELETED
@@ -1,11 +0,0 @@
1
- @import './reset.css';
2
- @import './colorize-on-hover.css';
3
- @import './heading.css';
4
- @import './button.css';
5
- @import './link.css';
6
- @import './font.css';
7
- @import './code.css';
8
- @import './note.css';
9
- @import './table.css';
10
- @import './tooltip.css';
11
- @import '../algolia/DocSearch.css';
package/src/css/link.css DELETED
@@ -1,17 +0,0 @@
1
- /*
2
- :root {
3
- --link-color: #4747ff;
4
- }
5
- */
6
-
7
- a {
8
- /*
9
- color: inherit;
10
- color: var(--link-color);
11
- */
12
- color: #4747ff;
13
- text-decoration: none;
14
- }
15
- a > button {
16
- color: var(--color-text);
17
- }
package/src/css/note.css DELETED
@@ -1,26 +0,0 @@
1
- blockquote {
2
- --color: 0, 0, 0;
3
- --color-strengh-bg: 0.7;
4
- --color-strengh-border: 1.5;
5
- border-left: 8px solid rgba(var(--color), calc(0.06 * var(--color-strengh-border)));
6
- background-color: rgba(var(--color), calc(0.03 * var(--color-strengh-bg)));
7
- margin-left: 0;
8
- padding: 4px 16px;
9
- }
10
- blockquote.error {
11
- --color-strengh-bg: 1.7;
12
- --color-strengh-border: 6;
13
- --color: 190, 25, 49;
14
- }
15
- blockquote.warning {
16
- --color-strengh-bg: 4;
17
- --color-strengh-border: 8;
18
- --color: 255, 204, 50;
19
- }
20
- blockquote > p:first-child::before,
21
- /* blockquote > p:first-of-type::before, */
22
- blockquote > div.paragraph:first-child::before {
23
- font-family: emoji;
24
- content: 'ℹ️';
25
- margin-right: 4px;
26
- }
package/src/css/reset.css DELETED
@@ -1,12 +0,0 @@
1
- * {
2
- box-sizing: border-box;
3
- }
4
- body {
5
- margin: 0;
6
- }
7
-
8
- /* Avoid tweet embeds to overflow the body width.
9
- * Settings `overflow: hidden` to a container doesn't work (This is a CSS bug?) */
10
- iframe {
11
- max-width: 100%;
12
- }
package/src/css/table.css DELETED
@@ -1,14 +0,0 @@
1
- table th {
2
- background-color: #f7f7f7;
3
- }
4
- table {
5
- border-collapse: collapse;
6
- }
7
- table td,
8
- table th {
9
- padding: 8px;
10
- border: 1px solid #ccc;
11
- }
12
- table th {
13
- text-align: left;
14
- }
@@ -1,11 +0,0 @@
1
- @import 'balloon-css';
2
-
3
- :root {
4
- --balloon-color: #444;
5
- --balloon-move: 2px;
6
- --balloon-font-size: 14px;
7
- --balloon-border-radius: 5px;
8
- }
9
- [aria-label][data-balloon-pos]:after {
10
- font-family: 'Inter';
11
- }
package/src/headings.ts DELETED
@@ -1,200 +0,0 @@
1
- import React from 'react'
2
- import { assert, Emoji, EmojiName } from './utils/server'
3
-
4
- export { getHeadings }
5
- export { parseTitle }
6
-
7
- export type Heading = Omit<HeadingDefinition, 'title' | 'titleInNav'> & {
8
- title: JSX.Element
9
- titleInNav: JSX.Element
10
- parentHeadings: Heading[]
11
- // Not sure why this is needed
12
- isListTitle?: true
13
- sectionTitles?: string[]
14
- }
15
- export type HeadingWithoutLink = {
16
- url: string
17
- title: string | JSX.Element
18
- }
19
- export type HeadingDefinition = HeadingBase &
20
- (
21
- | ({ level: 1; titleEmoji: EmojiName } & HeadingAbstract)
22
- | ({ level: 4 } & HeadingAbstract)
23
- | {
24
- level: 2
25
- isListTitle?: true
26
- sectionTitles?: string[]
27
- url: string
28
- }
29
- | {
30
- level: 3
31
- url: string
32
- }
33
- )
34
- type HeadingBase = {
35
- title: string
36
- level: number
37
- url?: string
38
- titleDocument?: string
39
- titleInNav?: string
40
- // titleSize?: string
41
- }
42
- type HeadingAbstract = {
43
- url?: undefined
44
- titleDocument?: undefined
45
- titleInNav?: undefined
46
- }
47
-
48
- function getHeadings(config: { headings: HeadingDefinition[]; headingsWithoutLink: HeadingWithoutLink[] }): {
49
- headings: Heading[]
50
- headingsWithoutLink: HeadingWithoutLink[]
51
- } {
52
- const headingsWithoutParent: Omit<Heading, 'parentHeadings'>[] = config.headings.map((heading: HeadingDefinition) => {
53
- const titleProcessed: JSX.Element = parseTitle(heading.title)
54
-
55
- const titleInNav = heading.titleInNav || heading.title
56
- let titleInNavProcessed: JSX.Element
57
- if ('isListTitle' in heading) {
58
- assert(heading.isListTitle === true)
59
- let titleParsed: JSX.Element = parseTitle(titleInNav)
60
- // if (heading.titleSize) {
61
- // titleParsed = React.createElement('span', { style: { fontSize: heading.titleSize } }, titleParsed)
62
- // }
63
- titleInNavProcessed = React.createElement(React.Fragment, {}, getListPrefix(), titleParsed)
64
- } else {
65
- titleInNavProcessed = parseTitle(titleInNav)
66
- }
67
- if ('titleEmoji' in heading) {
68
- assert(heading.titleEmoji)
69
- titleInNavProcessed = withEmoji(heading.titleEmoji, titleInNavProcessed)
70
- }
71
-
72
- const headingProcessed: Omit<Heading, 'parentHeadings'> = {
73
- ...heading,
74
- title: titleProcessed,
75
- titleInNav: titleInNavProcessed
76
- }
77
- return headingProcessed
78
- })
79
-
80
- const headings: Heading[] = []
81
- headingsWithoutParent.forEach((heading) => {
82
- const parentHeadings = findParentHeadings(heading, headings)
83
- headings.push({ ...heading, parentHeadings })
84
- })
85
-
86
- const headingsWithoutLink = config.headingsWithoutLink.map((headingsWithoutLink) => {
87
- const { url, title } = headingsWithoutLink
88
- assert(
89
- headings.find((heading) => heading.url === url) === undefined,
90
- `remove ${headingsWithoutLink.url} from headingsWithoutLink`
91
- )
92
- const titleProcessed = typeof title === 'string' ? parseTitle(title) : title
93
- return {
94
- ...headingsWithoutLink,
95
- title: titleProcessed
96
- }
97
- })
98
-
99
- assertHeadingsUrl([...headings, ...headingsWithoutLink])
100
- return { headings, headingsWithoutLink }
101
- }
102
-
103
- function findParentHeadings(heading: Omit<Heading, 'parentHeadings'>, headings: Heading[]) {
104
- const parentHeadings: Heading[] = []
105
- let levelCurrent = heading.level
106
- let listTitleParentFound = false
107
- headings
108
- .slice()
109
- .reverse()
110
- .forEach((parentCandidate) => {
111
- let isListTitleParent = false
112
- if (
113
- !listTitleParentFound &&
114
- levelCurrent === heading.level &&
115
- parentCandidate.level === heading.level &&
116
- !parentCandidate.isListTitle &&
117
- heading.isListTitle
118
- ) {
119
- isListTitleParent = true
120
- listTitleParentFound = true
121
- }
122
-
123
- const isParent = parentCandidate.level < levelCurrent
124
-
125
- if (isParent || isListTitleParent) {
126
- levelCurrent = parentCandidate.level
127
- parentHeadings.push(parentCandidate)
128
- }
129
- })
130
- return parentHeadings
131
- }
132
-
133
- function assertHeadingsUrl(headings: { url?: string }[]) {
134
- const urls: Record<string, true> = {}
135
- headings.forEach((heading) => {
136
- if (heading.url) {
137
- const { url } = heading
138
- assert(url.startsWith('/'))
139
- assert(!urls[url], { url })
140
- urls[url] = true
141
- }
142
- })
143
- }
144
-
145
- function getListPrefix() {
146
- const nonBreakingSpace = String.fromCodePoint(0x00a0)
147
- const bulletPoint = String.fromCodePoint(0x2022)
148
- return nonBreakingSpace + bulletPoint + nonBreakingSpace
149
- }
150
-
151
- function parseTitle(title: string): JSX.Element {
152
- type Part = { nodeType: 'text' | 'code'; content: string }
153
- const parts: Part[] = []
154
- let current: Part | undefined
155
- title.split('').forEach((letter) => {
156
- if (letter === '`') {
157
- if (current?.nodeType === 'code') {
158
- // </code>
159
- parts.push(current)
160
- current = undefined
161
- } else {
162
- // <code>
163
- if (current) {
164
- parts.push(current)
165
- }
166
- current = { nodeType: 'code', content: '' }
167
- }
168
- } else {
169
- if (!current) {
170
- current = { nodeType: 'text', content: '' }
171
- }
172
- current.content += letter
173
- }
174
- })
175
- if (current) {
176
- parts.push(current)
177
- }
178
-
179
- const titleJsx = React.createElement(
180
- React.Fragment,
181
- {},
182
- ...parts.map((part, i) =>
183
- React.createElement(part.nodeType === 'code' ? 'code' : React.Fragment, { key: i }, part.content)
184
- )
185
- )
186
-
187
- return titleJsx
188
- }
189
-
190
- function withEmoji(name: EmojiName, title: string | JSX.Element): JSX.Element {
191
- const style = { fontSize: '1.4em' }
192
- //return React.createElement(React.Fragment, null, Emoji({ name, style }), ' ', title)
193
- return React.createElement(
194
- 'span',
195
- { style },
196
- Emoji({ name }),
197
- ' ',
198
- React.createElement('span', { style: { fontSize: '1rem' } }, title)
199
- )
200
- }
package/src/index.ts DELETED
@@ -1,3 +0,0 @@
1
- export * from './components'
2
- export * from './utils/server'
3
- export * from './types'
@@ -1,50 +0,0 @@
1
- import { assert } from './utils/client'
2
-
3
- installSectionUrlHashs()
4
- /* Let browser restore previous scroll
5
- jumpToSection()
6
- */
7
-
8
- function installSectionUrlHashs() {
9
- const pageContainer = document.querySelector('.doc-page #page-container')
10
- if (!pageContainer) {
11
- assert(window.location.pathname === '/')
12
- return
13
- }
14
- const navigationEl = document.getElementById('navigation-content')
15
- assert(navigationEl)
16
- const docSections = Array.from(document.querySelectorAll('h2'))
17
- docSections.forEach((docSection) => {
18
- const docTitle = docSection.textContent
19
- assert(docTitle)
20
- assert(docSection.id, { docSection })
21
- const urlHash = '#' + docSection.id
22
- assertNavLink(navigationEl, urlHash)
23
- docSection.onclick = () => {
24
- window.location.hash = urlHash
25
- // The browser doesn't jump if hash doesn't change
26
- jumpToSection()
27
- }
28
- })
29
- }
30
-
31
- function assertNavLink(navigationEl: HTMLElement, urlHash: string) {
32
- const parentNavLinkMatch = Array.from(navigationEl.querySelectorAll(`a[href="${window.location.pathname}"]`))
33
- assert(parentNavLinkMatch.length <= 1)
34
- if (parentNavLinkMatch.length === 0) return
35
- const navLinks: HTMLElement[] = Array.from(navigationEl.querySelectorAll(`a[href="${urlHash}"]`))
36
- assert(navLinks.length === 1, { urlHash })
37
- }
38
-
39
- function jumpToSection() {
40
- const { hash } = window.location
41
- if (hash === '' || hash === '#') {
42
- return
43
- }
44
- assert(hash.startsWith('#'))
45
- const target = document.getElementById(hash.slice(1))
46
- if (!target) {
47
- return
48
- }
49
- target.scrollIntoView()
50
- }
@@ -1,128 +0,0 @@
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
- }
@@ -1,41 +0,0 @@
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
- */