Skip to content

Commit 646f161

Browse files
aduh95MoLow
authored andcommitted
tools: fix CJS/ESM toggle on small screens
PR-URL: #43506 Co-authored-by: Moshe Atlow <[email protected]> Fixes: #43468 Reviewed-By: LiviaMedeiros <[email protected]>
1 parent fc05822 commit 646f161

File tree

5 files changed

+78
-2
lines changed

5 files changed

+78
-2
lines changed

doc/api_assets/style.css

+3
Original file line numberDiff line numberDiff line change
@@ -953,6 +953,9 @@ kbd {
953953
background-repeat: no-repeat;
954954
width: 142px;
955955
height: 20px;
956+
display: block;
957+
cursor: pointer;
958+
margin: 0;
956959
}
957960
.js-flavor-selector:checked {
958961
background-image: url(./js-flavor-esm.svg);

doc/template.html

+1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
<link rel="stylesheet" href="assets/hljs.css">
1111
<link rel="canonical" href="https://nodejs.org/api/__FILENAME__.html">
1212
<script async defer src="assets/api.js" type="text/javascript"></script>
13+
__JS_FLAVORED_DYNAMIC_CSS__
1314
</head>
1415
<body class="alt apidoc" id="api-section-__FILENAME__">
1516
<div id="content" class="clearfix">

tools/doc/allhtml.mjs

+9-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// of the generated html files.
33

44
import fs from 'fs';
5+
import buildCSSForFlavoredJS from './buildCSSForFlavoredJS.mjs';
56

67
const source = new URL('../../out/doc/api/', import.meta.url);
78

@@ -90,7 +91,14 @@ all = all.slice(0, tocStart.index + tocStart[0].length) +
9091
// Replace apicontent with the concatenated set of apicontents from each source.
9192
const apiStart = /<\w+ id="apicontent">\s*/.exec(all);
9293
const apiEnd = all.lastIndexOf('<!-- API END -->');
93-
all = all.slice(0, apiStart.index + apiStart[0].length) +
94+
all = all.slice(0, apiStart.index + apiStart[0].length)
95+
.replace(
96+
'\n</head>',
97+
buildCSSForFlavoredJS(new Set(Array.from(
98+
apicontent.matchAll(/(?<=<pre class="with-)\d+(?=-chars">)/g),
99+
(x) => Number(x[0])
100+
))) + '\n</head>'
101+
) +
94102
apicontent +
95103
all.slice(apiEnd);
96104

tools/doc/buildCSSForFlavoredJS.mjs

+53
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
const CHAR_THRESHOLD = 68; // Around 68 characters, we have to take into
2+
// account the left column that appears on screen
3+
// wider than 1024px.
4+
5+
const ESTIMATED_CHAR_WIDTH = 8; // If the root element font-size is 16px (default value), 1ch is 7.8025px.
6+
const TOGGLE_WIDTH = 142; // https://github.com/nodejs/node/blob/dbd938549b16718f2e4cc2809746b8c44a191b1d/doc/api_assets/style.css#L954
7+
8+
const PRE_MARGIN_LEFT = 16; // https://github.com/nodejs/node/blob/dbd938549b16718f2e4cc2809746b8c44a191b1d/doc/api_assets/style.css#L516
9+
const PRE_MARGIN_RIGHT = 16; // https://github.com/nodejs/node/blob/dbd938549b16718f2e4cc2809746b8c44a191b1d/doc/api_assets/style.css#L516
10+
const PRE_PADDING_LEFT = 16; // https://github.com/nodejs/node/blob/dbd938549b16718f2e4cc2809746b8c44a191b1d/doc/api_assets/style.css#L513
11+
const PRE_PADDING_RIGHT = 16; // https://github.com/nodejs/node/blob/dbd938549b16718f2e4cc2809746b8c44a191b1d/doc/api_assets/style.css#L513
12+
13+
14+
const COLUMN_RIGHT_MARGIN_LEFT_LARGE_SCREEN = 234; // https://github.com/nodejs/node/blob/dbd938549b16718f2e4cc2809746b8c44a191b1d/doc/api_assets/style.css#L653
15+
const COLUMN_RIGHT_MARGIN_LEFT_SMALL_SCREEN = 0; // https://github.com/nodejs/node/blob/dbd938549b16718f2e4cc2809746b8c44a191b1d/doc/api_assets/style.css#L906
16+
const COLUMN_RIGHT_MARGIN_RIGHT_LARGE_SCREEN = 0;
17+
const COLUMN_RIGHT_MARGIN_RIGHT_SMALL_SCREEN = 0;
18+
const COLUMN_RIGHT_PADDING_LEFT_LARGE_SCREEN = 24; // https://github.com/nodejs/node/blob/dbd938549b16718f2e4cc2809746b8c44a191b1d/doc/api_assets/style.css#L655
19+
const COLUMN_RIGHT_PADDING_LEFT_SMALL_SCREEN = 8; // https://github.com/nodejs/node/blob/dbd938549b16718f2e4cc2809746b8c44a191b1d/doc/api_assets/style.css#L907
20+
const COLUMN_RIGHT_PADDING_RIGHT_LARGE_SCREEN = 32; // https://github.com/nodejs/node/blob/dbd938549b16718f2e4cc2809746b8c44a191b1d/doc/api_assets/style.css#L654
21+
const COLUMN_RIGHT_PADDING_RIGHT_SMALL_SCREEN = 8; // https://github.com/nodejs/node/blob/dbd938549b16718f2e4cc2809746b8c44a191b1d/doc/api_assets/style.css#L908
22+
23+
const getMarginLeft = (charCount) =>
24+
(charCount > CHAR_THRESHOLD ?
25+
COLUMN_RIGHT_MARGIN_LEFT_LARGE_SCREEN :
26+
COLUMN_RIGHT_MARGIN_LEFT_SMALL_SCREEN) + PRE_MARGIN_LEFT;
27+
const getPaddingLeft = (charCount) =>
28+
(charCount > CHAR_THRESHOLD ?
29+
COLUMN_RIGHT_PADDING_LEFT_LARGE_SCREEN :
30+
COLUMN_RIGHT_PADDING_LEFT_SMALL_SCREEN) + PRE_PADDING_LEFT;
31+
const getPaddingRight = (charCount) =>
32+
(charCount > CHAR_THRESHOLD ?
33+
COLUMN_RIGHT_PADDING_RIGHT_LARGE_SCREEN :
34+
COLUMN_RIGHT_PADDING_RIGHT_SMALL_SCREEN) + PRE_PADDING_RIGHT;
35+
const getMarginRight = (charCount) =>
36+
(charCount > CHAR_THRESHOLD ?
37+
COLUMN_RIGHT_MARGIN_RIGHT_LARGE_SCREEN :
38+
COLUMN_RIGHT_MARGIN_RIGHT_SMALL_SCREEN) + PRE_MARGIN_RIGHT;
39+
40+
41+
export default function buildCSSForFlavoredJS(dynamicSizes) {
42+
if (dynamicSizes == null || dynamicSizes.length === 0) return '';
43+
44+
return `<style>${Array.from(dynamicSizes, (charCount) =>
45+
`@media(max-width:${getMarginLeft(charCount) + getPaddingLeft(charCount) +
46+
charCount * ESTIMATED_CHAR_WIDTH + TOGGLE_WIDTH +
47+
getPaddingRight(charCount) + getMarginRight(charCount)}px){` +
48+
`.with-${charCount}-chars>.js-flavor-selector{` +
49+
'float:none;' +
50+
'margin:0 0 1em auto;' +
51+
'}' +
52+
'}').join('')}</style>`;
53+
}

tools/doc/html.mjs

+12-1
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@ import { visit } from 'unist-util-visit';
3333

3434
import * as common from './common.mjs';
3535
import * as typeParser from './type-parser.mjs';
36+
import buildCSSForFlavoredJS from './buildCSSForFlavoredJS.mjs';
37+
38+
const dynamicSizes = Object.create(null);
3639

3740
const { highlight, getLanguage } = highlightJs;
3841

@@ -90,6 +93,8 @@ function processContent(content) {
9093
}
9194

9295
export function toHTML({ input, content, filename, nodeVersion, versions }) {
96+
const dynamicSizesForThisFile = dynamicSizes[filename];
97+
9398
filename = path.basename(filename, '.md');
9499

95100
const id = filename.replace(/\W+/g, '-');
@@ -99,6 +104,7 @@ export function toHTML({ input, content, filename, nodeVersion, versions }) {
99104
.replace('__SECTION__', content.section)
100105
.replace(/__VERSION__/g, nodeVersion)
101106
.replace(/__TOC__/g, content.toc)
107+
.replace('__JS_FLAVORED_DYNAMIC_CSS__', buildCSSForFlavoredJS(dynamicSizesForThisFile))
102108
.replace(/__TOC_PICKER__/g, tocPicker(id, content))
103109
.replace(/__GTOC_PICKER__/g, gtocPicker(id))
104110
.replace(/__GTOC__/g, gtocHTML.replace(
@@ -228,14 +234,19 @@ export function preprocessElements({ filename }) {
228234
const previousNode = parent.children[index - 1] || {};
229235
const nextNode = parent.children[index + 1] || {};
230236

237+
const charCountFirstTwoLines = Math.max(...node.value.split('\n', 2).map((str) => str.length));
238+
231239
if (!isJSFlavorSnippet(previousNode) &&
232240
isJSFlavorSnippet(nextNode) &&
233241
nextNode.lang !== node.lang) {
234242
// Saving the highlight code as value to be added in the next node.
235243
node.value = highlighted;
244+
node.charCountFirstTwoLines = charCountFirstTwoLines;
236245
} else if (isJSFlavorSnippet(previousNode) &&
237246
previousNode.lang !== node.lang) {
238-
node.value = '<pre>' +
247+
const actualCharCount = Math.max(charCountFirstTwoLines, previousNode.charCountFirstTwoLines);
248+
(dynamicSizes[filename] ??= new Set()).add(actualCharCount);
249+
node.value = `<pre class="with-${actualCharCount}-chars">` +
239250
'<input class="js-flavor-selector" type="checkbox"' +
240251
// If CJS comes in second, ESM should display by default.
241252
(node.lang === 'cjs' ? ' checked' : '') +

0 commit comments

Comments
 (0)