@brillout/docpress 0.8.3 → 0.8.5
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 +4 -1
- package/Layout.tsx +36 -48
- package/MenuModal.tsx +39 -1
- package/components/EditPageNote.tsx +1 -2
- package/config/resolveHeadingsData.ts +16 -9
- package/config/resolvePageContext.ts +0 -2
- package/css/colorize-on-hover.css +15 -8
- package/css/heading.css +12 -6
- package/css/tooltip.css +28 -22
- package/dist/+config.d.ts +7 -0
- package/dist/+config.js +3 -0
- package/dist/config/resolveHeadingsData.d.ts +1 -4
- package/dist/config/resolveHeadingsData.js +13 -8
- package/dist/config/resolvePageContext.d.ts +1 -5
- package/dist/config/resolvePageContext.js +1 -2
- package/dist/types/Config.d.ts +0 -1
- package/dist/types/Heading.d.ts +0 -2
- package/docsearch/SearchLink.tsx +1 -1
- package/package.json +1 -1
- package/renderer/getPageElement.tsx +1 -4
- package/renderer/onRenderClient.tsx +1 -0
- package/renderer/onRenderHtml.tsx +1 -0
- package/types/Config.ts +0 -2
- package/types/Heading.ts +0 -2
- package/utils/PassTrough.tsx +7 -0
package/+config.ts
CHANGED
|
@@ -15,8 +15,10 @@ export default {
|
|
|
15
15
|
Layout: {
|
|
16
16
|
env: { client: true, server: true },
|
|
17
17
|
},
|
|
18
|
+
TopNavigation: {
|
|
19
|
+
env: { client: true, server: true },
|
|
20
|
+
},
|
|
18
21
|
},
|
|
19
|
-
|
|
20
22
|
prefetch: {
|
|
21
23
|
staticAssets: 'hover',
|
|
22
24
|
pageContext: Infinity,
|
|
@@ -32,6 +34,7 @@ declare global {
|
|
|
32
34
|
}
|
|
33
35
|
interface Config {
|
|
34
36
|
Layout?: ReactComponent | null | ImportString
|
|
37
|
+
TopNavigation?: ReactComponent
|
|
35
38
|
}
|
|
36
39
|
}
|
|
37
40
|
}
|
package/Layout.tsx
CHANGED
|
@@ -5,14 +5,15 @@ import React from 'react'
|
|
|
5
5
|
import { NavigationContent } from './navigation/Navigation'
|
|
6
6
|
import { EditPageNote } from './components/EditPageNote'
|
|
7
7
|
import { parseTitle } from './parseTitle'
|
|
8
|
-
import { usePageContext } from './renderer/usePageContext'
|
|
8
|
+
import { usePageContext, usePageContext2 } from './renderer/usePageContext'
|
|
9
9
|
import { Links } from './Links'
|
|
10
|
-
import {
|
|
10
|
+
import { toggleMenuModal } from './MenuModal'
|
|
11
11
|
import { MenuModal } from './MenuModal'
|
|
12
12
|
import { autoScrollNav_SSR } from './autoScrollNav'
|
|
13
13
|
import { SearchLink } from './docsearch/SearchLink'
|
|
14
14
|
import { navigate } from 'vike/client/router'
|
|
15
15
|
import { css } from './utils/css'
|
|
16
|
+
import { PassThrough } from './utils/PassTrough'
|
|
16
17
|
|
|
17
18
|
const mainViewWidthMax = 800
|
|
18
19
|
const mainViewPadding = 20
|
|
@@ -28,13 +29,13 @@ const mainViewMax = mainViewWidthMax + mainViewPadding * 2
|
|
|
28
29
|
const containerQuerySpacing = mainViewMax + navWidthMax + blockMargin
|
|
29
30
|
const containerQueryMobile = mainViewMax + navWidthMin
|
|
30
31
|
|
|
31
|
-
// Avoid
|
|
32
|
-
const
|
|
32
|
+
// Avoid whitespace at the bottom of pages with almost no content
|
|
33
|
+
const whitespaceBuster1: React.CSSProperties = {
|
|
33
34
|
minHeight: '100vh',
|
|
34
35
|
display: 'flex',
|
|
35
36
|
flexDirection: 'column',
|
|
36
37
|
}
|
|
37
|
-
const
|
|
38
|
+
const whitespaceBuster2: React.CSSProperties = {
|
|
38
39
|
flexGrow: 1,
|
|
39
40
|
}
|
|
40
41
|
|
|
@@ -50,21 +51,26 @@ function Layout({ children }: { children: React.ReactNode }) {
|
|
|
50
51
|
}
|
|
51
52
|
|
|
52
53
|
return (
|
|
53
|
-
|
|
54
|
+
<div
|
|
55
|
+
style={{
|
|
56
|
+
['--bg-color']: '#f5f5f7',
|
|
57
|
+
['--block-margin']: `${blockMargin}px`,
|
|
58
|
+
['--icon-text-padding']: '8px',
|
|
59
|
+
}}
|
|
60
|
+
>
|
|
61
|
+
<MenuModal />
|
|
54
62
|
<div
|
|
55
63
|
className={isLandingPage ? '' : 'doc-page'}
|
|
56
64
|
style={{
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
...
|
|
65
|
+
// We don't add `container` to `body` nor `html` beacuse in Firefox it breaks the `position: fixed` of <MenuModal>
|
|
66
|
+
// https://stackoverflow.com/questions/74601420/css-container-inline-size-and-fixed-child
|
|
67
|
+
containerType: 'inline-size',
|
|
68
|
+
...whitespaceBuster1,
|
|
61
69
|
}}
|
|
62
70
|
>
|
|
63
71
|
{content}
|
|
64
|
-
<MenuModal />
|
|
65
72
|
</div>
|
|
66
|
-
|
|
67
|
-
</>
|
|
73
|
+
</div>
|
|
68
74
|
)
|
|
69
75
|
}
|
|
70
76
|
|
|
@@ -75,7 +81,7 @@ function LayoutDocsPage({ children }: { children: React.ReactNode }) {
|
|
|
75
81
|
<>
|
|
76
82
|
<style>{getStyle()}</style>
|
|
77
83
|
<NavMobile />
|
|
78
|
-
<div style={{ display: 'flex', ...
|
|
84
|
+
<div style={{ display: 'flex', ...whitespaceBuster2 }}>
|
|
79
85
|
<NavLeft />
|
|
80
86
|
<div className="low-prio-grow" style={{ width: 0, maxWidth: 50, background: 'var(--bg-color)' }} />
|
|
81
87
|
<PageContent>{children}</PageContent>
|
|
@@ -190,16 +196,16 @@ function PageContent({ children }: { children: React.ReactNode }) {
|
|
|
190
196
|
function NavMobile() {
|
|
191
197
|
return (
|
|
192
198
|
<div id="nav-mobile">
|
|
193
|
-
<NavigationHeader headerHeight={
|
|
199
|
+
<NavigationHeader headerHeight={70} iconSize={40} paddingLeft={12} style={{ justifyContent: 'center' }} />
|
|
194
200
|
</div>
|
|
195
201
|
)
|
|
196
202
|
}
|
|
197
203
|
|
|
198
204
|
function NavTop() {
|
|
199
|
-
const
|
|
200
|
-
const { topNavigationList, topNavigationStyle } = pageContext
|
|
205
|
+
const pageContext2 = usePageContext2()
|
|
201
206
|
const paddingSize = 35
|
|
202
207
|
const padding = `0 ${paddingSize}px`
|
|
208
|
+
const TopNavigation = pageContext2.config.TopNavigation || PassThrough
|
|
203
209
|
return (
|
|
204
210
|
<div
|
|
205
211
|
id="top-navigation"
|
|
@@ -212,30 +218,13 @@ function NavTop() {
|
|
|
212
218
|
textDecoration: 'none',
|
|
213
219
|
marginBottom: 'var(--block-margin)',
|
|
214
220
|
backgroundColor: 'var(--bg-color)',
|
|
221
|
+
['--padding-side']: `${paddingSize}px`,
|
|
215
222
|
fontSize: '1.06em',
|
|
216
223
|
color: '#666',
|
|
217
|
-
...topNavigationStyle,
|
|
218
224
|
}}
|
|
219
225
|
>
|
|
220
226
|
<div style={{ display: 'flex', alignItems: 'center', height: 70 }}>
|
|
221
|
-
|
|
222
|
-
<a
|
|
223
|
-
href={url!}
|
|
224
|
-
key={url}
|
|
225
|
-
style={{
|
|
226
|
-
color: 'inherit',
|
|
227
|
-
height: '100%',
|
|
228
|
-
display: 'inline-flex',
|
|
229
|
-
alignItems: 'center',
|
|
230
|
-
justifyContent: 'center',
|
|
231
|
-
cursor: 'pointer',
|
|
232
|
-
padding,
|
|
233
|
-
marginRight: 7,
|
|
234
|
-
}}
|
|
235
|
-
>
|
|
236
|
-
{title}
|
|
237
|
-
</a>
|
|
238
|
-
))}
|
|
227
|
+
<TopNavigation />
|
|
239
228
|
<SearchLink style={{ padding }} />
|
|
240
229
|
<MenuLink style={{ padding }} />
|
|
241
230
|
<Links style={{ display: 'inline-flex', padding, marginLeft: -8 }} />
|
|
@@ -248,7 +237,6 @@ function NavLeft() {
|
|
|
248
237
|
const pageContext = usePageContext()
|
|
249
238
|
const { navItems, navItemsAll, isDetachedPage } = pageContext
|
|
250
239
|
const headerHeight = 60
|
|
251
|
-
const headerPadding = 10
|
|
252
240
|
return (
|
|
253
241
|
<>
|
|
254
242
|
<div
|
|
@@ -265,7 +253,7 @@ function NavLeft() {
|
|
|
265
253
|
top: 0,
|
|
266
254
|
}}
|
|
267
255
|
>
|
|
268
|
-
<NavigationHeader {
|
|
256
|
+
<NavigationHeader headerHeight={headerHeight} iconSize={39} paddingLeft={6} />
|
|
269
257
|
<div
|
|
270
258
|
style={{
|
|
271
259
|
backgroundColor: 'var(--bg-color)',
|
|
@@ -304,11 +292,11 @@ function NavLeft() {
|
|
|
304
292
|
|
|
305
293
|
function NavigationHeader({
|
|
306
294
|
headerHeight,
|
|
307
|
-
|
|
295
|
+
iconSize,
|
|
308
296
|
style,
|
|
309
|
-
|
|
297
|
+
paddingLeft,
|
|
298
|
+
}: { headerHeight: number; iconSize: number; paddingLeft: number; style?: React.CSSProperties }) {
|
|
310
299
|
const pageContext = usePageContext()
|
|
311
|
-
const iconSize = headerHeight - 2 * headerPadding
|
|
312
300
|
/*
|
|
313
301
|
const {projectName} = pageContext.meta
|
|
314
302
|
/*/
|
|
@@ -318,8 +306,9 @@ function NavigationHeader({
|
|
|
318
306
|
const childrenStyle: React.CSSProperties = {
|
|
319
307
|
justifyContent: 'center',
|
|
320
308
|
fontSize: isProjectNameShort ? '4.8cqw' : '4.5cqw',
|
|
321
|
-
['--icon-padding']: '1.8cqw',
|
|
309
|
+
['--icon-text-padding']: '1.8cqw',
|
|
322
310
|
}
|
|
311
|
+
const marginLeft = -10
|
|
323
312
|
return (
|
|
324
313
|
<div
|
|
325
314
|
style={{
|
|
@@ -345,9 +334,8 @@ function NavigationHeader({
|
|
|
345
334
|
color: 'inherit',
|
|
346
335
|
textDecoration: 'none',
|
|
347
336
|
height: '100%',
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
marginLeft: -10,
|
|
337
|
+
paddingLeft: paddingLeft + marginLeft * -1,
|
|
338
|
+
marginLeft: marginLeft,
|
|
351
339
|
...childrenStyle,
|
|
352
340
|
justifyContent: 'flex-start',
|
|
353
341
|
flexGrow: 0.5,
|
|
@@ -367,8 +355,8 @@ function NavigationHeader({
|
|
|
367
355
|
/>
|
|
368
356
|
<span
|
|
369
357
|
style={{
|
|
370
|
-
marginLeft: `calc(var(--icon-padding) + 2px)`,
|
|
371
|
-
fontSize: isProjectNameShort ? '1.
|
|
358
|
+
marginLeft: `calc(var(--icon-text-padding) + 2px)`,
|
|
359
|
+
fontSize: isProjectNameShort ? '1.65em' : '1.3em',
|
|
372
360
|
}}
|
|
373
361
|
>
|
|
374
362
|
{projectName}
|
|
@@ -420,7 +408,7 @@ function MenuLink(props: PropsAnchor) {
|
|
|
420
408
|
function MenuIcon() {
|
|
421
409
|
return (
|
|
422
410
|
<svg
|
|
423
|
-
style={{ marginRight: 'calc(var(--icon-padding) + 2px)', lineHeight: 0, width: '1.3em' }}
|
|
411
|
+
style={{ marginRight: 'calc(var(--icon-text-padding) + 2px)', lineHeight: 0, width: '1.3em' }}
|
|
424
412
|
className="decolorize-6"
|
|
425
413
|
viewBox="0 0 448 512"
|
|
426
414
|
>
|
package/MenuModal.tsx
CHANGED
|
@@ -8,6 +8,9 @@ import { NavigationContent } from './navigation/Navigation'
|
|
|
8
8
|
import { css } from './utils/css'
|
|
9
9
|
import { containerQueryMobile } from './Layout'
|
|
10
10
|
import { Links } from './Links'
|
|
11
|
+
import { isBrowser } from './utils/isBrowser'
|
|
12
|
+
|
|
13
|
+
initCloseListeners()
|
|
11
14
|
|
|
12
15
|
function MenuModal() {
|
|
13
16
|
return (
|
|
@@ -19,7 +22,14 @@ function MenuModal() {
|
|
|
19
22
|
style={{
|
|
20
23
|
position: 'fixed',
|
|
21
24
|
width: '100%',
|
|
25
|
+
/* Do this once Firefox supports `dvh`: https://caniuse.com/?search=dvh
|
|
26
|
+
* - Then also replace all `vh` values with `dvh` values.
|
|
27
|
+
* - https://stackoverflow.com/questions/37112218/css3-100vh-not-constant-in-mobile-browser/72245072#72245072
|
|
28
|
+
height: '100dh',
|
|
29
|
+
/*/
|
|
22
30
|
height: '100vh',
|
|
31
|
+
maxHeight: '100dvh',
|
|
32
|
+
//*/
|
|
23
33
|
top: 0,
|
|
24
34
|
left: 0,
|
|
25
35
|
zIndex: 9999,
|
|
@@ -32,8 +42,10 @@ function MenuModal() {
|
|
|
32
42
|
// Place <LinksBottom /> to the bottom
|
|
33
43
|
display: 'flex',
|
|
34
44
|
flexDirection: 'column',
|
|
35
|
-
minHeight: '
|
|
45
|
+
minHeight: '100dvh',
|
|
36
46
|
justifyContent: 'space-between',
|
|
47
|
+
// We don't set `container` to parent beacuse of a Chrome bug (showing a blank <MenuModal>)
|
|
48
|
+
containerType: 'inline-size',
|
|
37
49
|
}}
|
|
38
50
|
>
|
|
39
51
|
<Nav />
|
|
@@ -136,3 +148,29 @@ function autoScroll() {
|
|
|
136
148
|
function closeMenuModal() {
|
|
137
149
|
document.documentElement.classList.remove('menu-modal-show')
|
|
138
150
|
}
|
|
151
|
+
|
|
152
|
+
function initCloseListeners() {
|
|
153
|
+
if (!isBrowser()) return
|
|
154
|
+
document.addEventListener('click', onLinkClick)
|
|
155
|
+
// It's redundant (and onLinkClick() is enough), but just to be sure.
|
|
156
|
+
addEventListener('hashchange', closeMenuModal)
|
|
157
|
+
}
|
|
158
|
+
function onLinkClick(ev: MouseEvent) {
|
|
159
|
+
if (ev.altKey || ev.ctrlKey || ev.metaKey || ev.shiftKey) return
|
|
160
|
+
const linkTag = findLinkTag(ev.target as HTMLElement)
|
|
161
|
+
if (!linkTag) return
|
|
162
|
+
const href = linkTag.getAttribute('href')
|
|
163
|
+
if (!href) return
|
|
164
|
+
if (!href.startsWith('/') && !href.startsWith('#')) return
|
|
165
|
+
closeMenuModal()
|
|
166
|
+
}
|
|
167
|
+
function findLinkTag(target: HTMLElement): null | HTMLElement {
|
|
168
|
+
while (target.tagName !== 'A') {
|
|
169
|
+
const { parentNode } = target
|
|
170
|
+
if (!parentNode) {
|
|
171
|
+
return null
|
|
172
|
+
}
|
|
173
|
+
target = parentNode as HTMLElement
|
|
174
|
+
}
|
|
175
|
+
return target
|
|
176
|
+
}
|
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
import React from 'react'
|
|
2
2
|
import { RepoLink } from './RepoLink'
|
|
3
|
-
import { Emoji } from '../utils/server'
|
|
4
3
|
|
|
5
4
|
export { EditPageNote }
|
|
6
5
|
|
|
7
6
|
function EditPageNote({ pageContext }: { pageContext: { urlPathname: string } }) {
|
|
8
7
|
const text = (
|
|
9
8
|
<>
|
|
10
|
-
<
|
|
9
|
+
<span style={{ fontFamily: 'emoji' }}>✍</span> Edit this page
|
|
11
10
|
</>
|
|
12
11
|
)
|
|
13
12
|
return (
|
|
@@ -37,7 +37,11 @@ function resolveHeadingsData(pageContext: PageContextOriginal) {
|
|
|
37
37
|
const { headingsDetachedResolved } = resolved
|
|
38
38
|
let { headingsResolved } = resolved
|
|
39
39
|
|
|
40
|
-
const { activeHeading, isDetachedPage } = getActiveHeading(
|
|
40
|
+
const { activeHeading, isDetachedPage, activeCategory } = getActiveHeading(
|
|
41
|
+
headingsResolved,
|
|
42
|
+
headingsDetachedResolved,
|
|
43
|
+
pageContext,
|
|
44
|
+
)
|
|
41
45
|
|
|
42
46
|
const { documentTitle, isLandingPage, pageTitle } = getTitles(activeHeading, pageContext, config)
|
|
43
47
|
|
|
@@ -72,10 +76,6 @@ function resolveHeadingsData(pageContext: PageContextOriginal) {
|
|
|
72
76
|
}
|
|
73
77
|
}
|
|
74
78
|
|
|
75
|
-
const topNavigationList = headingsResolved
|
|
76
|
-
.filter((heading) => heading.topNavigation)
|
|
77
|
-
.map((h) => ({ title: typeof h.topNavigation === 'string' ? h.topNavigation : h.title, url: h.url }))
|
|
78
|
-
|
|
79
79
|
const pageContextAddendum = {
|
|
80
80
|
isDetachedPage,
|
|
81
81
|
navItems,
|
|
@@ -84,9 +84,10 @@ function resolveHeadingsData(pageContext: PageContextOriginal) {
|
|
|
84
84
|
isLandingPage,
|
|
85
85
|
pageTitle,
|
|
86
86
|
documentTitle,
|
|
87
|
-
topNavigationList,
|
|
88
87
|
// TODO: don't pass to client-side
|
|
89
88
|
columnLayouts,
|
|
89
|
+
// TODO: don't pass to client-side
|
|
90
|
+
activeCategory,
|
|
90
91
|
}
|
|
91
92
|
return pageContextAddendum
|
|
92
93
|
}
|
|
@@ -153,14 +154,20 @@ function getActiveHeading(
|
|
|
153
154
|
pageContext: { urlPathname: string; exports: Exports },
|
|
154
155
|
) {
|
|
155
156
|
let activeHeading: HeadingResolved | HeadingDetachedResolved | null = null
|
|
157
|
+
let activeCategory: string | undefined
|
|
156
158
|
const { urlPathname } = pageContext
|
|
157
159
|
assert(urlPathname)
|
|
158
|
-
|
|
160
|
+
for (const heading of headingsResolved) {
|
|
161
|
+
if (heading.level === 1) {
|
|
162
|
+
activeCategory = heading.title
|
|
163
|
+
}
|
|
159
164
|
if (heading.url === urlPathname) {
|
|
160
165
|
activeHeading = heading
|
|
166
|
+
assert(activeCategory)
|
|
161
167
|
assert(heading.level === 2, { pageUrl: urlPathname, heading })
|
|
168
|
+
break
|
|
162
169
|
}
|
|
163
|
-
}
|
|
170
|
+
}
|
|
164
171
|
const isDetachedPage = !activeHeading
|
|
165
172
|
if (!activeHeading) {
|
|
166
173
|
activeHeading = headingsDetachedResolved.find(({ url }) => urlPathname === url) ?? null
|
|
@@ -178,7 +185,7 @@ function getActiveHeading(
|
|
|
178
185
|
].join('\n'),
|
|
179
186
|
)
|
|
180
187
|
}
|
|
181
|
-
return { activeHeading, isDetachedPage }
|
|
188
|
+
return { activeHeading, isDetachedPage, activeCategory }
|
|
182
189
|
}
|
|
183
190
|
|
|
184
191
|
function getPageSectionsResolved(
|
|
@@ -30,7 +30,6 @@ function resolvePageContext(pageContext: PageContextOriginal) {
|
|
|
30
30
|
twitterHandle,
|
|
31
31
|
bannerUrl,
|
|
32
32
|
websiteUrl,
|
|
33
|
-
topNavigationStyle,
|
|
34
33
|
projectInfo: { projectName },
|
|
35
34
|
} = config
|
|
36
35
|
objectAssign(pageContextResolved, {
|
|
@@ -44,7 +43,6 @@ function resolvePageContext(pageContext: PageContextOriginal) {
|
|
|
44
43
|
tagline,
|
|
45
44
|
algolia,
|
|
46
45
|
},
|
|
47
|
-
topNavigationStyle,
|
|
48
46
|
config,
|
|
49
47
|
})
|
|
50
48
|
|
|
@@ -1,11 +1,22 @@
|
|
|
1
|
+
/* `@media (pointer: fine)`
|
|
2
|
+
* - Don't show tooltip on mobile devices:
|
|
3
|
+
* - https://stackoverflow.com/questions/23885255/how-to-remove-ignore-hover-css-style-on-touch-devices/64553121#64553121
|
|
4
|
+
*/
|
|
5
|
+
@media (hover: hover) and (pointer: fine) {
|
|
6
|
+
.colorize-on-hover:hover [class^='decolorize-'],
|
|
7
|
+
.colorize-on-hover:hover [class*=' decolorize-'] {
|
|
8
|
+
filter: grayscale(0) opacity(1) !important;
|
|
9
|
+
}
|
|
10
|
+
.link-hover-animation a:hover {
|
|
11
|
+
color: black !important;
|
|
12
|
+
background-color: var(--active-color);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
1
16
|
.colorize-on-hover [class^='decolorize-'],
|
|
2
17
|
.colorize-on-hover [class*=' decolorize-'] {
|
|
3
18
|
transition: filter 0.3s ease-in-out;
|
|
4
19
|
}
|
|
5
|
-
.colorize-on-hover:hover [class^='decolorize-'],
|
|
6
|
-
.colorize-on-hover:hover [class*=' decolorize-'] {
|
|
7
|
-
filter: grayscale(0) opacity(1) !important;
|
|
8
|
-
}
|
|
9
20
|
|
|
10
21
|
.decolorize-7 {
|
|
11
22
|
filter: grayscale(1) opacity(0.7);
|
|
@@ -24,10 +35,6 @@
|
|
|
24
35
|
transition: all 0.3s ease-in-out !important;
|
|
25
36
|
transition-property: color, background-color !important;
|
|
26
37
|
}
|
|
27
|
-
.link-hover-animation a:hover {
|
|
28
|
-
color: black !important;
|
|
29
|
-
background-color: var(--active-color);
|
|
30
|
-
}
|
|
31
38
|
body {
|
|
32
39
|
--active-color: rgba(0, 0, 0, 0.03);
|
|
33
40
|
}
|
package/css/heading.css
CHANGED
|
@@ -62,10 +62,16 @@ h3 { font-size: 1.25em }
|
|
|
62
62
|
padding-left: 26px;
|
|
63
63
|
margin-left: -26px;
|
|
64
64
|
}
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
65
|
+
/* `@media (pointer: fine)`
|
|
66
|
+
* - Don't show tooltip on mobile devices:
|
|
67
|
+
* - https://stackoverflow.com/questions/23885255/how-to-remove-ignore-hover-css-style-on-touch-devices/64553121#64553121
|
|
68
|
+
*/
|
|
69
|
+
@media (hover: hover) and (pointer: fine) {
|
|
70
|
+
.doc-page h2[id]:hover::before,
|
|
71
|
+
.doc-page h3[id]:hover::before {
|
|
72
|
+
content: '#';
|
|
73
|
+
position: absolute;
|
|
74
|
+
left: calc(-1 * (0.75em - 26px));
|
|
75
|
+
color: #aaa;
|
|
76
|
+
}
|
|
71
77
|
}
|
package/css/tooltip.css
CHANGED
|
@@ -1,23 +1,29 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
1
|
+
/* `@media (pointer: fine)`
|
|
2
|
+
* - Don't show tooltip on mobile devices:
|
|
3
|
+
* - https://stackoverflow.com/questions/23885255/how-to-remove-ignore-hover-css-style-on-touch-devices/64553121#64553121
|
|
4
|
+
*/
|
|
5
|
+
@media (hover: hover) and (pointer: fine) {
|
|
6
|
+
[aria-label] {
|
|
7
|
+
position: relative;
|
|
8
|
+
}
|
|
9
|
+
[aria-label]:hover::before {
|
|
10
|
+
font-family: monospace;
|
|
11
|
+
font-size: 12px;
|
|
12
|
+
content: attr(aria-label);
|
|
13
|
+
position: absolute;
|
|
14
|
+
top: 100%;
|
|
15
|
+
left: 50%;
|
|
16
|
+
transform: translate(-50%, 0);
|
|
17
|
+
margin-top: 5px;
|
|
18
|
+
background: #fdfdfd;
|
|
19
|
+
padding: 3px 10px;
|
|
20
|
+
box-shadow: rgb(0 0 0 / 8%) 2px 4px 7px 0px;
|
|
21
|
+
border-radius: 5px;
|
|
22
|
+
color: #333;
|
|
23
|
+
letter-spacing: -0.02em;
|
|
24
|
+
border: 1px solid #e3e3e3;
|
|
25
|
+
}
|
|
26
|
+
[data-label-shift]::before {
|
|
27
|
+
margin-left: -10px;
|
|
28
|
+
}
|
|
23
29
|
}
|
package/dist/+config.d.ts
CHANGED
|
@@ -16,6 +16,12 @@ declare const _default: {
|
|
|
16
16
|
server: true;
|
|
17
17
|
};
|
|
18
18
|
};
|
|
19
|
+
TopNavigation: {
|
|
20
|
+
env: {
|
|
21
|
+
client: true;
|
|
22
|
+
server: true;
|
|
23
|
+
};
|
|
24
|
+
};
|
|
19
25
|
};
|
|
20
26
|
prefetch: {
|
|
21
27
|
staticAssets: "hover";
|
|
@@ -32,6 +38,7 @@ declare global {
|
|
|
32
38
|
}
|
|
33
39
|
interface Config {
|
|
34
40
|
Layout?: ReactComponent | null | ImportString;
|
|
41
|
+
TopNavigation?: ReactComponent;
|
|
35
42
|
}
|
|
36
43
|
}
|
|
37
44
|
}
|
package/dist/+config.js
CHANGED
|
@@ -10,9 +10,6 @@ declare function resolveHeadingsData(pageContext: PageContextOriginal): {
|
|
|
10
10
|
isLandingPage: boolean;
|
|
11
11
|
pageTitle: string | null;
|
|
12
12
|
documentTitle: string;
|
|
13
|
-
topNavigationList: {
|
|
14
|
-
title: string;
|
|
15
|
-
url: string | null | undefined;
|
|
16
|
-
}[];
|
|
17
13
|
columnLayouts: number[][];
|
|
14
|
+
activeCategory: string | undefined;
|
|
18
15
|
};
|
|
@@ -34,7 +34,7 @@ function resolveHeadingsData(pageContext) {
|
|
|
34
34
|
var resolved = getHeadingsResolved(config);
|
|
35
35
|
var headingsDetachedResolved = resolved.headingsDetachedResolved;
|
|
36
36
|
var headingsResolved = resolved.headingsResolved;
|
|
37
|
-
var _a = getActiveHeading(headingsResolved, headingsDetachedResolved, pageContext), activeHeading = _a.activeHeading, isDetachedPage = _a.isDetachedPage;
|
|
37
|
+
var _a = getActiveHeading(headingsResolved, headingsDetachedResolved, pageContext), activeHeading = _a.activeHeading, isDetachedPage = _a.isDetachedPage, activeCategory = _a.activeCategory;
|
|
38
38
|
var _b = getTitles(activeHeading, pageContext, config), documentTitle = _b.documentTitle, isLandingPage = _b.isLandingPage, pageTitle = _b.pageTitle;
|
|
39
39
|
var pageSectionsResolved = getPageSectionsResolved(pageContext, activeHeading);
|
|
40
40
|
var linksAll = __spreadArray(__spreadArray(__spreadArray([], pageSectionsResolved.map(pageSectionToLinkData), true), headingsResolved.map(headingToLinkData), true), headingsDetachedResolved.map(headingToLinkData), true);
|
|
@@ -61,9 +61,6 @@ function resolveHeadingsData(pageContext) {
|
|
|
61
61
|
});
|
|
62
62
|
}
|
|
63
63
|
}
|
|
64
|
-
var topNavigationList = headingsResolved
|
|
65
|
-
.filter(function (heading) { return heading.topNavigation; })
|
|
66
|
-
.map(function (h) { return ({ title: typeof h.topNavigation === 'string' ? h.topNavigation : h.title, url: h.url }); });
|
|
67
64
|
var pageContextAddendum = {
|
|
68
65
|
isDetachedPage: isDetachedPage,
|
|
69
66
|
navItems: navItems,
|
|
@@ -72,9 +69,10 @@ function resolveHeadingsData(pageContext) {
|
|
|
72
69
|
isLandingPage: isLandingPage,
|
|
73
70
|
pageTitle: pageTitle,
|
|
74
71
|
documentTitle: documentTitle,
|
|
75
|
-
topNavigationList: topNavigationList,
|
|
76
72
|
// TODO: don't pass to client-side
|
|
77
73
|
columnLayouts: columnLayouts,
|
|
74
|
+
// TODO: don't pass to client-side
|
|
75
|
+
activeCategory: activeCategory,
|
|
78
76
|
};
|
|
79
77
|
return pageContextAddendum;
|
|
80
78
|
}
|
|
@@ -127,14 +125,21 @@ function getTitles(activeHeading, pageContext, config) {
|
|
|
127
125
|
function getActiveHeading(headingsResolved, headingsDetachedResolved, pageContext) {
|
|
128
126
|
var _a;
|
|
129
127
|
var activeHeading = null;
|
|
128
|
+
var activeCategory;
|
|
130
129
|
var urlPathname = pageContext.urlPathname;
|
|
131
130
|
assert(urlPathname);
|
|
132
|
-
headingsResolved.
|
|
131
|
+
for (var _i = 0, headingsResolved_1 = headingsResolved; _i < headingsResolved_1.length; _i++) {
|
|
132
|
+
var heading = headingsResolved_1[_i];
|
|
133
|
+
if (heading.level === 1) {
|
|
134
|
+
activeCategory = heading.title;
|
|
135
|
+
}
|
|
133
136
|
if (heading.url === urlPathname) {
|
|
134
137
|
activeHeading = heading;
|
|
138
|
+
assert(activeCategory);
|
|
135
139
|
assert(heading.level === 2, { pageUrl: urlPathname, heading: heading });
|
|
140
|
+
break;
|
|
136
141
|
}
|
|
137
|
-
}
|
|
142
|
+
}
|
|
138
143
|
var isDetachedPage = !activeHeading;
|
|
139
144
|
if (!activeHeading) {
|
|
140
145
|
activeHeading = (_a = headingsDetachedResolved.find(function (_a) {
|
|
@@ -152,7 +157,7 @@ function getActiveHeading(headingsResolved, headingsDetachedResolved, pageContex
|
|
|
152
157
|
.join('\n'),
|
|
153
158
|
].join('\n'));
|
|
154
159
|
}
|
|
155
|
-
return { activeHeading: activeHeading, isDetachedPage: isDetachedPage };
|
|
160
|
+
return { activeHeading: activeHeading, isDetachedPage: isDetachedPage, activeCategory: activeCategory };
|
|
156
161
|
}
|
|
157
162
|
function getPageSectionsResolved(pageContext, activeHeading) {
|
|
158
163
|
var _a;
|
|
@@ -17,11 +17,8 @@ declare function resolvePageContext(pageContext: PageContextOriginal): {
|
|
|
17
17
|
isLandingPage: boolean;
|
|
18
18
|
pageTitle: string | null;
|
|
19
19
|
documentTitle: string;
|
|
20
|
-
topNavigationList: {
|
|
21
|
-
title: string;
|
|
22
|
-
url: string | null | undefined;
|
|
23
|
-
}[];
|
|
24
20
|
columnLayouts: number[][];
|
|
21
|
+
activeCategory: string | undefined;
|
|
25
22
|
} & {
|
|
26
23
|
urlPathname: string;
|
|
27
24
|
meta: {
|
|
@@ -37,6 +34,5 @@ declare function resolvePageContext(pageContext: PageContextOriginal): {
|
|
|
37
34
|
indexName: string;
|
|
38
35
|
} | null;
|
|
39
36
|
};
|
|
40
|
-
topNavigationStyle: import("react").CSSProperties | undefined;
|
|
41
37
|
config: import("../types/Config").Config;
|
|
42
38
|
};
|
|
@@ -6,7 +6,7 @@ function resolvePageContext(pageContext) {
|
|
|
6
6
|
var pageContextResolved = {};
|
|
7
7
|
objectAssign(pageContextResolved, resolveHeadingsData(pageContext));
|
|
8
8
|
var config = getConfig();
|
|
9
|
-
var faviconUrl = config.faviconUrl, algolia = config.algolia, tagline = config.tagline, twitterHandle = config.twitterHandle, bannerUrl = config.bannerUrl, websiteUrl = config.websiteUrl,
|
|
9
|
+
var faviconUrl = config.faviconUrl, algolia = config.algolia, tagline = config.tagline, twitterHandle = config.twitterHandle, bannerUrl = config.bannerUrl, websiteUrl = config.websiteUrl, projectName = config.projectInfo.projectName;
|
|
10
10
|
objectAssign(pageContextResolved, {
|
|
11
11
|
urlPathname: pageContext.urlPathname, // TODO: remove
|
|
12
12
|
meta: {
|
|
@@ -18,7 +18,6 @@ function resolvePageContext(pageContext) {
|
|
|
18
18
|
tagline: tagline,
|
|
19
19
|
algolia: algolia,
|
|
20
20
|
},
|
|
21
|
-
topNavigationStyle: topNavigationStyle,
|
|
22
21
|
config: config,
|
|
23
22
|
});
|
|
24
23
|
return pageContextResolved;
|
package/dist/types/Config.d.ts
CHANGED
package/dist/types/Heading.d.ts
CHANGED
|
@@ -7,7 +7,6 @@ type HeadingResolved = {
|
|
|
7
7
|
level: number;
|
|
8
8
|
title: string;
|
|
9
9
|
titleInNav: string;
|
|
10
|
-
topNavigation?: true | string;
|
|
11
10
|
linkBreadcrumb: string[];
|
|
12
11
|
sectionTitles?: string[];
|
|
13
12
|
menuModalFullWidth?: true;
|
|
@@ -18,7 +17,6 @@ type HeadingDetachedResolved = Omit<HeadingResolved, 'level' | 'linkBreadcrumb'>
|
|
|
18
17
|
};
|
|
19
18
|
type HeadingDefinitionCommon = {
|
|
20
19
|
title: string;
|
|
21
|
-
topNavigation?: true | string;
|
|
22
20
|
menuModalFullWidth?: true;
|
|
23
21
|
};
|
|
24
22
|
type HeadingDetachedDefinition = HeadingDefinitionCommon & {
|
package/docsearch/SearchLink.tsx
CHANGED
|
@@ -30,7 +30,7 @@ function SearchLink(props: PropsAnchor) {
|
|
|
30
30
|
function SearchIcon() {
|
|
31
31
|
return (
|
|
32
32
|
<svg
|
|
33
|
-
style={{ marginRight: 'var(--icon-padding)', lineHeight: 0, width: '1.3em' }}
|
|
33
|
+
style={{ marginRight: 'var(--icon-text-padding)', lineHeight: 0, width: '1.3em' }}
|
|
34
34
|
className="decolorize-7"
|
|
35
35
|
viewBox="0 0 20 20"
|
|
36
36
|
>
|
package/package.json
CHANGED
|
@@ -5,6 +5,7 @@ import type { PageContextResolved } from '../config/resolvePageContext'
|
|
|
5
5
|
import { PageContextProvider, PageContextProvider2 } from './usePageContext'
|
|
6
6
|
import React from 'react'
|
|
7
7
|
import { DocSearchInstall } from '../docsearch/DocSearchInstall'
|
|
8
|
+
import { PassThrough } from '../utils/PassTrough'
|
|
8
9
|
|
|
9
10
|
function getPageElement(pageContext: PageContext, pageContextResolved: PageContextResolved) {
|
|
10
11
|
const { Page } = pageContext
|
|
@@ -33,7 +34,3 @@ function Wrapper({
|
|
|
33
34
|
</React.StrictMode>
|
|
34
35
|
)
|
|
35
36
|
}
|
|
36
|
-
|
|
37
|
-
function PassThrough({ children }: any) {
|
|
38
|
-
return <>{children}</>
|
|
39
|
-
}
|
|
@@ -34,6 +34,7 @@ Promise<Awaited<ReturnType<OnRenderHtmlAsync>>> => {
|
|
|
34
34
|
<meta name="viewport" content="width=device-width,initial-scale=1,user-scalable=no" />
|
|
35
35
|
${getOpenGraphTags(pageContext.urlPathname, pageContextResolved.documentTitle, pageContextResolved.meta)}
|
|
36
36
|
<style>${dangerouslySkipEscape(styleMenuModalLayout)}</style>
|
|
37
|
+
<meta name="docsearch:category" content="${pageContextResolved.activeCategory ?? 'Miscellaneous'}" />
|
|
37
38
|
</head>
|
|
38
39
|
<body>
|
|
39
40
|
<div id="page-view">${dangerouslySkipEscape(pageHtml)}</div>
|
package/types/Config.ts
CHANGED
package/types/Heading.ts
CHANGED
|
@@ -8,7 +8,6 @@ type HeadingResolved = {
|
|
|
8
8
|
level: number
|
|
9
9
|
title: string
|
|
10
10
|
titleInNav: string
|
|
11
|
-
topNavigation?: true | string
|
|
12
11
|
linkBreadcrumb: string[]
|
|
13
12
|
sectionTitles?: string[]
|
|
14
13
|
menuModalFullWidth?: true
|
|
@@ -21,7 +20,6 @@ type HeadingDetachedResolved = Omit<HeadingResolved, 'level' | 'linkBreadcrumb'>
|
|
|
21
20
|
|
|
22
21
|
type HeadingDefinitionCommon = {
|
|
23
22
|
title: string
|
|
24
|
-
topNavigation?: true | string
|
|
25
23
|
menuModalFullWidth?: true
|
|
26
24
|
}
|
|
27
25
|
|