@brillout/docpress 0.6.21 → 0.7.1
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/+config.ts +26 -3
- package/MobileHeader.tsx +5 -3
- package/PageLayout.tsx +28 -19
- package/algolia/DocSearch.css +6 -9
- package/autoScrollNav.ts +4 -3
- package/components/FeatureList/FeatureList.client.ts +6 -11
- package/components/Link.tsx +9 -9
- package/config/getConfig.ts +2 -1
- package/config/resolveHeadingsData.ts +22 -38
- package/config/resolvePageContext.ts +4 -6
- package/dist/+config.d.ts +25 -3
- package/dist/+config.js +7 -3
- package/dist/components/CodeBlockTransformer.d.ts +7 -0
- package/dist/components/CodeBlockTransformer.js +9 -0
- package/dist/components/Comment.d.ts +5 -0
- package/dist/components/Comment.js +6 -0
- package/dist/components/Consulting.d.ts +4 -0
- package/dist/components/Consulting.js +39 -0
- package/dist/components/Contributors.d.ts +7 -0
- package/dist/components/Contributors.js +74 -0
- package/dist/components/FileRemoved.d.ts +9 -0
- package/dist/components/FileRemoved.js +28 -0
- package/dist/components/HorizontalLine.d.ts +5 -0
- package/dist/components/HorizontalLine.js +15 -0
- package/dist/components/ImportMeta.d.ts +5 -0
- package/dist/components/ImportMeta.js +10 -0
- package/dist/components/Link.d.ts +16 -0
- package/dist/components/Link.js +108 -0
- package/dist/components/Note.d.ts +22 -0
- package/dist/components/Note.js +93 -0
- package/dist/components/P.d.ts +4 -0
- package/dist/components/P.js +17 -0
- package/dist/components/ReadingRecommendation.d.ts +6 -0
- package/dist/components/ReadingRecommendation.js +40 -0
- package/dist/components/RepoLink.d.ts +9 -0
- package/dist/components/RepoLink.js +22 -0
- package/dist/components/Sponsors.d.ts +22 -0
- package/dist/components/Sponsors.js +161 -0
- package/dist/components/Supporters.d.ts +32 -0
- package/dist/components/Supporters.js +80 -0
- package/dist/components/index.d.ts +15 -0
- package/dist/components/index.js +15 -0
- package/dist/config/getConfig.d.ts +3 -0
- package/dist/config/getConfig.js +14 -0
- package/dist/config/resolveHeadingsData.d.ts +16 -0
- package/dist/config/resolveHeadingsData.js +216 -0
- package/dist/config/resolvePageContext.d.ts +38 -0
- package/dist/config/resolvePageContext.js +23 -0
- package/dist/data/maintainersList.d.ts +9 -0
- package/dist/data/maintainersList.js +83 -0
- package/dist/data/sponsorsList.d.ts +3 -0
- package/dist/data/sponsorsList.js +151 -0
- package/dist/navigation/Navigation.d.ts +20 -0
- package/dist/navigation/Navigation.js +134 -0
- package/dist/navigation/NavigationHeader.d.ts +4 -0
- package/dist/navigation/NavigationHeader.js +85 -0
- package/dist/navigation/navigation-fullscreen/NavigationFullscreenButton.d.ts +6 -0
- package/dist/navigation/navigation-fullscreen/NavigationFullscreenButton.js +22 -0
- package/dist/parsePageSections.js +7 -3
- package/dist/parseTitle.d.ts +5 -0
- package/dist/parseTitle.js +52 -0
- package/dist/renderer/usePageContext.d.ts +17 -0
- package/dist/renderer/usePageContext.js +26 -0
- package/dist/types/Config.d.ts +30 -0
- package/dist/types/Config.js +1 -0
- package/dist/types/Heading.d.ts +43 -0
- package/dist/types/Heading.js +1 -0
- package/dist/utils/Emoji/Emoji.d.ts +8 -0
- package/dist/utils/Emoji/Emoji.js +191 -0
- package/dist/utils/Emoji/assets.d.ts +6 -0
- package/dist/utils/Emoji/assets.js +7 -0
- package/dist/utils/Emoji/index.d.ts +1 -0
- package/dist/utils/Emoji/index.js +1 -0
- package/dist/utils/assert.js +43 -8
- package/dist/utils/client.d.ts +2 -0
- package/dist/utils/client.js +2 -0
- package/dist/utils/filter.d.ts +2 -0
- package/dist/utils/filter.js +11 -0
- package/dist/utils/isBrowser.d.ts +2 -0
- package/dist/utils/isBrowser.js +4 -0
- package/dist/utils/jsxToTextContent.d.ts +2 -0
- package/dist/utils/jsxToTextContent.js +12 -0
- package/dist/utils/objectAssign.d.ts +2 -0
- package/dist/utils/objectAssign.js +5 -0
- package/dist/utils/server.d.ts +7 -0
- package/dist/utils/server.js +7 -0
- package/dist/vite.config.js +5 -3
- package/installSectionUrlHashs.ts +7 -13
- package/navigation/Navigation.tsx +28 -19
- package/navigation/NavigationHeader.tsx +33 -4
- package/navigation/initMobileNavigation.ts +2 -11
- package/navigation/initPressKit.ts +5 -2
- package/navigation/navigation-fullscreen/initNavigationFullscreen.ts +12 -5
- package/package.json +21 -15
- package/parsePageSections.ts +6 -1
- package/renderer/getPageElement.tsx +16 -0
- package/renderer/onBeforeRender.ts +12 -0
- package/renderer/onRenderClient.tsx +90 -0
- package/renderer/onRenderHtml.tsx +10 -22
- package/renderer/usePageContext.tsx +20 -0
- package/tsconfig.config.json +1 -1
- package/tsconfig.json +1 -1
- package/types/Config.ts +6 -20
- package/types/Heading.ts +5 -5
- package/utils/assert.ts +44 -8
- package/utils/jsxToTextContent.ts +1 -1
- package/vite.config.ts +5 -3
- package/algolia/DocSearch.ts +0 -62
- package/navigation/Navigation.client.ts +0 -7
- package/renderer/client.ts +0 -4
|
@@ -4,12 +4,16 @@ import iconTwitter from '../icons/twitter.svg'
|
|
|
4
4
|
import iconDiscord from '../icons/discord.svg'
|
|
5
5
|
import iconChangelog from '../icons/changelog.svg'
|
|
6
6
|
import iconLanguages from '../icons/languages.svg'
|
|
7
|
-
import { usePageContext } from '../renderer/usePageContext'
|
|
7
|
+
import { usePageContext, usePageContext2 } from '../renderer/usePageContext'
|
|
8
|
+
import { DocSearch } from '@docsearch/react'
|
|
9
|
+
import '@docsearch/css'
|
|
8
10
|
|
|
9
11
|
export { NavigationHeader }
|
|
10
12
|
|
|
11
13
|
function NavigationHeader() {
|
|
12
14
|
const pageContext = usePageContext()
|
|
15
|
+
const pageContext2 = usePageContext2()
|
|
16
|
+
const { NavHeader } = pageContext2.config.NavHeader!
|
|
13
17
|
return (
|
|
14
18
|
<div
|
|
15
19
|
id="navigation-header"
|
|
@@ -31,11 +35,11 @@ function NavigationHeader() {
|
|
|
31
35
|
textDecoration: 'none',
|
|
32
36
|
paddingTop: 12,
|
|
33
37
|
paddingBottom: 7,
|
|
34
|
-
...
|
|
38
|
+
...pageContext2.config.NavHeader?.navHeaderWrapperStyle,
|
|
35
39
|
}}
|
|
36
40
|
href="/"
|
|
37
41
|
>
|
|
38
|
-
|
|
42
|
+
<NavHeader />
|
|
39
43
|
</a>
|
|
40
44
|
<Links />
|
|
41
45
|
</div>
|
|
@@ -53,6 +57,7 @@ function Links() {
|
|
|
53
57
|
style={{ height: 21, position: 'relative', top: 0, left: 0 }}
|
|
54
58
|
/>
|
|
55
59
|
)
|
|
60
|
+
const { algolia } = pageContext.meta
|
|
56
61
|
return (
|
|
57
62
|
<div
|
|
58
63
|
style={{
|
|
@@ -67,7 +72,17 @@ function Links() {
|
|
|
67
72
|
<LinkIcon className="decolorize-6" icon={iconDiscord} href={projectInfo.discordInvite} />
|
|
68
73
|
)}
|
|
69
74
|
<LinkIcon className="decolorize-7" icon={iconTwitter} href={projectInfo.twitterProfile} />
|
|
70
|
-
|
|
75
|
+
{algolia && (
|
|
76
|
+
<div className="decolorize-6 colorize-on-hover">
|
|
77
|
+
<DocSearch
|
|
78
|
+
appId={algolia.appId}
|
|
79
|
+
indexName={algolia.indexName}
|
|
80
|
+
apiKey={algolia.apiKey}
|
|
81
|
+
transformItems={transformItems}
|
|
82
|
+
insights={true}
|
|
83
|
+
/>
|
|
84
|
+
</div>
|
|
85
|
+
)}
|
|
71
86
|
{iconI18n}
|
|
72
87
|
<ChangelogButton />
|
|
73
88
|
</div>
|
|
@@ -111,3 +126,17 @@ function LinkIcon({ className, icon, href, style }: { className: string; icon: s
|
|
|
111
126
|
</>
|
|
112
127
|
)
|
|
113
128
|
}
|
|
129
|
+
|
|
130
|
+
// Remove superfluous hash '#page-content' from URLs pointing to whole pages
|
|
131
|
+
// - https://github.com/algolia/docsearch/issues/1801
|
|
132
|
+
// - https://discourse.algolia.com/t/how-to-avoid-hash-in-search-result-url/6486
|
|
133
|
+
// - https://discourse.algolia.com/t/docsearchs-transformdata-function-cannot-remove-hashes-from-result-urls/8487
|
|
134
|
+
type TransformItems = Parameters<typeof DocSearch>[0]['transformItems']
|
|
135
|
+
const transformItems: TransformItems = (hits) => {
|
|
136
|
+
hits.map((hit) => {
|
|
137
|
+
if (hit.url.indexOf('#page-content') > 0) {
|
|
138
|
+
hit.url = hit.url.replace('#page-content', '')
|
|
139
|
+
}
|
|
140
|
+
})
|
|
141
|
+
return hits
|
|
142
|
+
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
export { initMobileNavigation }
|
|
2
|
+
export { hideMobileNavigation }
|
|
2
3
|
|
|
3
4
|
function initMobileNavigation() {
|
|
4
5
|
activateMobileShowNavigationToggle()
|
|
5
6
|
activateMobileNavigationMask()
|
|
6
|
-
autoHideNavigationOverlayOnLinkClick()
|
|
7
7
|
}
|
|
8
8
|
|
|
9
9
|
function activateMobileShowNavigationToggle() {
|
|
@@ -15,18 +15,9 @@ function activateMobileNavigationMask() {
|
|
|
15
15
|
navigationMask.onclick = toggleNavigation
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
-
function autoHideNavigationOverlayOnLinkClick() {
|
|
19
|
-
document.addEventListener('click', (ev: any) => {
|
|
20
|
-
const el = ev.target
|
|
21
|
-
if (!el || !('classList' in el)) return
|
|
22
|
-
if (!el.classList.contains('nav-item')) return
|
|
23
|
-
hideNavigation()
|
|
24
|
-
})
|
|
25
|
-
}
|
|
26
|
-
|
|
27
18
|
function toggleNavigation() {
|
|
28
19
|
document.body.classList.toggle('mobile-show-navigation')
|
|
29
20
|
}
|
|
30
|
-
function
|
|
21
|
+
function hideMobileNavigation() {
|
|
31
22
|
document.body.classList.remove('mobile-show-navigation')
|
|
32
23
|
}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
export { initPressKit }
|
|
2
2
|
|
|
3
|
+
import { navigate } from 'vike/client/router'
|
|
4
|
+
|
|
3
5
|
function initPressKit() {
|
|
4
6
|
// Right click navigation header => show /press
|
|
5
7
|
navigationHeaderRightClickInterceptor()
|
|
@@ -9,8 +11,9 @@ function navigationHeaderRightClickInterceptor() {
|
|
|
9
11
|
const navHeader = document.getElementById('navigation-header')!
|
|
10
12
|
if (!navHeader.classList.contains('press-kit')) return
|
|
11
13
|
if (window.location.pathname === '/press') return
|
|
12
|
-
|
|
14
|
+
const navHeaderImg = document.querySelector('#navigation-header-logo img') as HTMLElement
|
|
15
|
+
navHeaderImg.oncontextmenu = (ev) => {
|
|
13
16
|
ev.preventDefault()
|
|
14
|
-
|
|
17
|
+
navigate('/press')
|
|
15
18
|
}
|
|
16
19
|
}
|
|
@@ -1,14 +1,12 @@
|
|
|
1
1
|
export { initNavigationFullscreen }
|
|
2
|
+
export { hideNavigationFullScreen }
|
|
2
3
|
|
|
3
4
|
import { assert } from '../../utils/client'
|
|
4
|
-
|
|
5
5
|
let scrollPositionBeforeToggle: number = 0
|
|
6
|
+
initOnce()
|
|
6
7
|
|
|
7
|
-
function
|
|
8
|
-
updateColumnWidth()
|
|
8
|
+
function initOnce() {
|
|
9
9
|
window.addEventListener('resize', updateColumnWidth, { passive: true })
|
|
10
|
-
document.getElementById('navigation-fullscreen-button')!.onclick = toggleNavExpend
|
|
11
|
-
document.getElementById('navigation-fullscreen-close')!.onclick = toggleNavExpend
|
|
12
10
|
document.addEventListener(
|
|
13
11
|
// We don't use keydown to not interfere with user pressing `<Esc>` for closing the browser's `<Ctrl-F>` search diablog, see https://stackoverflow.com/questions/66595035/how-to-detect-escape-key-if-search-bar-of-browser-is-open
|
|
14
12
|
'keydown',
|
|
@@ -19,6 +17,11 @@ function initNavigationFullscreen() {
|
|
|
19
17
|
false,
|
|
20
18
|
)
|
|
21
19
|
}
|
|
20
|
+
function initNavigationFullscreen() {
|
|
21
|
+
document.getElementById('navigation-fullscreen-button')!.onclick = toggleNavExpend
|
|
22
|
+
document.getElementById('navigation-fullscreen-close')!.onclick = toggleNavExpend
|
|
23
|
+
updateColumnWidth()
|
|
24
|
+
}
|
|
22
25
|
|
|
23
26
|
function toggleNavExpend() {
|
|
24
27
|
const navContainer = document.getElementById('navigation-container')!
|
|
@@ -29,6 +32,10 @@ function toggleNavExpend() {
|
|
|
29
32
|
}
|
|
30
33
|
scrollPositionBeforeToggle = scrollPos
|
|
31
34
|
}
|
|
35
|
+
function hideNavigationFullScreen() {
|
|
36
|
+
if (!document.documentElement.classList.contains('navigation-fullscreen')) return
|
|
37
|
+
toggleNavExpend()
|
|
38
|
+
}
|
|
32
39
|
|
|
33
40
|
function updateColumnWidth() {
|
|
34
41
|
const navMinWidth = 299
|
package/package.json
CHANGED
|
@@ -1,21 +1,24 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@brillout/docpress",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"scripts": {
|
|
6
|
-
"
|
|
6
|
+
"======== Build": "",
|
|
7
|
+
"// Build vite.config.ts and +config.ts (other files don't need to be built as @brillout/docpress is noExternal)": "",
|
|
7
8
|
"build": "rm -rf dist/ && tsc --project tsconfig.config.json",
|
|
8
|
-
"
|
|
9
|
+
"======== Develop": "",
|
|
9
10
|
"dev": "tsc --watch --project tsconfig.config.json",
|
|
10
|
-
"// Check types while developing": "",
|
|
11
|
-
"
|
|
12
|
-
"
|
|
11
|
+
"// Check types of all source files while developing": "",
|
|
12
|
+
"typecheck": "tsc --noEmit --watch",
|
|
13
|
+
"========= Release": "",
|
|
13
14
|
"release": "release-me patch",
|
|
14
|
-
"release:
|
|
15
|
-
"release:
|
|
15
|
+
"release:minor": "release-me minor",
|
|
16
|
+
"release:commit": "release-me commit"
|
|
16
17
|
},
|
|
17
18
|
"dependencies": {
|
|
18
19
|
"@brillout/picocolors": "^1.0.10",
|
|
20
|
+
"@docsearch/css": "^3.6.1",
|
|
21
|
+
"@docsearch/react": "3.6.1",
|
|
19
22
|
"@mdx-js/mdx": "3.0.1",
|
|
20
23
|
"@mdx-js/react": "3.0.1",
|
|
21
24
|
"@mdx-js/rollup": "3.0.1",
|
|
@@ -39,7 +42,8 @@
|
|
|
39
42
|
},
|
|
40
43
|
"exports": {
|
|
41
44
|
"./renderer/onRenderHtml": "./renderer/onRenderHtml.tsx",
|
|
42
|
-
"./renderer/
|
|
45
|
+
"./renderer/onRenderClient": "./renderer/onRenderClient.tsx",
|
|
46
|
+
"./renderer/onBeforeRender": "./renderer/onBeforeRender.ts",
|
|
43
47
|
".": "./index.ts",
|
|
44
48
|
"./FeatureList/FeatureList": "./components/FeatureList/FeatureList.tsx",
|
|
45
49
|
"./FeatureList/FeatureList.client": {
|
|
@@ -70,12 +74,14 @@
|
|
|
70
74
|
},
|
|
71
75
|
"devDependencies": {
|
|
72
76
|
"@brillout/release-me": "^0.3.8",
|
|
73
|
-
"@types/node": "
|
|
74
|
-
"@types/react": "
|
|
75
|
-
"@types/react-dom": "
|
|
76
|
-
"
|
|
77
|
-
"
|
|
78
|
-
"
|
|
77
|
+
"@types/node": "link:../demo/node_modules/@types/node/",
|
|
78
|
+
"@types/react": "link:../demo/node_modules/@types/react/",
|
|
79
|
+
"@types/react-dom": "link:../demo/node_modules/@types/react-dom/",
|
|
80
|
+
"react": "link:../demo/node_modules/react/",
|
|
81
|
+
"react-dom": "link:../demo/node_modules/react-dom/",
|
|
82
|
+
"typescript": "link:../demo/node_modules/typescript/",
|
|
83
|
+
"vike": "link:../demo/node_modules/vike/",
|
|
84
|
+
"vite": "link:../demo/node_modules/vite/"
|
|
79
85
|
},
|
|
80
86
|
"repository": "https://github.com/brillout/docpress",
|
|
81
87
|
"license": "MIT",
|
package/parsePageSections.ts
CHANGED
|
@@ -44,7 +44,12 @@ function transform(code: string) {
|
|
|
44
44
|
return line
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
-
if (
|
|
47
|
+
if (
|
|
48
|
+
line.startsWith('#')
|
|
49
|
+
/* TODO/eventually: implement.
|
|
50
|
+
|| line.startsWith('<h2')
|
|
51
|
+
*/
|
|
52
|
+
) {
|
|
48
53
|
const { pageSectionId, pageSectionLevel, pageSectionTitle, headingHtml } = parsePageSection(line)
|
|
49
54
|
pageSections.push({ pageSectionId, pageSectionLevel, pageSectionTitle })
|
|
50
55
|
return headingHtml
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export { getPageElement }
|
|
2
|
+
|
|
3
|
+
import type { PageContext } from 'vike/types'
|
|
4
|
+
import type { PageContextResolved } from '../config/resolvePageContext'
|
|
5
|
+
import { PageLayout } from '../PageLayout'
|
|
6
|
+
import React from 'react'
|
|
7
|
+
|
|
8
|
+
function getPageElement(pageContext: PageContext, pageContextResolved: PageContextResolved) {
|
|
9
|
+
const { Page } = pageContext
|
|
10
|
+
const page = (
|
|
11
|
+
<PageLayout pageContext={pageContextResolved} pageContext2={pageContext}>
|
|
12
|
+
<Page />
|
|
13
|
+
</PageLayout>
|
|
14
|
+
)
|
|
15
|
+
return page
|
|
16
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export { onBeforeRender }
|
|
2
|
+
|
|
3
|
+
import { resolvePageContext, type PageContextOriginal, type PageContextResolved } from '../config/resolvePageContext'
|
|
4
|
+
|
|
5
|
+
function onBeforeRender(pageContextOriginal: PageContextOriginal) {
|
|
6
|
+
const pageContextResolved = resolvePageContext(pageContextOriginal)
|
|
7
|
+
return {
|
|
8
|
+
pageContext: {
|
|
9
|
+
pageContextResolved,
|
|
10
|
+
},
|
|
11
|
+
}
|
|
12
|
+
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
export { onRenderClient }
|
|
2
|
+
|
|
3
|
+
import React, { useEffect } from 'react'
|
|
4
|
+
import type { PageContextClient } from 'vike/types'
|
|
5
|
+
import ReactDOM from 'react-dom/client'
|
|
6
|
+
import { PageContextResolved } from '../config/resolvePageContext'
|
|
7
|
+
import { getPageElement } from './getPageElement'
|
|
8
|
+
import {
|
|
9
|
+
hideNavigationFullScreen,
|
|
10
|
+
initNavigationFullscreen,
|
|
11
|
+
} from '../navigation/navigation-fullscreen/initNavigationFullscreen'
|
|
12
|
+
import { hideMobileNavigation, initMobileNavigation } from '../navigation/initMobileNavigation'
|
|
13
|
+
import { initPressKit } from '../navigation/initPressKit'
|
|
14
|
+
import '../css/index.css'
|
|
15
|
+
import { autoScrollNav } from '../autoScrollNav'
|
|
16
|
+
import { installSectionUrlHashs } from '../installSectionUrlHashs'
|
|
17
|
+
import { addFeatureClickHandlers, addTwitterWidgets } from '../components/FeatureList/FeatureList.client'
|
|
18
|
+
|
|
19
|
+
initOnLinkClick()
|
|
20
|
+
|
|
21
|
+
let root: ReactDOM.Root
|
|
22
|
+
function onRenderClient(pageContext: PageContextClient) {
|
|
23
|
+
// TODO: stop using any
|
|
24
|
+
const pageContextResolved: PageContextResolved = (pageContext as any).pageContextResolved
|
|
25
|
+
let page = getPageElement(pageContext, pageContextResolved)
|
|
26
|
+
page = <OnRenderDoneHook>{page}</OnRenderDoneHook>
|
|
27
|
+
const container = document.getElementById('page-view')!
|
|
28
|
+
if (pageContext.isHydration) {
|
|
29
|
+
root = ReactDOM.hydrateRoot(container, page)
|
|
30
|
+
} else {
|
|
31
|
+
if (!root) {
|
|
32
|
+
root = ReactDOM.createRoot(container)
|
|
33
|
+
}
|
|
34
|
+
root.render(page)
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
if (!pageContext.isHydration) {
|
|
38
|
+
applyHead(pageContext)
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function applyHead(pageContext: PageContextClient) {
|
|
43
|
+
// TODO: stop using any
|
|
44
|
+
const pageContextResolved: PageContextResolved = (pageContext as any).pageContextResolved
|
|
45
|
+
document.title = pageContextResolved.documentTitle
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function onRenderDone() {
|
|
49
|
+
autoScrollNav()
|
|
50
|
+
installSectionUrlHashs()
|
|
51
|
+
initNavigationFullscreen()
|
|
52
|
+
initMobileNavigation()
|
|
53
|
+
initPressKit()
|
|
54
|
+
addFeatureClickHandlers()
|
|
55
|
+
addTwitterWidgets()
|
|
56
|
+
setHydrationIsFinished()
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function OnRenderDoneHook({ children }: { children: React.ReactNode }) {
|
|
60
|
+
useEffect(onRenderDone)
|
|
61
|
+
return children
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function initOnLinkClick() {
|
|
65
|
+
document.addEventListener('click', (ev) => {
|
|
66
|
+
const linkTag = findLinkTag(ev.target as HTMLElement)
|
|
67
|
+
if (!linkTag) return
|
|
68
|
+
const url = linkTag.getAttribute('href')
|
|
69
|
+
if (!url) return
|
|
70
|
+
hideMobileNavigation()
|
|
71
|
+
hideNavigationFullScreen()
|
|
72
|
+
})
|
|
73
|
+
}
|
|
74
|
+
function findLinkTag(target: HTMLElement): null | HTMLElement {
|
|
75
|
+
while (target.tagName !== 'A') {
|
|
76
|
+
const { parentNode } = target
|
|
77
|
+
if (!parentNode) {
|
|
78
|
+
return null
|
|
79
|
+
}
|
|
80
|
+
target = parentNode as HTMLElement
|
|
81
|
+
}
|
|
82
|
+
return target
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function setHydrationIsFinished() {
|
|
86
|
+
// Used by:
|
|
87
|
+
// - https://github.com/vikejs/vike/blob/9d67f3dd4bdfb38c835186b8147251e0e3b06657/docs/.testRun.ts#L22
|
|
88
|
+
// - https://github.com/brillout/telefunc/blob/57c942c15b7795cfda96b5106acc9e098aa509aa/docs/.testRun.ts#L26
|
|
89
|
+
;(window as any).__docpress_hydrationFinished = true
|
|
90
|
+
}
|
|
@@ -1,30 +1,24 @@
|
|
|
1
1
|
export { onRenderHtml }
|
|
2
2
|
|
|
3
3
|
import ReactDOMServer from 'react-dom/server'
|
|
4
|
-
import React from 'react'
|
|
5
4
|
import { escapeInject, dangerouslySkipEscape } from 'vike/server'
|
|
6
|
-
import { PageLayout } from '../PageLayout'
|
|
7
|
-
import { resolvePageContext, PageContextOriginal } from '../config/resolvePageContext'
|
|
8
|
-
import { getDocSearchJS, getDocSearchCSS } from '../algolia/DocSearch'
|
|
9
5
|
import { assert } from '../utils/server'
|
|
6
|
+
import type { PageContextResolved } from '../config/resolvePageContext'
|
|
7
|
+
import { getPageElement } from './getPageElement'
|
|
8
|
+
import type { OnRenderHtmlAsync } from 'vike/types'
|
|
10
9
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
10
|
+
const onRenderHtml: OnRenderHtmlAsync = async (
|
|
11
|
+
pageContext,
|
|
12
|
+
): // TODO: Why is Promise<Awaited<>> needed?
|
|
13
|
+
Promise<Awaited<ReturnType<OnRenderHtmlAsync>>> => {
|
|
14
|
+
const pageContextResolved: PageContextResolved = (pageContext as any).pageContextResolved
|
|
14
15
|
|
|
15
|
-
const page = (
|
|
16
|
-
<PageLayout pageContext={pageContextResolved}>
|
|
17
|
-
<Page />
|
|
18
|
-
</PageLayout>
|
|
19
|
-
)
|
|
16
|
+
const page = getPageElement(pageContext, pageContextResolved)
|
|
20
17
|
|
|
21
18
|
const descriptionTag = pageContextResolved.isLandingPage
|
|
22
19
|
? dangerouslySkipEscape(`<meta name="description" content="${pageContextResolved.meta.tagline}" />`)
|
|
23
20
|
: ''
|
|
24
21
|
|
|
25
|
-
const docSearchJS = getDocSearchJS(pageContextResolved)
|
|
26
|
-
const docSearchCSS = getDocSearchCSS(pageContextResolved)
|
|
27
|
-
|
|
28
22
|
const pageHtml = ReactDOMServer.renderToString(page)
|
|
29
23
|
|
|
30
24
|
return escapeInject`<!DOCTYPE html>
|
|
@@ -35,16 +29,10 @@ async function onRenderHtml(pageContextOriginal: PageContextOriginal) {
|
|
|
35
29
|
<title>${pageContextResolved.documentTitle}</title>
|
|
36
30
|
${descriptionTag}
|
|
37
31
|
<meta name="viewport" content="width=device-width,initial-scale=1,user-scalable=no" />
|
|
38
|
-
${
|
|
39
|
-
${getOpenGraphTags(
|
|
40
|
-
pageContextOriginal.urlPathname,
|
|
41
|
-
pageContextResolved.documentTitle,
|
|
42
|
-
pageContextResolved.meta,
|
|
43
|
-
)}
|
|
32
|
+
${getOpenGraphTags(pageContext.urlPathname, pageContextResolved.documentTitle, pageContextResolved.meta)}
|
|
44
33
|
</head>
|
|
45
34
|
<body>
|
|
46
35
|
<div id="page-view">${dangerouslySkipEscape(pageHtml)}</div>
|
|
47
|
-
${docSearchJS}
|
|
48
36
|
</body>
|
|
49
37
|
</html>`
|
|
50
38
|
}
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
|
|
4
4
|
import React, { useContext } from 'react'
|
|
5
5
|
import type { PageContextResolved } from '../config/resolvePageContext'
|
|
6
|
+
import type { PageContext } from 'vike/types'
|
|
6
7
|
|
|
7
8
|
export { PageContextProvider }
|
|
8
9
|
export { usePageContext }
|
|
@@ -23,3 +24,22 @@ function usePageContext(): PageContextResolved {
|
|
|
23
24
|
const pageContext = useContext(Context)
|
|
24
25
|
return pageContext
|
|
25
26
|
}
|
|
27
|
+
|
|
28
|
+
export { PageContextProvider2 }
|
|
29
|
+
// TODO/refactor: rename to usePageContext and remove old implementation
|
|
30
|
+
export { usePageContext2 }
|
|
31
|
+
|
|
32
|
+
const Context2 = React.createContext<PageContext>(undefined as any)
|
|
33
|
+
function usePageContext2(): PageContext {
|
|
34
|
+
const pageContext = useContext(Context2)
|
|
35
|
+
return pageContext
|
|
36
|
+
}
|
|
37
|
+
function PageContextProvider2({
|
|
38
|
+
pageContext,
|
|
39
|
+
children,
|
|
40
|
+
}: {
|
|
41
|
+
pageContext: PageContext
|
|
42
|
+
children: React.ReactNode
|
|
43
|
+
}) {
|
|
44
|
+
return <Context2.Provider value={pageContext}>{children}</Context2.Provider>
|
|
45
|
+
}
|
package/tsconfig.config.json
CHANGED
package/tsconfig.json
CHANGED
package/types/Config.ts
CHANGED
|
@@ -13,28 +13,14 @@ type Config = {
|
|
|
13
13
|
twitterProfile: string
|
|
14
14
|
}
|
|
15
15
|
faviconUrl: string
|
|
16
|
-
algolia:
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
| {
|
|
22
|
-
appId?: undefined
|
|
23
|
-
apiKey?: undefined
|
|
24
|
-
indexName?: undefined
|
|
25
|
-
}
|
|
26
|
-
| {
|
|
27
|
-
appId: string
|
|
28
|
-
apiKey: string
|
|
29
|
-
indexName: string
|
|
30
|
-
}
|
|
31
|
-
))
|
|
16
|
+
algolia: null | {
|
|
17
|
+
appId: string
|
|
18
|
+
apiKey: string
|
|
19
|
+
indexName: string
|
|
20
|
+
}
|
|
32
21
|
headings: HeadingDefinition[]
|
|
33
22
|
headingsDetached: HeadingDetachedDefinition[]
|
|
34
|
-
|
|
35
|
-
navHeaderMobileWrapperStyle?: React.CSSProperties
|
|
36
|
-
navHeader: React.ReactNode
|
|
37
|
-
navHeaderWrapperStyle?: React.CSSProperties
|
|
23
|
+
|
|
38
24
|
/** Sets `<meta name="description" content="${tagline}" />` */
|
|
39
25
|
tagline: string
|
|
40
26
|
websiteUrl: string
|
package/types/Heading.ts
CHANGED
|
@@ -8,9 +8,9 @@ import type { EmojiName } from '../utils/server'
|
|
|
8
8
|
type HeadingResolved = {
|
|
9
9
|
url?: null | string
|
|
10
10
|
level: number
|
|
11
|
-
title:
|
|
12
|
-
titleInNav:
|
|
13
|
-
linkBreadcrumb:
|
|
11
|
+
title: string
|
|
12
|
+
titleInNav: string
|
|
13
|
+
linkBreadcrumb: string[]
|
|
14
14
|
sectionTitles?: string[]
|
|
15
15
|
} & Tmp
|
|
16
16
|
|
|
@@ -21,7 +21,7 @@ type HeadingDetachedResolved = Omit<HeadingResolved, 'level' | 'linkBreadcrumb'>
|
|
|
21
21
|
|
|
22
22
|
type HeadingDetachedDefinition = {
|
|
23
23
|
url: string
|
|
24
|
-
title: string
|
|
24
|
+
title: string
|
|
25
25
|
sectionTitles?: string[]
|
|
26
26
|
}
|
|
27
27
|
|
|
@@ -37,7 +37,7 @@ type IsCategory = {
|
|
|
37
37
|
titleInNav?: undefined
|
|
38
38
|
}
|
|
39
39
|
type HeadingDefinitionLevel =
|
|
40
|
-
| ({ level: 1
|
|
40
|
+
| ({ level: 1 } & IsCategory)
|
|
41
41
|
| ({ level: 4 } & IsCategory)
|
|
42
42
|
| {
|
|
43
43
|
level: 2
|
package/utils/assert.ts
CHANGED
|
@@ -2,6 +2,27 @@ export { assert }
|
|
|
2
2
|
export { assertUsage }
|
|
3
3
|
export { assertWarning }
|
|
4
4
|
|
|
5
|
+
const devModeKey = '__docpress_dev_mode'
|
|
6
|
+
|
|
7
|
+
if (isBrowser()) {
|
|
8
|
+
;(window as any).toggleDevMode = toggleDevMode
|
|
9
|
+
console.log(
|
|
10
|
+
[
|
|
11
|
+
'[@brillout/docpress] DEV MODE',
|
|
12
|
+
isDevMode() ? 'enabled' : 'disabled',
|
|
13
|
+
!isLocalhost() && 'run window.toggleDevMode() to toggle DEV MODE',
|
|
14
|
+
]
|
|
15
|
+
.filter(Boolean)
|
|
16
|
+
.join(' '),
|
|
17
|
+
)
|
|
18
|
+
if (isDevMode()) {
|
|
19
|
+
window.onerror = (err) => {
|
|
20
|
+
alert(err)
|
|
21
|
+
window.onerror = null
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
5
26
|
function assert(condition: unknown, debugInfo?: unknown): asserts condition {
|
|
6
27
|
if (condition) {
|
|
7
28
|
return
|
|
@@ -18,8 +39,8 @@ function assert(condition: unknown, debugInfo?: unknown): asserts condition {
|
|
|
18
39
|
errMsg += ' Debug info: ' + String(debugInfo)
|
|
19
40
|
}
|
|
20
41
|
const err = new Error(errMsg)
|
|
21
|
-
if (
|
|
22
|
-
alert(err.stack)
|
|
42
|
+
if (isBrowser() && isDevMode()) {
|
|
43
|
+
window.alert(err.stack)
|
|
23
44
|
}
|
|
24
45
|
throw err
|
|
25
46
|
}
|
|
@@ -29,14 +50,29 @@ function assertUsage(condition: unknown, msg: string): asserts condition {
|
|
|
29
50
|
return
|
|
30
51
|
}
|
|
31
52
|
const err = new Error('[DocPress][Wrong Usage] ' + msg)
|
|
32
|
-
if (
|
|
33
|
-
alert(err.stack)
|
|
53
|
+
if (isBrowser() && isDevMode()) {
|
|
54
|
+
window.alert(err.stack)
|
|
34
55
|
}
|
|
35
56
|
throw err
|
|
36
57
|
}
|
|
37
58
|
|
|
38
|
-
function
|
|
39
|
-
return typeof window !== 'undefined'
|
|
59
|
+
function isBrowser() {
|
|
60
|
+
return typeof window !== 'undefined'
|
|
61
|
+
}
|
|
62
|
+
function isDevMode() {
|
|
63
|
+
return !!window.localStorage[devModeKey] || isLocalhost()
|
|
64
|
+
}
|
|
65
|
+
function isLocalhost() {
|
|
66
|
+
return window?.location?.port !== ''
|
|
67
|
+
}
|
|
68
|
+
function toggleDevMode() {
|
|
69
|
+
if (isLocalhost()) throw new Error('On localhost DEV MODE is always on.')
|
|
70
|
+
if (window.localStorage[devModeKey]) {
|
|
71
|
+
window.localStorage[devModeKey] = 'true'
|
|
72
|
+
} else {
|
|
73
|
+
delete window.localStorage[devModeKey]
|
|
74
|
+
}
|
|
75
|
+
console.log(`DEV MODE ${isDevMode() ? 'enabled' : 'disabled'}`)
|
|
40
76
|
}
|
|
41
77
|
|
|
42
78
|
function assertWarning(condition: unknown, msg: string): asserts condition {
|
|
@@ -45,7 +81,7 @@ function assertWarning(condition: unknown, msg: string): asserts condition {
|
|
|
45
81
|
}
|
|
46
82
|
msg = '[DocPress][Warning] ' + msg
|
|
47
83
|
console.warn(msg)
|
|
48
|
-
if (
|
|
49
|
-
alert(msg)
|
|
84
|
+
if (isBrowser() && isDevMode()) {
|
|
85
|
+
window.alert(msg)
|
|
50
86
|
}
|
|
51
87
|
}
|
|
@@ -3,7 +3,7 @@ import { assert } from './assert'
|
|
|
3
3
|
export { jsxToTextContent }
|
|
4
4
|
|
|
5
5
|
// https://stackoverflow.com/questions/34204975/react-is-there-something-similar-to-node-textcontent/60564620#60564620
|
|
6
|
-
function jsxToTextContent(node: JSX.Element
|
|
6
|
+
function jsxToTextContent(node: JSX.Element): string {
|
|
7
7
|
if (['string', 'number'].includes(typeof node)) return String(node)
|
|
8
8
|
if (node instanceof Array) return node.map(jsxToTextContent).join('')
|
|
9
9
|
if (typeof node === 'object' && node) return jsxToTextContent(node.props.children)
|
package/vite.config.ts
CHANGED
|
@@ -26,10 +26,12 @@ const config: UserConfig = {
|
|
|
26
26
|
includeAssetsImportedByServer: true,
|
|
27
27
|
}),
|
|
28
28
|
],
|
|
29
|
-
optimizeDeps: {
|
|
30
|
-
|
|
29
|
+
optimizeDeps: {
|
|
30
|
+
include: ['react', 'react-dom', 'react-dom/client'],
|
|
31
|
+
exclude: ['@brillout/docpress'],
|
|
32
|
+
},
|
|
31
33
|
ssr: {
|
|
32
|
-
noExternal: ['@brillout/docpress'],
|
|
34
|
+
noExternal: ['@brillout/docpress', '@docsearch/react'],
|
|
33
35
|
},
|
|
34
36
|
clearScreen: false,
|
|
35
37
|
}
|