Skip to content

Commit ac87a84

Browse files
authored
Merge branch 'main' into repo-sync
2 parents e6acdb3 + be8aa2b commit ac87a84

13 files changed

Lines changed: 233 additions & 6 deletions

File tree

content/README.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ See the [contributing docs](/CONTRIBUTING.md) for general information about work
2121
- [`miniTocMaxHeadingLevel`](#minitocmaxheadinglevel)
2222
- [`allowTitleToDifferFromFilename`](#allowtitletodifferfromfilename)
2323
- [`defaultPlatform`](#defaultplatform)
24+
- [`defaultTool`](#defaulttool)
2425
- [`learningTracks`](#learningTracks)
2526
- [`includeGuides`](#includeGuides)
2627
- [`type`](#type)
@@ -202,6 +203,16 @@ Example:
202203
defaultPlatform: linux
203204
```
204205

206+
### `defaultTool`
207+
208+
- Purpose: Override the initial tool selection for a page, where tool refers to the application the reader is using to work with GitHub, such as GitHub.com's web UI, the GitHub CLI, or GitHub Desktop. If this frontmatter is omitted, then the tool-specific content matching the GitHub web UI is shown by default. This behavior can be changed for individual pages, for which a manual selection is more reasonable.
209+
- Type: `String`, one of: `webui`, `cli`, `desktop`.
210+
- Optional.
211+
212+
```yaml
213+
defaultTool: cli
214+
```
215+
205216
### `learningTracks`
206217
- Purpose: Render a list of learning tracks on a product's sub-landing page.
207218
- type: `String`. This should reference learning tracks' names defined in [`data/learning-tracks/*.yml`](../data/learning-tracks/README.md).

contributing/content-markup-reference.md

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,40 @@ These instructions are pertinent to Windows users.
100100

101101
You can define a default platform in the frontmatter. For more information, see the [content README](../content/README.md#defaultplatform).
102102

103+
## Tool tags
104+
105+
We occasionally need to write documentation for different tools (GitHub UI, GitHub CLI, GitHub Desktop). Each tool may require a different set of instructions. We use tool tags to demarcate information for each tool.
106+
107+
### Usage
108+
109+
```
110+
{% webui %}
111+
112+
These instructions are pertinent to GitHub UI users.
113+
114+
{% endwebui %}
115+
```
116+
117+
```
118+
{% cli %}
119+
120+
These instructions are pertinent to GitHub CLI users.
121+
122+
{% endcli %}
123+
```
124+
125+
```
126+
{% desktop %}
127+
128+
These instructions are pertinent to GitHub Desktop.
129+
130+
{% enddesktop %}
131+
```
132+
133+
Unlike [operating system tags](#operating-system-tags), which will automatically add tabs to select the operating system at the top of the article, you must add `{% include tool-switcher %}` wherever you want to display tabs to select the tool. This allows you to display the tabs at the top of the article or immediately before a relevant section.
134+
135+
You can define a default tool in the frontmatter. For more information, see the [content README](../content/README.md#defaulttool).
136+
103137
## Reusable and variable strings of text
104138

105139
Reusable strings (commonly called content references or conrefs) contain content that’s used in more than one place in our documentation and allow us to change the content in a single location rather than every place the string appears.

includes/tool-switcher.html

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<nav class="UnderlineNav my-3" id="tool-switcher"
2+
{%- if page.defaultTool %} data-default-tool="{{ page.defaultTool }}"{% endif %}>
3+
<div class="UnderlineNav-body">
4+
<a href="#" class="UnderlineNav-item tool-switcher" data-tool="webui">GitHub.com</a>
5+
<a href="#" class="UnderlineNav-item tool-switcher" data-tool="cli">CLI</a>
6+
<a href="#" class="UnderlineNav-item tool-switcher" data-tool="desktop">Desktop</a>
7+
</div>
8+
</nav>
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
const supportedTools = ['cli', 'desktop', 'webui']
2+
const detectedTools = new Set()
3+
4+
export default function displayToolSpecificContent () {
5+
let tool = getDefaultTool()
6+
7+
if (!tool) tool = 'webui'
8+
9+
const toolsInContent = findToolSpecificContent(tool)
10+
11+
hideSwitcherLinks(toolsInContent)
12+
13+
showContentForTool(tool)
14+
15+
// configure links for switching tool content
16+
switcherLinks().forEach(link => {
17+
link.addEventListener('click', (event) => {
18+
event.preventDefault()
19+
showContentForTool(event.target.dataset.tool)
20+
findToolSpecificContent(event.target.dataset.tool)
21+
})
22+
})
23+
}
24+
25+
function showContentForTool (tool) {
26+
// (de)activate switcher link appearances
27+
switcherLinks().forEach(link => {
28+
(link.dataset.tool === tool)
29+
? link.classList.add('selected')
30+
: link.classList.remove('selected')
31+
})
32+
}
33+
34+
function findToolSpecificContent (tool) {
35+
// find all tool-specific *block* elements and hide or show as appropriate
36+
// example: {{ #cli }} block content {{/cli}}
37+
Array.from(document.querySelectorAll('.extended-markdown'))
38+
.filter(el => supportedTools.some(tool => el.classList.contains(tool)))
39+
.forEach(el => {
40+
detectTools(el)
41+
el.style.display = el.classList.contains(tool)
42+
? ''
43+
: 'none'
44+
})
45+
46+
// find all tool-specific *inline* elements and hide or show as appropriate
47+
// example: <span class="tool-cli">inline content</span>
48+
Array.from(document.querySelectorAll('.tool-cli, .tool-desktop, .tool-webui'))
49+
.forEach(el => {
50+
detectTools(el)
51+
el.style.display = el.classList.contains('tool-' + tool)
52+
? ''
53+
: 'none'
54+
})
55+
56+
return Array.from(detectedTools)
57+
}
58+
59+
// hide links for any tool-specific sections that are not present
60+
function hideSwitcherLinks (toolsInContent) {
61+
Array.from(document.querySelectorAll('a.tool-switcher'))
62+
.forEach(link => {
63+
if (toolsInContent.includes(link.dataset.tool)) return
64+
link.style.display = 'none'
65+
})
66+
}
67+
68+
function detectTools (el) {
69+
el.classList.forEach(elClass => {
70+
const value = elClass.replace(/tool-/, '')
71+
if (supportedTools.includes(value)) detectedTools.add(value)
72+
})
73+
}
74+
75+
function getDefaultTool () {
76+
const el = document.querySelector('[data-default-tool]')
77+
if (el) return el.dataset.defaultTool
78+
}
79+
80+
function switcherLinks () {
81+
return Array.from(document.querySelectorAll('a.tool-switcher'))
82+
}

javascripts/experiment.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,4 +27,13 @@ export default function () {
2727
// const x = document.querySelector(...)
2828
// x.addEventListener('click', () => { sendSuccess(testName) })
2929
// if (xbucket === TREATMENT) applyTreatment(x)
30+
31+
const testName = 'search_lunr'
32+
const xbucket = bucket(testName)
33+
document.addEventListener('click', evt => {
34+
if (!evt.target.closest('.search-result > a')) return
35+
console.log(testName, xbucket) // eslint-disable-line
36+
sendSuccess(testName)
37+
})
38+
// Treatment code in middleware/search.js
3039
}

javascripts/index.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// Import our SCSS files so webpack will process them
22
import '../stylesheets/index.scss'
33
import displayPlatformSpecificContent from './display-platform-specific-content'
4+
import displayToolSpecificContent from './display-tool-specific-content'
45
import explorer from './explorer'
56
import scrollUp from './scroll-up'
67
import search from './search'
@@ -24,6 +25,7 @@ import toggleImages from './toggle-images'
2425

2526
document.addEventListener('DOMContentLoaded', async () => {
2627
displayPlatformSpecificContent()
28+
displayToolSpecificContent()
2729
explorer()
2830
scrollUp()
2931
search()

lib/frontmatter.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,11 @@ const schema = {
119119
type: 'string',
120120
enum: ['mac', 'windows', 'linux']
121121
},
122+
// Tool-specific content preference
123+
defaultTool: {
124+
type: 'string',
125+
enum: ['webui', 'cli', 'desktop']
126+
},
122127
// Documentation contributed by a third party, such as a GitHub Partner
123128
contributor: {
124129
type: 'object',

lib/liquid-tags/extended-markdown.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@ const tags = {
22
mac: '',
33
windows: '',
44
linux: '',
5+
cli: '',
6+
desktop: '',
7+
webui: '',
58
all: '',
69
tip: 'border rounded-1 mb-4 p-3 color-border-info color-bg-info f5',
710
note: 'border rounded-1 mb-4 p-3 color-border-info color-bg-info f5',

lib/search/lunr-search.js

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
const path = require('path')
22
const lunr = require('lunr')
3+
require('lunr-languages/lunr.stemmer.support')(lunr)
4+
require('lunr-languages/tinyseg')(lunr)
5+
require('lunr-languages/lunr.ja')(lunr)
6+
require('lunr-languages/lunr.es')(lunr)
7+
require('lunr-languages/lunr.pt')(lunr)
8+
require('lunr-languages/lunr.de')(lunr)
39
const { get } = require('lodash')
410
const readFileAsync = require('../readfile-async')
511
const { namePrefix } = require('./config')
@@ -9,7 +15,7 @@ const LUNR_DIR = './indexes'
915
const lunrIndexes = new Map()
1016
const lunrRecords = new Map()
1117

12-
module.exports = async function loadLunrResults ({ version, language, query, limit }) {
18+
async function loadLunrResults ({ version, language, query, limit }) {
1319
const indexName = `${namePrefix}-${version}-${language}`
1420
if (!lunrIndexes.has(indexName) || !lunrRecords.has(indexName)) {
1521
lunrIndexes.set(indexName, await loadLunrIndex(indexName))
@@ -33,6 +39,15 @@ module.exports = async function loadLunrResults ({ version, language, query, lim
3339
return results
3440
}
3541

42+
loadLunrResults.warmLunr = async function warmLunr () {
43+
// Took about 60 seconds on local to warm them all...
44+
// so doing just the most common for prewarming
45+
const indexName = 'github-docs-dotcom-en'
46+
lunrRecords.set(indexName, await loadLunrRecords(indexName))
47+
lunrIndexes.set(indexName, await loadLunrIndex(indexName))
48+
return true
49+
}
50+
3651
async function loadLunrIndex (indexName) {
3752
const filePath = path.posix.join(__dirname, LUNR_DIR, `${indexName}.json.br`)
3853
// Do not set to 'utf8' on file reads
@@ -82,3 +97,5 @@ function field (result, record, name) {
8297
function mark (text) {
8398
return `<mark>${text}</mark>`
8499
}
100+
101+
module.exports = loadLunrResults

lib/warm-server.js

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ const { loadPages, loadPageMap } = require('./pages')
33
const loadRedirects = require('./redirects/precompile')
44
const loadSiteData = require('./site-data')
55
const loadSiteTree = require('./site-tree')
6+
const { warmLunr } = require('./search/lunr-search')
67

78
// Instrument these functions so that
89
// it's wrapped in a timer that reports to Datadog
@@ -11,15 +12,16 @@ const dog = {
1112
loadPageMap: statsd.asyncTimer(loadPageMap, 'load_page_map'),
1213
loadRedirects: statsd.asyncTimer(loadRedirects, 'load_redirects'),
1314
loadSiteData: statsd.timer(loadSiteData, 'load_site_data'),
14-
loadSiteTree: statsd.asyncTimer(loadSiteTree, 'load_site_tree')
15+
loadSiteTree: statsd.asyncTimer(loadSiteTree, 'load_site_tree'),
16+
warmLunr: statsd.asyncTimer(warmLunr, 'warm_lunr')
1517
}
1618

1719
// For local caching
18-
let pageList, pageMap, site, redirects, siteTree
20+
let pageList, pageMap, site, redirects, siteTree, isLunrWarmed
1921

2022
function isFullyWarmed () {
2123
// NOTE: Yes, `pageList` is specifically excluded here as it is transient data
22-
const fullyWarmed = !!(pageMap && site && redirects && siteTree)
24+
const fullyWarmed = !!(pageMap && site && redirects && siteTree && isLunrWarmed)
2325
return fullyWarmed
2426
}
2527

@@ -28,7 +30,8 @@ function getWarmedCache () {
2830
pages: pageMap,
2931
site,
3032
redirects,
31-
siteTree
33+
siteTree,
34+
isLunrWarmed
3235
}
3336
}
3437

@@ -59,6 +62,10 @@ async function warmServer () {
5962
siteTree = await dog.loadSiteTree(pageMap, site, redirects)
6063
}
6164

65+
if (!isLunrWarmed) {
66+
isLunrWarmed = /* await */ dog.warmLunr()
67+
}
68+
6269
if (process.env.NODE_ENV !== 'test') {
6370
console.log(`Context primed in ${Date.now() - startTime} ms`)
6471
}

0 commit comments

Comments
 (0)