Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

tools,doc: add support for several flavors of JS code snippets #37162

Merged
merged 1 commit into from Mar 6, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
21 changes: 21 additions & 0 deletions doc/api/wasi.md
Expand Up @@ -29,6 +29,27 @@ const instance = await WebAssembly.instantiate(wasm, importObject);
wasi.start(instance);
```

```cjs
aduh95 marked this conversation as resolved.
Show resolved Hide resolved
'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`:

Expand Down
5 changes: 5 additions & 0 deletions doc/api_assets/js-flavor-cjs.svg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 5 additions & 0 deletions doc/api_assets/js-flavor-esm.svg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
47 changes: 47 additions & 0 deletions doc/api_assets/style.css
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
}
}
10 changes: 9 additions & 1 deletion test/doctool/test-doctool-html.js
Expand Up @@ -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;
Expand Down
11 changes: 11 additions & 0 deletions test/fixtures/document_with_cjs_and_esm_code_snippet.md
@@ -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 changes: 11 additions & 0 deletions test/fixtures/document_with_esm_and_cjs_code_snippet.md
@@ -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');
```
49 changes: 40 additions & 9 deletions tools/doc/html.js
Expand Up @@ -187,14 +187,16 @@ 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) => {
const STABILITY_RE = /(.*:)\s*(\d)([\s\S]*)/;
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;
Expand All @@ -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);

Expand Down