@brillout/docpress 0.15.1 → 0.15.3

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 CHANGED
@@ -4,7 +4,7 @@ import type { Config } from 'vike/types'
4
4
  import { viteConfig } from './vite.config.js'
5
5
  import type { Config as DocpressConfig } from './types/Config'
6
6
  import type { PageSection } from './parsePageSections'
7
- import type { Conf } from './resolveConf.js'
7
+ import type { Resolved } from './resolvePageContext.js'
8
8
 
9
9
  const config = {
10
10
  name: '@brillout/docpress',
@@ -33,7 +33,7 @@ declare global {
33
33
  namespace Vike {
34
34
  interface PageContext {
35
35
  Page: ReactComponent
36
- conf: Conf
36
+ resolved: Resolved
37
37
  }
38
38
  interface Config {
39
39
  docpress?: DocpressConfig
package/Layout.tsx CHANGED
@@ -46,7 +46,7 @@ const whitespaceBuster2: React.CSSProperties = {
46
46
 
47
47
  function Layout({ children }: { children: React.ReactNode }) {
48
48
  const pageContext = usePageContext()
49
- const { isLandingPage } = pageContext.conf
49
+ const { isLandingPage } = pageContext.resolved
50
50
 
51
51
  let content: React.JSX.Element
52
52
  if (isLandingPage) {
@@ -85,8 +85,8 @@ function Layout({ children }: { children: React.ReactNode }) {
85
85
  function LayoutDocsPage({ children }: { children: React.ReactNode }) {
86
86
  const pageContext = usePageContext()
87
87
  const hideNavLeftAlways =
88
- pageContext.conf.pageDesign?.hideMenuLeft ||
89
- (pageContext.conf.navItemsDetached && pageContext.conf.navItemsDetached.length <= 1)
88
+ pageContext.resolved.pageDesign?.hideMenuLeft ||
89
+ (pageContext.resolved.navItemsDetached && pageContext.resolved.navItemsDetached.length <= 1)
90
90
  return (
91
91
  <>
92
92
  <Style>{getStyle()}</Style>
@@ -155,13 +155,13 @@ function LayoutLandingPage({ children }: { children: React.ReactNode }) {
155
155
 
156
156
  function PageContent({ children }: { children: React.ReactNode }) {
157
157
  const pageContext = usePageContext()
158
- const { isLandingPage, pageTitle } = pageContext.conf
158
+ const { isLandingPage, pageTitle } = pageContext.resolved
159
159
  const pageTitleParsed = pageTitle && parseMarkdownMini(pageTitle)
160
160
  /*
161
161
  const { globalNote } = pageContext.globalContext.config.docpress
162
162
  */
163
163
  const ifDocPage = (style: React.CSSProperties) => (isLandingPage ? {} : style)
164
- const contentMaxWidth = pageContext.conf.pageDesign?.contentMaxWidth ?? mainViewWidthMax
164
+ const contentMaxWidth = pageContext.resolved.pageDesign?.contentMaxWidth ?? mainViewWidthMax
165
165
  return (
166
166
  <div
167
167
  className="page-wrapper low-prio-grow"
@@ -187,7 +187,7 @@ function PageContent({ children }: { children: React.ReactNode }) {
187
187
  }}
188
188
  >
189
189
  {/* globalNote */}
190
- {pageTitleParsed && !pageContext.conf.pageDesign?.hideTitle && (
190
+ {pageTitleParsed && !pageContext.resolved.pageDesign?.hideTitle && (
191
191
  <div>
192
192
  <EditLink className="show-only-on-desktop" style={{ float: 'right', marginTop: 6, padding: 10 }} />
193
193
  <h1 id={`${pageContext.urlPathname.replace('/', '')}`}>{pageTitleParsed}</h1>
@@ -201,7 +201,7 @@ function PageContent({ children }: { children: React.ReactNode }) {
201
201
 
202
202
  function NavLeft() {
203
203
  const pageContext = usePageContext()
204
- const { navItemsAll, navItemsDetached } = pageContext.conf
204
+ const { navItemsAll, navItemsDetached } = pageContext.resolved
205
205
  return (
206
206
  <>
207
207
  <div
@@ -280,7 +280,7 @@ const menuLinkStyle: React.CSSProperties = {
280
280
 
281
281
  function NavHead({ isNavLeft }: { isNavLeft?: true }) {
282
282
  const pageContext = usePageContext()
283
- const { isLandingPage } = pageContext.conf
283
+ const { isLandingPage } = pageContext.resolved
284
284
  const { navMaxWidth, name, algolia } = pageContext.globalContext.config.docpress
285
285
 
286
286
  const navSecondaryContent = (
@@ -482,8 +482,36 @@ function NavHeaderLeftFullWidthBackground() {
482
482
 
483
483
  function NavLogo({ className }: { className: string }) {
484
484
  const pageContext = usePageContext()
485
- const iconSize = pageContext.globalContext.config.docpress.navLogoSize ?? 39
486
- const { name } = pageContext.globalContext.config.docpress
485
+
486
+ const { navLogo } = pageContext.globalContext.config.docpress
487
+ let navLogoResolved = navLogo
488
+ if (!navLogoResolved) {
489
+ const iconSize = pageContext.globalContext.config.docpress.navLogoSize ?? 39
490
+ const { name, logo, navLogoStyle, navLogoTextStyle } = pageContext.globalContext.config.docpress
491
+ navLogoResolved = (
492
+ <>
493
+ <img
494
+ src={logo}
495
+ style={{
496
+ height: iconSize,
497
+ width: iconSize,
498
+ ...navLogoStyle,
499
+ }}
500
+ onContextMenu={onContextMenu}
501
+ />
502
+ <span
503
+ style={{
504
+ marginLeft: `calc(var(--icon-text-padding) + 2px)`,
505
+ fontSize: isProjectNameShort(name) ? '1.65em' : '1.3em',
506
+ ...navLogoTextStyle,
507
+ }}
508
+ >
509
+ {name}
510
+ </span>
511
+ </>
512
+ )
513
+ }
514
+
487
515
  return (
488
516
  <a
489
517
  className={cls(['nav-logo', className])}
@@ -494,32 +522,18 @@ function NavLogo({ className }: { className: string }) {
494
522
  color: 'inherit',
495
523
  }}
496
524
  href="/"
525
+ onContextMenu={!navLogo ? undefined : onContextMenu}
497
526
  >
498
- <img
499
- src={pageContext.globalContext.config.docpress.logo}
500
- style={{
501
- height: iconSize,
502
- width: iconSize,
503
- ...pageContext.globalContext.config.docpress.navLogoStyle,
504
- }}
505
- onContextMenu={(ev) => {
506
- if (!pageContext.globalContext.config.docpress.pressKit) return // no /press page
507
- if (window.location.pathname === '/press') return
508
- ev.preventDefault()
509
- navigate('/press#logo')
510
- }}
511
- />
512
- <span
513
- style={{
514
- marginLeft: `calc(var(--icon-text-padding) + 2px)`,
515
- fontSize: isProjectNameShort(name) ? '1.65em' : '1.3em',
516
- ...pageContext.globalContext.config.docpress.navLogoTextStyle,
517
- }}
518
- >
519
- {name}
520
- </span>
527
+ {navLogoResolved}
521
528
  </a>
522
529
  )
530
+
531
+ function onContextMenu(ev: React.MouseEvent<unknown, MouseEvent>) {
532
+ if (!pageContext.globalContext.config.docpress.pressKit) return // no /press page
533
+ if (window.location.pathname === '/press') return
534
+ ev.preventDefault()
535
+ navigate('/press#logo')
536
+ }
523
537
  }
524
538
  function isProjectNameShort(name: string) {
525
539
  return name.length <= 4
package/MenuModal.tsx CHANGED
@@ -73,7 +73,7 @@ function BorderBottom() {
73
73
  }
74
74
  function Nav() {
75
75
  const pageContext = usePageContext()
76
- const navItems = pageContext.conf.navItemsAll
76
+ const navItems = pageContext.resolved.navItemsAll
77
77
  return <NavigationWithColumnLayout navItems={navItems} />
78
78
  }
79
79
 
@@ -141,7 +141,7 @@ function findLinkData(
141
141
  { pageContext, noWarning }: { pageContext: PageContext; noWarning?: boolean },
142
142
  ): LinkData | null {
143
143
  assert(href.startsWith('/') || href.startsWith('#'))
144
- const { linksAll } = pageContext.conf
144
+ const { linksAll } = pageContext.resolved
145
145
  const linkData = linksAll.find(({ url }) => href === url)
146
146
  if (href.startsWith('#')) {
147
147
  if (!noWarning) {
package/dist/+config.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  export { config as default };
2
2
  import type { Config as DocpressConfig } from './types/Config';
3
3
  import type { PageSection } from './parsePageSections';
4
- import type { Conf } from './resolveConf.js';
4
+ import type { Resolved } from './resolvePageContext.js';
5
5
  declare const config: {
6
6
  name: string;
7
7
  require: {
@@ -35,7 +35,7 @@ declare global {
35
35
  namespace Vike {
36
36
  interface PageContext {
37
37
  Page: ReactComponent;
38
- conf: Conf;
38
+ resolved: Resolved;
39
39
  }
40
40
  interface Config {
41
41
  docpress?: DocpressConfig;
@@ -91,7 +91,7 @@ function getLinkTextData(_a) {
91
91
  function findLinkData(href, _a) {
92
92
  var pageContext = _a.pageContext, noWarning = _a.noWarning;
93
93
  assert(href.startsWith('/') || href.startsWith('#'));
94
- var linksAll = pageContext.conf.linksAll;
94
+ var linksAll = pageContext.resolved.linksAll;
95
95
  var linkData = linksAll.find(function (_a) {
96
96
  var url = _a.url;
97
97
  return href === url;
@@ -9,7 +9,7 @@ var globalObject = getGlobalObject('usePageContext.ts', {
9
9
  function usePageContextLegacy() {
10
10
  var Ctx = globalObject.Ctx;
11
11
  var pageContext = useContext(Ctx);
12
- return pageContext.conf;
12
+ return pageContext.resolved;
13
13
  }
14
14
  function usePageContext() {
15
15
  var pageContext = useContext(globalObject.Ctx);
@@ -1,9 +1,9 @@
1
- export { resolveConf };
2
- export type Conf = ReturnType<typeof resolveConf>;
1
+ export { resolvePageContext };
2
+ export type Resolved = ReturnType<typeof resolvePageContext>;
3
3
  import type { NavItem } from './NavItemComponent';
4
4
  import type { LinkData } from './components';
5
5
  import type { PageContextServer } from 'vike/types';
6
- declare function resolveConf(pageContext: PageContextServer): {
6
+ declare function resolvePageContext(pageContext: PageContextServer): {
7
7
  navItemsAll: NavItem[];
8
8
  navItemsDetached: NavItem[] | undefined;
9
9
  pageDesign: {
@@ -18,13 +18,13 @@ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
18
18
  }
19
19
  return to.concat(ar || Array.prototype.slice.call(from));
20
20
  };
21
- export { resolveConf };
21
+ export { resolvePageContext };
22
22
  import { assert } from './utils/assert';
23
23
  import { jsxToTextContent } from './utils/jsxToTextContent';
24
24
  import pc from '@brillout/picocolors';
25
25
  import { parseMarkdownMini } from './parseMarkdownMini';
26
26
  import { determineNavItemsColumnLayout } from './determineNavItemsColumnLayout';
27
- function resolveConf(pageContext) {
27
+ function resolvePageContext(pageContext) {
28
28
  var _a;
29
29
  var config = pageContext.globalContext.config.docpress;
30
30
  var urlPathname = pageContext.urlPathname;
@@ -33,9 +33,9 @@ function resolveConf(pageContext) {
33
33
  var headings = config.headings, headingsDetached = config.headingsDetached;
34
34
  assertHeadingsDefinition(__spreadArray(__spreadArray([], headings, true), headingsDetached, true));
35
35
  }
36
- var resolved = getHeadingsResolved(config);
37
- var headingsDetachedResolved = resolved.headingsDetachedResolved;
38
- var headingsResolved = resolved.headingsResolved;
36
+ var ret = getHeadingsResolved(config);
37
+ var headingsDetachedResolved = ret.headingsDetachedResolved;
38
+ var headingsResolved = ret.headingsResolved;
39
39
  var _b = getActiveHeading(headingsResolved, headingsDetachedResolved, urlPathname), activeHeading = _b.activeHeading, isDetachedPage = _b.isDetachedPage, activeCategoryName = _b.activeCategoryName;
40
40
  var _c = getTitles(activeHeading, urlPathname, config), documentTitle = _c.documentTitle, isLandingPage = _c.isLandingPage, pageTitle = _c.pageTitle;
41
41
  var pageSectionsResolved = getPageSectionsResolved(pageSections, activeHeading);
@@ -61,7 +61,7 @@ function resolveConf(pageContext) {
61
61
  });
62
62
  }
63
63
  }
64
- var conf = {
64
+ var resolved = {
65
65
  navItemsAll: navItemsAll,
66
66
  navItemsDetached: navItemsDetached,
67
67
  pageDesign: activeHeading.pageDesign,
@@ -71,7 +71,7 @@ function resolveConf(pageContext) {
71
71
  documentTitle: documentTitle,
72
72
  activeCategoryName: activeCategoryName,
73
73
  };
74
- return conf;
74
+ return resolved;
75
75
  }
76
76
  function headingToNavItem(heading) {
77
77
  return {
@@ -21,15 +21,17 @@ type Config = {
21
21
  apiKey: string;
22
22
  indexName: string;
23
23
  };
24
+ googleAnalytics?: string;
24
25
  i18n?: true;
25
26
  pressKit?: true;
26
27
  docsDir?: string;
27
- topNavigation?: React.ReactNode;
28
- globalNote?: React.ReactNode;
29
28
  navMaxWidth?: number;
29
+ topNavigation?: React.ReactNode;
30
+ navLogo?: React.ReactNode;
30
31
  navLogoSize?: number;
31
32
  navLogoStyle?: React.CSSProperties;
32
33
  navLogoTextStyle?: React.CSSProperties;
34
+ globalNote?: React.ReactNode;
33
35
  };
34
36
  /** Order in Algolia search results */
35
37
  type Category = string | {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@brillout/docpress",
3
- "version": "0.15.1",
3
+ "version": "0.15.3",
4
4
  "type": "module",
5
5
  "dependencies": {
6
6
  "@brillout/picocolors": "^1.0.10",
@@ -1,8 +1,8 @@
1
1
  export { onCreatePageContext }
2
2
 
3
3
  import type { PageContextServer } from 'vike/types'
4
- import { resolveConf } from '../resolveConf'
4
+ import { resolvePageContext } from '../resolvePageContext'
5
5
 
6
6
  function onCreatePageContext(pageContext: PageContextServer) {
7
- pageContext.conf = resolveConf(pageContext)
7
+ pageContext.resolved = resolvePageContext(pageContext)
8
8
  }
@@ -12,9 +12,11 @@ import { getGlobalObject } from '../utils/client'
12
12
  import { initKeyBindings } from '../initKeyBindings'
13
13
  import { initOnNavigation } from './initOnNavigation'
14
14
  import { setHydrationIsFinished } from './getHydrationPromise'
15
+ import { addScript } from '../utils/addScript'
15
16
 
16
17
  const globalObject = getGlobalObject<{
17
18
  root?: ReactDOM.Root
19
+ isNotFirstRender?: true
18
20
  }>('onRenderClient.ts', {})
19
21
 
20
22
  addEcosystemStamp()
@@ -30,6 +32,7 @@ async function onRenderClient(pageContext: PageContextClient) {
30
32
  })
31
33
  let page = getPageElement(pageContext)
32
34
  page = <OnRenderDoneHook renderPromiseResolve={renderPromiseResolve}>{page}</OnRenderDoneHook>
35
+
33
36
  const container = document.getElementById('page-view')!
34
37
  if (pageContext.isHydration) {
35
38
  globalObject.root = ReactDOM.hydrateRoot(container, page)
@@ -42,11 +45,19 @@ async function onRenderClient(pageContext: PageContextClient) {
42
45
  if (!pageContext.isHydration) {
43
46
  applyHead(pageContext)
44
47
  }
48
+
45
49
  await renderPromise
50
+
51
+ autoScrollNav()
52
+ installSectionUrlHashs()
53
+ setHydrationIsFinished()
54
+ initGoogleAnalytics(pageContext)
55
+
56
+ globalObject.isNotFirstRender = true
46
57
  }
47
58
 
48
59
  function applyHead(pageContext: PageContextClient) {
49
- document.title = pageContext.conf.documentTitle
60
+ document.title = pageContext.resolved.documentTitle
50
61
  }
51
62
 
52
63
  function onRenderStart() {
@@ -54,18 +65,13 @@ function onRenderStart() {
54
65
  closeMenuModal()
55
66
  }
56
67
 
57
- function onRenderDone(renderPromiseResolve: () => void) {
58
- autoScrollNav()
59
- installSectionUrlHashs()
60
- setHydrationIsFinished()
61
- renderPromiseResolve()
62
- }
63
-
64
68
  function OnRenderDoneHook({
65
69
  renderPromiseResolve,
66
70
  children,
67
71
  }: { renderPromiseResolve: () => void; children: React.ReactNode }) {
68
- useEffect(() => onRenderDone(renderPromiseResolve))
72
+ useEffect(() => {
73
+ renderPromiseResolve()
74
+ })
69
75
  return children
70
76
  }
71
77
 
@@ -74,3 +80,27 @@ function OnRenderDoneHook({
74
80
  function addEcosystemStamp() {
75
81
  ;(window as any)._isBrilloutDocpress = true
76
82
  }
83
+
84
+ async function initGoogleAnalytics(pageContext: PageContextClient) {
85
+ const isFirstRender = !globalObject.isNotFirstRender
86
+ const id = pageContext.config.docpress.googleAnalytics
87
+
88
+ if (!id) return
89
+ if (isFirstRender) await installGoogleAnalytics(id)
90
+ }
91
+ async function installGoogleAnalytics(id: string) {
92
+ window.dataLayer = window.dataLayer || []
93
+ window.gtag = function gtag() {
94
+ window.dataLayer.push(arguments)
95
+ }
96
+ window.gtag('js', new Date())
97
+ window.gtag('config', id)
98
+
99
+ await addScript(`https://www.googletagmanager.com/gtag/js?id=${id}`)
100
+ }
101
+ declare global {
102
+ interface Window {
103
+ dataLayer: any[]
104
+ gtag: (...args: any[]) => void
105
+ }
106
+ }
@@ -10,7 +10,7 @@ import type { Config } from '../types/Config'
10
10
  async function onRenderHtml(pageContext: PageContextServer): Promise<any> {
11
11
  const page = getPageElement(pageContext)
12
12
 
13
- const { isLandingPage } = pageContext.conf
13
+ const { isLandingPage } = pageContext.resolved
14
14
  assert(typeof isLandingPage === 'boolean')
15
15
  const { tagline } = pageContext.globalContext.config.docpress
16
16
  assert(tagline)
@@ -21,7 +21,7 @@ async function onRenderHtml(pageContext: PageContextServer): Promise<any> {
21
21
  const faviconUrl = pageContext.globalContext.config.docpress.favicon ?? pageContext.globalContext.config.docpress.logo
22
22
  assert(faviconUrl)
23
23
 
24
- const { documentTitle } = pageContext.conf
24
+ const { documentTitle } = pageContext.resolved
25
25
  assert(documentTitle)
26
26
  return escapeInject`<!DOCTYPE html>
27
27
  <html>
@@ -56,7 +56,7 @@ type ActiveCategory = {
56
56
  }
57
57
  function getActiveCategory(pageContext: PageContextServer) {
58
58
  const config = pageContext.globalContext.config.docpress
59
- const { activeCategoryName } = pageContext.conf
59
+ const { activeCategoryName } = pageContext.resolved
60
60
 
61
61
  const activeCategory: ActiveCategory = config.categories
62
62
  // normalize
@@ -13,7 +13,7 @@ const globalObject = getGlobalObject('usePageContext.ts', {
13
13
  function usePageContextLegacy() {
14
14
  const { Ctx } = globalObject
15
15
  const pageContext = useContext(Ctx)
16
- return pageContext.conf
16
+ return pageContext.resolved
17
17
  }
18
18
 
19
19
  function usePageContext(): PageContext {
@@ -1,5 +1,5 @@
1
- export { resolveConf }
2
- export type Conf = ReturnType<typeof resolveConf>
1
+ export { resolvePageContext }
2
+ export type Resolved = ReturnType<typeof resolvePageContext>
3
3
 
4
4
  import type { Config } from './types/Config'
5
5
  import type { NavItem } from './NavItemComponent'
@@ -26,7 +26,7 @@ type PageSectionResolved = {
26
26
  pageSectionLevel: number
27
27
  }
28
28
 
29
- function resolveConf(pageContext: PageContextServer) {
29
+ function resolvePageContext(pageContext: PageContextServer) {
30
30
  const config = pageContext.globalContext.config.docpress
31
31
  const { urlPathname } = pageContext
32
32
  const pageSections = pageContext.config.pageSectionsExport ?? []
@@ -36,9 +36,9 @@ function resolveConf(pageContext: PageContextServer) {
36
36
  assertHeadingsDefinition([...headings, ...headingsDetached])
37
37
  }
38
38
 
39
- const resolved = getHeadingsResolved(config)
40
- const { headingsDetachedResolved } = resolved
41
- let { headingsResolved } = resolved
39
+ const ret = getHeadingsResolved(config)
40
+ const { headingsDetachedResolved } = ret
41
+ let { headingsResolved } = ret
42
42
 
43
43
  const { activeHeading, isDetachedPage, activeCategoryName } = getActiveHeading(
44
44
  headingsResolved,
@@ -76,7 +76,7 @@ function resolveConf(pageContext: PageContextServer) {
76
76
  }
77
77
  }
78
78
 
79
- const conf = {
79
+ const resolved = {
80
80
  navItemsAll,
81
81
  navItemsDetached,
82
82
  pageDesign: activeHeading.pageDesign,
@@ -86,7 +86,7 @@ function resolveConf(pageContext: PageContextServer) {
86
86
  documentTitle,
87
87
  activeCategoryName,
88
88
  }
89
- return conf
89
+ return resolved
90
90
  }
91
91
 
92
92
  function headingToNavItem(heading: HeadingResolved | HeadingDetachedResolved): NavItem {
package/types/Config.ts CHANGED
@@ -26,17 +26,21 @@ type Config = {
26
26
  apiKey: string
27
27
  indexName: string
28
28
  }
29
+ googleAnalytics?: string
29
30
 
30
31
  i18n?: true
31
32
  pressKit?: true
32
33
  docsDir?: string
34
+ navMaxWidth?: number
33
35
 
34
36
  topNavigation?: React.ReactNode
35
- globalNote?: React.ReactNode
36
- navMaxWidth?: number
37
+
38
+ navLogo?: React.ReactNode
37
39
  navLogoSize?: number
38
40
  navLogoStyle?: React.CSSProperties
39
41
  navLogoTextStyle?: React.CSSProperties
42
+
43
+ globalNote?: React.ReactNode
40
44
  }
41
45
 
42
46
  /** Order in Algolia search results */
@@ -0,0 +1,12 @@
1
+ export { addScript }
2
+
3
+ import { genPromise } from './genPromise'
4
+
5
+ async function addScript(src: string) {
6
+ const { promise, resolve, reject } = genPromise()
7
+ const script = document.createElement('script')
8
+ script.onload = () => resolve()
9
+ script.onerror = () => reject(new Error(`Failed to load script: ${src}`))
10
+ script.src = src
11
+ return promise
12
+ }
@@ -1,5 +1,13 @@
1
- export function genPromise<T = void>(): { promise: Promise<T>; resolve: (val: T) => void } {
1
+ export function genPromise<T = void>(): {
2
+ promise: Promise<T>
3
+ resolve: (val: T) => void
4
+ reject: (err: unknown) => void
5
+ } {
2
6
  let resolve!: (val: T) => void
3
- const promise = new Promise<T>((r) => (resolve = r))
4
- return { promise, resolve }
7
+ let reject!: (err: unknown) => void
8
+ const promise = new Promise<T>((resolve_, reject_) => {
9
+ resolve = resolve_
10
+ reject = reject_
11
+ })
12
+ return { promise, resolve, reject }
5
13
  }