mirror of
https://github.com/nodejs/node.git
synced 2025-08-15 13:48:44 +02:00
tools,doc: add support for several flavors of JS code snippets
Enable code example using both modern ESM syntax and legacy CJS syntax. It adds a toggle on the web interface to let users switch from one JavaScript flavor to the other. PR-URL: https://github.com/nodejs/node/pull/37162 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Rich Trott <rtrott@gmail.com> Reviewed-By: Michaël Zasso <targos@protonmail.com>
This commit is contained in:
parent
0afc8ac12e
commit
2e1e74e9f8
8 changed files with 149 additions and 10 deletions
|
@ -29,6 +29,27 @@ const instance = await WebAssembly.instantiate(wasm, importObject);
|
|||
wasi.start(instance);
|
||||
```
|
||||
|
||||
```cjs
|
||||
'use strict';
|
||||
const fs = require('fs');
|
||||
const { WASI } = require('wasi');
|
||||
const wasi = new WASI({
|
||||
args: process.argv,
|
||||
env: process.env,
|
||||
preopens: {
|
||||
'/sandbox': '/some/real/path/that/wasm/can/access'
|
||||
}
|
||||
});
|
||||
const importObject = { wasi_snapshot_preview1: wasi.wasiImport };
|
||||
|
||||
(async () => {
|
||||
const wasm = await WebAssembly.compile(fs.readFileSync('./demo.wasm'));
|
||||
const instance = await WebAssembly.instantiate(wasm, importObject);
|
||||
|
||||
wasi.start(instance);
|
||||
})();
|
||||
```
|
||||
|
||||
To run the above example, create a new WebAssembly text format file named
|
||||
`demo.wat`:
|
||||
|
||||
|
|
5
doc/api_assets/js-flavor-cjs.svg
Normal file
5
doc/api_assets/js-flavor-cjs.svg
Normal file
|
@ -0,0 +1,5 @@
|
|||
<!--
|
||||
* Font Awesome Free 5.15.2 by @fontawesome - https://fontawesome.com
|
||||
* License - https://fontawesome.com/license/free - CC BY 4.0
|
||||
-->
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="2719" height="384"><path d="M1191.326 384h192c106 0 192-86 192-192s-86-192-192-192h-192c-106 0-192 86-192 192s86 192 192 192zm0-320c70.8 0 128 57.3 128 128 0 70.8-57.3 128-128 128-70.8 0-128-57.3-128-128 0-70.8 57.3-128 128-128z"/><text stroke-width="42" font-family="sans-serif" font-weight="lighter" font-size="490" y="370">CJS</text><text stroke-width="42" font-weight="lighter" font-family="sans-serif" font-size="490" y="370" x="1682">ESM</text></svg>
|
After Width: | Height: | Size: 645 B |
5
doc/api_assets/js-flavor-esm.svg
Normal file
5
doc/api_assets/js-flavor-esm.svg
Normal file
|
@ -0,0 +1,5 @@
|
|||
<!--
|
||||
* Font Awesome Free 5.15.2 by @fontawesome - https://fontawesome.com
|
||||
* License - https://fontawesome.com/license/free - CC BY 4.0
|
||||
-->
|
||||
<svg xmlns="http://www.w3.org/2000/svg" height="384" width="2719"><defs><path d="M-136.321-230.336h2994.365v653.401H-136.321z"/></defs><path d="M1383.326 0h-192c-106 0-192 86-192 192s86 192 192 192h192c106 0 192-86 192-192s-86-192-192-192zm0 320c-70.8 0-128-57.3-128-128 0-70.8 57.3-128 128-128 70.8 0 128 57.3 128 128 0 70.8-57.3 128-128 128z"/><text stroke-width="42" font-family="sans-serif" font-weight="lighter" font-size="490" y="370">CJS</text><text stroke-width="42" font-weight="lighter" font-family="sans-serif" font-size="490" y="370" x="1682">ESM</text></svg>
|
After Width: | Height: | Size: 713 B |
|
@ -765,6 +765,33 @@ kbd {
|
|||
display: block;
|
||||
}
|
||||
|
||||
.js-flavor-selector {
|
||||
appearance: none;
|
||||
float: right;
|
||||
background-image: url(./js-flavor-cjs.svg);
|
||||
background-size: contain;
|
||||
background-repeat: no-repeat;
|
||||
width: 142px;
|
||||
height: 20px;
|
||||
}
|
||||
.js-flavor-selector:checked {
|
||||
background-image: url(./js-flavor-esm.svg);
|
||||
}
|
||||
.js-flavor-selector:not(:checked) ~ .esm,
|
||||
.js-flavor-selector:checked ~ .cjs {
|
||||
display: none;
|
||||
}
|
||||
.dark-mode .js-flavor-selector {
|
||||
filter: invert(1);
|
||||
}
|
||||
@supports (aspect-ratio: 1 / 1) {
|
||||
.js-flavor-selector {
|
||||
height: 1.5em;
|
||||
width: auto;
|
||||
aspect-ratio: 2719 / 384;
|
||||
}
|
||||
}
|
||||
|
||||
@media print {
|
||||
html {
|
||||
height: auto;
|
||||
|
@ -815,4 +842,24 @@ kbd {
|
|||
#apicontent {
|
||||
overflow: hidden;
|
||||
}
|
||||
.js-flavor-selector {
|
||||
display: none;
|
||||
}
|
||||
.js-flavor-selector + * {
|
||||
margin-bottom: 2rem;
|
||||
padding-bottom: 2rem;
|
||||
border-bottom: 1px solid var(--color-text-primary);
|
||||
}
|
||||
.js-flavor-selector ~ * {
|
||||
display: block !important;
|
||||
background-position: top right;
|
||||
background-size: 142px 20px;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
.js-flavor-selector ~ .cjs {
|
||||
background-image: url(./js-flavor-cjs.svg);
|
||||
}
|
||||
.js-flavor-selector ~ .mjs {
|
||||
background-image: url(./js-flavor-esm.svg);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -129,7 +129,15 @@ const testData = [
|
|||
{
|
||||
file: fixtures.path('document_with_special_heading.md'),
|
||||
html: '<title>Sample markdown with special heading |',
|
||||
}
|
||||
},
|
||||
{
|
||||
file: fixtures.path('document_with_esm_and_cjs_code_snippet.md'),
|
||||
html: '<input class="js-flavor-selector" type="checkbox" checked',
|
||||
},
|
||||
{
|
||||
file: fixtures.path('document_with_cjs_and_esm_code_snippet.md'),
|
||||
html: '<input class="js-flavor-selector" type="checkbox" aria-label',
|
||||
},
|
||||
];
|
||||
|
||||
const spaces = /\s/g;
|
||||
|
|
11
test/fixtures/document_with_cjs_and_esm_code_snippet.md
vendored
Normal file
11
test/fixtures/document_with_cjs_and_esm_code_snippet.md
vendored
Normal file
|
@ -0,0 +1,11 @@
|
|||
# Usage and Example
|
||||
|
||||
CJS snippet is first, it should be the one displayed by default.
|
||||
|
||||
```cjs
|
||||
require('path');
|
||||
```
|
||||
|
||||
```mjs
|
||||
import 'node:url';
|
||||
```
|
11
test/fixtures/document_with_esm_and_cjs_code_snippet.md
vendored
Normal file
11
test/fixtures/document_with_esm_and_cjs_code_snippet.md
vendored
Normal file
|
@ -0,0 +1,11 @@
|
|||
# Usage and Example
|
||||
|
||||
ESM snippet is first, it should be the one displayed by default.
|
||||
|
||||
```mjs
|
||||
import 'node:url';
|
||||
```
|
||||
|
||||
```cjs
|
||||
require('path');
|
||||
```
|
|
@ -187,6 +187,8 @@ function linkJsTypeDocs(text) {
|
|||
return parts.join('`');
|
||||
}
|
||||
|
||||
const isJSFlavorSnippet = (node) => node.lang === 'cjs' || node.lang === 'mjs';
|
||||
|
||||
// Preprocess headers, stability blockquotes, and YAML blocks.
|
||||
function preprocessElements({ filename }) {
|
||||
return (tree) => {
|
||||
|
@ -194,7 +196,7 @@ function preprocessElements({ filename }) {
|
|||
let headingIndex = -1;
|
||||
let heading = null;
|
||||
|
||||
visit(tree, null, (node, index) => {
|
||||
visit(tree, null, (node, index, parent) => {
|
||||
if (node.type === 'heading') {
|
||||
headingIndex = index;
|
||||
heading = node;
|
||||
|
@ -204,15 +206,44 @@ function preprocessElements({ filename }) {
|
|||
`No language set in ${filename}, ` +
|
||||
`line ${node.position.start.line}`);
|
||||
}
|
||||
const language = (node.lang || '').split(' ')[0];
|
||||
const highlighted = getLanguage(language) ?
|
||||
highlight(language, node.value).value :
|
||||
node.value;
|
||||
const className = isJSFlavorSnippet(node) ?
|
||||
`language-js ${node.lang}` :
|
||||
`language-${node.lang}`;
|
||||
const highlighted =
|
||||
`<code class='${className}'>` +
|
||||
(getLanguage(node.lang || '') ?
|
||||
highlight(node.lang, node.value) : node).value +
|
||||
'</code>';
|
||||
node.type = 'html';
|
||||
node.value = '<pre>' +
|
||||
`<code class = 'language-${node.lang}'>` +
|
||||
highlighted +
|
||||
'</code></pre>';
|
||||
|
||||
if (isJSFlavorSnippet(node)) {
|
||||
const previousNode = parent.children[index - 1] || {};
|
||||
const nextNode = parent.children[index + 1] || {};
|
||||
|
||||
if (!isJSFlavorSnippet(previousNode) &&
|
||||
isJSFlavorSnippet(nextNode) &&
|
||||
nextNode.lang !== node.lang) {
|
||||
// Saving the highlight code as value to be added in the next node.
|
||||
node.value = highlighted;
|
||||
} else if (isJSFlavorSnippet(previousNode)) {
|
||||
node.value = '<pre>' +
|
||||
'<input class="js-flavor-selector" type="checkbox"' +
|
||||
// If CJS comes in second, ESM should display by default.
|
||||
(node.lang === 'cjs' ? ' checked' : '') +
|
||||
' aria-label="Show modern ES modules syntax">' +
|
||||
previousNode.value +
|
||||
highlighted +
|
||||
'</pre>';
|
||||
node.lang = null;
|
||||
previousNode.value = '';
|
||||
previousNode.lang = null;
|
||||
} else {
|
||||
// Isolated JS snippet, no need to add the checkbox.
|
||||
node.value = `<pre>${highlighted}</pre>`;
|
||||
}
|
||||
} else {
|
||||
node.value = `<pre>${highlighted}</pre>`;
|
||||
}
|
||||
} else if (node.type === 'html' && common.isYAMLBlock(node.value)) {
|
||||
node.value = parseYAML(node.value);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue