Skip to content

Commit f4d1a46

Browse files
authored
chore: validate example code (#474)
Validates `example` as valid javascript.
1 parent eb5511c commit f4d1a46

File tree

3 files changed

+22
-6
lines changed

3 files changed

+22
-6
lines changed

manifests/micro-utilities.json

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@
2121
"snippet::array-last": {
2222
"id": "snippet::array-last",
2323
"type": "simple",
24-
"description": "You can use arr.at(-1) if supported or arr[arr.length - 1] to get the last element of an array.",
25-
"example": "const last = (arr) => arr.at(-1);\n// or in older environments\nconst last = (arr) => arr[arr.length - 1]"
24+
"description": "You can use `arr.at(-1)` if supported or `arr[arr.length - 1]` to get the last element of an array.",
25+
"example": "const last = (arr) => arr.at(-1);\n// or in older environments\nconst lastLegacy = (arr) => arr[arr.length - 1]"
2626
},
2727
"snippet::array-slice-exclude-last-n": {
2828
"id": "snippet::array-slice-exclude-last-n",
@@ -64,7 +64,7 @@
6464
"id": "snippet::char-last",
6565
"type": "simple",
6666
"description": "You can use `str.at(-1)` if supported or `str[str.length - 1]` to get the last character of a string.",
67-
"example": "const last = (str) => str.at(-1);\n// or in older environments\nconst last = (str) => str[str.length - 1]"
67+
"example": "const last = (str) => str.at(-1);\n// or in older environments\nconst lastLegacy = (str) => str[str.length - 1]"
6868
},
6969
"snippet::for-own": {
7070
"id": "snippet::for-own",
@@ -232,7 +232,7 @@
232232
"id": "snippet::json-file",
233233
"type": "simple",
234234
"description": "You can use `JSON` and 'node:fs' to read and write json file.",
235-
"example": "import * as fs from 'node:fs/promises'\nfs.readFile(file, 'utf8').then(JSON.parse)\nfs.writeFile(file, JSON.stringify(data, null, 2) + '\n')"
235+
"example": "import * as fs from 'node:fs/promises'\nfs.readFile(file, 'utf8').then(JSON.parse)\nfs.writeFile(file, JSON.stringify(data, null, 2) + '\\n')"
236236
},
237237
"snippet::math-random": {
238238
"id": "snippet::math-random",
@@ -304,7 +304,7 @@
304304
"id": "snippet::unix-paths",
305305
"type": "simple",
306306
"description": "You can check the start of a path for the Windows extended-length path prefix and if it's not present, replace backslashes with forward slashes.",
307-
"example": "path.startsWith('\\\\?\\') ? path : path.replace(/\\/g, '/')"
307+
"example": "path.startsWith('\\\\\\\\?\\\\') ? path : path.replace(/\\\\/g, '/')"
308308
},
309309
"snippet:is-number": {
310310
"id": "snippet:is-number",

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
"prepare": "tsc",
1414
"lint": "npm run lint:format && npm run lint:manifests",
1515
"lint:format": "prettier --check \"./**/*.{js,ts,json,md,yml}\"",
16-
"lint:manifests": "node scripts/validate-modules.js",
16+
"lint:manifests": "node --experimental-vm-modules scripts/validate-modules.js",
1717
"sort-manifests": "node scripts/sort-manifests.js",
1818
"update-engines": "npm run update-engines:web && npm run update-engines:bcd && npm run update-engines:runtimes && npm run update-engines:node",
1919
"update-engines:web": "node scripts/update-engines-web.ts",

scripts/check-manifest-problems.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import {readdir, readFile, access} from 'node:fs/promises';
22
import {fileURLToPath} from 'node:url';
33
import * as path from 'node:path';
4+
import vm from 'node:vm';
45

56
const scriptDir = fileURLToPath(new URL('.', import.meta.url));
67
const manifestsDir = path.resolve(scriptDir, '../manifests');
@@ -68,11 +69,26 @@ export async function checkManifestsForProblems() {
6869
await checkManifestForDuplicates(manifestName, manifest);
6970
checkManifestIsSorted(manifestName, manifest);
7071
checkNoEngines(manifestName, manifest);
72+
checkExamplesAreValidJS(manifestName, manifest);
7173
await checkDocPathsExist(manifestName, manifest);
7274
}
7375
console.log('OK');
7476
}
7577

78+
function checkExamplesAreValidJS(name, manifest) {
79+
for (const [id, replacement] of Object.entries(manifest.replacements)) {
80+
if (replacement.example !== undefined) {
81+
try {
82+
new vm.SourceTextModule(replacement.example);
83+
} catch (err) {
84+
throw new Error(
85+
`Replacement ${id} in ${name} has an invalid JS example: ${err.message}`
86+
);
87+
}
88+
}
89+
}
90+
}
91+
7692
async function checkDocExists(name, id, label) {
7793
const docFile = path.join(docsDir, `${id}.md`);
7894
try {

0 commit comments

Comments
 (0)