feat: table of contents on documentation (#5108)

This commit is contained in:
Erick Zhao 2021-02-09 09:52:58 -08:00 коммит произвёл GitHub
Родитель ef42f6427d
Коммит 780ff29e07
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
13 изменённых файлов: 290 добавлений и 249 удалений

Просмотреть файл

@ -39,11 +39,10 @@ docs:
main_proc_modules: Main Process Modules
renderer_proc_modules: Renderer Process Modules
both_proc_modules: Modules for Both Process Types
footer:
propose_change: Improve this doc
version_history: Version history
translate: Translate this doc
view_all_docs: All Docs on One Page
propose_change: Improve this doc
version_history: Version history
translate: Translate this doc
view_all_docs: All Docs on One Page
languages:
choose_language: Choose Your Site Language

5
package-lock.json сгенерированный
Просмотреть файл

@ -16580,6 +16580,11 @@
}
}
},
"tocbot": {
"version": "4.12.2",
"resolved": "https://registry.npmjs.org/tocbot/-/tocbot-4.12.2.tgz",
"integrity": "sha512-rhw3BQkVrO+DdsFyK8UbVGtjWPg5BVrftscVFoUHOAxea4CZmTsLBmxfezeTdgk1wfHXiZWbtGst/NkFdttLFQ=="
},
"toidentifier": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz",

Просмотреть файл

@ -84,6 +84,7 @@
"search-with-your-keyboard": "^2.0.0",
"semver": "^7.3.4",
"set-query-string": "^2.2.0",
"tocbot": "^4.12.2",
"ultimate-pagination": "^1.0.0"
},
"devDependencies": {

Просмотреть файл

@ -95,7 +95,6 @@ img[data-src] {
h2 {
margin: 1.75em 0 1em !important;
font-size: 32px !important;
font-weight: 300 !important;
-webkit-font-smoothing: initial !important;
border-bottom: $border !important;
@ -103,7 +102,6 @@ img[data-src] {
h3 {
margin: 2em 0 0.75em !important;
font-size: 26px !important;
font-weight: 300 !important;
-webkit-font-smoothing: initial !important;
}
@ -144,4 +142,5 @@ img[data-src] {
.PRIMER-REMOVE-ME {
@import "@primer/css/index.scss";
@import 'tocbot/src/scss/_tocbot-core.scss';
}

Просмотреть файл

@ -1,209 +1,203 @@
// Docs ------------------------------
.docs-page {
a { color: #3a585f; }
}
.docs-version {
display: inline-block;
padding: 0 0.4em;
margin-left: 10px;
vertical-align: middle;
font-size: $body-font-size * 0.95;
line-height: 1.8;
font-weight: 200;
-webkit-font-smoothing: initial;
background-color: $main-bg-color;
border: 1px solid $border-color;
border-radius: $border-radius;
}
.docs-breadcrumbs {
margin: 0;
color: $main-color-subtle !important;
font-weight: 300;
a {
color: $main-color;
}
}
.docs-breadcrumbs-divider {
color: $main-color-subtle;
}
// Used on the docs index page
.docs-title {
font-size: $h1-size-mobile !important;
font-weight: $font-weight-light !important;
@include breakpoint(md) { font-size: $h1-size !important; }
color: inherit;
}
.docs {
h1 {
font-size: $h0-size-mobile !important;
font-weight: $font-weight-light !important;
@include breakpoint(md) { font-size: $h0-size !important; }
.PRIMER-REMOVE-ME {
.docs-page {
a { color: #3a585f; }
}
h2 {
.docs-version {
display: inline-block;
padding: 0 0.4em;
margin-left: 10px;
vertical-align: middle;
font-size: $body-font-size * 0.95;
line-height: 1.8;
font-weight: 200;
-webkit-font-smoothing: initial;
background-color: $main-bg-color;
border: 1px solid $border-color;
border-radius: $border-radius;
}
.docs__actions-bar {
float: right;
margin-bottom: $spacer-6;
}
.docs__nav-wrapper {
position: -webkit-sticky; /* Safari */
position: sticky;
top: $spacer-4;
}
.docs__nav {
overflow-y: auto;
max-height: 100vh;
h1 {
font-size: $h3-size;
font-weight: bold !important;
}
ol {
list-style: none !important;
}
}
.table-of-contents__list-item {
margin-bottom: initial;
}
.table-of-contents__link {
font-weight: 300;
font-size: 14px;
}
.table-of-contents__link--active {
font-weight: bold;
}
.docs-breadcrumbs {
margin: 0;
color: $main-color-subtle !important;
font-weight: 300;
a {
color: $main-color;
}
}
.docs-breadcrumbs-divider {
color: $main-color-subtle;
}
// Used on the docs index page
.docs-title {
font-size: $h1-size-mobile !important;
font-weight: $font-weight-light !important;
@include breakpoint(md) { font-size: $h1-size !important; }
color: inherit;
}
h3 {
font-size: $h2-size-mobile !important;
font-weight: $font-weight-light !important;
.docs-heading {
border-bottom: 1px solid #eee;
@include breakpoint(md) { font-size: $h2-size !important; }
}
h4 {
font-size: $h3-size-mobile !important;
font-weight: $font-weight-light !important;
@include breakpoint(md) { font-size: $h3-size !important; }
}
.sub-section[data-lang='en-US'] .en-toggle h5 {
color: $main-link-color !important;
}
.sub-section:not([data-lang='en-US']) {
.en-toggle h5 {
color: $main-bg-color !important;
}
&:hover .en-toggle h5 {
color: $main-border-color !important;
// thin titles to match the main /docs index
.strong-headers & {
font-weight: 300;
-webkit-font-smoothing: antialiased;
}
}
}
.docs-heading {
border-bottom: 1px solid #eee;
// thin titles to match the main /docs index
.strong-headers & {
font-weight: 300;
-webkit-font-smoothing: antialiased;
}
}
.docs-list,
.docs-guides > ul {
margin-left: 0;
list-style-type: none;
}
.header-link .octicon {
color: $main-color-subtle !important;
margin-left: 0.5em !important;
vertical-align: middle !important;
visibility: hidden !important;
:hover > & {
visibility: visible !important;
}
}
// labels on API docs
%doc-label {
padding: 0.1em 0.4em;
vertical-align: middle;
font-size: 0.66em;
font-weight: 300;
font-style: normal;
color: $main-bg-color;
border-radius: $border-radius;
background-color: $main-color;
margin: 0 0.3em;
a & {
&:hover {
filter: contrast(150%);
transition: all 0.2s;
}
}
}
.docs .platform-label {
@extend %doc-label;
background-color: $main-color-strong;
}
.docs .flag-label {
@extend %doc-label;
background-color: $main-color-subtle;
}
.docs table {
th {
text-align: left;
padding: $spacer-2;
}
width: 100%;
}
.doc-actions {
a {
text-decoration: none;
}
}
.docs p a,
.docs li a {
text-decoration: underline;
}
.docs-container-xl {
max-width: 1280px;
margin-right: auto;
margin-left: auto;
}
.docs-guides {
h2 {
// Match the default from primer
margin-bottom: 12px;
padding-bottom: 12px;
}
}
.docs-sub-heading {
border-bottom: 1px solid #eee;
padding-top: 12px;
}
.docs-guides-readme {
li {
break-inside: avoid;
margin-bottom: 3px;
}
> ul {
.docs-list,
.docs-guides > ul {
margin-left: 0;
list-style-type: none;
}
> li {
list-style-type: none;
.header-link .octicon {
color: $main-color-subtle !important;
margin-left: 0.5em !important;
vertical-align: middle !important;
visibility: hidden !important;
:hover > & {
visibility: visible !important;
}
}
// Hide various elements we only need on GitHub
> h2,
> h3,
> p,
> hr {
display: none;
// labels on API docs
%doc-label {
padding: 0.1em 0.4em;
vertical-align: middle;
font-size: 0.66em;
font-weight: 300;
font-style: normal;
color: $main-bg-color;
border-radius: $border-radius;
background-color: $main-color;
margin: 0 0.3em;
a & {
&:hover {
filter: contrast(150%);
transition: all 0.2s;
}
}
}
.docs .platform-label {
@extend %doc-label;
background-color: $main-color-strong;
}
.docs .flag-label {
@extend %doc-label;
background-color: $main-color-subtle;
}
.docs table {
th {
text-align: left;
padding: $spacer-2;
}
width: 100%;
}
.docs .markdown-body {
overflow: auto;
padding-bottom: 500px;
:not(h1, h2, h3, h4, h5, h6) > a {
text-decoration: underline;
}
}
.docs-container-xl {
max-width: 1280px;
margin-right: auto;
margin-left: auto;
}
.docs-guides {
h2 {
// Match the default from primer
margin-bottom: 12px;
padding-bottom: 12px;
}
}
.docs-sub-heading {
border-bottom: 1px solid #eee;
padding-top: 12px;
}
.docs-guides-readme {
li {
break-inside: avoid;
margin-bottom: 3px;
}
> ul {
margin-left: 0;
> li {
list-style-type: none;
}
}
// Hide various elements we only need on GitHub
> h2,
> h3,
> p,
> hr {
display: none;
}
}
}

Просмотреть файл

@ -3,9 +3,9 @@ const editorCodes = require('crowdin-editor-language-codes')
module.exports = (req, res, next) => {
const doc = i18n.docs[req.language][req.path]
const docEn = req.context.currentLocale.startsWith('en')
? null
: i18n.docs['en-US'][req.path]
// const docEn = req.context.currentLocale.startsWith('en')
// ? null
// : i18n.docs['en-US'][req.path]
if (!doc) return next()
// Crowdin's undocumented mystery locale URL format. See https://git.io/vADu0
@ -19,7 +19,8 @@ module.exports = (req, res, next) => {
const context = Object.assign(req.context, {
doc: doc,
docEn: docEn,
// docEn: docEn,
isDocPage: true,
page: {
title: `${doc.title} | Electron`,
description: doc.description,

Просмотреть файл

@ -0,0 +1,39 @@
const tocbot = require('tocbot')
function generateTableOfContents() {
if (!!document.querySelector('.docs__table-of-contents')) {
tocbot.init({
tocSelector: '.docs__table-of-contents',
linkClass: 'table-of-contents__link',
activeLinkClass: 'table-of-contents__link--active',
listClass: 'table-of-contents__list',
listItemClass: 'table-of-contents__list-item',
contentSelector: '.markdown-body',
headingSelector: 'h2, h3, h4, h5, h6', // avoid h1 because there's only one h1
hasInnerContainers: true,
collapseDepth: 6, // don't collapse any elements (looks bad with large lists)
disableTocScrollSync: true, // don't scroll TOC with page scroll (looks bad with large lists)
headingLabelCallback: (str) => {
/**
* Clean up table of content strings using regex. We want to avoid
* having long and repetitive strings for our Events and APIs.
* 1. For events: `Event: 'close'` becomes `close`
* 2. For properties/methods: `win.previewFile(path[, displayName]) macOS`
* becomes `previewFile`
*/
let regexMatch
if ((regexMatch = str.match(/Event: '([a-z]*(?:-[a-z]+)*)'/))) {
return regexMatch[1]
} else if (
(regexMatch = str.match(/^[a-zA-Z]+\.((?:[a-zA-Z]+[\.]?)+)/))
) {
return regexMatch[1]
}
return str
},
})
}
}
module.exports = generateTableOfContents

Просмотреть файл

@ -22,6 +22,7 @@ document.addEventListener('DOMContentLoaded', () => {
require('./language-selector')()
require('./kb-shortcut-dialog')()
require('./docs-api-labels')()
require('./docs-table-of-contents')()
require('./anchor-links')()
require('./science')()
})

Просмотреть файл

@ -8,7 +8,7 @@ const nock = require('nock')
const cheerio = require('cheerio')
const chai = require('chai')
const i18n = require('../lib/i18n')
chai.should()
const should = chai.should()
chai.use(require('chai-cheerio'))
const app = require('../server.js')
@ -290,14 +290,14 @@ describe('electronjs.org', () => {
res.statusCode.should.equal(404)
})
describe('docs footer', () => {
describe('docs actions', () => {
test('includes a link to edit the doc on GitHub', async () => {
const $ = await get('/docs/api/accelerator')
$('.propose-change')
.attr('href')
.should.eq(
'https://github.com/electron/electron/tree/master/docs/api/accelerator.md'
should.exist(
$(
'[href="https://github.com/electron/electron/tree/master/docs/api/accelerator.md"]'
)
)
})
test('includes a link to translate the doc on Crowdin', async () => {
@ -305,9 +305,9 @@ describe('electronjs.org', () => {
.get('/docs/api/accelerator')
.set('Cookie', ['language=zh-CN'])
const $ = cheerio.load(res.text)
$('.translate-on-crowdin')
.attr('href')
.should.eq('https://crowdin.com/translate/electron/63/en-zhcn')
should.exist(
$('[href="https://crowdin.com/translate/electron/63/en-zhcn"]')
)
})
test('includes a link to translate the doc on Crowdin for French', async () => {
@ -315,9 +315,9 @@ describe('electronjs.org', () => {
.get('/docs/api/crash-reporter')
.set('Cookie', ['language=fr-FR'])
const $ = cheerio.load(res.text)
$('.translate-on-crowdin')
.attr('href')
.should.eq('https://crowdin.com/translate/electron/74/en-fr')
should.exist(
$('[href="https://crowdin.com/translate/electron/74/en-fr"]')
)
})
test('includes a link to Crowdin language picker when language is English', async () => {
@ -327,9 +327,9 @@ describe('electronjs.org', () => {
.get('/docs/api/browser-view')
.set('Cookie', ['language=en-US'])
const $ = cheerio.load(res.text)
$('.translate-on-crowdin')
.attr('href')
.should.eq('https://crowdin.com/translate/electron/66/en-en')
should.exist(
$('[href="https://crowdin.com/translate/electron/66/en-en"]')
)
})
test('includes a link to view doc history', async () => {
@ -341,7 +341,7 @@ describe('electronjs.org', () => {
})
})
describe('language toggle on docs', () => {
describe.skip('language toggle on docs', () => {
test('each localized documentation section should have an corresponding english section', async () => {
const res = await supertest(app)
.get('/docs/tutorial/desktop-environment-integration')

Просмотреть файл

@ -111,7 +111,7 @@
<div class="py-6 py-md-7 py-lg-8">
<div class="container-lg p-responsive clearfix">
<p class="text-center">
<a href="/docs/all">{{localized.docs.footer.view_all_docs}}</a>
<a href="/docs/all">{{localized.docs.view_all_docs}}</a>
{{localized.or}}
<a href="/docs/faq">{{localized.footer.see_the_faq}}</a>.
</p>

Просмотреть файл

@ -1,7 +1,6 @@
{{#each doc.sections}}
{{> doc
doc=this
docEn=(lookup ../docEn.sections @index)
currentLocale=../currentLocale
}}
{{/each}}

Просмотреть файл

@ -5,7 +5,6 @@
<div class='container-lg'>
<h1>
<span class="f0-light mr-3 mr-lg-4">{{localized.docs.title}}</span>
<!-- <span class="docs-version">{{electronLatestStableVersion}}</span> -->
</h1>
</div>
@ -22,7 +21,7 @@
<a href="{{doc.href}}">{{doc.title}}</a>
{{#if viewingDocHistory}}
/ Version History
/ {{localized.docs.version_history}}
{{else}}
<a href="{{doc.href}}/history">
<span class="docs-version">
@ -34,9 +33,6 @@
</span>
</a>
{{/if}}
{{else if viewingAllDocs}}
All
{{/if}}
@ -44,28 +40,35 @@
</div>
</div>
<div class='py-6 py-md-7 py-lg-8'>
<div class='container-lg p-responsive docs strong-headers'>
<div class="markdown-body">{{{body}}}</div>
<hr>
<div class="doc-actions text-center">
<a class="mr-4 propose-change" href='{{doc.githubUrl}}'>
<span class="octicon octicon-mark-github"></span>
{{localized.docs.footer.propose_change}}
</a>
<a class="mr-4 translate-on-crowdin" href='{{doc.crowdinUrl}}'>
<span class="octicon octicon-globe"></span>
{{localized.docs.footer.translate}}
</a>
<a class="mr-4" href='{{doc.href}}/history'>
<span class="octicon octicon-history"></span>
{{localized.docs.footer.version_history}}
</a>
</div>
<div class='d-flex full-width p-responsive docs strong-headers'>
<div class="hide-md col-lg-2 p-4">
<!-- Left Column -->
</div>
<div class="col-lg-12 col-xl-7 pt-4 markdown-body">
<!-- Middle Column -->
{{#if isDocPage}}
<aside class="docs__actions-bar">
<a class="btn btn-sm btn-outline" href="{{doc.githubUrl}}" role="button">{{localized.docs.propose_change}}</a>
<a class="btn btn-sm btn-outline" href="{{doc.crowdinUrl}}">{{localized.docs.translate}}</a>
</aside>
{{/if}}
{{{body}}}
</div>
<div class="hide-sm hide-md hide-lg col-lg-4 col-xl-3 pt-4">
<!-- Right Column -->
{{#if isDocPage}} <!-- if generated from docs/show.js -->
<div class="docs__nav-wrapper">
<nav class="docs__nav">
<h1>Table of Contents</h1>
<div class="docs__table-of-contents pb-12">
</div>
</nav>
</div>
{{/if}}
</div>
</div>
</main>

Просмотреть файл

@ -1,16 +1,16 @@
<div class="sub-section position-relative" data-name="{{name}}" data-lang="{{currentLocale}}">
{{#unless viewingAllDocs}}
{{!-- {{#unless viewingAllDocs}}
{{#if docEn}}
<button data-sc-category="docs" data-sc-name="Toggle section language" class="btn-link position-absolute right-0 mr-2 mt-2 no-underline en-toggle" alt="toggle section language"><h5 class="h5-mktg m-0">EN</h5></button>
<button data-sc-category="docs" data-sc-name="Toggle section language" class="btn-link position-absolute right-0 mr-2 mt-2 no-underline en-toggle" alt="toggle section language">EN</button>
{{/if}}
{{/unless}}
{{/unless}} --}}
{{{html}}}
</div>
{{#if docEn}}
{{!-- {{#if docEn}}
{{#unless viewingAllDocs}}
<div class="sub-section position-relative hidden" data-name="{{name}}" data-lang="en-US">
<button data-sc-category="docs" data-sc-name="Toggle section language" class="btn-link position-absolute right-0 mr-2 mt-2 no-underline en-toggle" alt="toggle section language"><h5 class="h5-mktg m-0">EN</h5></button>
<button data-sc-category="docs" data-sc-name="Toggle section language" class="btn-link position-absolute right-0 mr-2 mt-2 no-underline en-toggle" alt="toggle section language">EN</button>
{{{docEn.html}}}
</div>
{{/unless}}
{{/if}}
{{/if}} --}}