Skip to content

Commit ed9f804

Browse files
committed
Merge branch 'main' of github.com:github/docs-internal into deprecate-2.19
2 parents fdc6ffc + 08880d9 commit ed9f804

13 files changed

Lines changed: 204 additions & 86 deletions

File tree

javascripts/dev-toc.js

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
const expandText = 'Expand All'
2+
const closeText = 'Close All'
3+
4+
export default function devToc () {
5+
const expandButton = document.querySelector('.js-expand')
6+
if (!expandButton) return
7+
8+
const detailsElements = document.querySelectorAll('details')
9+
10+
expandButton.addEventListener('click', () => {
11+
// on click, toggle all the details elements open or closed
12+
const anyDetailsOpen = Array.from(detailsElements).find(details => details.open)
13+
14+
for (const detailsElement of detailsElements) {
15+
anyDetailsOpen
16+
? detailsElement.removeAttribute('open')
17+
: detailsElement.open = true
18+
}
19+
20+
// toggle the button text on click
21+
anyDetailsOpen
22+
? expandButton.textContent = expandText
23+
: expandButton.textContent = closeText
24+
})
25+
26+
// also toggle the button text on clicking any of the details elements
27+
for (const detailsElement of detailsElements) {
28+
detailsElement.addEventListener('click', () => {
29+
expandButton.textContent = closeText
30+
31+
// we can only get an accurate count of the open details elements if we wait a fraction after click
32+
setTimeout(() => {
33+
if (!Array.from(detailsElements).find(details => details.open)) {
34+
expandButton.textContent = expandText
35+
}
36+
}, 50)
37+
})
38+
}
39+
}

javascripts/events.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,8 @@ export default function initializeEvents () {
192192
})
193193
})
194194

195+
if (!document.querySelector('.sidebar-products')) return
196+
195197
// Navigate event
196198
Array.from(
197199
document.querySelectorAll('.sidebar-products details')

javascripts/index.js

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import { fillCsrf } from './get-csrf'
1616
import initializeEvents from './events'
1717
import filterCodeExamples from './filter-code-examples'
1818
import allArticles from './all-articles'
19+
import devToc from './dev-toc'
1920

2021
document.addEventListener('DOMContentLoaded', async () => {
2122
displayPlatformSpecificContent()
@@ -27,11 +28,12 @@ document.addEventListener('DOMContentLoaded', async () => {
2728
wrapCodeTerms()
2829
print()
2930
localization()
30-
await fillCsrf() // this must complete before any POST calls
31-
helpfulness()
32-
experiment()
3331
copyCode()
34-
initializeEvents()
3532
filterCodeExamples()
3633
allArticles()
34+
devToc()
35+
await fillCsrf() // this must complete before any POST calls
36+
initializeEvents() // requires fillCsrf to complete
37+
experiment() // requires fillCsrf to complete
38+
helpfulness() // requires fillCsrf to complete
3739
})

javascripts/nav.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ export default function () {
33
const hamburgerButton = document.querySelector('.nav-mobile-burgerIcon')
44
const mobileDropdown = document.querySelector('.nav-mobile-dropdown')
55

6+
if (!(hamburgerButton && mobileDropdown)) return
7+
68
hamburgerButton.addEventListener('click', (event) => {
79
event.preventDefault()
810
hamburgerButton.classList.toggle('js-open')

javascripts/search.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,8 @@ const resultTemplate = (item) => {
6363
}
6464

6565
export default function () {
66+
if (!document.querySelector('#search-results-container')) return
67+
6668
window.initialPageLoad = true
6769
const opts = {
6870

layouts/dev-toc.html

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
<!doctype html>
2+
<html lang="{{currentLanguage}}">
3+
<head>
4+
<meta charset="utf-8" />
5+
<title>Docs TOC</title>
6+
<link rel="stylesheet" href="/dist/index.css">
7+
<link rel="alternate icon" type="image/png" href="/assets/images/site/favicon.png">
8+
<link rel="icon" type="image/svg+xml" href="/assets/images/site/favicon.svg">
9+
</head>
10+
11+
<body class="dev-toc p-3 m-3">
12+
<main class="width-full">
13+
14+
<h3>Versions</h3>
15+
<ul class="versions-list">
16+
{% for version in allVersions %}
17+
<li><a href="/{{ version[0] }}/dev-toc">{{ version[1].versionTitle }}</a>
18+
{% endfor %}
19+
</ul>
20+
21+
{% if allVersions[currentVersion] %}
22+
<h2 class="mt-3 mb-3"><abbr>TOC</abbr> for {{ allVersions[currentVersion].versionTitle }}</h2>
23+
24+
<button class="btn mb-3 js-expand" type="button">Expand All</button>
25+
<div/>
26+
27+
{% for product in siteTree[currentLanguage][currentVersion].products %}
28+
<details class="mb-1"><summary>{{product[1].title}}</summary>
29+
<ul class="products-list">
30+
<li title="{{product[1].title}}">
31+
<a href="/{{currentLanguage}}{{product[1].href}}">{{ product[1].title }}</a>
32+
{% for category in product[1].categories %}
33+
{% capture fullPathToCategory %}/{{currentLanguage}}{{category[1].href}}{% endcapture %}
34+
<ul>
35+
<li>
36+
<a href="{{fullPathToCategory}}">{{ category[1].title }}</a>
37+
<!-- some categories have maptopics with child articles -->
38+
{% if category[1].maptopics %}
39+
<ul">
40+
{% for maptopic in category[1].maptopics %}
41+
{% unless maptopic[1].hidden %}
42+
{% capture fullPathToMaptopic %}/{{currentLanguage}}{{maptopic[1].href}}{% endcapture %}
43+
44+
<li>
45+
<a href="{{fullPathToMaptopic}}">{{ maptopic[1].title }}</a>
46+
<ul>
47+
{% for article in maptopic[1].articles %}
48+
{% capture fullPathToArticle %}/{{currentLanguage}}{{article[1].href}}{% endcapture %}
49+
50+
<li>
51+
<a href="{{fullPathToArticle}}">{{ article[1].title }}</a>
52+
</li>
53+
{% endfor %}
54+
</ul>
55+
</li>
56+
{% endunless %}
57+
{% endfor %}
58+
</ul>
59+
<!-- some categories have no maptopics, only articles -->
60+
{% else %}
61+
<ul>
62+
{% for article in category[1].articles %}
63+
{% capture fullPathToArticle %}/{{currentLanguage}}{{article[1].href}}{% endcapture %}
64+
<li>
65+
<a href="{{fullPathToArticle}}">{{ article[1].title }}</a>
66+
</li>
67+
{% endfor %}
68+
</ul>
69+
{% endif %}
70+
</li>
71+
{% endfor %}
72+
</ul>
73+
</li>
74+
</ul>
75+
</details>
76+
{% endfor %}
77+
{% endif %}
78+
79+
{% include scripts %}
80+
</main>
81+
</body>
82+
</html>

middleware/dev-toc.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
const { liquid } = require('../lib/render-content')
2+
const layouts = require('../lib/layouts')
3+
4+
module.exports = async (req, res, next) => {
5+
if (process.env.NODE_ENV !== 'development') return next()
6+
if (!req.path.endsWith('/dev-toc')) return next()
7+
8+
return res.send(await liquid.parseAndRender(layouts['dev-toc'], req.context))
9+
}

middleware/enterprise-homepage.js

Lines changed: 0 additions & 10 deletions
This file was deleted.

middleware/homepages.js

Lines changed: 0 additions & 26 deletions
This file was deleted.

middleware/index.js

Lines changed: 47 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -10,52 +10,73 @@ const asyncMiddleware = fn =>
1010
}
1111

1212
module.exports = function (app) {
13+
// *** Development tools ***
14+
app.use(require('morgan')('dev', { skip: (req, res) => !isDevelopment }))
15+
if (isDevelopment) app.use(require('./webpack'))
16+
17+
// *** Early exits ***
1318
// Don't use the proxy's IP, use the requester's for rate limiting
1419
// See https://expressjs.com/en/guide/behind-proxies.html
1520
app.set('trust proxy', 1)
16-
app.use(require('morgan')('dev', { skip: (req, res) => !isDevelopment }))
1721
app.use(require('./rate-limit'))
18-
if (isDevelopment) app.use(require('./webpack'))
19-
app.use(require('./cookie-parser'))
20-
app.use(require('./req-utils'))
21-
app.use(require('./record-redirect'))
22-
app.use(require('./redirects/external'))
23-
app.use(require('./redirects/help-to-docs'))
24-
app.use(require('./set-fastly-cache-headers'))
2522
app.use(require('./handle-invalid-paths'))
26-
app.use(require('./loaderio-verification'))
23+
24+
// *** Security ***
2725
app.use(require('./cors'))
28-
app.use(require('./csp'))
26+
app.use(require('./csp')) // Must come before helmet
2927
app.use(require('helmet')())
30-
app.use(require('./robots'))
31-
app.use(express.json()) // Must come before ./csrf
28+
app.use(require('./cookie-parser')) // Must come before csrf
29+
app.use(express.json()) // Must come before csrf
3230
app.use(require('./csrf'))
33-
app.use(require('./handle-csrf-errors'))
31+
app.use(require('./handle-csrf-errors')) // Must come before regular handle-errors
32+
33+
// *** Headers ***
3434
app.use(require('compression')())
35+
app.use(require('./set-fastly-cache-headers'))
36+
app.use(require('./disable-caching-on-safari'))
37+
38+
// *** Config and context for redirects ***
39+
app.use(require('./req-utils')) // Must come before record-redirect and events
40+
app.use(require('./record-redirect'))
41+
app.use(require('./detect-language')) // Must come before context, breadcrumbs, find-page, handle-errors, homepages
42+
app.use(asyncMiddleware(require('./context'))) // Must come before early-access-*, handle-redirects
43+
44+
// *** Redirects, 3xx responses ***
45+
// I ordered these by use frequency
3546
app.use(require('connect-slashes')(false))
47+
app.use(require('./redirects/external'))
48+
app.use(require('./redirects/help-to-docs'))
49+
app.use(require('./redirects/language-code-redirects')) // Must come before contextualizers
50+
app.use(require('./redirects/handle-redirects')) // Must come before contextualizers
51+
52+
// *** Config and context for rendering ***
53+
app.use(require('./find-page')) // Must come before archived-enterprise-versions, breadcrumbs, featured-links, products, render-page
54+
55+
// *** Rendering, 2xx responses ***
56+
// I largely ordered these by use frequency
57+
app.use(require('./archived-enterprise-versions-assets')) // Must come before static/assets
3658
app.use('/dist', express.static('dist'))
59+
app.use('/assets', express.static('assets'))
60+
app.use('/public', express.static('data/graphql'))
3761
app.use('/events', require('./events'))
38-
app.use(require('./categories-for-support-team'))
39-
app.use(require('./detect-language'))
40-
app.use(asyncMiddleware(require('./context')))
4162
app.use('/csrf', require('./csrf-route'))
63+
app.use(require('./archived-enterprise-versions'))
64+
app.use(require('./robots'))
4265
app.use(require('./early-access-paths'))
4366
app.use(require('./early-access-proxy'))
44-
app.use(require('./find-page'))
45-
app.use(require('./archived-enterprise-versions'))
46-
app.use(require('./archived-enterprise-versions-assets'))
47-
app.use('/assets', express.static('assets'))
48-
app.use('/public', express.static('data/graphql'))
49-
app.use(require('./redirects/language-code-redirects'))
50-
// redirects need to be handled before the contextualizers
51-
app.use(require('./redirects/handle-redirects'))
67+
app.use(require('./categories-for-support-team'))
68+
app.use(require('./loaderio-verification'))
69+
app.get('/_500', asyncMiddleware(require('./trigger-error')))
70+
71+
// *** Preparation for render-page ***
5272
app.use(require('./contextualizers/graphql'))
5373
app.use(require('./contextualizers/rest'))
5474
app.use(require('./contextualizers/webhooks'))
55-
app.use(require('./disable-caching-on-safari'))
56-
app.get('/_500', asyncMiddleware(require('./trigger-error')))
5775
app.use(require('./breadcrumbs'))
76+
app.use(require('./dev-toc'))
5877
app.use(require('./featured-links'))
78+
79+
// *** Rendering, must go last ***
5980
app.get('/*', asyncMiddleware(require('./render-page')))
6081
app.use(require('./handle-errors'))
6182
}

0 commit comments

Comments
 (0)