From af50d6e859b489120983562d734e366232e7f148 Mon Sep 17 00:00:00 2001 From: Sarah Schneider Date: Wed, 10 Aug 2022 15:05:23 -0400 Subject: [PATCH 1/4] re-add the dev toc in script/static form --- script/dev-toc/generate.js | 55 +++++++++++++++++++++++++++++++++ script/dev-toc/index.js | 41 +++++++++++++++++++++++++ script/dev-toc/layout.html | 62 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 158 insertions(+) create mode 100755 script/dev-toc/generate.js create mode 100644 script/dev-toc/index.js create mode 100644 script/dev-toc/layout.html diff --git a/script/dev-toc/generate.js b/script/dev-toc/generate.js new file mode 100755 index 0000000000..955ccd154d --- /dev/null +++ b/script/dev-toc/generate.js @@ -0,0 +1,55 @@ +#!/usr/bin/env node + +import fs from 'fs' +import path from 'path' +import { execSync } from 'child_process' +import fpt from '../../lib/non-enterprise-default-version.js' +import { allVersionKeys } from '../../lib/all-versions.js' +import { liquid } from '../../lib/render-content/index.js' +import contextualize from '../../middleware/context.js' + +const layoutFilename = path.posix.join(process.cwd(), 'script/dev-toc/layout.html') +const layout = fs.readFileSync(layoutFilename, 'utf8') + +const staticDirName = 'script/dev-toc/static' +const staticDir = path.posix.join(process.cwd(), staticDirName) +if (!fs.existsSync(staticDir)) fs.mkdirSync(staticDir) + +main() + +async function main() { + const next = () => {} + const res = {} + const req = { language: 'en', cookies: {} } + + for (const version of allVersionKeys) { + req.pagePath = version === fpt ? '/' : `/${version}` + + // Create a subdir for the version if one doesn't exist yet. + const versionStaticDir = path.posix.join(staticDir, version) + if (!fs.existsSync(versionStaticDir)) fs.mkdirSync(versionStaticDir) + + // Create a versioned filename. + const filename = path.posix.join(versionStaticDir, 'dev-toc.html') + + // Create a minimal context object. + await contextualize(req, res, next) + + // Add the tree to the req.context. + req.context.currentEnglishTree = req.context.siteTree.en[req.context.currentVersion] + + // Parse the layout in script/dev-toc/layout.html with the context we created above. + const outputHtml = await liquid.parseAndRender(layout, Object.assign({}, req.context)) + + // Write a static file for each version. + fs.writeFileSync(filename, outputHtml) + } + + // Default to FPT for the file to open. + const fptFile = path.posix.join(staticDirName, fpt, 'dev-toc.html') + + execSync(`open ${fptFile}`) + + console.log(`\nCreated the TOC! If it doesn't open automatically, open the following file in your browser to view it:\n +${fptFile}`) +} diff --git a/script/dev-toc/index.js b/script/dev-toc/index.js new file mode 100644 index 0000000000..2502cf21b3 --- /dev/null +++ b/script/dev-toc/index.js @@ -0,0 +1,41 @@ +const expandText = 'Expand All' +const closeText = 'Close All' + +document.addEventListener('DOMContentLoaded', async () => { + devToc() +}) + +function devToc() { + const expandButton = document.querySelector('.js-expand') + if (!expandButton) return + + const detailsElements = document.querySelectorAll('details') + + expandButton.addEventListener('click', () => { + // on click, toggle all the details elements open or closed + const anyDetailsOpen = Array.from(detailsElements).find((details) => details.open) + + for (const detailsElement of detailsElements) { + anyDetailsOpen ? detailsElement.removeAttribute('open') : (detailsElement.open = true) + } + + // toggle the button text on click + anyDetailsOpen + ? (expandButton.textContent = expandText) + : (expandButton.textContent = closeText) + }) + + // also toggle the button text on clicking any of the details elements + for (const detailsElement of detailsElements) { + detailsElement.addEventListener('click', () => { + expandButton.textContent = closeText + + // we can only get an accurate count of the open details elements if we wait a fraction after click + setTimeout(() => { + if (!Array.from(detailsElements).find((details) => details.open)) { + expandButton.textContent = expandText + } + }, 50) + }) + } +} diff --git a/script/dev-toc/layout.html b/script/dev-toc/layout.html new file mode 100644 index 0000000000..b002c78431 --- /dev/null +++ b/script/dev-toc/layout.html @@ -0,0 +1,62 @@ + + + + +Docs TOC + + + + +
+ +

Versions

+ + +{% assign docsRoot = "https://docs.github.com" %} + +{% if allVersions[currentVersion] %} +

TOC for {{ allVersions[currentVersion].versionTitle }}

+ + +
+ +{% for productPage in currentEnglishTree.childPages %} +
{{productPage.renderedFullTitle}} + +
+{% endfor %} +{% endif %} + + +
+ + From 73ae7681a76b89609cc76d39e40786cc59d2cd3a Mon Sep 17 00:00:00 2001 From: Sarah Schneider Date: Wed, 10 Aug 2022 15:05:46 -0400 Subject: [PATCH 2/4] gitignore the script/dev-toc/static folder --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 8b780e4e2e..7a5746c1df 100644 --- a/.gitignore +++ b/.gitignore @@ -9,6 +9,7 @@ coverage/ /assets/images/early-access /content/early-access /data/early-access +/script/dev-toc/static .next .eslintcache *.tsbuildinfo From db6f3c88909983ff3ea9fbe8c6d7caed1389d51a Mon Sep 17 00:00:00 2001 From: Sarah Schneider Date: Wed, 10 Aug 2022 15:26:13 -0400 Subject: [PATCH 3/4] change toc filenames to index.html --- script/dev-toc/generate.js | 4 ++-- script/dev-toc/layout.html | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/script/dev-toc/generate.js b/script/dev-toc/generate.js index 955ccd154d..49a3625fc0 100755 --- a/script/dev-toc/generate.js +++ b/script/dev-toc/generate.js @@ -30,7 +30,7 @@ async function main() { if (!fs.existsSync(versionStaticDir)) fs.mkdirSync(versionStaticDir) // Create a versioned filename. - const filename = path.posix.join(versionStaticDir, 'dev-toc.html') + const filename = path.posix.join(versionStaticDir, 'index.html') // Create a minimal context object. await contextualize(req, res, next) @@ -46,7 +46,7 @@ async function main() { } // Default to FPT for the file to open. - const fptFile = path.posix.join(staticDirName, fpt, 'dev-toc.html') + const fptFile = path.posix.join(staticDirName, fpt, 'index.html') execSync(`open ${fptFile}`) diff --git a/script/dev-toc/layout.html b/script/dev-toc/layout.html index b002c78431..ee44646d8f 100644 --- a/script/dev-toc/layout.html +++ b/script/dev-toc/layout.html @@ -12,7 +12,7 @@

Versions

From 9236898431f23c9b25b6ff151079ff426bd2816a Mon Sep 17 00:00:00 2001 From: Sarah Schneider Date: Thu, 11 Aug 2022 11:21:20 -0400 Subject: [PATCH 4/4] add support for passing an option to open sections by default --- script/dev-toc/generate.js | 17 +++++++++++++++++ script/dev-toc/layout.html | 5 +++++ 2 files changed, 22 insertions(+) diff --git a/script/dev-toc/generate.js b/script/dev-toc/generate.js index 49a3625fc0..3f27157680 100755 --- a/script/dev-toc/generate.js +++ b/script/dev-toc/generate.js @@ -3,6 +3,7 @@ import fs from 'fs' import path from 'path' import { execSync } from 'child_process' +import { program } from 'commander' import fpt from '../../lib/non-enterprise-default-version.js' import { allVersionKeys } from '../../lib/all-versions.js' import { liquid } from '../../lib/render-content/index.js' @@ -15,6 +16,19 @@ const staticDirName = 'script/dev-toc/static' const staticDir = path.posix.join(process.cwd(), staticDirName) if (!fs.existsSync(staticDir)) fs.mkdirSync(staticDir) +program + .description('Generate a local TOC of the docs website and open it in your browser') + .option( + '-o, --openSections [product-ids...]', + 'open sections for one or more product IDs by default (e.g., "-o codespaces pull-requests")' + ) + .parse(process.argv) + +const options = program.opts() + +const openSections = options.openSections || '' +const defaultOpenSections = Array.isArray(openSections) ? openSections : [openSections] + main() async function main() { @@ -38,6 +52,9 @@ async function main() { // Add the tree to the req.context. req.context.currentEnglishTree = req.context.siteTree.en[req.context.currentVersion] + // Add any defaultOpenSections to the context. + req.context.defaultOpenSections = defaultOpenSections + // Parse the layout in script/dev-toc/layout.html with the context we created above. const outputHtml = await liquid.parseAndRender(layout, Object.assign({}, req.context)) diff --git a/script/dev-toc/layout.html b/script/dev-toc/layout.html index ee44646d8f..0aa79e1971 100644 --- a/script/dev-toc/layout.html +++ b/script/dev-toc/layout.html @@ -25,7 +25,12 @@
{% for productPage in currentEnglishTree.childPages %} +{% assign productId = productPage.page.relativePath | replace: "/index.md", "" %} +{% if defaultOpenSections contains productId %} +
{{productPage.renderedFullTitle}} +{% else %}
{{productPage.renderedFullTitle}} +{% endif %}