diff --git a/.eslintrc.json b/.eslintrc.json index 0e0899c3..83b5cae5 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -59,8 +59,9 @@ }, "globals": { "multipageMap": "readonly", - "usesMultipage": "readonly", + "isMultipage": "readonly", "idToSection": "readonly", + "toggleMultipage": "readonly", "sdoMap": "readonly", "biblio": "readonly", "debounce": "writable", diff --git a/css/elements.css b/css/elements.css index 202c1739..d211284e 100644 --- a/css/elements.css +++ b/css/elements.css @@ -267,9 +267,7 @@ body { word-wrap: break-word; font-size: 18px; line-height: 1.5; - font-family: - 'IBM Plex Serif', - serif; + font-family: 'IBM Plex Serif', serif; font-variant-numeric: slashed-zero; padding: 0; margin: 0; @@ -287,7 +285,9 @@ body { padding-bottom: 1em; } -h1.shortname { display: none; } +h1.shortname { + display: none; +} body.oldtoc { margin: 0 auto; @@ -345,9 +345,7 @@ span.e-user-code::before { line-height: normal; vertical-align: middle; text-transform: uppercase; - font-family: - 'IBM Plex Sans', - sans-serif; + font-family: 'IBM Plex Sans', sans-serif; font-weight: 900; font-size: x-small; } @@ -370,10 +368,7 @@ span.e-user-code::before { code { font-weight: bold; - font-family: - 'Comic Code', - 'IBM Plex Mono', - monospace; + font-family: 'Comic Code', 'IBM Plex Mono', monospace; white-space: pre; } @@ -451,9 +446,7 @@ var.referenced6 { } emu-const { - font-family: - 'IBM Plex Sans', - sans-serif; + font-family: 'IBM Plex Sans', sans-serif; font-variant: small-caps; text-transform: uppercase; } @@ -476,11 +469,12 @@ emu-alg li.exit::before { vertical-align: middle; } -html.show-early-exits emu-alg li.exit:not(emu-alg ol.ac-body > li:last-child):not(emu-alg > ol > li:last-child)::before { +html.show-early-exits + emu-alg + li.exit:not(emu-alg ol.ac-body > li:last-child):not(emu-alg > ol > li:last-child)::before { display: inline-block; } - /* depth 1 */ emu-alg ol, /* depth 4 */ @@ -673,9 +667,7 @@ emu-rhs emu-nt { emu-t { display: inline-block; - font-family: - 'IBM Plex Mono', - monospace; + font-family: 'IBM Plex Mono', monospace; font-weight: bold; white-space: nowrap; text-indent: 0; @@ -710,9 +702,7 @@ emu-mods { emu-params, emu-opt { margin-right: 1ex; - font-family: - 'IBM Plex Mono', - monospace; + font-family: 'IBM Plex Mono', monospace; } emu-params, @@ -726,9 +716,7 @@ emu-opt { emu-gprose { font-size: 0.9em; - font-family: - 'IBM Plex Sans', - sans-serif; + font-family: 'IBM Plex Sans', sans-serif; } emu-production emu-gprose { @@ -999,7 +987,8 @@ emu-table td { background: var(--background-color); } -td[colspan]:not([colspan="1"]), th[colspan]:not([colspan="1"]) { +td[colspan]:not([colspan='1']), +th[colspan]:not([colspan='1']) { text-align: center; } @@ -1667,3 +1656,10 @@ li.menu-search-result-term::before { background: var(--figure-background); width: 500px; } + +/* Other dynamic elements */ +:root[data-multipage-preference=''] [data-multipage-preference=''], +:root[data-multipage-preference='single-page'] [data-multipage-preference='single-page'], +:root[data-multipage-preference='multi-page'] [data-multipage-preference='multi-page'] { + font-weight: bold; +} diff --git a/css/print.css b/css/print.css index f67a6e23..a4f6180b 100644 --- a/css/print.css +++ b/css/print.css @@ -1,10 +1,14 @@ +.no-print { + display: none !important; +} + @font-face { - font-family: "Arial Plus"; - src: local("Arial"); + font-family: 'Arial Plus'; + src: local('Arial'); } @font-face { - font-family: "Arial Plus"; + font-family: 'Arial Plus'; unicode-range: U+30; font-style: normal; font-weight: 400; @@ -12,15 +16,15 @@ } @font-face { - font-family: "Arial Plus"; + font-family: 'Arial Plus'; unicode-range: U+221e; font-style: normal; font-weight: 400; - src: local("DejaVu Math TeX Gyre"); + src: local('DejaVu Math TeX Gyre'); } @font-face { - font-family: "Arial Plus"; + font-family: 'Arial Plus'; unicode-range: U+30; font-style: normal; font-weight: 700; @@ -28,15 +32,15 @@ } @font-face { - font-family: "Arial Plus"; + font-family: 'Arial Plus'; unicode-range: U+221e; font-style: normal; font-weight: 700; - src: local("DejaVu Math TeX Gyre"); + src: local('DejaVu Math TeX Gyre'); } @font-face { - font-family: "Arial Plus"; + font-family: 'Arial Plus'; unicode-range: U+30; font-style: italic; font-weight: 400; @@ -44,15 +48,15 @@ } @font-face { - font-family: "Arial Plus"; + font-family: 'Arial Plus'; unicode-range: U+221e; font-style: italic; font-weight: 400; - src: local("DejaVu Math TeX Gyre"); + src: local('DejaVu Math TeX Gyre'); } @font-face { - font-family: "Arial Plus"; + font-family: 'Arial Plus'; unicode-range: U+30; font-style: italic; font-weight: 700; @@ -60,11 +64,11 @@ } @font-face { - font-family: "Arial Plus"; + font-family: 'Arial Plus'; unicode-range: U+221e; font-style: italic; font-weight: 700; - src: local("DejaVu Math TeX Gyre"); + src: local('DejaVu Math TeX Gyre'); } :root { @@ -186,18 +190,27 @@ page-break-after: always; } -html, body { +html, +body { background-color: initial; } body { - font-family: 'Arial Plus', Arial, Helvetica, sans-serif, "DejaVu Math TeX Gyre", Symbola, monospace; + font-family: 'Arial Plus', Arial, Helvetica, sans-serif, 'DejaVu Math TeX Gyre', Symbola, + monospace; font-size: 10pt; color: #000; line-height: 1.15; } -h1, h2, h3, h4, h5, h6 { -prince-bookmark-level: none } /* see https://www.princexml.com/doc/prince-output/#pdf-bookmarks */ +h1, +h2, +h3, +h4, +h5, +h6 { + -prince-bookmark-level: none; +} /* see https://www.princexml.com/doc/prince-output/#pdf-bookmarks */ .copyright-notice + h1.title { break-before: recto; @@ -217,8 +230,12 @@ p { text-wrap: pretty; overflow-wrap: break-word; hyphens: auto; - orphans: 2, -prince-prefer 3; /* see https://www.princexml.com/doc/prince-for-books/#pagination-goals */ - widows: 2, -prince-prefer 3; + orphans: + 2, + -prince-prefer 3; /* see https://www.princexml.com/doc/prince-for-books/#pagination-goals */ + widows: + 2, + -prince-prefer 3; } h1 { @@ -294,7 +311,8 @@ emu-table td p { overflow: hidden; } -emu-nt, emu-t { +emu-nt, +emu-t { display: initial; } @@ -310,7 +328,9 @@ emu-intro { page: intro; } -emu-intro, emu-clause, emu-annex { +emu-intro, +emu-clause, +emu-annex { margin-top: 4ex; } @@ -335,7 +355,9 @@ emu-clause > p:first-of-type + emu-alg { break-before: avoid; } -emu-intro emu-intro, emu-clause emu-clause, emu-annex emu-annex { +emu-intro emu-intro, +emu-clause emu-clause, +emu-annex emu-annex { margin-top: 3.5ex; } @@ -351,56 +373,80 @@ emu-annex emu-annex emu-annex emu-annex emu-annex { margin-top: 3.2ex; } -emu-intro h1, emu-clause h1 , emu-annex h1 { +emu-intro h1, +emu-clause h1, +emu-annex h1 { break-after: avoid; font-size: 12pt; -prince-bookmark-level: 1; -prince-bookmark-label: content(); } -emu-clause emu-clause h1, emu-annex emu-annex h1 { +emu-clause emu-clause h1, +emu-annex emu-annex h1 { -prince-bookmark-level: 2; -prince-bookmark-state: closed; } -emu-clause emu-clause h1, emu-annex emu-annex h1, -emu-intro h2, emu-clause h2, emu-annex h2 { +emu-clause emu-clause h1, +emu-annex emu-annex h1, +emu-intro h2, +emu-clause h2, +emu-annex h2 { font-size: 11pt; } -emu-clause emu-clause emu-clause h1, emu-annex emu-annex emu-annex h1 { +emu-clause emu-clause emu-clause h1, +emu-annex emu-annex emu-annex h1 { -prince-bookmark-level: 3; } -emu-clause emu-clause emu-clause emu-clause h1, emu-annex emu-annex emu-annex emu-annex h1 { +emu-clause emu-clause emu-clause emu-clause h1, +emu-annex emu-annex emu-annex emu-annex h1 { -prince-bookmark-level: 4; } -emu-clause emu-clause emu-clause emu-clause emu-clause h1, emu-annex emu-annex emu-annex emu-annex emu-annex h1 { +emu-clause emu-clause emu-clause emu-clause emu-clause h1, +emu-annex emu-annex emu-annex emu-annex emu-annex h1 { -prince-bookmark-level: 5; } -emu-clause emu-clause emu-clause emu-clause emu-clause emu-clause h1, emu-annex emu-annex emu-annex emu-annex emu-annex emu-annex h1 { +emu-clause emu-clause emu-clause emu-clause emu-clause emu-clause h1, +emu-annex emu-annex emu-annex emu-annex emu-annex emu-annex h1 { -prince-bookmark-level: 6; } -emu-clause emu-clause emu-clause h1, emu-annex emu-annex emu-annex h1, -emu-clause emu-clause h2, emu-annex emu-annex h2, -emu-clause emu-clause emu-clause emu-clause h1, emu-annex emu-annex emu-annex emu-annex h1, -emu-clause emu-clause emu-clause h2, emu-annex emu-annex emu-annex h2, -emu-clause emu-clause emu-clause emu-clause emu-clause h1, emu-annex emu-annex emu-annex emu-annex emu-annex h1, -emu-clause emu-clause emu-clause emu-clause h2, emu-annex emu-annex emu-annex emu-annex h2, -emu-clause emu-clause emu-clause emu-clause emu-clause emu-clause h1, emu-annex emu-annex emu-annex emu-annex emu-annex emu-annex h1, -emu-clause emu-clause emu-clause emu-clause emu-clause h2, emu-annex emu-annex emu-annex emu-annex emu-annex h2 { +emu-clause emu-clause emu-clause h1, +emu-annex emu-annex emu-annex h1, +emu-clause emu-clause h2, +emu-annex emu-annex h2, +emu-clause emu-clause emu-clause emu-clause h1, +emu-annex emu-annex emu-annex emu-annex h1, +emu-clause emu-clause emu-clause h2, +emu-annex emu-annex emu-annex h2, +emu-clause emu-clause emu-clause emu-clause emu-clause h1, +emu-annex emu-annex emu-annex emu-annex emu-annex h1, +emu-clause emu-clause emu-clause emu-clause h2, +emu-annex emu-annex emu-annex emu-annex h2, +emu-clause emu-clause emu-clause emu-clause emu-clause emu-clause h1, +emu-annex emu-annex emu-annex emu-annex emu-annex emu-annex h1, +emu-clause emu-clause emu-clause emu-clause emu-clause h2, +emu-annex emu-annex emu-annex emu-annex emu-annex h2 { font-size: 10pt; } -emu-clause ol, emu-clause ul, emu-clause dl, emu-annex ol, emu-annex ul, emu-annex dl { +emu-clause ol, +emu-clause ul, +emu-clause dl, +emu-annex ol, +emu-annex ul, +emu-annex dl { margin-left: 0; padding-left: 1.75em; } -emu-clause ol ol, emu-clause ul ul { +emu-clause ol ol, +emu-clause ul ul { padding-left: 2em; } @@ -425,7 +471,8 @@ emu-table th { overflow-wrap: break-word; } -caption, table > figcaption { +caption, +table > figcaption { caption-side: top; color: #000; font-weight: bold; @@ -571,7 +618,8 @@ emu-annex > h1 .secnum { margin: 0 0 1lh; } -.copyright-notice { /* ecma mandated */ +.copyright-notice { + /* ecma mandated */ font-style: italic; border: 1px solid black; padding: 1em; @@ -607,7 +655,10 @@ h1.shortname { margin-top: 0; } -h1.shortname a:link, h1.shortname a:visited, h1.shortname a:hover, h1.shortname a:active { +h1.shortname a:link, +h1.shortname a:visited, +h1.shortname a:hover, +h1.shortname a:active { color: black; } diff --git a/js/menu.js b/js/menu.js index 4b1a8515..27f4ab1b 100644 --- a/js/menu.js +++ b/js/menu.js @@ -1074,11 +1074,11 @@ function sortByClauseNumber(clause1, clause2) { function makeLinkToId(id) { let hash = '#' + id; - if (typeof idToSection === 'undefined' || !idToSection[id]) { - return hash; + if (typeof isMultipage !== 'undefined' && isMultipage && idToSection[id]) { + let targetSec = idToSection[id]; + return (targetSec === 'index' ? './' : targetSec + '.html') + hash; } - let targetSec = idToSection[id]; - return (targetSec === 'index' ? './' : targetSec + '.html') + hash; + return hash; } function doShortcut(e) { @@ -1093,23 +1093,8 @@ function doShortcut(e) { if (e.altKey || e.ctrlKey || e.metaKey) { return; } - if (e.key === 'm' && usesMultipage) { - let pathParts = location.pathname.split('/'); - let hash = location.hash; - if (pathParts[pathParts.length - 2] === 'multipage') { - if (hash === '') { - let sectionName = pathParts[pathParts.length - 1]; - if (sectionName.endsWith('.html')) { - sectionName = sectionName.slice(0, -5); - } - if (idToSection['sec-' + sectionName] !== undefined) { - hash = '#sec-' + sectionName; - } - } - location = pathParts.slice(0, -2).join('/') + '/' + hash; - } else { - location = 'multipage/' + hash; - } + if (e.key === 'm' && typeof toggleMultipage !== 'undefined') { + toggleMultipage(); } else if (e.key === 'u') { document.documentElement.classList.toggle('show-uc-annotations'); } else if (e.key === 'e') { diff --git a/js/multipage.js b/js/multipage.js index a813ea76..d68baa68 100644 --- a/js/multipage.js +++ b/js/multipage.js @@ -1,4 +1,14 @@ 'use strict'; + +let parseSpecPath = url => { + let pathParts = url.pathname.split('/'); + let isMultipage = pathParts[pathParts.length - 2] === 'multipage'; + let pathPrefixEnd = isMultipage ? -2 : pathParts.findLastIndex(part => part !== '') + 1; + let pathPrefix = pathParts.slice(0, pathPrefixEnd).join('/'); + return { pathParts, pathPrefix, isMultipage }; +}; + +// initialize globals let idToSection = Object.create(null); for (let [section, ids] of Object.entries(multipageMap)) { for (let id of ids) { @@ -7,13 +17,91 @@ for (let [section, ids] of Object.entries(multipageMap)) { } } } -if (location.hash) { - let targetSec = idToSection[location.hash.substring(1)]; - if (targetSec != null) { - let match = location.pathname.match(/([^/]+)\.html?$/); - if ((match != null && match[1] !== targetSec) || location.pathname.endsWith('/multipage/')) { - window.navigating = true; - location = (targetSec === 'index' ? './' : targetSec + '.html') + location.hash; +let { pathParts, pathPrefix, isMultipage } = parseSpecPath(location); +let activeSec = isMultipage ? pathParts[pathParts.length - 1].replace(/\.html$/, '') : undefined; +let activeSecHash = + activeSec && idToSection['sec-' + activeSec] != null ? '#sec-' + activeSec : undefined; +let storage = typeof localStorage !== 'undefined' ? localStorage : Object.create(null); +let toggleMultipage = () => { + let hash = location.hash; + if (isMultipage) { + location = pathParts.slice(0, -2).join('/') + '/' + (hash || activeSecHash || ''); + } else { + let targetSec = hash ? idToSection[hash.substring(1)] : undefined; + location = 'multipage/' + (targetSec ? targetSec + '.html' : '') + hash; + } +}; + +// redirect to single-page/multi-page per preference +(() => { + // ...except from internal links + let referrer; + try { + referrer = new URL(document.referrer); + } catch (_err) { + // ignore + } + if (referrer && referrer.host === location.host) { + if (parseSpecPath(referrer).pathPrefix === pathPrefix) return; + } + + let resolvedHash = location.hash || activeSecHash || ''; + let targetSec = resolvedHash ? idToSection[resolvedHash.substring(1)] : undefined; + let multipagePreference = storage.multipagePreference; + if (isMultipage && multipagePreference === 'single-page') { + window.navigating = true; + location = pathParts.slice(0, -2).join('/') + '/' + resolvedHash; + } else if ( + isMultipage + ? targetSec != null && (activeSec || 'index') !== targetSec + : multipagePreference === 'multi-page' + ) { + window.navigating = true; + location = 'multipage/' + (targetSec ? targetSec + '.html' : '') + location.hash; + } +})(); + +// enable preference togglers +document.documentElement.dataset.multipagePreference = storage.multipagePreference || ''; +if (typeof localStorage !== 'undefined') { + let enableToggles = () => { + for (let el of document.querySelectorAll('[disabled][data-multipage-preference]')) { + el.disabled = false; } + }; + if (document.readyState === 'loading') { + document.addEventListener('DOMContentLoaded', enableToggles); + } else { + enableToggles(); } + document.addEventListener('click', e => { + if (!(e.target instanceof HTMLElement)) { + return; + } + let target = e.target; + let toggler = target.closest('[data-multipage-preference]'); + if (target.isContentEditable || !toggler || toggler === document.documentElement) { + return; + } + switch (target.nodeName.toLowerCase()) { + case 'textarea': + case 'select': + return; + case 'input': { + let isCheckable = target.type === 'checkbox' || target.type === 'radio'; + if (toggler !== target || !isCheckable || !target.checked) { + return; + } + } + } + let multipagePreference = toggler.dataset.multipagePreference; + if (multipagePreference !== (storage.multipagePreference || '')) { + storage.multipagePreference = multipagePreference; + document.documentElement.dataset.multipagePreference = multipagePreference; + if (multipagePreference === (isMultipage ? 'single-page' : 'multi-page')) { + toggleMultipage(); + } + } + e.preventDefault(); + }); } diff --git a/spec/index.html b/spec/index.html index 944b0866..813dfbd3 100644 --- a/spec/index.html +++ b/spec/index.html @@ -90,6 +90,12 @@

Stylesheets and other assets

Ecmarkup requires CSS styles and other assets. By default all assets are inlined into the document. You can override this by setting assets to "none" (for example if you want to manually link to external assets) or "external". When using "external" the default directory for assets is `assets` in the same directory as the output file, but you can override this with `--assets-dir`.

+ +

Multipage

+

Multi-page builds support a sticky preference for accessing the resulting document as a single page or as multiple pages. It can be set by embedding elements (such as <a> or <button>) with attribute data-multipage-preference set to either an empty string (for the default lack of preference), "single-page", or "multi-page". When such an element is clicked, the corresponding preference is written into localStorage and a navigation is triggered if necessary. From that point forward, loading any page directly or from an external link will respect that preference and redirect as necessary.

+ Links internal to the document are not subject to such redirection, allowing free alternation between single-page and multi-page experiences. +
+

Editorial Conventions

There are a large number of features in Ecmarkup. Detailed documentation can be found in later sections. This section provides a high-level overview of what capabilities are available and when to use them.

diff --git a/src/Spec.ts b/src/Spec.ts index cf675b84..55c9631c 100644 --- a/src/Spec.ts +++ b/src/Spec.ts @@ -687,8 +687,7 @@ export default class Spec { this.doc.body.insertBefore(ele, this.doc.body.firstChild); } - const jsContents = - (await concatJs(sdoJs, tocJs)) + `\n;let usesMultipage = ${!!this.opts.multipage}`; + const jsContents = await concatJs(sdoJs, tocJs); const jsSha = sha(jsContents); await this.buildAssets(jsContents, jsSha); @@ -1010,8 +1009,6 @@ export default class Spec { htmlEle = src.substring(0, src.length - ''.length); } - const head = this.doc.head.cloneNode(true) as HTMLHeadElement; - const containedMap = JSON.stringify(Object.fromEntries(sectionToContainedIds)).replace( /[\\`$]/g, '\\$&', @@ -1035,10 +1032,13 @@ ${await utils.readFile(path.join(__dirname, '../js/multipage.js'))} path.relative(this.opts.outfile!, multipageLocationOnDisk) + '?cache=' + sha(multipageJsContents); - multipageScript.setAttribute('defer', ''); - head.insertBefore(multipageScript, head.querySelector('script')); + // fetch in parallel, but evaluate ASAP in case of redirect + multipageScript.setAttribute('async', ''); + this.doc.head.insertBefore(multipageScript, this.doc.head.querySelector('script')); } + const head = this.doc.head.cloneNode(true) as HTMLHeadElement; + for (const { name, eles } of sections) { this.log(`Generating section ${name}...`); const headClone = head.cloneNode(true) as HTMLHeadElement; @@ -1335,7 +1335,13 @@ ${this.opts.multipage ? `
  • Navigate to/from multipagemJump to the nth pin1-9
  • Jump to the 10th pin0
  • Jump to the most recent link target\`
  • -`; + +
    + Multipage preference + + + +
    `; return shortcutsHelp; } diff --git a/test/baselines/generated-reference/abstract-methods.html b/test/baselines/generated-reference/abstract-methods.html index d5e1221f..7ec886bd 100644 --- a/test/baselines/generated-reference/abstract-methods.html +++ b/test/baselines/generated-reference/abstract-methods.html @@ -10,7 +10,13 @@
  • Jump to the nth pin1-9
  • Jump to the 10th pin0
  • Jump to the most recent link target`
  • -
    + +
    + Multipage preference + + + +
    Table 1: Abstract Methods of Module Record
    diff --git a/test/baselines/generated-reference/algorithm-replacements.html b/test/baselines/generated-reference/algorithm-replacements.html index 7ddc347c..b6d9b085 100644 --- a/test/baselines/generated-reference/algorithm-replacements.html +++ b/test/baselines/generated-reference/algorithm-replacements.html @@ -10,7 +10,13 @@
  • Jump to the nth pin1-9
  • Jump to the 10th pin0
  • Jump to the most recent link target`
  • -
    + +
    + Multipage preference + + + +

    1 Title

    diff --git a/test/baselines/generated-reference/algorithms.html b/test/baselines/generated-reference/algorithms.html index ba9d53c1..f806082b 100644 --- a/test/baselines/generated-reference/algorithms.html +++ b/test/baselines/generated-reference/algorithms.html @@ -10,7 +10,13 @@
  • Jump to the nth pin1-9
  • Jump to the 10th pin0
  • Jump to the most recent link target`
  • -
    + +
    + Multipage preference + + + +
    1. Can call abstract operations in this spec: Internal();
    2. Can call abstract operations in ES6: ReturnIfAbrupt(completion);
    3. Can call abstract operations in a biblio file: Biblio();
    4. Unfound abstract operations just don't link: Unfound();
    5. Can prefix with ! and ?.
      1. Let foo be ? Internal();
      2. Set foo to ! Internal();
      3. Set foo to ! SDO of operation.
      4. Set foo to ! operation.[[MOP]]().
    6. A Record looks like this: Record { [[Key]]: 0 }.
    7. A List looks like this: « 0, 1 ».
    diff --git a/test/baselines/generated-reference/assets-inline.html b/test/baselines/generated-reference/assets-inline.html index fe3bb564..62b7a41c 100644 --- a/test/baselines/generated-reference/assets-inline.html +++ b/test/baselines/generated-reference/assets-inline.html @@ -1158,11 +1158,11 @@ function makeLinkToId(id) { let hash = '#' + id; - if (typeof idToSection === 'undefined' || !idToSection[id]) { - return hash; + if (typeof isMultipage !== 'undefined' && isMultipage && idToSection[id]) { + let targetSec = idToSection[id]; + return (targetSec === 'index' ? './' : targetSec + '.html') + hash; } - let targetSec = idToSection[id]; - return (targetSec === 'index' ? './' : targetSec + '.html') + hash; + return hash; } function doShortcut(e) { @@ -1177,23 +1177,8 @@ if (e.altKey || e.ctrlKey || e.metaKey) { return; } - if (e.key === 'm' && usesMultipage) { - let pathParts = location.pathname.split('/'); - let hash = location.hash; - if (pathParts[pathParts.length - 2] === 'multipage') { - if (hash === '') { - let sectionName = pathParts[pathParts.length - 1]; - if (sectionName.endsWith('.html')) { - sectionName = sectionName.slice(0, -5); - } - if (idToSection['sec-' + sectionName] !== undefined) { - hash = '#sec-' + sectionName; - } - } - location = pathParts.slice(0, -2).join('/') + '/' + hash; - } else { - location = 'multipage/' + hash; - } + if (e.key === 'm' && typeof toggleMultipage !== 'undefined') { + toggleMultipage(); } else if (e.key === 'u') { document.documentElement.classList.toggle('show-uc-annotations'); } else if (e.key === 'e') { @@ -1617,8 +1602,7 @@ }); let sdoMap = JSON.parse(`{}`); -let biblio = JSON.parse(`{"refsByClause":{},"entries":[{"type":"clause","id":"sec-intro","titleHTML":"Intro","number":""},{"type":"clause","id":"sec-copyright-and-software-license","title":"Copyright & Software License","titleHTML":"Copyright & Software License","number":"A"}]}`); -;let usesMultipage = false