| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -7,4 +7,5 @@ tools/icu | |||
| 7 | 7 | tools/lint-md/lint-md.mjs | |
| 8 | 8 | benchmark/tmp | |
| 9 | 9 | doc/**/*.js | |
| 10 | + !doc/api_assets/*.js | ||
| 10 | 11 | !.eslintrc.js | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1,5 +1,9 @@ | |||
| 1 | 1 | # API Reference Document Assets | |
| 2 | 2 | ||
| 3 | + ## api.js | ||
| 4 | + | ||
| 5 | + The main script for API reference documents. | ||
| 6 | + | ||
| 3 | 7 | ## hljs.css | |
| 4 | 8 | ||
| 5 | 9 | The syntax theme for code snippets in API reference documents. | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,141 @@ | |||
| 1 | + 'use strict'; | ||
| 2 | + | ||
| 3 | + { | ||
| 4 | + function setupTheme() { | ||
| 5 | + const kCustomPreference = 'customDarkTheme'; | ||
| 6 | + const userSettings = sessionStorage.getItem(kCustomPreference); | ||
| 7 | + const themeToggleButton = document.getElementById('theme-toggle-btn'); | ||
| 8 | + | ||
| 9 | + if (userSettings === null && window.matchMedia) { | ||
| 10 | + const mq = window.matchMedia('(prefers-color-scheme: dark)'); | ||
| 11 | + | ||
| 12 | + if ('onchange' in mq) { | ||
| 13 | + function mqChangeListener(e) { | ||
| 14 | + document.documentElement.classList.toggle('dark-mode', e.matches); | ||
| 15 | + } | ||
| 16 | + mq.addEventListener('change', mqChangeListener); | ||
| 17 | + if (themeToggleButton) { | ||
| 18 | + themeToggleButton.addEventListener('click', function() { | ||
| 19 | + mq.removeEventListener('change', mqChangeListener); | ||
| 20 | + }, { once: true }); | ||
| 21 | + } | ||
| 22 | + } | ||
| 23 | + | ||
| 24 | + if (mq.matches) { | ||
| 25 | + document.documentElement.classList.add('dark-mode'); | ||
| 26 | + } | ||
| 27 | + } else if (userSettings === 'true') { | ||
| 28 | + document.documentElement.classList.add('dark-mode'); | ||
| 29 | + } | ||
| 30 | + | ||
| 31 | + if (themeToggleButton) { | ||
| 32 | + themeToggleButton.hidden = false; | ||
| 33 | + themeToggleButton.addEventListener('click', function() { | ||
| 34 | + sessionStorage.setItem( | ||
| 35 | + kCustomPreference, | ||
| 36 | + document.documentElement.classList.toggle('dark-mode') | ||
| 37 | + ); | ||
| 38 | + }); | ||
| 39 | + } | ||
| 40 | + } | ||
| 41 | + | ||
| 42 | + function setupPickers() { | ||
| 43 | + function closeAllPickers() { | ||
| 44 | + for (const picker of pickers) { | ||
| 45 | + picker.parentNode.classList.remove('expanded'); | ||
| 46 | + } | ||
| 47 | + | ||
| 48 | + window.removeEventListener('click', closeAllPickers); | ||
| 49 | + window.removeEventListener('keydown', onKeyDown); | ||
| 50 | + } | ||
| 51 | + | ||
| 52 | + function onKeyDown(e) { | ||
| 53 | + if (e.key === 'Escape') { | ||
| 54 | + closeAllPickers(); | ||
| 55 | + } | ||
| 56 | + } | ||
| 57 | + | ||
| 58 | + const pickers = document.querySelectorAll('.picker-header > a'); | ||
| 59 | + | ||
| 60 | + for (const picker of pickers) { | ||
| 61 | + const parentNode = picker.parentNode; | ||
| 62 | + | ||
| 63 | + picker.addEventListener('click', (e) => { | ||
| 64 | + e.preventDefault(); | ||
| 65 | + | ||
| 66 | + /* | ||
| 67 | + closeAllPickers as window event trigger already closed all the pickers, | ||
| 68 | + if it already closed there is nothing else to do here | ||
| 69 | + */ | ||
| 70 | + if (parentNode.classList.contains('expanded')) { | ||
| 71 | + return; | ||
| 72 | + } | ||
| 73 | + | ||
| 74 | + /* | ||
| 75 | + In the next frame reopen the picker if needed and also setup events | ||
| 76 | + to close pickers if needed. | ||
| 77 | + */ | ||
| 78 | + | ||
| 79 | + requestAnimationFrame(() => { | ||
| 80 | + parentNode.classList.add('expanded'); | ||
| 81 | + window.addEventListener('click', closeAllPickers); | ||
| 82 | + window.addEventListener('keydown', onKeyDown); | ||
| 83 | + }); | ||
| 84 | + }); | ||
| 85 | + } | ||
| 86 | + } | ||
| 87 | + | ||
| 88 | + function setupStickyHeaders() { | ||
| 89 | + const header = document.querySelector('.header'); | ||
| 90 | + let ignoreNextIntersection = false; | ||
| 91 | + | ||
| 92 | + new IntersectionObserver( | ||
| 93 | + ([e]) => { | ||
| 94 | + const currentStatus = header.classList.contains('is-pinned'); | ||
| 95 | + const newStatus = e.intersectionRatio < 1; | ||
| 96 | + | ||
| 97 | + // Same status, do nothing | ||
| 98 | + if (currentStatus === newStatus) { | ||
| 99 | + return; | ||
| 100 | + } else if (ignoreNextIntersection) { | ||
| 101 | + ignoreNextIntersection = false; | ||
| 102 | + return; | ||
| 103 | + } | ||
| 104 | + | ||
| 105 | + /* | ||
| 106 | + To avoid flickering, ignore the next changes event that is triggered | ||
| 107 | + as the visible elements in the header change once we pin it. | ||
| 108 | + | ||
| 109 | + The timer is reset anyway after few milliseconds. | ||
| 110 | + */ | ||
| 111 | + ignoreNextIntersection = true; | ||
| 112 | + setTimeout(() => { | ||
| 113 | + ignoreNextIntersection = false; | ||
| 114 | + }, 50); | ||
| 115 | + | ||
| 116 | + header.classList.toggle('is-pinned', newStatus); | ||
| 117 | + }, | ||
| 118 | + { threshold: [1] } | ||
| 119 | + ).observe(header); | ||
| 120 | + } | ||
| 121 | + | ||
| 122 | + function bootstrap() { | ||
| 123 | + // Check if we have JavaScript support | ||
| 124 | + document.documentElement.classList.add('has-js'); | ||
| 125 | + | ||
| 126 | + // Restore user mode preferences | ||
| 127 | + setupTheme(); | ||
| 128 | + | ||
| 129 | + // Handle pickers with click/taps rather than hovers | ||
| 130 | + setupPickers(); | ||
| 131 | + | ||
| 132 | + // Track when the header is in sticky position | ||
| 133 | + setupStickyHeaders(); | ||
| 134 | + } | ||
| 135 | + | ||
| 136 | + if (document.readyState === 'loading') { | ||
| 137 | + document.addEventListener('DOMContentLoaded', bootstrap, { once: true }); | ||
| 138 | + } else { | ||
| 139 | + bootstrap(); | ||
| 140 | + } | ||
| 141 | + } | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -189,19 +189,23 @@ li.picker-header .expanded-arrow { | |||
| 189 | 189 | display: none; | |
| 190 | 190 | } | |
| 191 | 191 | ||
| 192 | - li.picker-header:hover .collapsed-arrow { | ||
| 192 | + li.picker-header.expanded .collapsed-arrow, | ||
| 193 | + :root:not(.has-js) li.picker-header:hover .collapsed-arrow { | ||
| 193 | 194 | display: none; | |
| 194 | 195 | } | |
| 195 | 196 | ||
| 196 | - li.picker-header:hover .expanded-arrow { | ||
| 197 | + li.picker-header.expanded .expanded-arrow, | ||
| 198 | + :root:not(.has-js) li.picker-header:hover .expanded-arrow { | ||
| 197 | 199 | display: inline-block; | |
| 198 | 200 | } | |
| 199 | 201 | ||
| 200 | - li.picker-header:hover > a { | ||
| 202 | + li.picker-header.expanded > a, | ||
| 203 | + :root:not(.has-js) li.picker-header:hover > a { | ||
| 201 | 204 | border-radius: 2px 2px 0 0; | |
| 202 | 205 | } | |
| 203 | 206 | ||
| 204 | - li.picker-header:hover > .picker { | ||
| 207 | + li.picker-header.expanded > .picker, | ||
| 208 | + :root:not(.has-js) li.picker-header:hover > .picker { | ||
| 205 | 209 | display: block; | |
| 206 | 210 | z-index: 1; | |
| 207 | 211 | } | |
@@ -807,13 +811,38 @@ kbd { | |||
| 807 | 811 | background-color: var(--color-fill-app); | |
| 808 | 812 | } | |
| 809 | 813 | ||
| 810 | - @media not screen, (max-height: 1000px) { | ||
| 814 | + @media not screen, (max-width: 600px) { | ||
| 811 | 815 | .header { | |
| 812 | 816 | position: relative; | |
| 813 | 817 | top: 0; | |
| 814 | 818 | } | |
| 815 | 819 | } | |
| 816 | 820 | ||
| 821 | + @media not screen, (max-height: 1000px) { | ||
| 822 | + :root:not(.has-js) .header { | ||
| 823 | + position: relative; | ||
| 824 | + top: 0; | ||
| 825 | + } | ||
| 826 | + } | ||
| 827 | + | ||
| 828 | + .header .pinned-header { | ||
| 829 | + display: none; | ||
| 830 | + margin-right: 0.4rem; | ||
| 831 | + font-weight: 700; | ||
| 832 | + } | ||
| 833 | + | ||
| 834 | + .header.is-pinned .header-container { | ||
| 835 | + display: none; | ||
| 836 | + } | ||
| 837 | + | ||
| 838 | + .header.is-pinned .pinned-header { | ||
| 839 | + display: inline; | ||
| 840 | + } | ||
| 841 | + | ||
| 842 | + .header.is-pinned #gtoc { | ||
| 843 | + margin: 0; | ||
| 844 | + } | ||
| 845 | + | ||
| 817 | 846 | .header-container { | |
| 818 | 847 | display: flex; | |
| 819 | 848 | align-items: center; | |
@@ -845,6 +874,14 @@ kbd { | |||
| 845 | 874 | padding-right: 0; | |
| 846 | 875 | } | |
| 847 | 876 | ||
| 877 | + .header #gtoc > ul > li.pinned-header { | ||
| 878 | + display: none; | ||
| 879 | + } | ||
| 880 | + | ||
| 881 | + .header.is-pinned #gtoc > ul > li.pinned-header { | ||
| 882 | + display: inline; | ||
| 883 | + } | ||
| 884 | + | ||
| 848 | 885 | #gtoc > ul > li.gtoc-picker-header { | |
| 849 | 886 | display: none; | |
| 850 | 887 | } | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -9,6 +9,7 @@ | |||
| 9 | 9 | <link rel="stylesheet" href="assets/style.css"> | |
| 10 | 10 | <link rel="stylesheet" href="assets/hljs.css"> | |
| 11 | 11 | <link rel="canonical" href="https://nodejs.org/api/__FILENAME__.html"> | |
| 12 | + <script async defer src="assets/api.js" type="text/javascript"></script> | ||
| 12 | 13 | </head> | |
| 13 | 14 | <body class="alt apidoc" id="api-section-__FILENAME__"> | |
| 14 | 15 | <div id="content" class="clearfix"> | |
@@ -39,6 +40,7 @@ <h1>Node.js __VERSION__ documentation</h1> | |||
| 39 | 40 | </div> | |
| 40 | 41 | <div id="gtoc"> | |
| 41 | 42 | <ul> | |
| 43 | + <li class="pinned-header">Node.js __VERSION__</li> | ||
| 42 | 44 | __TOC_PICKER__ | |
| 43 | 45 | __GTOC_PICKER__ | |
| 44 | 46 | __ALTDOCS__ | |
@@ -73,41 +75,5 @@ <h1>Node.js __VERSION__ documentation</h1> | |||
| 73 | 75 | </div> | |
| 74 | 76 | </div> | |
| 75 | 77 | </div> | |
| 76 | - <script> | ||
| 77 | - 'use strict'; | ||
| 78 | - { | ||
| 79 | - const kCustomPreference = 'customDarkTheme'; | ||
| 80 | - const userSettings = sessionStorage.getItem(kCustomPreference); | ||
| 81 | - const themeToggleButton = document.getElementById('theme-toggle-btn'); | ||
| 82 | - if (userSettings === null && window.matchMedia) { | ||
| 83 | - const mq = window.matchMedia('(prefers-color-scheme: dark)'); | ||
| 84 | - if ('onchange' in mq) { | ||
| 85 | - function mqChangeListener(e) { | ||
| 86 | - document.documentElement.classList.toggle('dark-mode', e.matches); | ||
| 87 | - } | ||
| 88 | - mq.addEventListener('change', mqChangeListener); | ||
| 89 | - if (themeToggleButton) { | ||
| 90 | - themeToggleButton.addEventListener('click', function() { | ||
| 91 | - mq.removeEventListener('change', mqChangeListener); | ||
| 92 | - }, { once: true }); | ||
| 93 | - } | ||
| 94 | - } | ||
| 95 | - if (mq.matches) { | ||
| 96 | - document.documentElement.classList.add('dark-mode'); | ||
| 97 | - } | ||
| 98 | - } else if (userSettings === 'true') { | ||
| 99 | - document.documentElement.classList.add('dark-mode'); | ||
| 100 | - } | ||
| 101 | - if (themeToggleButton) { | ||
| 102 | - themeToggleButton.hidden = false; | ||
| 103 | - themeToggleButton.addEventListener('click', function() { | ||
| 104 | - sessionStorage.setItem( | ||
| 105 | - kCustomPreference, | ||
| 106 | - document.documentElement.classList.toggle('dark-mode') | ||
| 107 | - ); | ||
| 108 | - }); | ||
| 109 | - } | ||
| 110 | - } | ||
| 111 | - </script> | ||
| 112 | 78 | </body> | |
| 113 | 79 | </html> | |
| Back | FazBrowse Home | New Git URL |
0 commit comments