@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.
Files changed (110) hide show
  1. package/+config.ts +26 -3
  2. package/MobileHeader.tsx +5 -3
  3. package/PageLayout.tsx +28 -19
  4. package/algolia/DocSearch.css +6 -9
  5. package/autoScrollNav.ts +4 -3
  6. package/components/FeatureList/FeatureList.client.ts +6 -11
  7. package/components/Link.tsx +9 -9
  8. package/config/getConfig.ts +2 -1
  9. package/config/resolveHeadingsData.ts +22 -38
  10. package/config/resolvePageContext.ts +4 -6
  11. package/dist/+config.d.ts +25 -3
  12. package/dist/+config.js +7 -3
  13. package/dist/components/CodeBlockTransformer.d.ts +7 -0
  14. package/dist/components/CodeBlockTransformer.js +9 -0
  15. package/dist/components/Comment.d.ts +5 -0
  16. package/dist/components/Comment.js +6 -0
  17. package/dist/components/Consulting.d.ts +4 -0
  18. package/dist/components/Consulting.js +39 -0
  19. package/dist/components/Contributors.d.ts +7 -0
  20. package/dist/components/Contributors.js +74 -0
  21. package/dist/components/FileRemoved.d.ts +9 -0
  22. package/dist/components/FileRemoved.js +28 -0
  23. package/dist/components/HorizontalLine.d.ts +5 -0
  24. package/dist/components/HorizontalLine.js +15 -0
  25. package/dist/components/ImportMeta.d.ts +5 -0
  26. package/dist/components/ImportMeta.js +10 -0
  27. package/dist/components/Link.d.ts +16 -0
  28. package/dist/components/Link.js +108 -0
  29. package/dist/components/Note.d.ts +22 -0
  30. package/dist/components/Note.js +93 -0
  31. package/dist/components/P.d.ts +4 -0
  32. package/dist/components/P.js +17 -0
  33. package/dist/components/ReadingRecommendation.d.ts +6 -0
  34. package/dist/components/ReadingRecommendation.js +40 -0
  35. package/dist/components/RepoLink.d.ts +9 -0
  36. package/dist/components/RepoLink.js +22 -0
  37. package/dist/components/Sponsors.d.ts +22 -0
  38. package/dist/components/Sponsors.js +161 -0
  39. package/dist/components/Supporters.d.ts +32 -0
  40. package/dist/components/Supporters.js +80 -0
  41. package/dist/components/index.d.ts +15 -0
  42. package/dist/components/index.js +15 -0
  43. package/dist/config/getConfig.d.ts +3 -0
  44. package/dist/config/getConfig.js +14 -0
  45. package/dist/config/resolveHeadingsData.d.ts +16 -0
  46. package/dist/config/resolveHeadingsData.js +216 -0
  47. package/dist/config/resolvePageContext.d.ts +38 -0
  48. package/dist/config/resolvePageContext.js +23 -0
  49. package/dist/data/maintainersList.d.ts +9 -0
  50. package/dist/data/maintainersList.js +83 -0
  51. package/dist/data/sponsorsList.d.ts +3 -0
  52. package/dist/data/sponsorsList.js +151 -0
  53. package/dist/navigation/Navigation.d.ts +20 -0
  54. package/dist/navigation/Navigation.js +134 -0
  55. package/dist/navigation/NavigationHeader.d.ts +4 -0
  56. package/dist/navigation/NavigationHeader.js +85 -0
  57. package/dist/navigation/navigation-fullscreen/NavigationFullscreenButton.d.ts +6 -0
  58. package/dist/navigation/navigation-fullscreen/NavigationFullscreenButton.js +22 -0
  59. package/dist/parsePageSections.js +7 -3
  60. package/dist/parseTitle.d.ts +5 -0
  61. package/dist/parseTitle.js +52 -0
  62. package/dist/renderer/usePageContext.d.ts +17 -0
  63. package/dist/renderer/usePageContext.js +26 -0
  64. package/dist/types/Config.d.ts +30 -0
  65. package/dist/types/Config.js +1 -0
  66. package/dist/types/Heading.d.ts +43 -0
  67. package/dist/types/Heading.js +1 -0
  68. package/dist/utils/Emoji/Emoji.d.ts +8 -0
  69. package/dist/utils/Emoji/Emoji.js +191 -0
  70. package/dist/utils/Emoji/assets.d.ts +6 -0
  71. package/dist/utils/Emoji/assets.js +7 -0
  72. package/dist/utils/Emoji/index.d.ts +1 -0
  73. package/dist/utils/Emoji/index.js +1 -0
  74. package/dist/utils/assert.js +43 -8
  75. package/dist/utils/client.d.ts +2 -0
  76. package/dist/utils/client.js +2 -0
  77. package/dist/utils/filter.d.ts +2 -0
  78. package/dist/utils/filter.js +11 -0
  79. package/dist/utils/isBrowser.d.ts +2 -0
  80. package/dist/utils/isBrowser.js +4 -0
  81. package/dist/utils/jsxToTextContent.d.ts +2 -0
  82. package/dist/utils/jsxToTextContent.js +12 -0
  83. package/dist/utils/objectAssign.d.ts +2 -0
  84. package/dist/utils/objectAssign.js +5 -0
  85. package/dist/utils/server.d.ts +7 -0
  86. package/dist/utils/server.js +7 -0
  87. package/dist/vite.config.js +5 -3
  88. package/installSectionUrlHashs.ts +7 -13
  89. package/navigation/Navigation.tsx +28 -19
  90. package/navigation/NavigationHeader.tsx +33 -4
  91. package/navigation/initMobileNavigation.ts +2 -11
  92. package/navigation/initPressKit.ts +5 -2
  93. package/navigation/navigation-fullscreen/initNavigationFullscreen.ts +12 -5
  94. package/package.json +21 -15
  95. package/parsePageSections.ts +6 -1
  96. package/renderer/getPageElement.tsx +16 -0
  97. package/renderer/onBeforeRender.ts +12 -0
  98. package/renderer/onRenderClient.tsx +90 -0
  99. package/renderer/onRenderHtml.tsx +10 -22
  100. package/renderer/usePageContext.tsx +20 -0
  101. package/tsconfig.config.json +1 -1
  102. package/tsconfig.json +1 -1
  103. package/types/Config.ts +6 -20
  104. package/types/Heading.ts +5 -5
  105. package/utils/assert.ts +44 -8
  106. package/utils/jsxToTextContent.ts +1 -1
  107. package/vite.config.ts +5 -3
  108. package/algolia/DocSearch.ts +0 -62
  109. package/navigation/Navigation.client.ts +0 -7
  110. 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
- ...pageContext.config.navHeaderWrapperStyle,
38
+ ...pageContext2.config.NavHeader?.navHeaderWrapperStyle,
35
39
  }}
36
40
  href="/"
37
41
  >
38
- {pageContext.config.navHeader}
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
- <div className="decolorize-6 colorize-on-hover" id="docsearch-desktop" />
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 hideNavigation() {
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
- navHeader.oncontextmenu = (ev) => {
14
+ const navHeaderImg = document.querySelector('#navigation-header-logo img') as HTMLElement
15
+ navHeaderImg.oncontextmenu = (ev) => {
13
16
  ev.preventDefault()
14
- window.location.href = '/press'
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 initNavigationFullscreen() {
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.6.21",
3
+ "version": "0.7.1",
4
4
  "type": "module",
5
5
  "scripts": {
6
- "// Build vite.config.ts and +config.ts": "",
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
- "// Development": "",
9
+ "======== Develop": "",
9
10
  "dev": "tsc --watch --project tsconfig.config.json",
10
- "// Check types while developing": "",
11
- "types": "tsc --noEmit --watch",
12
- "// Release": "",
11
+ "// Check types of all source files while developing": "",
12
+ "typecheck": "tsc --noEmit --watch",
13
+ "========= Release": "",
13
14
  "release": "release-me patch",
14
- "release:commit": "release-me commit",
15
- "release:breaking-change": "release-me minor"
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/client": "./renderer/client.ts",
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": "^15.12.1",
74
- "@types/react": "^18.2.45",
75
- "@types/react-dom": "^18.2.18",
76
- "typescript": "^5.4.3",
77
- "vike": "^0.4.195",
78
- "vite": "^5.2.2"
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",
@@ -44,7 +44,12 @@ function transform(code: string) {
44
44
  return line
45
45
  }
46
46
 
47
- if (line.startsWith('#')) {
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
- async function onRenderHtml(pageContextOriginal: PageContextOriginal) {
12
- const { Page } = pageContextOriginal
13
- const pageContextResolved = resolvePageContext(pageContextOriginal)
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
- ${docSearchCSS}
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
+ }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "extends": "./tsconfig.json",
3
- "include": ["vite.config.ts", "+config.ts"],
3
+ "files": ["vite.config.ts", "+config.ts"],
4
4
  "compilerOptions": {
5
5
  "outDir": "./dist/"
6
6
  }
package/tsconfig.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "compilerOptions": {
3
3
  "jsx": "react",
4
4
  "module": "ES2020",
5
- "moduleResolution": "Node",
5
+ "moduleResolution": "Bundler",
6
6
  "lib": ["DOM", "DOM.Iterable", "ESNext"],
7
7
  "types": ["vite/client"],
8
8
  "esModuleInterop": true,
package/types/Config.ts CHANGED
@@ -13,28 +13,14 @@ type Config = {
13
13
  twitterProfile: string
14
14
  }
15
15
  faviconUrl: string
16
- algolia:
17
- | null
18
- | ({
19
- PENDING_APPROVAL?: true
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
- navHeaderMobile: React.ReactNode
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: JSX.Element
12
- titleInNav: JSX.Element
13
- linkBreadcrumb: JSX.Element[]
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 | JSX.Element
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; titleEmoji: EmojiName } & IsCategory)
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 (isBrowserAndDev()) {
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 (isBrowserAndDev()) {
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 isBrowserAndDev() {
39
- return typeof window !== 'undefined' && window?.location?.port !== ''
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 (isBrowserAndDev()) {
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 | string): string {
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: { include: ['@brillout/docpress', 'react-dom'] },
30
- // @ts-ignore
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
  }