forked from github/docs
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathToolPicker.tsx
82 lines (68 loc) · 3.13 KB
/
ToolPicker.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
import { preserveAnchorNodePosition } from 'scroll-anchoring'
import { useArticleContext } from 'components/context/ArticleContext'
import { InArticlePicker } from './InArticlePicker'
// example: http://localhost:4000/en/codespaces/developing-in-codespaces/creating-a-codespace
// Nota bene: tool === application
// Nota bene: picker === switcher
// Imperatively modify article content to show only the selected tool
// find all platform-specific *block* elements and hide or show as appropriate
// example: {% webui %} block content {% endwebui %}
function showToolSpecificContent(tool: string, supportedTools: Array<string>) {
const markdowns = Array.from(document.querySelectorAll<HTMLElement>('.ghd-tool'))
markdowns
.filter((el) => supportedTools.some((tool) => el.classList.contains(tool)))
.forEach((el) => {
el.style.display = el.classList.contains(tool) ? '' : 'none'
// hack: special handling for minitoc links -- we can't pass the tool classes
// directly to the Primer NavList.Item generated <li>, it gets passed down
// to the child <a>. So if we find an <a> that has the tool class and its
// parent is an <li>, we hide/unhide that element as well.
if (el.tagName === 'A' && el.parentElement && el.parentElement.tagName === 'LI') {
el.parentElement.style.display = el.classList.contains(tool) ? '' : 'none'
}
})
// find all tool-specific *inline* elements and hide or show as appropriate
// example: <span class="tool-webui">inline content</span>
const toolEls = Array.from(
document.querySelectorAll<HTMLElement>(
supportedTools.map((tool) => `.tool-${tool}`).join(', '),
),
)
toolEls.forEach((el) => {
el.style.display = el.classList.contains(`tool-${tool}`) ? '' : 'none'
})
}
function getDefaultTool(defaultTool: string | undefined, detectedTools: Array<string>): string {
// If there is a default tool and the tool is present on this page
if (defaultTool && detectedTools.includes(defaultTool)) return defaultTool
// Default to webui if present (this is generally the case where we show UI/CLI/Desktop info)
if (detectedTools.includes('webui')) return 'webui'
// Default to cli if present (this is generally the case where we show curl/CLI info)
if (detectedTools.includes('cli')) return 'cli'
// Otherwise, just choose the first detected tool
return detectedTools[0]
}
const toolQueryKey = 'tool'
export const ToolPicker = () => {
// allTools comes from the ArticleContext which contains the list of tools available
const { defaultTool, detectedTools, allTools } = useArticleContext()
if (!detectedTools.length) return null
const options = detectedTools.map((value) => {
return { value, label: allTools[value] }
})
return (
<InArticlePicker
fallbackValue={getDefaultTool(defaultTool, detectedTools)}
cookieKey="toolPreferred"
queryStringKey={toolQueryKey}
onValue={(value: string) => {
preserveAnchorNodePosition(document, () => {
showToolSpecificContent(value, Object.keys(allTools))
})
}}
preferenceName="application"
ariaLabel="Tool"
options={options}
/>
)
}