Skip to content
34 changes: 5 additions & 29 deletions components/article/ToolPicker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,35 +12,10 @@ import { useArticleContext } from 'components/context/ArticleContext'
// Nota bene: tool === application
// Nota bene: picker === switcher

const supportedTools = [
'cli',
'desktop',
'webui',
'curl',
'codespaces',
'vscode',
'importer_cli',
'graphql',
'powershell',
'bash',
]
const toolTitles = {
webui: 'Web browser',
cli: 'GitHub CLI',
curl: 'cURL',
desktop: 'Desktop',
codespaces: 'Codespaces',
vscode: 'Visual Studio Code',
importer_cli: 'GitHub Enterprise Importer CLI',
graphql: 'GraphQL API',
powershell: 'PowerShell',
bash: 'Bash',
} as Record<string, string>

// 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) {
function showToolSpecificContent(tool: string, supportedTools: Array<string>) {
const markdowns = Array.from(document.querySelectorAll<HTMLElement>('.extended-markdown'))
markdowns
.filter((el) => supportedTools.some((tool) => el.classList.contains(tool)))
Expand Down Expand Up @@ -77,7 +52,8 @@ type Props = {
}
export const ToolPicker = ({ variant = 'subnav' }: Props) => {
const { asPath } = useRouter()
const { defaultTool, detectedTools } = useArticleContext()
// allTools comes from the ArticleContext which contains the list of tools available
const { defaultTool, detectedTools, allTools } = useArticleContext()
const [currentTool, setCurrentTool] = useState(getDefaultTool(defaultTool, detectedTools))

const sharedContainerProps = {
Expand All @@ -100,7 +76,7 @@ export const ToolPicker = ({ variant = 'subnav' }: Props) => {
// Whenever the currentTool is changed, update the article content
useEffect(() => {
preserveAnchorNodePosition(document, () => {
showToolSpecificContent(currentTool)
showToolSpecificContent(currentTool, Object.keys(allTools))
})
}, [currentTool, asPath])

Expand Down Expand Up @@ -137,7 +113,7 @@ export const ToolPicker = ({ variant = 'subnav' }: Props) => {
onClickTool(tool)
}}
>
{toolTitles[tool]}
{allTools[tool]}
</UnderlineNav.Link>
))}
</UnderlineNav>
Expand Down
2 changes: 2 additions & 0 deletions components/context/ArticleContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ export type ArticleContextT = {
currentLearningTrack?: LearningTrack
detectedPlatforms: Array<string>
detectedTools: Array<string>
allTools: Record<string, string>
}

export const ArticleContext = createContext<ArticleContextT | null>(null)
Expand Down Expand Up @@ -70,5 +71,6 @@ export const getArticleContextFromRequest = (req: any): ArticleContextT => {
currentLearningTrack: req.context.currentLearningTrack,
detectedPlatforms: page.detectedPlatforms || [],
detectedTools: page.detectedTools || [],
allTools: page.allToolsParsed || [], // this is set at the page level, see lib/page.js
}
}
2 changes: 1 addition & 1 deletion contributing/content-markup-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ You can define a default platform in the frontmatter. For more information, see

## Tool tags

We occasionally need to write documentation for different tools (GitHub UI, GitHub CLI, GitHub Desktop, cURL, Codespaces, VS Code, GitHub Enterprise Importer CLI, GraphQL API). Each tool may require a different set of instructions. We use tool tags to demarcate information for each tool.
We occasionally need to write documentation for different tools (GitHub UI, GitHub CLI, GitHub Desktop, cURL, Codespaces, VS Code, GitHub Enterprise Importer CLI, GraphQL API). Each tool may require a different set of instructions. We use tool tags to demarcate information for each tool. To modify the list of possible tools, edit [`lib/all-tools.js`](../lib/all-tools.js).

### Usage

Expand Down
13 changes: 13 additions & 0 deletions lib/all-tools.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// all the tools available for the Tool Picker
export const allTools = {
bash: 'Bash',
cli: 'GitHub CLI',
codespaces: 'Codespaces',
curl: 'cURL',
desktop: 'Dekstop',
importer_cli: 'GitHub Enterprise Importer CLI',
graphql: 'GraphQL API',
powershell: 'PowerShell',
vscode: 'Visual Studio Code',
webui: 'Web browser',
}
18 changes: 5 additions & 13 deletions lib/frontmatter.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import path from 'path'
import parse from './read-frontmatter.js'
import semver from 'semver'
import { allVersions } from './all-versions.js'
import { allTools } from './all-tools.js'

const layoutNames = [
'default',
Expand All @@ -20,6 +21,7 @@ const semverRange = {
message: 'Must be a valid SemVer range',
}
const versionObjs = Object.values(allVersions)

const guideTypes = ['overview', 'quick_start', 'tutorial', 'how_to', 'reference']
const featureVersions = fs
.readdirSync(path.posix.join(process.cwd(), 'data/features'))
Expand Down Expand Up @@ -177,21 +179,11 @@ export const schema = {
type: 'string',
enum: ['mac', 'windows', 'linux'],
},
// Tool-specific content preference
// Tool-specific content preference, the list of tools are kept in
// make it easier to update in a single place
defaultTool: {
type: 'string',
enum: [
'webui',
'cli',
'desktop',
'curl',
'codespaces',
'vscode',
'importer_cli',
'graphql',
'powershell',
'bash',
],
enum: Object.keys(allTools),
},
// Documentation contributed by a third party, such as a GitHub Partner
contributor: {
Expand Down
19 changes: 8 additions & 11 deletions lib/liquid-tags/extended-markdown.js
Original file line number Diff line number Diff line change
@@ -1,24 +1,21 @@
export const tags = {
import { allTools } from '../all-tools.js'

// we do this to get an object that combines all possible liquid tags
const toolTags = Object.fromEntries(Object.keys(allTools).map((tool) => [tool, '']))

const subsetTags = {
mac: '',
windows: '',
linux: '',
cli: '',
desktop: '',
webui: '',
curl: '',
codespaces: '',
vscode: '',
importer_cli: '',
graphql: '',
powershell: '',
bash: '',
all: '',
tip: 'border rounded-1 mb-4 p-3 color-border-accent-emphasis color-bg-accent f5',
note: 'border rounded-1 mb-4 p-3 color-border-accent-emphasis color-bg-accent f5',
warning: 'border rounded-1 mb-4 p-3 color-border-danger color-bg-danger f5',
danger: 'border rounded-1 mb-4 p-3 color-border-danger color-bg-danger f5',
}

export const tags = Object.assign({}, subsetTags, toolTags)

export const template =
'<div class="extended-markdown {{ tagName }} {{ classes }}">{{ output }}</div>'

Expand Down
20 changes: 8 additions & 12 deletions lib/page.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import readFileContents from './read-file-contents.js'
import getLinkData from './get-link-data.js'
import getDocumentType from './get-document-type.js'
import { union } from 'lodash-es'
import { allTools } from './all-tools.js'

// We're going to check a lot of pages' "ID" (the first part of
// the relativePath) against `productMap` to make sure it's valid.
Expand Down Expand Up @@ -261,18 +262,13 @@ class Page {
this.includesPlatformSpecificContent = this.detectedPlatforms.length > 0

// set flags for webui, cli, etc switcher element
this.detectedTools = [
'cli',
'desktop',
'webui',
'curl',
'codespaces',
'vscode',
`importer_cli`,
`graphql`,
'powershell',
'bash',
].filter((tool) => html.includes(`extended-markdown ${tool}`) || html.includes(`tool-${tool}`))
this.detectedTools = Object.keys(allTools).filter(
(tool) => html.includes(`extended-markdown ${tool}`) || html.includes(`tool-${tool}`)
)

// pass the list of all possible tools around to components and utilities that will need it later on
this.allToolsParsed = allTools

this.includesToolSpecificContent = this.detectedTools.length > 0

return html
Expand Down
31 changes: 5 additions & 26 deletions lib/schema-event.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { languageKeys } from './languages.js'
import { allVersionKeys } from './all-versions.js'
import { productIds } from './all-products.js'

import { allTools } from './all-tools.js'
const context = {
type: 'object',
additionalProperties: false,
Expand Down Expand Up @@ -146,18 +146,7 @@ const context = {
},
application_preference: {
type: 'string',
enum: [
'webui',
'cli',
'desktop',
'curl',
'codespaces',
'vscode',
'importer_cli',
'graphql',
'powershell',
'bash',
],
enum: Object.keys(allTools),
description: 'The application selected by the user.',
},
color_mode_preference: {
Expand Down Expand Up @@ -451,26 +440,16 @@ const preferenceSchema = {
},
preference_value: {
type: 'string',
enum: [
'webui',
'cli',
'desktop',
'curl',
'codespaces',
'vscode',
'importer_cli',
'graphql',
'powershell',
'bash',
enum: Object.keys(allTools).concat(
'dark',
'light',
'auto',
'auto:dark',
'auto:light',
'linux',
'mac',
'windows',
],
'windows'
),
description: 'The application, color_mode, or os selected by the user.',
},
},
Expand Down