@brillout/docpress 0.5.39 → 0.5.40-commit-1ba896e

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 (143) hide show
  1. package/MobileHeader.tsx +68 -0
  2. package/PageLayout.css +42 -0
  3. package/PageLayout.tsx +39 -0
  4. package/algolia/DocSearch.css +34 -0
  5. package/algolia/DocSearch.ts +62 -0
  6. package/autoScrollNav.ts +36 -0
  7. package/components/CodeBlockTransformer.css +9 -0
  8. package/components/CodeBlockTransformer.tsx +18 -0
  9. package/components/Comment.tsx +7 -0
  10. package/components/Consulting.tsx +47 -0
  11. package/components/Contributors.tsx +113 -0
  12. package/components/EditPageNote.tsx +18 -0
  13. package/components/HorizontalLine.tsx +20 -0
  14. package/components/ImportMeta.tsx +11 -0
  15. package/components/Link.tsx +144 -0
  16. package/components/Note.css +54 -0
  17. package/components/Note.tsx +78 -0
  18. package/components/P.css +8 -0
  19. package/components/P.tsx +8 -0
  20. package/components/ReadingRecommendation.tsx +56 -0
  21. package/components/RepoLink.tsx +24 -0
  22. package/components/Sponsors/label.draft.svg +108 -0
  23. package/components/Sponsors.tsx +218 -0
  24. package/components/Supporters.tsx +136 -0
  25. package/{dist/components → components}/features/FeatureList.css +10 -2
  26. package/components/features/FeatureList.tsx +114 -0
  27. package/components/features/initFeatureList.ts +66 -0
  28. package/components/index.ts +15 -0
  29. package/config/getConfig.ts +18 -0
  30. package/config/resolveConfig/resolveHeading.ts +0 -0
  31. package/config/resolvePageContext.ts +186 -0
  32. package/css/button.css +7 -0
  33. package/css/code/block.css +36 -0
  34. package/css/code/inline.css +27 -0
  35. package/css/code.css +20 -0
  36. package/css/colorize-on-hover.css +29 -0
  37. package/css/font.css +25 -0
  38. package/css/heading.css +45 -0
  39. package/css/index.css +12 -0
  40. package/css/link.css +17 -0
  41. package/css/reset.css +12 -0
  42. package/css/table.css +14 -0
  43. package/css/tooltip.css +11 -0
  44. package/data/maintainersList.tsx +92 -0
  45. package/data/sponsorsList.ts +147 -0
  46. package/dist/markdownHeadingsVitePlugin.d.ts +13 -0
  47. package/dist/markdownHeadingsVitePlugin.js +170 -0
  48. package/dist/utils/assert.d.ts +6 -0
  49. package/dist/utils/assert.js +48 -0
  50. package/dist/utils/determineSectionUrlHash.d.ts +4 -0
  51. package/dist/utils/determineSectionUrlHash.js +38 -0
  52. package/dist/vite.config.d.ts +3 -0
  53. package/dist/vite.config.js +32 -0
  54. package/index.ts +4 -0
  55. package/installSectionUrlHashs.ts +60 -0
  56. package/markdownHeadingsVitePlugin.ts +150 -0
  57. package/navigation/Navigation-highlight.css +41 -0
  58. package/navigation/Navigation-items.css +119 -0
  59. package/navigation/Navigation-layout.css +127 -0
  60. package/navigation/Navigation.client.ts +43 -0
  61. package/navigation/Navigation.css +3 -0
  62. package/navigation/Navigation.tsx +211 -0
  63. package/navigation/NavigationHeader.tsx +111 -0
  64. package/navigation/navigation-fullscreen/NavigationFullscreenButton.css +32 -0
  65. package/navigation/navigation-fullscreen/NavigationFullscreenButton.tsx +44 -0
  66. package/navigation/navigation-fullscreen/initNavigationFullscreen.ts +116 -0
  67. package/package.json +27 -47
  68. package/parseEmojis.ts +35 -0
  69. package/parseTitle.ts +139 -0
  70. package/renderer/client.ts +4 -0
  71. package/renderer/onRenderHtml.tsx +69 -0
  72. package/renderer/usePageContext.tsx +25 -0
  73. package/tsconfig.json +15 -0
  74. package/tsconfig.vite-config.json +7 -0
  75. package/types/Config.ts +46 -0
  76. package/types/Heading.ts +49 -0
  77. package/utils/Emoji/Emoji.ts +224 -0
  78. package/utils/Emoji/assets.ts +9 -0
  79. package/utils/Emoji/index.ts +1 -0
  80. package/utils/Emoji/mountain.svg +1 -0
  81. package/utils/assert.ts +51 -0
  82. package/utils/client.ts +2 -0
  83. package/utils/determineSectionUrlHash.ts +44 -0
  84. package/utils/filesystemPathHandling.ts +42 -0
  85. package/utils/filter.ts +12 -0
  86. package/utils/isBrowser.ts +5 -0
  87. package/utils/jsxToTextContent.ts +11 -0
  88. package/utils/objectAssign.ts +9 -0
  89. package/utils/server.ts +7 -0
  90. package/vite.config.ts +36 -0
  91. package/bin.js +0 -3
  92. package/dist/chunk-2ZTPUQGS.js +0 -58
  93. package/dist/chunk-3QC7HYIF.js +0 -7
  94. package/dist/chunk-MGOI4AFO.js +0 -165
  95. package/dist/chunk-NVJING6T.js +0 -91
  96. package/dist/chunk-QWL3MA4E.js +0 -171
  97. package/dist/chunk-UN23G34B.js +0 -157
  98. package/dist/cli/index.d.ts +0 -1
  99. package/dist/cli/index.js +0 -34
  100. package/dist/components/features/FeatureList.d.ts +0 -13
  101. package/dist/components/features/FeatureList.js +0 -7
  102. package/dist/components/features/initFeatureList.d.ts +0 -3
  103. package/dist/components/features/initFeatureList.js +0 -59
  104. package/dist/devServer-JKH6U5PF.js +0 -36
  105. package/dist/index.css +0 -120
  106. package/dist/index.d.ts +0 -225
  107. package/dist/index.js +0 -948
  108. package/dist/renderer/_default.page.client.css +0 -318
  109. package/dist/renderer/_default.page.client.d.ts +0 -1
  110. package/dist/renderer/_default.page.client.js +0 -218
  111. package/dist/renderer/_default.page.server.css +0 -310
  112. package/dist/renderer/_default.page.server.d.ts +0 -22
  113. package/dist/renderer/_default.page.server.js +0 -665
  114. package/readme.md +0 -5
  115. /package/{dist/label-MP75CTIA.svg → components/Sponsors/label.svg} +0 -0
  116. /package/{dist/medalBronze-CO4CTUR4.svg → components/Sponsors/medalBronze.svg} +0 -0
  117. /package/{dist/medalGold-UP6A73FL.svg → components/Sponsors/medalGold.svg} +0 -0
  118. /package/{dist/medalSilver-FAPGGOBN.svg → components/Sponsors/medalSilver.svg} +0 -0
  119. /package/{dist/chevron-R2IYJD62.svg → components/features/chevron.svg} +0 -0
  120. /package/{dist/Inter-Var-IOAEQULN.ttf → css/Inter-Var.ttf} +0 -0
  121. /package/{dist/alignable-B4QZV4X7.svg → data/sponsorsList/companyLogos/alignable.svg} +0 -0
  122. /package/{dist/bluefin-JQABZFGV.svg → data/sponsorsList/companyLogos/bluefin.svg} +0 -0
  123. /package/{dist/burdaforward-EUGURYZY.png → data/sponsorsList/companyLogos/burdaforward.png} +0 -0
  124. /package/{dist/contra-WLZBOPBV.svg → data/sponsorsList/companyLogos/contra.svg} +0 -0
  125. /package/{dist/ecosia-OYRLTR5T.svg → data/sponsorsList/companyLogos/ecosia.svg} +0 -0
  126. /package/{dist/inlang-GFRWND6X.png → data/sponsorsList/companyLogos/inlang.png} +0 -0
  127. /package/{dist/optimizers-SFEZF3NW.svg → data/sponsorsList/companyLogos/optimizers.svg} +0 -0
  128. /package/{dist/sourcegraph-YR2HADLS.svg → data/sponsorsList/companyLogos/sourcegraph.svg} +0 -0
  129. /package/{dist/changelog-IPI5F42D.svg → icons/changelog.svg} +0 -0
  130. /package/{dist/discord-JD33TUSF.svg → icons/discord.svg} +0 -0
  131. /package/{dist/github-P5ZSKN2N.svg → icons/github.svg} +0 -0
  132. /package/{dist/heart-OINVKOXO.svg → icons/heart.svg} +0 -0
  133. /package/{dist/languages-KXPKJFQL.svg → icons/languages.svg} +0 -0
  134. /package/{dist/people-72KKQHU4.svg → icons/people.svg} +0 -0
  135. /package/{dist/twitter-I7DXDN3J.svg → icons/twitter.svg} +0 -0
  136. /package/{dist/chevron-K3WPYLOP.svg → navigation/navigation-fullscreen/chevron.svg} +0 -0
  137. /package/{dist/close-IQXTDOHV.svg → navigation/navigation-fullscreen/close.svg} +0 -0
  138. /package/{dist/compass-2RWQU3E4.svg → utils/Emoji/compass.svg} +0 -0
  139. /package/{dist/engine-6Q6VSCVA.png → utils/Emoji/engine.png} +0 -0
  140. /package/{dist/mechanical-arm-TR7IQQMG.svg → utils/Emoji/mechanical-arm.svg} +0 -0
  141. /package/{dist/road-fork-3WZLW3HB.svg → utils/Emoji/road-fork.svg} +0 -0
  142. /package/{dist/shield-CU45RG5C.svg → utils/Emoji/shield.svg} +0 -0
  143. /package/{dist/typescript-ALIPKLRM.svg → utils/Emoji/typescript.svg} +0 -0
@@ -0,0 +1,68 @@
1
+ import React from 'react'
2
+ import { usePageContext } from './renderer/usePageContext'
3
+
4
+ export { MobileHeader }
5
+
6
+ function MobileHeader() {
7
+ const pageContext = usePageContext()
8
+ return (
9
+ <div
10
+ id="mobile-header"
11
+ style={{
12
+ height: 'var(--mobile-header-height)',
13
+ width: '100%',
14
+ position: 'relative'
15
+ }}
16
+ >
17
+ <div
18
+ style={{
19
+ position: 'fixed',
20
+ display: 'flex',
21
+ alignItems: 'center',
22
+ background: 'white',
23
+ zIndex: 99,
24
+ top: 0,
25
+ left: 0,
26
+ height: 'var(--mobile-header-height)',
27
+ width: '100%',
28
+ borderBottom: '1px solid #ddd'
29
+ }}
30
+ >
31
+ <MenuToggle />
32
+ <a
33
+ href="/"
34
+ style={{
35
+ color: 'inherit',
36
+ display: 'flex',
37
+ alignItems: 'center',
38
+ justifyContent: 'left',
39
+ textDecoration: 'none',
40
+ ...pageContext.config.navHeaderMobileWrapperStyle
41
+ }}
42
+ >
43
+ {pageContext.config.navHeaderMobile}
44
+ </a>
45
+ </div>
46
+ </div>
47
+ )
48
+ }
49
+
50
+ function MenuToggle() {
51
+ return (
52
+ <div style={{ padding: 20, lineHeight: 0, cursor: 'pointer' }} id="menu-toggle">
53
+ <svg
54
+ style={{ width: 20 }}
55
+ className="icon"
56
+ xmlns="http://www.w3.org/2000/svg"
57
+ aria-hidden="true"
58
+ role="img"
59
+ viewBox="0 0 448 512"
60
+ >
61
+ <path
62
+ fill="currentColor"
63
+ d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"
64
+ ></path>
65
+ </svg>
66
+ </div>
67
+ )
68
+ }
package/PageLayout.css ADDED
@@ -0,0 +1,42 @@
1
+ .doc-page #page-container {
2
+ padding-bottom: 100px;
3
+ }
4
+
5
+ #page-layout {
6
+ display: flex;
7
+ justify-content: center;
8
+ width: 100%;
9
+ }
10
+ #page-layout > #navigation-wrapper,
11
+ #page-layout > #page-wrapper {
12
+ flex-grow: 1;
13
+ }
14
+ /* Avoid overflow, see https://stackoverflow.com/questions/36230944/prevent-flex-items-from-overflowing-a-container/66689926#66689926 */
15
+ #page-layout > #page-wrapper {
16
+ min-width: 0;
17
+ }
18
+
19
+ .doc-page #page-wrapper {
20
+ --main-view-max-width: 800px;
21
+ }
22
+ .landing-page #page-wrapper {
23
+ --main-view-max-width: 1010px;
24
+ }
25
+ #page-wrapper {
26
+ max-width: calc(var(--main-view-max-width) + 80px);
27
+ }
28
+ #page-content {
29
+ box-sizing: content-box;
30
+ max-width: var(--main-view-max-width);
31
+ padding: 20px var(--main-view-padding);
32
+ margin: auto;
33
+ }
34
+
35
+ #page-content {
36
+ --main-view-padding: 20px;
37
+ }
38
+ @media screen and (max-width: 1139px) {
39
+ #page-content {
40
+ --main-view-padding: 10px;
41
+ }
42
+ }
package/PageLayout.tsx ADDED
@@ -0,0 +1,39 @@
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 } from './renderer/usePageContext'
7
+ import './PageLayout.css'
8
+ import { NavigationFullscreenButton } from './navigation/navigation-fullscreen/NavigationFullscreenButton'
9
+
10
+ export { PageLayout }
11
+
12
+ function PageLayout({ pageContext, children }: { pageContext: PageContextResolved; children: React.ReactNode }) {
13
+ const { isLandingPage, pageTitle } = pageContext
14
+ const { globalNote } = pageContext.config
15
+ return (
16
+ <React.StrictMode>
17
+ <PageContextProvider pageContext={pageContext}>
18
+ <div id="page-layout" className={isLandingPage ? 'landing-page' : 'doc-page'}>
19
+ <div id="navigation-wrapper">
20
+ <Navigation pageContext={pageContext} />
21
+ </div>
22
+ <NavigationFullscreenButton />
23
+ <div id="page-wrapper">
24
+ <div id="page-container">
25
+ <MobileHeader />
26
+ <div id="page-content">
27
+ {globalNote}
28
+ {pageTitle && <h1>{pageTitle}</h1>}
29
+ {children}
30
+ {!isLandingPage && <EditPageNote pageContext={pageContext} />}
31
+ </div>
32
+ </div>
33
+ <NavigationMask />
34
+ </div>
35
+ </div>
36
+ </PageContextProvider>
37
+ </React.StrictMode>
38
+ )
39
+ }
@@ -0,0 +1,34 @@
1
+ .DocSearch-Button-Keys {
2
+ margin-left: 6px !important;
3
+ }
4
+ .DocSearch-Search-Icon {
5
+ margin-right: 0 !important;
6
+ }
7
+ .DocSearch-Button-Placeholder {
8
+ padding-right: 6px !important;
9
+ }
10
+
11
+ #docsearch-desktop {
12
+ max-width: 110px !important;
13
+ }
14
+ #docsearch-desktop .DocSearch-Button-Placeholder,
15
+ #docsearch-desktop .DocSearch-Button-Keys {
16
+ display: none;
17
+ }
18
+ #docsearch-desktop .DocSearch-Button {
19
+ background: transparent !important;
20
+ padding: 0 !important;
21
+ position: relative;
22
+ top: -1px;
23
+ outline: none !important;
24
+ border: none !important;
25
+ box-shadow: none !important;
26
+ }
27
+ #docsearch-desktop .DocSearch-Search-Icon {
28
+ height: 21px !important;
29
+ width: 21px !important;
30
+ }
31
+ #docsearch-desktop .DocSearch-Button {
32
+ margin-right: 3px !important;
33
+ margin-left: 1px !important;
34
+ }
@@ -0,0 +1,62 @@
1
+ export { getDocSearchCSS }
2
+ export { getDocSearchJS }
3
+
4
+ import { dangerouslySkipEscape, escapeInject } from 'vike/server'
5
+ import { PageContextResolved } from '../config/resolvePageContext'
6
+ /* Imorted in /src/css/index.css instead
7
+ import './DocSearch.css'
8
+ */
9
+
10
+ function getDocSearchCSS(pageContext: PageContextResolved) {
11
+ const docSearchCSS = !pageContext.meta.algolia
12
+ ? ''
13
+ : escapeInject`
14
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@docsearch/css@alpha" />
15
+ `
16
+ return docSearchCSS
17
+ }
18
+
19
+ function getDocSearchJS(pageContext: PageContextResolved) {
20
+ const { algolia } = pageContext.meta
21
+ // If the docpress website doesn't use algolia => we don't inject the algolia assets => the search icon wrapper stays empty
22
+ // If algolia is PENDING_APPROVAL => we fill a FAKE API key so that the algolia popup shows (while no results are shown).
23
+ // - We show an alert warning users that there aren't any results until algolia's approval is pending (see below).
24
+ let docSearchJS = !algolia
25
+ ? ''
26
+ : escapeInject`
27
+ <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/@docsearch/js@alpha"></script>
28
+ <script type="text/javascript">
29
+ const appId = '${algolia.appId || 'FAKE'}';
30
+ const apiKey = '${algolia.apiKey || 'FAKE'}';
31
+ const indexName = '${algolia.indexName || 'FAKE'}';
32
+ const transformItems = ${dangerouslySkipEscape(getTransformItems())};
33
+ docsearch({
34
+ container: '#docsearch-desktop',
35
+ appId, apiKey, indexName, transformItems,
36
+ insights: true,
37
+ });
38
+ </script>
39
+ `
40
+ if (algolia?.PENDING_APPROVAL) {
41
+ docSearchJS = escapeInject`
42
+ ${docSearchJS}
43
+ <script>document.getElementById('docsearch-desktop').addEventListener('click', () => window.alert("Algolia approval is pending: the search results may be empty until the approval process is completed."))</script>
44
+ `
45
+ }
46
+ return docSearchJS
47
+ }
48
+
49
+ // Remove superfluous hash '#page-content' from URLs pointing to whole pages
50
+ // - https://github.com/algolia/docsearch/issues/1801
51
+ // - https://discourse.algolia.com/t/how-to-avoid-hash-in-search-result-url/6486
52
+ // - https://discourse.algolia.com/t/docsearchs-transformdata-function-cannot-remove-hashes-from-result-urls/8487
53
+ function getTransformItems() {
54
+ return `function(hits) {
55
+ hits.map(hit => {
56
+ if (hit.url.indexOf('#page-content') > 0) {
57
+ hit.url = hit.url.replace('#page-content', '');
58
+ }
59
+ });
60
+ return hits;
61
+ }`
62
+ }
@@ -0,0 +1,36 @@
1
+ import { assert } from './utils/client'
2
+
3
+ autoScrollNav()
4
+
5
+ function autoScrollNav() {
6
+ const navigationEl = document.getElementById('navigation-content-main')
7
+ assert(navigationEl)
8
+ const href = window.location.pathname
9
+ const navLinks: HTMLElement[] = Array.from(navigationEl.querySelectorAll(`a[href="${href}"]`))
10
+ assert(navLinks.length <= 1, { navLinks, href })
11
+ const navLink = navLinks[0]
12
+ if (!navLink) return
13
+
14
+ /* Doesn't work: the scrolling is off by hundreds of px (I guess because this function runs too early while the page is still rendering)
15
+ const navigationContainerEl = document.getElementById("navigation-container")
16
+ const offset = navLink.offsetTop - (window.innerHeight / 2)
17
+ navigationContainerEl.scrollTop = offset
18
+ */
19
+
20
+ /* Doesn't work: scrollIntoView() still scrolls the main view
21
+ const overflowOriginal = document.documentElement.style.overflow
22
+ document.documentElement.style.overflow = 'hidden'
23
+ ...
24
+ document.documentElement.style.overflow = overflowOriginal
25
+ */
26
+
27
+ const scrollTopOriginal = document.documentElement.scrollTop
28
+ navLink.scrollIntoView({
29
+ // @ts-ignore https://github.com/microsoft/TypeScript/issues/46654
30
+ behavior: 'instant',
31
+ block: 'center',
32
+ inline: 'start'
33
+ })
34
+ // Avoid scrollIntoView() from scrolling the main view. Alternatively, we could use scrollIntoViewIfNeeded() (https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoViewIfNeeded) which doesn't scroll the main view but Firefox doesn't support it.
35
+ document.documentElement.scrollTop = scrollTopOriginal
36
+ }
@@ -0,0 +1,9 @@
1
+ .with-line-break_white-space code,
2
+ .with-line-break_break-word code {
3
+ white-space: break-spaces;
4
+ padding-right: 16px !important;
5
+ }
6
+ .with-line-break_break-word code {
7
+ word-wrap: break-word;
8
+ word-break: break-all;
9
+ }
@@ -0,0 +1,18 @@
1
+ export { CodeBlockTransformer }
2
+
3
+ import React from 'react'
4
+ import { assert } from '../utils/server'
5
+ /* Imorted in /src/css/index.css instead
6
+ import './CodeBlockTransformer.css'
7
+ */
8
+
9
+ type LineBreak = 'white-space' | 'break-word'
10
+
11
+ function CodeBlockTransformer({ children, lineBreak }: { children: React.ReactNode; lineBreak: LineBreak }) {
12
+ assert(
13
+ lineBreak === 'white-space' || lineBreak === 'break-word',
14
+ '`lineBreak` is currently the only use case for <CodeBlockTransformer>'
15
+ )
16
+ const className = `with-line-break_${lineBreak}` as const
17
+ return <div className={className}>{children}</div>
18
+ }
@@ -0,0 +1,7 @@
1
+ export { Comment }
2
+
3
+ import React from 'react'
4
+
5
+ function Comment({ children }: { children: React.ReactNode }) {
6
+ return <></>
7
+ }
@@ -0,0 +1,47 @@
1
+ export { Consulting, Consultants }
2
+
3
+ import React from 'react'
4
+ import iconPeople from '../icons/people.svg'
5
+ import { usePageContext } from '../renderer/usePageContext'
6
+ import { SupporterSection, SectionDescription, CallToAction } from './Supporters'
7
+ import { Maintainer } from './Contributors'
8
+ import { maintainers } from '../data/maintainersList'
9
+ import { Link } from './Link'
10
+ const consultingPageHref = '/consulting'
11
+
12
+ function Consulting() {
13
+ const pageContext = usePageContext()
14
+ const { projectInfo } = pageContext.config
15
+ const { projectName } = projectInfo
16
+ return (
17
+ <SupporterSection>
18
+ <CallToAction iconUrl={iconPeople} text="Consulting" href={consultingPageHref} />
19
+ <div></div>
20
+ <SectionDescription>
21
+ For questions and issues related to {projectName}, open a{' '}
22
+ <a href={projectInfo.githubDiscussions || projectInfo.githubIssues}>GitHub Discussion</a>. For advanced help or
23
+ help not directly related to {projectName}, the {projectName} team offers{' '}
24
+ <Link href={consultingPageHref} noBreadcrumb>
25
+ consulting
26
+ </Link>
27
+ .
28
+ </SectionDescription>
29
+ </SupporterSection>
30
+ )
31
+ }
32
+
33
+ function Consultants() {
34
+ return (
35
+ <SupporterSection>
36
+ <div style={{ display: 'flex', flexWrap: 'wrap', alignItems: 'end' }}>
37
+ {maintainers
38
+ .filter((maintainer) => {
39
+ return !!maintainer.consultingUrl
40
+ })
41
+ .map((maintainer, i) => (
42
+ <Maintainer maintainer={maintainer} key={i} />
43
+ ))}
44
+ </div>
45
+ </SupporterSection>
46
+ )
47
+ }
@@ -0,0 +1,113 @@
1
+ export { Contributors, Maintainer }
2
+
3
+ import React from 'react'
4
+ import { usePageContext } from '../renderer/usePageContext'
5
+ import { Supporter, SupporterSection, SectionDescription, Individuals, SupporterImg } from './Supporters'
6
+ import { maintainers } from '../data/maintainersList'
7
+ import { contributors } from 'vike-contributors' // sorted by number of contributions
8
+
9
+ function Contributors() {
10
+ const pageContext = usePageContext()
11
+ const { projectInfo } = pageContext.config
12
+ return (
13
+ <SupporterSection>
14
+ <SectionDescription>
15
+ {projectInfo.projectName} is built and maintained by passionate contributors.
16
+ </SectionDescription>
17
+ <div style={{ display: 'flex', flexWrap: 'wrap', justifyContent: 'space-evenly', alignItems: 'end' }}>
18
+ {maintainers.map((maintainer, i) => (
19
+ <Maintainer maintainer={maintainer} key={i} />
20
+ ))}
21
+ </div>
22
+ <Individuals>
23
+ {contributors
24
+ .filter((contributor) => {
25
+ return (
26
+ !contributor.login.includes('[bot]') && !maintainers.map((m) => m.username).includes(contributor.login)
27
+ )
28
+ })
29
+ .map((contributor, i) => (
30
+ <Supporter username={contributor.login} avatarUrl={contributor.avatarUrl} key={i} />
31
+ ))}
32
+ </Individuals>
33
+ </SupporterSection>
34
+ )
35
+ }
36
+
37
+ function Maintainer({ maintainer }: { maintainer: (typeof maintainers)[0] }) {
38
+ const marginHeight = 20
39
+ const marginWidth = 10
40
+ const imgSize = 50
41
+ const githubUrl = `https://github.com/${maintainer.username}`
42
+ return (
43
+ <div
44
+ style={{
45
+ borderRadius: 7,
46
+ borderWidth: 1,
47
+ borderStyle: 'solid',
48
+ borderColor: '#e0e0e0',
49
+ overflow: 'hidden',
50
+ width: 430,
51
+ maxWidth: `calc(100vw - 2 * var(--main-view-padding) - 2 * ${marginWidth}px)`,
52
+ margin: `${marginHeight}px ${marginWidth}px`,
53
+ display: 'flex',
54
+ flexWrap: 'wrap',
55
+ padding: 20,
56
+ gap: 20,
57
+ textAlign: 'left'
58
+ }}
59
+ >
60
+ <a href={githubUrl}>
61
+ <div style={{ width: imgSize, height: imgSize, borderRadius: imgSize / 2, overflow: 'hidden' }}>
62
+ <SupporterImg
63
+ username={maintainer.username}
64
+ avatarUrl={getAvatarUrl(maintainer)}
65
+ imgAlt={maintainer.firstName}
66
+ width={imgSize}
67
+ height={imgSize}
68
+ />
69
+ </div>
70
+ </a>
71
+ <div>
72
+ <b>{maintainer.firstName}</b> ·{' '}
73
+ <a href={githubUrl}>
74
+ <i style={{ fontSize: '.9em', color: '#505050' }}>{maintainer.username}</i>
75
+ </a>
76
+ {maintainer.consultingUrl ? (
77
+ <>
78
+ {' '}
79
+ ·{' '}
80
+ <a href={maintainer.consultingUrl}>
81
+ <b
82
+ style={{
83
+ fontSize: '.7em',
84
+ color: 'white',
85
+ backgroundColor: '#305090',
86
+ padding: '1px 5px 2px 5px',
87
+ verticalAlign: 'text-top',
88
+ borderRadius: 3
89
+ }}
90
+ >
91
+ consulting
92
+ </b>
93
+ </a>
94
+ </>
95
+ ) : null}
96
+ <ul style={{ fontSize: '.8em', paddingLeft: 15, marginTop: 5, marginBottom: 0 }}>
97
+ {maintainer.roles.map((role, i) => (
98
+ <li key={i}>{role}</li>
99
+ ))}
100
+ </ul>
101
+ </div>
102
+ </div>
103
+ )
104
+ }
105
+
106
+ function getAvatarUrl(maintainer: (typeof maintainers)[0]) {
107
+ for (const contributor of contributors) {
108
+ if (maintainer.username === contributor.login) {
109
+ return contributor.avatarUrl
110
+ }
111
+ }
112
+ throw new Error(`Maintainer ${maintainer.username} not found in contributors' list.`)
113
+ }
@@ -0,0 +1,18 @@
1
+ import React from 'react'
2
+ import { RepoLink } from './RepoLink'
3
+ import { Emoji } from '../utils/server'
4
+
5
+ export { EditPageNote }
6
+
7
+ function EditPageNote({ pageContext }: { pageContext: { urlPathname: string } }) {
8
+ const text = (
9
+ <>
10
+ <Emoji name="writing-hang" /> Edit this page
11
+ </>
12
+ )
13
+ return (
14
+ <div style={{ marginTop: 50 }}>
15
+ <RepoLink path={'/docs/pages' + pageContext.urlPathname + '/+Page.mdx'} text={text} editMode={true} />
16
+ </div>
17
+ )
18
+ }
@@ -0,0 +1,20 @@
1
+ import React from 'react'
2
+
3
+ export { HorizontalLine }
4
+
5
+ function HorizontalLine({ primary }: { primary?: true }) {
6
+ return (
7
+ <div className={'header-separator-line ' + (primary ? 'primary' : '')} style={{ textAlign: 'center' }}>
8
+ <hr
9
+ style={{
10
+ display: 'inline-block',
11
+ margin: 0,
12
+ border: 0,
13
+ borderTop: '1px solid #eee',
14
+ maxWidth: 500,
15
+ width: '80%'
16
+ }}
17
+ />
18
+ </div>
19
+ )
20
+ }
@@ -0,0 +1,11 @@
1
+ import React from 'react'
2
+ import { assert } from '../utils/server'
3
+
4
+ export { ImportMeta }
5
+
6
+ function ImportMeta({ prop }: { prop: string }) {
7
+ assert(!prop.startsWith('import'))
8
+ assert(!prop.startsWith('.'))
9
+ const text = 'imp' + 'ort.meta.' + prop
10
+ return <code>{text}</code>
11
+ }
@@ -0,0 +1,144 @@
1
+ export { Link }
2
+
3
+ import React from 'react'
4
+ import { isRepoLink, RepoLink } from './RepoLink'
5
+ import type { Heading, HeadingDetached } from '../types/Heading'
6
+ import type { PageContextResolved } from '../config/resolvePageContext'
7
+ import { usePageContext } from '../renderer/usePageContext'
8
+ import { assert, assertUsage, determineSectionTitle, determineSectionUrlHash } from '../utils/server'
9
+ import { parseTitle } from '../parseTitle'
10
+
11
+ function Link({
12
+ href,
13
+ text,
14
+ noBreadcrumb,
15
+ doNotInferSectionTitle,
16
+ children
17
+ }: {
18
+ href: string
19
+ text?: string | JSX.Element
20
+ noBreadcrumb?: true
21
+ doNotInferSectionTitle?: true
22
+ children?: React.ReactNode
23
+ }) {
24
+ assertUsage(
25
+ href.startsWith('/') || href.startsWith('#'),
26
+ `<Link href /> prop \`href==='${href}'\` but should start with '/' or '#'`
27
+ )
28
+ assertUsage(!text || !children, 'Cannot use both `text` or `children`')
29
+
30
+ if (isRepoLink(href)) {
31
+ return <RepoLink path={href} text={text} />
32
+ } else {
33
+ const pageContext = usePageContext()
34
+ return (
35
+ <a href={href}>{children || text || getLinkText({ href, noBreadcrumb, pageContext, doNotInferSectionTitle })}</a>
36
+ )
37
+ }
38
+ }
39
+
40
+ function getLinkText({
41
+ href,
42
+ noBreadcrumb,
43
+ pageContext,
44
+ doNotInferSectionTitle
45
+ }: {
46
+ href: string
47
+ noBreadcrumb: true | undefined
48
+ pageContext: PageContextResolved
49
+ doNotInferSectionTitle: true | undefined
50
+ }): string | JSX.Element {
51
+ let urlHash: string | null = null
52
+ let hrefWithoutHash: string = href
53
+ if (href.includes('#')) {
54
+ ;[hrefWithoutHash, urlHash] = href.split('#')
55
+ assert(hrefWithoutHash || urlHash)
56
+ }
57
+
58
+ let heading: Heading | HeadingDetached
59
+ let isLinkOnSamePage: boolean = false
60
+ if (hrefWithoutHash) {
61
+ heading = findHeading(hrefWithoutHash, pageContext)
62
+ if (heading.url === pageContext.urlPathname) {
63
+ isLinkOnSamePage = true
64
+ // heading !== pageContext.activeHeading because activeHeading is a different object holding on-this-page subheadings
65
+ heading = pageContext.activeHeading
66
+ }
67
+ } else {
68
+ assert(urlHash)
69
+ isLinkOnSamePage = true
70
+ heading = pageContext.activeHeading
71
+ }
72
+ assert(heading)
73
+ assert(isLinkOnSamePage === (heading.url === pageContext.urlPathname))
74
+ assert(isLinkOnSamePage === (heading.url === pageContext.activeHeading.url))
75
+ assert(isLinkOnSamePage === (heading === pageContext.activeHeading))
76
+
77
+ const breadcrumbParts: (string | JSX.Element)[] = []
78
+
79
+ if (heading.headingsBreadcrumb) {
80
+ breadcrumbParts.push(
81
+ ...(heading.headingsBreadcrumb ?? [])
82
+ .slice()
83
+ .reverse()
84
+ .map(({ title }) => title)
85
+ )
86
+ }
87
+
88
+ breadcrumbParts.push(heading.title)
89
+
90
+ if (urlHash) {
91
+ let sectionTitle: string | JSX.Element | undefined = undefined
92
+ assert(!urlHash.startsWith('#'))
93
+ if (isLinkOnSamePage) {
94
+ const pageHeading = findHeading(`#${urlHash}`, pageContext)
95
+ sectionTitle = pageHeading.title
96
+ } else if ('sectionTitles' in heading && heading.sectionTitles) {
97
+ heading.sectionTitles.forEach((title) => {
98
+ if (determineSectionUrlHash(title) === urlHash) {
99
+ sectionTitle = parseTitle(title)
100
+ }
101
+ })
102
+ }
103
+ if (!sectionTitle) {
104
+ assertUsage(
105
+ !doNotInferSectionTitle,
106
+ `Page section title not found for <Link href="\`${href}\`" doNotInferSectionTitle={true} />.`
107
+ )
108
+ sectionTitle = determineSectionTitle(href)
109
+ }
110
+ breadcrumbParts.push(sectionTitle)
111
+ }
112
+
113
+ {
114
+ if (noBreadcrumb || isLinkOnSamePage) {
115
+ return breadcrumbParts[breadcrumbParts.length - 1]
116
+ }
117
+ }
118
+
119
+ return (
120
+ <>
121
+ {breadcrumbParts.map((title, i) => {
122
+ const seperator = i === 0 ? <></> : ' > '
123
+ return (
124
+ <React.Fragment key={i}>
125
+ {seperator}
126
+ {title}
127
+ </React.Fragment>
128
+ )
129
+ })}
130
+ </>
131
+ )
132
+ }
133
+
134
+ function findHeading(href: string, pageContext: PageContextResolved): Heading | HeadingDetached {
135
+ assert(href.startsWith('/') || href.startsWith('#'))
136
+ const { headingsAll } = pageContext
137
+ const heading = headingsAll.find(({ url }) => href === url)
138
+ if (href.startsWith('#')) {
139
+ assertUsage(heading, `Couldn't find ${href} in ${pageContext.urlPathname}, does it exist?`)
140
+ } else {
141
+ assertUsage(heading, `Couldn't find heading for ${href}, did you define the heading for ${href}?`)
142
+ }
143
+ return heading
144
+ }