@brillout/docpress 0.5.40 → 0.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (146) hide show
  1. package/+config.ts +17 -0
  2. package/MobileHeader.tsx +68 -0
  3. package/PageLayout.css +42 -0
  4. package/PageLayout.tsx +39 -0
  5. package/algolia/DocSearch.css +34 -0
  6. package/algolia/DocSearch.ts +62 -0
  7. package/autoScrollNav.ts +36 -0
  8. package/components/CodeBlockTransformer.css +9 -0
  9. package/components/CodeBlockTransformer.tsx +18 -0
  10. package/components/Comment.tsx +7 -0
  11. package/components/Consulting.tsx +47 -0
  12. package/components/Contributors.tsx +113 -0
  13. package/components/EditPageNote.tsx +18 -0
  14. package/components/FeatureList/FeatureList.client.ts +66 -0
  15. package/{dist/components/features → components/FeatureList}/FeatureList.css +10 -2
  16. package/components/FeatureList/FeatureList.tsx +114 -0
  17. package/components/HorizontalLine.tsx +20 -0
  18. package/components/ImportMeta.tsx +11 -0
  19. package/components/Link.tsx +144 -0
  20. package/components/Note.css +54 -0
  21. package/components/Note.tsx +78 -0
  22. package/components/P.css +8 -0
  23. package/components/P.tsx +8 -0
  24. package/components/ReadingRecommendation.tsx +56 -0
  25. package/components/RepoLink.tsx +24 -0
  26. package/components/Sponsors/label.draft.svg +108 -0
  27. package/components/Sponsors.tsx +218 -0
  28. package/components/Supporters.tsx +136 -0
  29. package/components/index.ts +14 -0
  30. package/config/getConfig.ts +18 -0
  31. package/config/resolveConfig/resolveHeading.ts +0 -0
  32. package/config/resolvePageContext.ts +186 -0
  33. package/css/button.css +7 -0
  34. package/css/code/block.css +36 -0
  35. package/css/code/inline.css +27 -0
  36. package/css/code.css +20 -0
  37. package/css/colorize-on-hover.css +29 -0
  38. package/css/font.css +25 -0
  39. package/css/heading.css +45 -0
  40. package/css/index.css +12 -0
  41. package/css/link.css +17 -0
  42. package/css/reset.css +12 -0
  43. package/css/table.css +14 -0
  44. package/css/tooltip.css +11 -0
  45. package/data/maintainersList.tsx +92 -0
  46. package/data/sponsorsList.ts +147 -0
  47. package/dist/+config.d.ts +19 -0
  48. package/dist/+config.js +15 -0
  49. package/dist/markdownHeadingsVitePlugin.d.ts +13 -0
  50. package/dist/markdownHeadingsVitePlugin.js +170 -0
  51. package/dist/utils/assert.d.ts +6 -0
  52. package/dist/utils/assert.js +48 -0
  53. package/dist/utils/determineSectionUrlHash.d.ts +4 -0
  54. package/dist/utils/determineSectionUrlHash.js +38 -0
  55. package/dist/vite.config.d.ts +3 -0
  56. package/dist/vite.config.js +32 -0
  57. package/index.ts +4 -0
  58. package/installSectionUrlHashs.ts +60 -0
  59. package/markdownHeadingsVitePlugin.ts +150 -0
  60. package/navigation/Navigation-highlight.css +41 -0
  61. package/navigation/Navigation-items.css +119 -0
  62. package/navigation/Navigation-layout.css +127 -0
  63. package/navigation/Navigation.client.ts +43 -0
  64. package/navigation/Navigation.css +3 -0
  65. package/navigation/Navigation.tsx +211 -0
  66. package/navigation/NavigationHeader.tsx +111 -0
  67. package/navigation/navigation-fullscreen/NavigationFullscreenButton.css +32 -0
  68. package/navigation/navigation-fullscreen/NavigationFullscreenButton.tsx +44 -0
  69. package/navigation/navigation-fullscreen/initNavigationFullscreen.ts +116 -0
  70. package/package.json +38 -53
  71. package/parseEmojis.ts +35 -0
  72. package/parseTitle.ts +139 -0
  73. package/renderer/client.ts +4 -0
  74. package/renderer/onRenderHtml.tsx +69 -0
  75. package/renderer/usePageContext.tsx +25 -0
  76. package/tsconfig.config.json +7 -0
  77. package/tsconfig.json +15 -0
  78. package/types/Config.ts +46 -0
  79. package/types/Heading.ts +49 -0
  80. package/utils/Emoji/Emoji.ts +224 -0
  81. package/utils/Emoji/assets.ts +9 -0
  82. package/utils/Emoji/index.ts +1 -0
  83. package/utils/Emoji/mountain.svg +1 -0
  84. package/utils/assert.ts +51 -0
  85. package/utils/client.ts +2 -0
  86. package/utils/determineSectionUrlHash.ts +44 -0
  87. package/utils/filesystemPathHandling.ts +42 -0
  88. package/utils/filter.ts +12 -0
  89. package/utils/isBrowser.ts +5 -0
  90. package/utils/jsxToTextContent.ts +11 -0
  91. package/utils/objectAssign.ts +9 -0
  92. package/utils/server.ts +7 -0
  93. package/vite.config.ts +36 -0
  94. package/bin.js +0 -3
  95. package/dist/chunk-2ZTPUQGS.js +0 -58
  96. package/dist/chunk-3QC7HYIF.js +0 -7
  97. package/dist/chunk-MGOI4AFO.js +0 -165
  98. package/dist/chunk-NVJING6T.js +0 -91
  99. package/dist/chunk-QWL3MA4E.js +0 -171
  100. package/dist/chunk-UN23G34B.js +0 -157
  101. package/dist/cli/index.d.ts +0 -1
  102. package/dist/cli/index.js +0 -34
  103. package/dist/components/features/FeatureList.d.ts +0 -13
  104. package/dist/components/features/FeatureList.js +0 -7
  105. package/dist/components/features/initFeatureList.d.ts +0 -3
  106. package/dist/components/features/initFeatureList.js +0 -59
  107. package/dist/devServer-JKH6U5PF.js +0 -36
  108. package/dist/index.css +0 -120
  109. package/dist/index.d.ts +0 -221
  110. package/dist/index.js +0 -947
  111. package/dist/renderer/_default.page.client.css +0 -318
  112. package/dist/renderer/_default.page.client.d.ts +0 -1
  113. package/dist/renderer/_default.page.client.js +0 -218
  114. package/dist/renderer/_default.page.server.css +0 -310
  115. package/dist/renderer/_default.page.server.d.ts +0 -22
  116. package/dist/renderer/_default.page.server.js +0 -665
  117. package/readme.md +0 -5
  118. /package/{dist/chevron-R2IYJD62.svg → components/FeatureList/chevron.svg} +0 -0
  119. /package/{dist/label-MP75CTIA.svg → components/Sponsors/label.svg} +0 -0
  120. /package/{dist/medalBronze-CO4CTUR4.svg → components/Sponsors/medalBronze.svg} +0 -0
  121. /package/{dist/medalGold-UP6A73FL.svg → components/Sponsors/medalGold.svg} +0 -0
  122. /package/{dist/medalSilver-FAPGGOBN.svg → components/Sponsors/medalSilver.svg} +0 -0
  123. /package/{dist/Inter-Var-IOAEQULN.ttf → css/Inter-Var.ttf} +0 -0
  124. /package/{dist/alignable-B4QZV4X7.svg → data/sponsorsList/companyLogos/alignable.svg} +0 -0
  125. /package/{dist/bluefin-JQABZFGV.svg → data/sponsorsList/companyLogos/bluefin.svg} +0 -0
  126. /package/{dist/burdaforward-EUGURYZY.png → data/sponsorsList/companyLogos/burdaforward.png} +0 -0
  127. /package/{dist/contra-WLZBOPBV.svg → data/sponsorsList/companyLogos/contra.svg} +0 -0
  128. /package/{dist/ecosia-OYRLTR5T.svg → data/sponsorsList/companyLogos/ecosia.svg} +0 -0
  129. /package/{dist/inlang-GFRWND6X.png → data/sponsorsList/companyLogos/inlang.png} +0 -0
  130. /package/{dist/optimizers-SFEZF3NW.svg → data/sponsorsList/companyLogos/optimizers.svg} +0 -0
  131. /package/{dist/sourcegraph-YR2HADLS.svg → data/sponsorsList/companyLogos/sourcegraph.svg} +0 -0
  132. /package/{dist/changelog-IPI5F42D.svg → icons/changelog.svg} +0 -0
  133. /package/{dist/discord-JD33TUSF.svg → icons/discord.svg} +0 -0
  134. /package/{dist/github-P5ZSKN2N.svg → icons/github.svg} +0 -0
  135. /package/{dist/heart-OINVKOXO.svg → icons/heart.svg} +0 -0
  136. /package/{dist/languages-KXPKJFQL.svg → icons/languages.svg} +0 -0
  137. /package/{dist/people-72KKQHU4.svg → icons/people.svg} +0 -0
  138. /package/{dist/twitter-I7DXDN3J.svg → icons/twitter.svg} +0 -0
  139. /package/{dist/chevron-K3WPYLOP.svg → navigation/navigation-fullscreen/chevron.svg} +0 -0
  140. /package/{dist/close-IQXTDOHV.svg → navigation/navigation-fullscreen/close.svg} +0 -0
  141. /package/{dist/compass-2RWQU3E4.svg → utils/Emoji/compass.svg} +0 -0
  142. /package/{dist/engine-6Q6VSCVA.png → utils/Emoji/engine.png} +0 -0
  143. /package/{dist/mechanical-arm-TR7IQQMG.svg → utils/Emoji/mechanical-arm.svg} +0 -0
  144. /package/{dist/road-fork-3WZLW3HB.svg → utils/Emoji/road-fork.svg} +0 -0
  145. /package/{dist/shield-CU45RG5C.svg → utils/Emoji/shield.svg} +0 -0
  146. /package/{dist/typescript-ALIPKLRM.svg → utils/Emoji/typescript.svg} +0 -0
package/+config.ts ADDED
@@ -0,0 +1,17 @@
1
+ import type { Config } from 'vike/types'
2
+
3
+ export default {
4
+ // @ts-expect-error remove this @ts-expect-error once Vike's new version is released
5
+ name: '@brillout/docpress' ,
6
+ onRenderHtml: 'import:@brillout/docpress/renderer/onRenderHtml:onRenderHtml',
7
+ client: 'import:@brillout/docpress/renderer/client:doesNotExist',
8
+ meta: {
9
+ Page: {
10
+ env: { client: false, server: true }
11
+ },
12
+ // Vike already defines the setting 'name', but we redundantly define it here for older Vike versions (otherwise older Vike versions will complain that 'name` is an unknown config).
13
+ name: {
14
+ env: { config: true }
15
+ }
16
+ }
17
+ } satisfies Config
@@ -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,66 @@
1
+ import { assert } from '../../utils/client'
2
+
3
+ addTwitterWidgets()
4
+ addFeatureClickHandlers()
5
+ window.__docpress_hydrationFinished = true
6
+
7
+ function addTwitterWidgets() {
8
+ loadScript('https://platform.twitter.com/widgets.js')
9
+ }
10
+
11
+ function addFeatureClickHandlers() {
12
+ const featureEls: HTMLElement[] = Array.from(
13
+ document.getElementById('features')!.querySelectorAll('.feature.has-learn-more')
14
+ )
15
+ featureEls.forEach((featureEl) => {
16
+ featureEl.onclick = () => {
17
+ expandLearnMore(featureEl)
18
+ }
19
+ })
20
+ }
21
+
22
+ function expandLearnMore(featureEl: HTMLElement) {
23
+ const featureId = featureEl.id
24
+ assert(featureId.startsWith('feature-'), { featureId })
25
+ const featureName = featureId.slice('feature-'.length)
26
+
27
+ const selectedClass = 'selected'
28
+ const learnId = 'learn-more-' + featureName
29
+ const learnEl = document.getElementById(learnId)
30
+ assert(learnEl, { learnId })
31
+
32
+ const isExpanded = featureEl.classList.contains(selectedClass)
33
+
34
+ if (!isExpanded) {
35
+ const rowEl = featureEl.parentNode as HTMLElement
36
+ if (getComputedStyle(rowEl, 'display') === 'grid') {
37
+ ;[
38
+ ...(rowEl.querySelectorAll('.learn-more') as any as HTMLElement[]),
39
+ ...(rowEl.querySelectorAll('.feature') as any as HTMLElement[])
40
+ ].forEach((el) => {
41
+ el.classList.remove(selectedClass)
42
+ })
43
+ }
44
+ }
45
+
46
+ ;[featureEl, learnEl].forEach((el) => {
47
+ el.classList.toggle(selectedClass)
48
+ })
49
+ }
50
+
51
+ function loadScript(scriptUrl: string): void {
52
+ assert(scriptUrl.startsWith('https://'))
53
+ const scriptEl = document.createElement('script')
54
+ scriptEl.src = scriptUrl
55
+ scriptEl.async = true
56
+ scriptEl.setAttribute('charset', 'utf-8')
57
+ document.getElementsByTagName('head')[0].appendChild(scriptEl)
58
+ }
59
+
60
+ function getComputedStyle(el: HTMLElement, styleProp: string) {
61
+ return window.document.defaultView!.getComputedStyle(el).getPropertyValue(styleProp)
62
+ }
63
+
64
+ declare global {
65
+ var __docpress_hydrationFinished: undefined | true
66
+ }
@@ -1,4 +1,3 @@
1
- /* src/components/features/FeatureList.css */
2
1
  @media screen and (min-width: 840px) {
3
2
  .features-row {
4
3
  display: grid;
@@ -17,6 +16,7 @@
17
16
  grid-column: 1 / 3;
18
17
  }
19
18
  }
19
+
20
20
  @media screen and (min-width: 840px) {
21
21
  .features-row.single-column .feature {
22
22
  grid-column: 1 / span 2 !important;
@@ -25,11 +25,13 @@
25
25
  margin: auto !important;
26
26
  }
27
27
  }
28
+
28
29
  #features {
29
30
  margin: auto;
30
31
  margin-top: 0;
31
32
  max-width: 1080px;
32
33
  }
34
+
33
35
  #features summary p {
34
36
  margin: 10px 0;
35
37
  }
@@ -44,6 +46,7 @@
44
46
  .learn-more h3:first-of-type {
45
47
  margin-top: 15px;
46
48
  }
49
+
47
50
  .learn-more {
48
51
  border: var(--border-width) solid var(--border-color);
49
52
  padding: 10px 8px;
@@ -95,6 +98,8 @@ aside.learn-more.right-side {
95
98
  border-bottom: 0 !important;
96
99
  z-index: 1;
97
100
  }
101
+
102
+ /* Hide top border of .learn-more */
98
103
  .learn-more {
99
104
  position: relative;
100
105
  top: calc(-1 * var(--border-width));
@@ -103,8 +108,11 @@ aside.learn-more.right-side {
103
108
  position: relative;
104
109
  z-index: 1;
105
110
  }
111
+
106
112
  .feature .chevron {
107
- transition: filter 0.3s ease-in-out, transform 0.3s ease-in-out !important;
113
+ transition:
114
+ filter 0.3s ease-in-out,
115
+ transform 0.3s ease-in-out !important;
108
116
  }
109
117
  .feature.selected .chevron {
110
118
  transform: rotate(180deg);