diff --git a/manifests/micro-utilities.json b/manifests/micro-utilities.json index 26d294b..19a8f59 100644 --- a/manifests/micro-utilities.json +++ b/manifests/micro-utilities.json @@ -21,8 +21,8 @@ "snippet::array-last": { "id": "snippet::array-last", "type": "simple", - "description": "You can use arr.at(-1) if supported or arr[arr.length - 1] to get the last element of an array.", - "example": "const last = (arr) => arr.at(-1);\n// or in older environments\nconst last = (arr) => arr[arr.length - 1]" + "description": "You can use `arr.at(-1)` if supported or `arr[arr.length - 1]` to get the last element of an array.", + "example": "const last = (arr) => arr.at(-1);\n// or in older environments\nconst lastLegacy = (arr) => arr[arr.length - 1]" }, "snippet::array-slice-exclude-last-n": { "id": "snippet::array-slice-exclude-last-n", @@ -64,7 +64,7 @@ "id": "snippet::char-last", "type": "simple", "description": "You can use `str.at(-1)` if supported or `str[str.length - 1]` to get the last character of a string.", - "example": "const last = (str) => str.at(-1);\n// or in older environments\nconst last = (str) => str[str.length - 1]" + "example": "const last = (str) => str.at(-1);\n// or in older environments\nconst lastLegacy = (str) => str[str.length - 1]" }, "snippet::for-own": { "id": "snippet::for-own", @@ -232,7 +232,7 @@ "id": "snippet::json-file", "type": "simple", "description": "You can use `JSON` and 'node:fs' to read and write json file.", - "example": "import * as fs from 'node:fs/promises'\nfs.readFile(file, 'utf8').then(JSON.parse)\nfs.writeFile(file, JSON.stringify(data, null, 2) + '\n')" + "example": "import * as fs from 'node:fs/promises'\nfs.readFile(file, 'utf8').then(JSON.parse)\nfs.writeFile(file, JSON.stringify(data, null, 2) + '\\n')" }, "snippet::math-random": { "id": "snippet::math-random", @@ -304,7 +304,7 @@ "id": "snippet::unix-paths", "type": "simple", "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.", - "example": "path.startsWith('\\\\?\\') ? path : path.replace(/\\/g, '/')" + "example": "path.startsWith('\\\\\\\\?\\\\') ? path : path.replace(/\\\\/g, '/')" }, "snippet:is-number": { "id": "snippet:is-number", diff --git a/package.json b/package.json index 97a2730..27dc511 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ "prepare": "tsc", "lint": "npm run lint:format && npm run lint:manifests", "lint:format": "prettier --check \"./**/*.{js,ts,json,md,yml}\"", - "lint:manifests": "node scripts/validate-modules.js", + "lint:manifests": "node --experimental-vm-modules scripts/validate-modules.js", "sort-manifests": "node scripts/sort-manifests.js", "update-engines": "npm run update-engines:web && npm run update-engines:bcd && npm run update-engines:runtimes && npm run update-engines:node", "update-engines:web": "node scripts/update-engines-web.ts", diff --git a/scripts/check-manifest-problems.js b/scripts/check-manifest-problems.js index b319079..3199c4a 100644 --- a/scripts/check-manifest-problems.js +++ b/scripts/check-manifest-problems.js @@ -1,6 +1,7 @@ import {readdir, readFile, access} from 'node:fs/promises'; import {fileURLToPath} from 'node:url'; import * as path from 'node:path'; +import vm from 'node:vm'; const scriptDir = fileURLToPath(new URL('.', import.meta.url)); const manifestsDir = path.resolve(scriptDir, '../manifests'); @@ -68,11 +69,26 @@ export async function checkManifestsForProblems() { await checkManifestForDuplicates(manifestName, manifest); checkManifestIsSorted(manifestName, manifest); checkNoEngines(manifestName, manifest); + checkExamplesAreValidJS(manifestName, manifest); await checkDocPathsExist(manifestName, manifest); } console.log('OK'); } +function checkExamplesAreValidJS(name, manifest) { + for (const [id, replacement] of Object.entries(manifest.replacements)) { + if (replacement.example !== undefined) { + try { + new vm.SourceTextModule(replacement.example); + } catch (err) { + throw new Error( + `Replacement ${id} in ${name} has an invalid JS example: ${err.message}` + ); + } + } + } +} + async function checkDocExists(name, id, label) { const docFile = path.join(docsDir, `${id}.md`); try {