@brillout/docpress 0.7.3 → 0.7.4

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 (38) hide show
  1. package/+config.ts +10 -1
  2. package/LICENSE.md +9 -0
  3. package/{PageLayout.css → Layout.css} +21 -0
  4. package/Layout.tsx +92 -0
  5. package/algolia/DocSearch.css +2 -5
  6. package/components/Algolia/Hit.tsx +67 -0
  7. package/components/Algolia/README.md +21 -0
  8. package/components/Algolia/SelectIcon.tsx +12 -0
  9. package/components/Algolia/Snippet.tsx +32 -0
  10. package/components/Algolia/SourceIcon.tsx +55 -0
  11. package/components/Algolia/types.ts +86 -0
  12. package/config/resolveHeadingsData.ts +11 -3
  13. package/dist/+config.d.ts +13 -0
  14. package/dist/+config.js +8 -0
  15. package/dist/components/Algolia/Hit.d.ts +4 -0
  16. package/dist/components/Algolia/Hit.js +30 -0
  17. package/dist/components/Algolia/SelectIcon.d.ts +2 -0
  18. package/dist/components/Algolia/SelectIcon.js +7 -0
  19. package/dist/components/Algolia/Snippet.d.ts +13 -0
  20. package/dist/components/Algolia/Snippet.js +37 -0
  21. package/dist/components/Algolia/SourceIcon.d.ts +4 -0
  22. package/dist/components/Algolia/SourceIcon.js +23 -0
  23. package/dist/components/Algolia/types.d.ts +79 -0
  24. package/dist/components/Algolia/types.js +1 -0
  25. package/dist/config/resolveHeadingsData.d.ts +5 -0
  26. package/dist/config/resolveHeadingsData.js +13 -6
  27. package/dist/config/resolvePageContext.d.ts +5 -0
  28. package/dist/navigation/NavigationHeader.d.ts +4 -0
  29. package/dist/navigation/NavigationHeader.js +9 -19
  30. package/dist/types/Heading.d.ts +10 -4
  31. package/icons/twitter.svg +1 -16
  32. package/navigation/NavigationHeader.tsx +10 -21
  33. package/navigation/navigation-fullscreen/initNavigationFullscreen.ts +31 -7
  34. package/package.json +22 -18
  35. package/renderer/getPageElement.tsx +15 -4
  36. package/renderer/onRenderClient.tsx +9 -0
  37. package/types/Heading.ts +11 -6
  38. package/PageLayout.tsx +0 -48
@@ -0,0 +1,23 @@
1
+ import React from 'react';
2
+ var LvlIcon = function () {
3
+ return (React.createElement("svg", { width: "20", height: "20", viewBox: "0 0 20 20" },
4
+ React.createElement("path", { d: "M17 6v12c0 .52-.2 1-1 1H4c-.7 0-1-.33-1-1V2c0-.55.42-1 1-1h8l5 5zM14 8h-3.13c-.51 0-.87-.34-.87-.87V4", stroke: "currentColor", fill: "none", fillRule: "evenodd", strokeLinejoin: "round" })));
5
+ };
6
+ export function SourceIcon(props) {
7
+ switch (props.type) {
8
+ case 'lvl1':
9
+ return React.createElement(LvlIcon, null);
10
+ case 'content':
11
+ return React.createElement(ContentIcon, null);
12
+ default:
13
+ return React.createElement(AnchorIcon, null);
14
+ }
15
+ }
16
+ function AnchorIcon() {
17
+ return (React.createElement("svg", { width: "20", height: "20", viewBox: "0 0 20 20" },
18
+ React.createElement("path", { d: "M13 13h4-4V8H7v5h6v4-4H7V8H3h4V3v5h6V3v5h4-4v5zm-6 0v4-4H3h4z", stroke: "currentColor", fill: "none", fillRule: "evenodd", strokeLinecap: "round", strokeLinejoin: "round" })));
19
+ }
20
+ function ContentIcon() {
21
+ return (React.createElement("svg", { width: "20", height: "20", viewBox: "0 0 20 20" },
22
+ React.createElement("path", { d: "M17 5H3h14zm0 5H3h14zm0 5H3h14z", stroke: "currentColor", fill: "none", fillRule: "evenodd", strokeLinejoin: "round" })));
23
+ }
@@ -0,0 +1,79 @@
1
+ export type InternalDocSearchHit = DocSearchHit & {
2
+ __docsearch_parent: InternalDocSearchHit | null;
3
+ };
4
+ export type StoredDocSearchHit = Omit<DocSearchHit, '_highlightResult' | '_snippetResult'>;
5
+ type ContentType = 'content' | 'lvl0' | 'lvl1' | 'lvl2' | 'lvl3' | 'lvl4' | 'lvl5' | 'lvl6';
6
+ interface DocSearchHitAttributeHighlightResult {
7
+ value: string;
8
+ matchLevel: 'full' | 'none' | 'partial';
9
+ matchedWords: string[];
10
+ fullyHighlighted?: boolean;
11
+ }
12
+ interface DocSearchHitHighlightResultHierarchy {
13
+ lvl0: DocSearchHitAttributeHighlightResult;
14
+ lvl1: DocSearchHitAttributeHighlightResult;
15
+ lvl2: DocSearchHitAttributeHighlightResult;
16
+ lvl3: DocSearchHitAttributeHighlightResult;
17
+ lvl4: DocSearchHitAttributeHighlightResult;
18
+ lvl5: DocSearchHitAttributeHighlightResult;
19
+ lvl6: DocSearchHitAttributeHighlightResult;
20
+ }
21
+ interface DocSearchHitHighlightResult {
22
+ content: DocSearchHitAttributeHighlightResult;
23
+ hierarchy: DocSearchHitHighlightResultHierarchy;
24
+ hierarchy_camel: DocSearchHitHighlightResultHierarchy[];
25
+ }
26
+ interface DocSearchHitAttributeSnippetResult {
27
+ value: string;
28
+ matchLevel: 'full' | 'none' | 'partial';
29
+ }
30
+ interface DocSearchHitSnippetResult {
31
+ content: DocSearchHitAttributeSnippetResult;
32
+ hierarchy: DocSearchHitHighlightResultHierarchy;
33
+ hierarchy_camel: DocSearchHitHighlightResultHierarchy[];
34
+ }
35
+ export declare type DocSearchHit = {
36
+ objectID: string;
37
+ content: string | null;
38
+ url: string;
39
+ url_without_anchor: string;
40
+ type: ContentType;
41
+ anchor: string | null;
42
+ hierarchy: {
43
+ lvl0: string;
44
+ lvl1: string;
45
+ lvl2: string | null;
46
+ lvl3: string | null;
47
+ lvl4: string | null;
48
+ lvl5: string | null;
49
+ lvl6: string | null;
50
+ };
51
+ _highlightResult: DocSearchHitHighlightResult;
52
+ _snippetResult: DocSearchHitSnippetResult;
53
+ _rankingInfo?: {
54
+ promoted: boolean;
55
+ nbTypos: number;
56
+ firstMatchedWord: number;
57
+ proximityDistance?: number;
58
+ geoDistance: number;
59
+ geoPrecision?: number;
60
+ nbExactWords: number;
61
+ words: number;
62
+ filters: number;
63
+ userScore: number;
64
+ matchedGeoLocation?: {
65
+ lat: number;
66
+ lng: number;
67
+ distance: number;
68
+ };
69
+ };
70
+ _distinctSeqID?: number;
71
+ __autocomplete_indexName?: string;
72
+ __autocomplete_queryID?: string;
73
+ __autocomplete_algoliaCredentials?: {
74
+ appId: string;
75
+ apiKey: string;
76
+ };
77
+ __autocomplete_id?: number;
78
+ };
79
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -13,4 +13,9 @@ declare function resolveHeadingsData(pageContext: PageContextOriginal): {
13
13
  isLandingPage: boolean;
14
14
  pageTitle: string | null;
15
15
  documentTitle: string;
16
+ noSideNavigation: true | undefined;
17
+ topNavigationList: {
18
+ title: string;
19
+ url: string | null | undefined;
20
+ }[];
16
21
  };
@@ -67,12 +67,17 @@ function resolveHeadingsData(pageContext) {
67
67
  };
68
68
  }
69
69
  }
70
+ var topNavigationList = headingsResolved
71
+ .filter(function (heading) { return heading.topNavigation; })
72
+ .map(function (h) { return ({ title: typeof h.topNavigation === 'string' ? h.topNavigation : h.title, url: h.url }); });
70
73
  var pageContextAddendum = {
71
74
  navigationData: navigationData,
72
75
  linksAll: linksAll,
73
76
  isLandingPage: isLandingPage,
74
77
  pageTitle: pageTitle,
75
78
  documentTitle: documentTitle,
79
+ noSideNavigation: activeHeading.noSideNavigation,
80
+ topNavigationList: topNavigationList,
76
81
  };
77
82
  return pageContextAddendum;
78
83
  }
@@ -140,12 +145,14 @@ function getActiveHeading(headingsResolved, headingsDetachedResolved, pageContex
140
145
  })) !== null && _a !== void 0 ? _a : null;
141
146
  }
142
147
  if (!activeHeading) {
143
- throw new Error(__spreadArray([
144
- "URL ".concat(pc.bold(urlPathname), " not found in following URLs:")
145
- ], headingsResolved
146
- .map(function (h) { return " ".concat(h.url); })
147
- .filter(Boolean)
148
- .sort(), true).join('\n'));
148
+ throw new Error([
149
+ "URL ".concat(pc.bold(urlPathname), " not found in following URLs:"),
150
+ __spreadArray(__spreadArray([], headingsResolved, true), headingsDetachedResolved, true).filter(Boolean)
151
+ .map(function (h) { return h.url; })
152
+ .sort()
153
+ .map(function (url) { return " ".concat(url); })
154
+ .join('\n'),
155
+ ].join('\n'));
149
156
  }
150
157
  return { activeHeading: activeHeading, isDetachedPage: isDetachedPage };
151
158
  }
@@ -20,6 +20,11 @@ declare function resolvePageContext(pageContext: PageContextOriginal): {
20
20
  isLandingPage: boolean;
21
21
  pageTitle: string | null;
22
22
  documentTitle: string;
23
+ noSideNavigation: true | undefined;
24
+ topNavigationList: {
25
+ title: string;
26
+ url: string | null | undefined;
27
+ }[];
23
28
  } & {
24
29
  urlPathname: string;
25
30
  meta: {
@@ -1,4 +1,8 @@
1
1
  import React from 'react';
2
2
  import '@docsearch/css';
3
3
  export { NavigationHeader };
4
+ export { Links };
4
5
  declare function NavigationHeader(): React.JSX.Element;
6
+ declare function Links({ style }: {
7
+ style?: React.CSSProperties;
8
+ }): React.JSX.Element;
@@ -17,8 +17,10 @@ import iconChangelog from '../icons/changelog.svg';
17
17
  import iconLanguages from '../icons/languages.svg';
18
18
  import { usePageContext, usePageContext2 } from '../renderer/usePageContext';
19
19
  import { DocSearch } from '@docsearch/react';
20
+ import { Hit } from '../components/Algolia/Hit';
20
21
  import '@docsearch/css';
21
22
  export { NavigationHeader };
23
+ export { Links };
22
24
  function NavigationHeader() {
23
25
  var _a;
24
26
  var pageContext = usePageContext();
@@ -34,22 +36,18 @@ function NavigationHeader() {
34
36
  React.createElement(NavHeader, null)),
35
37
  React.createElement(Links, null)));
36
38
  }
37
- function Links() {
39
+ function Links(_a) {
40
+ var style = _a.style;
38
41
  var pageContext = usePageContext();
39
- var _a = pageContext.config, projectInfo = _a.projectInfo, i18n = _a.i18n;
42
+ var _b = pageContext.config, projectInfo = _b.projectInfo, i18n = _b.i18n;
40
43
  var iconI18n = !i18n ? null : (React.createElement(LinkIcon, { className: "decolorize-4", icon: iconLanguages, href: '/languages', style: { height: 21, position: 'relative', top: 0, left: 0 } }));
41
44
  var algolia = pageContext.meta.algolia;
42
- return (React.createElement("div", { style: {
43
- display: 'flex',
44
- alignItems: 'center',
45
- paddingTop: 0,
46
- justifyContent: 'left',
47
- } },
45
+ return (React.createElement("div", { style: __assign({ display: 'flex', alignItems: 'center', paddingTop: 0, justifyContent: 'left' }, style) },
46
+ algolia && (React.createElement("div", { className: "decolorize-6 colorize-on-hover" },
47
+ React.createElement(DocSearch, { appId: algolia.appId, indexName: algolia.indexName, apiKey: algolia.apiKey, insights: true, hitComponent: Hit }))),
48
48
  React.createElement(LinkIcon, { className: "decolorize-4", icon: iconGithub, href: projectInfo.githubRepository }),
49
49
  projectInfo.discordInvite && (React.createElement(LinkIcon, { className: "decolorize-6", icon: iconDiscord, href: projectInfo.discordInvite })),
50
- React.createElement(LinkIcon, { className: "decolorize-7", icon: iconTwitter, href: projectInfo.twitterProfile }),
51
- algolia && (React.createElement("div", { className: "decolorize-6 colorize-on-hover" },
52
- React.createElement(DocSearch, { appId: algolia.appId, indexName: algolia.indexName, apiKey: algolia.apiKey, transformItems: transformItems, insights: true }))),
50
+ React.createElement(LinkIcon, { className: "decolorize-4", icon: iconTwitter, href: projectInfo.twitterProfile }),
53
51
  iconI18n,
54
52
  React.createElement(ChangelogButton, null)));
55
53
  }
@@ -75,11 +73,3 @@ function LinkIcon(_a) {
75
73
  React.createElement("a", { className: 'colorize-on-hover ' + className, href: href, style: { padding: 3, display: 'inline-block', lineHeight: 0 } },
76
74
  React.createElement("img", { src: icon, height: "20", style: style }))));
77
75
  }
78
- var transformItems = function (hits) {
79
- hits.map(function (hit) {
80
- if (hit.url.indexOf('#page-content') > 0) {
81
- hit.url = hit.url.replace('#page-content', '');
82
- }
83
- });
84
- return hits;
85
- };
@@ -7,6 +7,8 @@ type HeadingResolved = {
7
7
  level: number;
8
8
  title: string;
9
9
  titleInNav: string;
10
+ noSideNavigation?: true;
11
+ topNavigation?: true | string;
10
12
  linkBreadcrumb: string[];
11
13
  sectionTitles?: string[];
12
14
  } & Tmp;
@@ -14,20 +16,24 @@ type HeadingDetachedResolved = Omit<HeadingResolved, 'level' | 'linkBreadcrumb'>
14
16
  level: 2;
15
17
  linkBreadcrumb: null;
16
18
  };
17
- type HeadingDetachedDefinition = {
18
- url: string;
19
+ type HeadingDefinitionCommon = {
19
20
  title: string;
21
+ topNavigation?: true | string;
22
+ };
23
+ type HeadingDetachedDefinition = HeadingDefinitionCommon & {
24
+ url: string;
20
25
  sectionTitles?: string[];
21
26
  };
22
- type HeadingDefinition = {
27
+ type HeadingDefinition = HeadingDefinitionCommon & {
23
28
  url?: null | string;
24
- title: string;
25
29
  titleInNav?: string;
30
+ noSideNavigation?: true;
26
31
  } & HeadingDefinitionLevel & Tmp;
27
32
  type IsCategory = {
28
33
  url?: undefined;
29
34
  titleDocument?: undefined;
30
35
  titleInNav?: undefined;
36
+ noSideNavigation?: undefined;
31
37
  };
32
38
  type HeadingDefinitionLevel = ({
33
39
  level: 1;
package/icons/twitter.svg CHANGED
@@ -1,16 +1 @@
1
- <?xml version="1.0" encoding="utf-8"?>
2
- <!-- Generator: Adobe Illustrator 24.2.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
3
- <svg version="1.1" id="Logo" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
4
- viewBox="0 0 248 204" style="enable-background:new 0 0 248 204;" xml:space="preserve">
5
- <style type="text/css">
6
- .st0{fill:#1D9BF0;}
7
- </style>
8
- <g id="Logo_1_">
9
- <path id="white_background" class="st0" d="M221.95,51.29c0.15,2.17,0.15,4.34,0.15,6.53c0,66.73-50.8,143.69-143.69,143.69v-0.04
10
- C50.97,201.51,24.1,193.65,1,178.83c3.99,0.48,8,0.72,12.02,0.73c22.74,0.02,44.83-7.61,62.72-21.66
11
- c-21.61-0.41-40.56-14.5-47.18-35.07c7.57,1.46,15.37,1.16,22.8-0.87C27.8,117.2,10.85,96.5,10.85,72.46c0-0.22,0-0.43,0-0.64
12
- c7.02,3.91,14.88,6.08,22.92,6.32C11.58,63.31,4.74,33.79,18.14,10.71c25.64,31.55,63.47,50.73,104.08,52.76
13
- c-4.07-17.54,1.49-35.92,14.61-48.25c20.34-19.12,52.33-18.14,71.45,2.19c11.31-2.23,22.15-6.38,32.07-12.26
14
- c-3.77,11.69-11.66,21.62-22.2,27.93c10.01-1.18,19.79-3.86,29-7.95C240.37,35.29,231.83,44.14,221.95,51.29z"/>
15
- </g>
16
- </svg>
1
+ <svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M18.901 1.153h3.68l-8.04 9.19L24 22.846h-7.406l-5.8-7.584-6.638 7.584H.474l8.6-9.83L0 1.154h7.594l5.243 6.932ZM17.61 20.644h2.039L6.486 3.24H4.298Z'/></svg>
@@ -6,9 +6,11 @@ import iconChangelog from '../icons/changelog.svg'
6
6
  import iconLanguages from '../icons/languages.svg'
7
7
  import { usePageContext, usePageContext2 } from '../renderer/usePageContext'
8
8
  import { DocSearch } from '@docsearch/react'
9
+ import { Hit } from '../components/Algolia/Hit'
9
10
  import '@docsearch/css'
10
11
 
11
12
  export { NavigationHeader }
13
+ export { Links }
12
14
 
13
15
  function NavigationHeader() {
14
16
  const pageContext = usePageContext()
@@ -46,7 +48,7 @@ function NavigationHeader() {
46
48
  )
47
49
  }
48
50
 
49
- function Links() {
51
+ function Links({ style }: { style?: React.CSSProperties }) {
50
52
  const pageContext = usePageContext()
51
53
  const { projectInfo, i18n } = pageContext.config
52
54
  const iconI18n = !i18n ? null : (
@@ -65,24 +67,25 @@ function Links() {
65
67
  alignItems: 'center',
66
68
  paddingTop: 0,
67
69
  justifyContent: 'left',
70
+ ...style,
68
71
  }}
69
72
  >
70
- <LinkIcon className="decolorize-4" icon={iconGithub} href={projectInfo.githubRepository} />
71
- {projectInfo.discordInvite && (
72
- <LinkIcon className="decolorize-6" icon={iconDiscord} href={projectInfo.discordInvite} />
73
- )}
74
- <LinkIcon className="decolorize-7" icon={iconTwitter} href={projectInfo.twitterProfile} />
75
73
  {algolia && (
76
74
  <div className="decolorize-6 colorize-on-hover">
77
75
  <DocSearch
78
76
  appId={algolia.appId}
79
77
  indexName={algolia.indexName}
80
78
  apiKey={algolia.apiKey}
81
- transformItems={transformItems}
82
79
  insights={true}
80
+ hitComponent={Hit}
83
81
  />
84
82
  </div>
85
83
  )}
84
+ <LinkIcon className="decolorize-4" icon={iconGithub} href={projectInfo.githubRepository} />
85
+ {projectInfo.discordInvite && (
86
+ <LinkIcon className="decolorize-6" icon={iconDiscord} href={projectInfo.discordInvite} />
87
+ )}
88
+ <LinkIcon className="decolorize-4" icon={iconTwitter} href={projectInfo.twitterProfile} />
86
89
  {iconI18n}
87
90
  <ChangelogButton />
88
91
  </div>
@@ -126,17 +129,3 @@ function LinkIcon({ className, icon, href, style }: { className: string; icon: s
126
129
  </>
127
130
  )
128
131
  }
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,12 +1,16 @@
1
1
  export { initNavigationFullscreen }
2
+ export { initNavigationFullscreenOnce }
2
3
  export { hideNavigationFullScreen }
3
4
 
4
5
  import { assert } from '../../utils/client'
5
- let scrollPositionBeforeToggle: number = 0
6
- initOnce()
7
6
 
8
- function initOnce() {
9
- window.addEventListener('resize', updateColumnWidth, { passive: true })
7
+ let scrollPositionBeforeToggle: number
8
+
9
+ function initNavigationFullscreenOnce() {
10
+ scrollPositionBeforeToggle = 0
11
+ initKeyBindings()
12
+ }
13
+ function initKeyBindings() {
10
14
  document.addEventListener(
11
15
  // 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
12
16
  'keydown',
@@ -16,6 +20,8 @@ function initOnce() {
16
20
  },
17
21
  false,
18
22
  )
23
+ window.addEventListener('resize', updateColumnWidth, { passive: true })
24
+ initTopNavigation()
19
25
  }
20
26
  function initNavigationFullscreen() {
21
27
  document.getElementById('navigation-fullscreen-button')!.onclick = toggleNavExpend
@@ -24,12 +30,11 @@ function initNavigationFullscreen() {
24
30
  }
25
31
 
26
32
  function toggleNavExpend() {
33
+ assert(scrollPositionBeforeToggle !== undefined)
27
34
  const navContainer = document.getElementById('navigation-container')!
28
35
  const scrollPos = navContainer.scrollTop
29
36
  document.documentElement.classList.toggle('navigation-fullscreen')
30
- if (scrollPositionBeforeToggle !== undefined) {
31
- navContainer.scrollTop = scrollPositionBeforeToggle
32
- }
37
+ navContainer.scrollTop = scrollPositionBeforeToggle
33
38
  scrollPositionBeforeToggle = scrollPos
34
39
  }
35
40
  function hideNavigationFullScreen() {
@@ -121,3 +126,22 @@ function sum(arr: number[]): number {
121
126
  arr.forEach((n) => (total += n))
122
127
  return total
123
128
  }
129
+
130
+ function initTopNavigation() {
131
+ document.addEventListener('click', (ev) => {
132
+ const linkTag = findLinkTag(ev.target as HTMLElement)
133
+ if (!linkTag) return
134
+ if (linkTag.id !== 'doclink') return
135
+ toggleNavExpend()
136
+ })
137
+ }
138
+ function findLinkTag(target: HTMLElement): null | HTMLElement {
139
+ while (target.tagName !== 'A') {
140
+ const { parentNode } = target
141
+ if (!parentNode) {
142
+ return null
143
+ }
144
+ target = parentNode as HTMLElement
145
+ }
146
+ return target
147
+ }
package/package.json CHANGED
@@ -1,20 +1,7 @@
1
1
  {
2
2
  "name": "@brillout/docpress",
3
- "version": "0.7.3",
3
+ "version": "0.7.4",
4
4
  "type": "module",
5
- "scripts": {
6
- "======== Build": "",
7
- "// Build vite.config.ts and +config.ts (other files don't need to be built as @brillout/docpress is noExternal)": "",
8
- "build": "rm -rf dist/ && tsc --project tsconfig.config.json",
9
- "======== Develop": "",
10
- "dev": "tsc --watch --project tsconfig.config.json",
11
- "// Check types of all source files while developing": "",
12
- "typecheck": "tsc --noEmit --watch",
13
- "========= Release": "",
14
- "release": "release-me patch",
15
- "release:minor": "release-me minor",
16
- "release:commit": "release-me commit"
17
- },
18
5
  "dependencies": {
19
6
  "@brillout/picocolors": "^1.0.10",
20
7
  "@docsearch/css": "^3.6.1",
@@ -37,13 +24,14 @@
37
24
  "react": ">=18.0.0",
38
25
  "react-dom": ">=18.0.0",
39
26
  "typescript": "*",
40
- "vike": ">=0.4.195",
27
+ "vike": ">=0.4.198",
41
28
  "vite": ">=5.2.0"
42
29
  },
43
30
  "exports": {
44
31
  "./renderer/onRenderHtml": "./renderer/onRenderHtml.tsx",
45
32
  "./renderer/onRenderClient": "./renderer/onRenderClient.tsx",
46
33
  "./renderer/onBeforeRender": "./renderer/onBeforeRender.ts",
34
+ "./Layout": "./Layout.tsx",
47
35
  ".": "./index.ts",
48
36
  "./FeatureList/FeatureList": "./components/FeatureList/FeatureList.tsx",
49
37
  "./FeatureList/FeatureList.client": {
@@ -51,7 +39,10 @@
51
39
  },
52
40
  "./vite-config": "./dist/vite.config.js",
53
41
  "./config": "./dist/+config.js",
54
- "./style": "./css/index.css"
42
+ "./style": "./css/index.css",
43
+ "./types": {
44
+ "types": "./types.d.ts"
45
+ }
55
46
  },
56
47
  "typesVersions": {
57
48
  "*": {
@@ -73,7 +64,7 @@
73
64
  }
74
65
  },
75
66
  "devDependencies": {
76
- "@brillout/release-me": "^0.3.8",
67
+ "@brillout/release-me": "^0.4.2",
77
68
  "@types/node": "link:../demo/node_modules/@types/node/",
78
69
  "@types/react": "link:../demo/node_modules/@types/react/",
79
70
  "@types/react-dom": "link:../demo/node_modules/@types/react-dom/",
@@ -87,5 +78,18 @@
87
78
  "license": "MIT",
88
79
  "publishConfig": {
89
80
  "access": "public"
81
+ },
82
+ "scripts": {
83
+ "======== Build": "",
84
+ "// Build vite.config.ts and +config.ts (other files don't need to be built as @brillout/docpress is noExternal)": "",
85
+ "build": "rm -rf dist/ && tsc --project tsconfig.config.json",
86
+ "======== Develop": "",
87
+ "dev": "tsc --watch --project tsconfig.config.json",
88
+ "// Check types of all source files while developing": "",
89
+ "typecheck": "tsc --noEmit --watch",
90
+ "========= Release": "",
91
+ "release": "release-me patch",
92
+ "release:minor": "release-me minor",
93
+ "release:commit": "release-me commit"
90
94
  }
91
- }
95
+ }
@@ -2,15 +2,26 @@ export { getPageElement }
2
2
 
3
3
  import type { PageContext } from 'vike/types'
4
4
  import type { PageContextResolved } from '../config/resolvePageContext'
5
- import { PageLayout } from '../PageLayout'
5
+ import { PageContextProvider, PageContextProvider2 } from './usePageContext'
6
6
  import React from 'react'
7
7
 
8
8
  function getPageElement(pageContext: PageContext, pageContextResolved: PageContextResolved) {
9
9
  const { Page } = pageContext
10
+ const { Layout = PassThrough } = pageContext.config
10
11
  const page = (
11
- <PageLayout pageContext={pageContextResolved} pageContext2={pageContext}>
12
- <Page />
13
- </PageLayout>
12
+ <React.StrictMode>
13
+ <PageContextProvider2 pageContext={pageContext}>
14
+ <PageContextProvider pageContext={pageContextResolved}>
15
+ <Layout pageContext={pageContextResolved} pageContext2={pageContext}>
16
+ <Page />
17
+ </Layout>
18
+ </PageContextProvider>
19
+ </PageContextProvider2>
20
+ </React.StrictMode>
14
21
  )
15
22
  return page
16
23
  }
24
+
25
+ function PassThrough({ children }: any) {
26
+ return <>{children}</>
27
+ }
@@ -8,6 +8,7 @@ import { getPageElement } from './getPageElement'
8
8
  import {
9
9
  hideNavigationFullScreen,
10
10
  initNavigationFullscreen,
11
+ initNavigationFullscreenOnce,
11
12
  } from '../navigation/navigation-fullscreen/initNavigationFullscreen'
12
13
  import { hideMobileNavigation, initMobileNavigation } from '../navigation/initMobileNavigation'
13
14
  import { initPressKit } from '../navigation/initPressKit'
@@ -16,7 +17,9 @@ import { autoScrollNav } from '../autoScrollNav'
16
17
  import { installSectionUrlHashs } from '../installSectionUrlHashs'
17
18
  import { addFeatureClickHandlers, addTwitterWidgets } from '../components/FeatureList/FeatureList.client'
18
19
 
20
+ addEcosystemStamp()
19
21
  initOnLinkClick()
22
+ initNavigationFullscreenOnce()
20
23
 
21
24
  let root: ReactDOM.Root
22
25
  let renderPromiseResolve: () => void
@@ -93,3 +96,9 @@ function setHydrationIsFinished() {
93
96
  // - https://github.com/brillout/telefunc/blob/57c942c15b7795cfda96b5106acc9e098aa509aa/docs/.testRun.ts#L26
94
97
  ;(window as any).__docpress_hydrationFinished = true
95
98
  }
99
+
100
+ // Used by:
101
+ // - https://github.com/vikejs/vike/blob/87cca54f30b3c7e71867763d5723493d7eef37ab/vike/client/client-routing-runtime/prefetch.ts#L309-L312
102
+ function addEcosystemStamp() {
103
+ ;(window as any)._isBrilloutDocpress = true
104
+ }
package/types/Heading.ts CHANGED
@@ -3,13 +3,13 @@ export { HeadingDetachedResolved }
3
3
  export { HeadingDetachedDefinition }
4
4
  export { HeadingDefinition }
5
5
 
6
- import type { EmojiName } from '../utils/server'
7
-
8
6
  type HeadingResolved = {
9
7
  url?: null | string
10
8
  level: number
11
9
  title: string
12
10
  titleInNav: string
11
+ noSideNavigation?: true
12
+ topNavigation?: true | string
13
13
  linkBreadcrumb: string[]
14
14
  sectionTitles?: string[]
15
15
  } & Tmp
@@ -19,22 +19,27 @@ type HeadingDetachedResolved = Omit<HeadingResolved, 'level' | 'linkBreadcrumb'>
19
19
  linkBreadcrumb: null
20
20
  }
21
21
 
22
- type HeadingDetachedDefinition = {
23
- url: string
22
+ type HeadingDefinitionCommon = {
24
23
  title: string
24
+ topNavigation?: true | string
25
+ }
26
+
27
+ type HeadingDetachedDefinition = HeadingDefinitionCommon & {
28
+ url: string
25
29
  sectionTitles?: string[]
26
30
  }
27
31
 
28
- type HeadingDefinition = {
32
+ type HeadingDefinition = HeadingDefinitionCommon & {
29
33
  url?: null | string
30
- title: string
31
34
  titleInNav?: string
35
+ noSideNavigation?: true
32
36
  } & HeadingDefinitionLevel &
33
37
  Tmp
34
38
  type IsCategory = {
35
39
  url?: undefined
36
40
  titleDocument?: undefined
37
41
  titleInNav?: undefined
42
+ noSideNavigation?: undefined
38
43
  }
39
44
  type HeadingDefinitionLevel =
40
45
  | ({ level: 1 } & IsCategory)
package/PageLayout.tsx DELETED
@@ -1,48 +0,0 @@
1
- import React from 'react'
2
- import { Navigation, NavigationMask } from './navigation/Navigation'
3
- import type { PageContextResolved } from './config/resolvePageContext'
4
- import { MobileHeader } from './MobileHeader'
5
- import { EditPageNote } from './components/EditPageNote'
6
- import { PageContextProvider, PageContextProvider2 } from './renderer/usePageContext'
7
- import './PageLayout.css'
8
- import { NavigationFullscreenButton } from './navigation/navigation-fullscreen/NavigationFullscreenButton'
9
- import type { PageContext } from 'vike/types'
10
- import { parseTitle } from './parseTitle'
11
-
12
- export { PageLayout }
13
-
14
- function PageLayout({
15
- pageContext,
16
- children,
17
- pageContext2,
18
- }: { pageContext: PageContextResolved; children: React.ReactNode; pageContext2: PageContext }) {
19
- const { isLandingPage, pageTitle, navigationData } = pageContext
20
- const pageTitleParsed = pageTitle && parseTitle(pageTitle)
21
- const { globalNote } = pageContext.config
22
- return (
23
- <React.StrictMode>
24
- <PageContextProvider2 pageContext={pageContext2}>
25
- <PageContextProvider pageContext={pageContext}>
26
- <div className={`page-layout ${isLandingPage ? 'landing-page' : 'doc-page'}`}>
27
- <div id="navigation-wrapper">
28
- <Navigation {...pageContext.navigationData} />
29
- </div>
30
- <NavigationFullscreenButton />
31
- <div className="page-wrapper">
32
- <div className="page-container">
33
- <MobileHeader />
34
- <div className="page-content">
35
- {globalNote}
36
- {pageTitleParsed && <h1 id={`${navigationData.currentUrl.replace('/', '')}`}>{pageTitleParsed}</h1>}
37
- {children}
38
- {!isLandingPage && <EditPageNote pageContext={pageContext} />}
39
- </div>
40
- </div>
41
- <NavigationMask />
42
- </div>
43
- </div>
44
- </PageContextProvider>
45
- </PageContextProvider2>
46
- </React.StrictMode>
47
- )
48
- }