@brillout/docpress 0.7.2 → 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 (44) 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/Navigation.js +8 -8
  29. package/dist/navigation/NavigationHeader.d.ts +4 -0
  30. package/dist/navigation/NavigationHeader.js +9 -19
  31. package/dist/types/Heading.d.ts +10 -4
  32. package/dist/utils/assert.js +6 -10
  33. package/icons/twitter.svg +1 -16
  34. package/navigation/Navigation-items.css +1 -1
  35. package/navigation/Navigation-layout.css +1 -1
  36. package/navigation/Navigation.tsx +10 -11
  37. package/navigation/NavigationHeader.tsx +10 -21
  38. package/navigation/navigation-fullscreen/initNavigationFullscreen.ts +32 -8
  39. package/package.json +22 -18
  40. package/renderer/getPageElement.tsx +15 -4
  41. package/renderer/onRenderClient.tsx +16 -2
  42. package/types/Heading.ts +11 -6
  43. package/utils/assert.ts +5 -10
  44. 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: {
@@ -34,11 +34,11 @@ function NavigationMask() {
34
34
  }
35
35
  function NavigationContent(props) {
36
36
  var navItemsWithComputed = addComputedProps(props.navItems, props.currentUrl);
37
- var navItemsGrouped = groupByLevel1(navItemsWithComputed);
37
+ var navItemsGrouped = groupByLevelMin(navItemsWithComputed);
38
38
  return (React.createElement("div", { id: props.id, className: "navigation-content" },
39
- React.createElement("div", { className: "nav-column", style: { position: 'relative' } }, navItemsGrouped.map(function (navItemLevel1, i) { return (React.createElement("div", { className: "nav-items-level-1-group", key: i },
40
- React.createElement(NavItemComponent, { navItem: navItemLevel1 }),
41
- navItemLevel1.navItemChilds.map(function (navItem, j) { return (React.createElement(NavItemComponent, { navItem: navItem, key: j })); }))); }))));
39
+ React.createElement("div", { className: "nav-column", style: { position: 'relative' } }, navItemsGrouped.map(function (navItemGroup, i) { return (React.createElement("div", { className: "nav-items-group", key: i },
40
+ React.createElement(NavItemComponent, { navItem: navItemGroup }),
41
+ navItemGroup.navItemChilds.map(function (navItem, j) { return (React.createElement(NavItemComponent, { navItem: navItem, key: j })); }))); }))));
42
42
  }
43
43
  function NavItemComponent(_a) {
44
44
  var _b;
@@ -62,16 +62,16 @@ function NavItemComponent(_a) {
62
62
  return (React.createElement("a", { className: [
63
63
  'nav-item',
64
64
  'nav-item-level-' + navItem.level,
65
- navItem.isActive && ' is-active',
66
- navItem.isActiveFirst && ' is-active-first',
67
- navItem.isActiveLast && ' is-active-last',
65
+ navItem.url && navItem.isActive && ' is-active',
66
+ navItem.url && navItem.isActiveFirst && ' is-active-first',
67
+ navItem.url && navItem.isActiveLast && ' is-active-last',
68
68
  navItem.isFirstOfItsKind && 'nav-item-first-of-its-kind',
69
69
  navItem.isLastOfItsKind && 'nav-item-last-of-its-kind',
70
70
  ]
71
71
  .filter(Boolean)
72
72
  .join(' '), href: (_b = navItem.url) !== null && _b !== void 0 ? _b : undefined }, titleInNavJsx));
73
73
  }
74
- function groupByLevel1(navItems) {
74
+ function groupByLevelMin(navItems) {
75
75
  var navItemsGrouped = [];
76
76
  var levelMin = Math.min.apply(Math, navItems.map(function (h) { return h.level; }));
77
77
  navItems.forEach(function (navItem) {
@@ -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;
@@ -8,13 +8,13 @@ if (isBrowser()) {
8
8
  console.log([
9
9
  '[@brillout/docpress] DEV MODE',
10
10
  isDevMode() ? 'enabled' : 'disabled',
11
- !isLocalhost() && 'run window.toggleDevMode() to toggle DEV MODE',
11
+ !isLocalhost() && 'run window.toggleDevMode() to toggle DEV MODE',
12
12
  ]
13
13
  .filter(Boolean)
14
14
  .join(' '));
15
15
  if (isDevMode()) {
16
16
  window.onerror = function (err) {
17
- alert(err);
17
+ window.alert(err);
18
18
  window.onerror = null;
19
19
  };
20
20
  }
@@ -35,9 +35,6 @@ function assert(condition, debugInfo) {
35
35
  errMsg += ' Debug info: ' + String(debugInfo);
36
36
  }
37
37
  var err = new Error(errMsg);
38
- if (isBrowser() && isDevMode()) {
39
- window.alert(err.stack);
40
- }
41
38
  throw err;
42
39
  }
43
40
  function assertUsage(condition, msg) {
@@ -45,9 +42,6 @@ function assertUsage(condition, msg) {
45
42
  return;
46
43
  }
47
44
  var err = new Error('[DocPress][Wrong Usage] ' + msg);
48
- if (isBrowser() && isDevMode()) {
49
- window.alert(err.stack);
50
- }
51
45
  throw err;
52
46
  }
53
47
  function isBrowser() {
@@ -77,8 +71,10 @@ function assertWarning(condition, msg) {
77
71
  return;
78
72
  }
79
73
  msg = '[DocPress][Warning] ' + msg;
80
- console.warn(msg);
81
74
  if (isBrowser() && isDevMode()) {
82
- window.alert(msg);
75
+ throw new Error(msg);
76
+ }
77
+ else {
78
+ console.warn(msg);
83
79
  }
84
80
  }
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>
@@ -22,7 +22,7 @@
22
22
  padding-right: 4px;
23
23
  text-decoration: none;
24
24
  }
25
- .nav-column:first-of-type > .nav-items-level-1-group:first-of-type > .nav-item-level-1:first-of-type {
25
+ .nav-column:first-of-type > .nav-items-group:first-of-type > .nav-item-level-1:first-of-type {
26
26
  margin-top: 20px;
27
27
  }
28
28
  .nav-item-level-1 {
@@ -118,7 +118,7 @@ html.navigation-fullscreen .navigation-content > .nav-column {
118
118
  flex-grow: 1;
119
119
  max-width: 350px;
120
120
  }
121
- html.navigation-fullscreen .nav-column > .nav-items-level-1-group:first-child > .nav-item-level-1:first-child {
121
+ html.navigation-fullscreen .nav-column > .nav-items-group:first-child > .nav-item-level-1:first-child {
122
122
  margin-top: 0px;
123
123
  }
124
124
  html.navigation-fullscreen {
@@ -37,7 +37,6 @@ function Navigation({
37
37
  </>
38
38
  )}
39
39
  <NavigationContent id="navigation-content-main" navItems={navItemsAll} currentUrl={currentUrl} />
40
- {/* <ScrollOverlay /> */}
41
40
  <NavigationFullscreenClose />
42
41
  </div>
43
42
  </div>
@@ -69,15 +68,15 @@ function NavigationContent(props: {
69
68
  currentUrl: string
70
69
  }) {
71
70
  const navItemsWithComputed = addComputedProps(props.navItems, props.currentUrl)
72
- const navItemsGrouped = groupByLevel1(navItemsWithComputed)
71
+ const navItemsGrouped = groupByLevelMin(navItemsWithComputed)
73
72
 
74
73
  return (
75
74
  <div id={props.id} className="navigation-content">
76
75
  <div className="nav-column" style={{ position: 'relative' }}>
77
- {navItemsGrouped.map((navItemLevel1, i) => (
78
- <div className="nav-items-level-1-group" key={i}>
79
- <NavItemComponent navItem={navItemLevel1} />
80
- {navItemLevel1.navItemChilds.map((navItem, j) => (
76
+ {navItemsGrouped.map((navItemGroup, i) => (
77
+ <div className="nav-items-group" key={i}>
78
+ <NavItemComponent navItem={navItemGroup} />
79
+ {navItemGroup.navItemChilds.map((navItem, j) => (
81
80
  <NavItemComponent navItem={navItem} key={j} />
82
81
  ))}
83
82
  </div>
@@ -115,9 +114,9 @@ function NavItemComponent({
115
114
  className={[
116
115
  'nav-item',
117
116
  'nav-item-level-' + navItem.level,
118
- navItem.isActive && ' is-active',
119
- navItem.isActiveFirst && ' is-active-first',
120
- navItem.isActiveLast && ' is-active-last',
117
+ navItem.url && navItem.isActive && ' is-active',
118
+ navItem.url && navItem.isActiveFirst && ' is-active-first',
119
+ navItem.url && navItem.isActiveLast && ' is-active-last',
121
120
  navItem.isFirstOfItsKind && 'nav-item-first-of-its-kind',
122
121
  navItem.isLastOfItsKind && 'nav-item-last-of-its-kind',
123
122
  ]
@@ -131,8 +130,8 @@ function NavItemComponent({
131
130
  )
132
131
  }
133
132
 
134
- function groupByLevel1<T extends { level: number }>(navItems: T[]) {
135
- const navItemsGrouped: (T & { navItemChilds: T[] })[] = []
133
+ function groupByLevelMin(navItems: NavItemComputed[]) {
134
+ const navItemsGrouped: (NavItemComputed & { navItemChilds: NavItemComputed[] })[] = []
136
135
  const levelMin: number = Math.min(...navItems.map((h) => h.level))
137
136
  navItems.forEach((navItem) => {
138
137
  if (navItem.level === levelMin) {
@@ -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() {
@@ -39,7 +44,7 @@ function hideNavigationFullScreen() {
39
44
 
40
45
  function updateColumnWidth() {
41
46
  const navMinWidth = 299
42
- const navH1Groups = Array.from(document.querySelectorAll('#navigation-content-main .nav-items-level-1-group'))
47
+ const navH1Groups = Array.from(document.querySelectorAll('#navigation-content-main .nav-items-group'))
43
48
  const numberOfColumnsMax = navH1Groups.length
44
49
 
45
50
  const widthAvailable = getViewportWidth()
@@ -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
+ }