From 6e460ca486be26d71d1becd0e6dc24d5665cb826 Mon Sep 17 00:00:00 2001 From: David Anson Date: Tue, 17 Dec 2024 20:29:23 -0800 Subject: [PATCH] wip --- markdownlint-cli2.mjs | 85 ++++++++++++++------------- test/markdownlint-cli2-test-cases.mjs | 36 ++++++------ test/markdownlint-cli2-test-exec.mjs | 4 +- test/markdownlint-cli2-test-fs.mjs | 6 +- test/markdownlint-cli2-test-main.mjs | 6 +- test/markdownlint-cli2-test.mjs | 14 ++--- 6 files changed, 77 insertions(+), 74 deletions(-) diff --git a/markdownlint-cli2.mjs b/markdownlint-cli2.mjs index 6db8cbd..f3d046d 100755 --- a/markdownlint-cli2.mjs +++ b/markdownlint-cli2.mjs @@ -1,6 +1,6 @@ // @ts-ignore -// Requires +// Imports import fsNode from "node:fs"; import { createRequire } from "node:module"; const dynamicRequire = createRequire(import.meta.url); @@ -66,19 +66,21 @@ const readConfigFile = (fs, dir, name, otherwise) => () => { }; // Import a module ID with a custom directory in the path -const importModule = async (dirOrDirs, id, noRequire) => { +const importModule = async (dirOrDirs, id, noImport) => { if (typeof id !== "string") { return id; - } else if (noRequire) { + } else if (noImport) { return null; } - const expandId = expandTildePath(id, os); const dirs = Array.isArray(dirOrDirs) ? dirOrDirs : [ dirOrDirs ]; + const expandId = expandTildePath(id, os); + const errors = []; + let moduleName = null; try { - let moduleName = null; try { moduleName = pathToFileURL(resolveModule(dynamicRequire, expandId, dirs)); - } catch { + } catch (error) { + errors.push(error); moduleName = // eslint-disable-next-line n/no-unsupported-features/node-builtins (!pathDefault.isAbsolute(expandId) && URL.canParse(expandId)) @@ -89,38 +91,39 @@ const importModule = async (dirOrDirs, id, noRequire) => { const module = await import(/* webpackIgnore: true */ moduleName); return module.default; } catch (error) { - throw new Error( - `Unable to require or import module '${id}'.`, - { "cause": error } + errors.push(error); + throw new AggregateError( + errors, + `Unable to import module '${id}'.` ); } }; // Import an array of modules by ID -const importModuleIds = (dirs, ids, noRequire) => ( +const importModuleIds = (dirs, ids, noImport) => ( Promise.all( ids.map( - (id) => importModule(dirs, id, noRequire) + (id) => importModule(dirs, id, noImport) ) ).then((results) => results.filter(Boolean)) ); // Import an array of modules by ID (preserving parameters) -const importModuleIdsAndParams = (dirs, idsAndParams, noRequire) => ( +const importModuleIdsAndParams = (dirs, idsAndParams, noImport) => ( Promise.all( idsAndParams.map( - (idAndParams) => importModule(dirs, idAndParams[0], noRequire). + (idAndParams) => importModule(dirs, idAndParams[0], noImport). then((module) => module && [ module, ...idAndParams.slice(1) ]) ) ).then((results) => results.filter(Boolean)) ); // Import a JavaScript file and return the exported object -const importConfig = (fs, dir, name, noRequire, otherwise) => () => { +const importConfig = (fs, dir, name, noImport, otherwise) => () => { const file = pathPosix.join(dir, name); return fs.promises.access(file). then( - () => importModule(dir, name, noRequire), + () => importModule(dir, name, noImport), otherwise ); }; @@ -140,7 +143,7 @@ const getExtendedConfig = (config, configPath, fs) => { }; // Read an options or config file in any format and return the object -const readOptionsOrConfig = async (configPath, fs, noRequire) => { +const readOptionsOrConfig = async (configPath, fs, noImport) => { const basename = pathPosix.basename(configPath); const dirname = pathPosix.dirname(configPath); let options = null; @@ -154,7 +157,7 @@ const readOptionsOrConfig = async (configPath, fs, noRequire) => { basename.endsWith(".markdownlint-cli2.cjs") || basename.endsWith(".markdownlint-cli2.mjs") ) { - options = await importModule(dirname, basename, noRequire); + options = await importModule(dirname, basename, noImport); } else if ( basename.endsWith(".markdownlint.jsonc") || basename.endsWith(".markdownlint.json") || @@ -166,7 +169,7 @@ const readOptionsOrConfig = async (configPath, fs, noRequire) => { basename.endsWith(".markdownlint.cjs") || basename.endsWith(".markdownlint.mjs") ) { - config = await importModule(dirname, basename, noRequire); + config = await importModule(dirname, basename, noImport); } else { throw new Error( "File name should be (or end with) one of the supported types " + @@ -277,7 +280,7 @@ const getAndProcessDirInfo = ( dirToDirInfo, dir, relativeDir, - noRequire, + noImport, allowPackageJson ) => { // Create dirInfo @@ -311,10 +314,10 @@ const getAndProcessDirInfo = ( () => fs.promises.readFile(file, utf8).then(yamlParse), () => fs.promises.access(captureFile(markdownlintCli2Cjs)). then( - () => importModule(dir, file, noRequire), + () => importModule(dir, file, noImport), () => fs.promises.access(captureFile(markdownlintCli2Mjs)). then( - () => importModule(dir, file, noRequire), + () => importModule(dir, file, noImport), () => (allowPackageJson ? fs.promises.access(captureFile(packageJson)) // eslint-disable-next-line prefer-promise-reject-errors @@ -372,12 +375,12 @@ const getAndProcessDirInfo = ( fs, dir, ".markdownlint.cjs", - noRequire, + noImport, importConfig( fs, dir, ".markdownlint.mjs", - noRequire, + noImport, noop ) ) @@ -406,7 +409,7 @@ const getBaseOptions = async ( options, fixDefault, noGlobs, - noRequire + noImport ) => { const tasks = []; const dirToDirInfo = {}; @@ -416,7 +419,7 @@ const getBaseOptions = async ( dirToDirInfo, baseDir, relativeDir, - noRequire, + noImport, true ); await Promise.all(tasks); @@ -457,7 +460,7 @@ const enumerateFiles = async ( dirToDirInfo, gitignore, ignoreFiles, - noRequire + noImport ) => { const tasks = []; /** @type {import("globby").Options} */ @@ -525,7 +528,7 @@ const enumerateFiles = async ( dirToDirInfo, dir, null, - noRequire, + noImport, false ); dirInfo.files.push(file); @@ -538,7 +541,7 @@ const enumerateParents = async ( fs, baseDir, dirToDirInfo, - noRequire + noImport ) => { const tasks = []; @@ -567,7 +570,7 @@ const enumerateParents = async ( dirToDirInfo, dir, null, - noRequire, + noImport, false ); lastDirInfo.parent = dirInfo; @@ -592,7 +595,7 @@ const createDirInfos = async ( optionsOverride, gitignore, ignoreFiles, - noRequire + noImport ) => { await enumerateFiles( fs, @@ -602,13 +605,13 @@ const createDirInfos = async ( dirToDirInfo, gitignore, ignoreFiles, - noRequire + noImport ); await enumerateParents( fs, baseDir, dirToDirInfo, - noRequire + noImport ); // Merge file lists with identical configuration @@ -642,7 +645,7 @@ const createDirInfos = async ( importModuleIds( [ effectiveDir, ...effectiveModulePaths ], markdownlintOptions.customRules, - noRequire + noImport ).then((customRules) => { // Expand nested arrays (for packages that export multiple rules) markdownlintOptions.customRules = customRules.flat(); @@ -654,7 +657,7 @@ const createDirInfos = async ( importModuleIdsAndParams( [ effectiveDir, ...effectiveModulePaths ], markdownlintOptions.markdownItPlugins, - noRequire + noImport ).then((markdownItPlugins) => { markdownlintOptions.markdownItPlugins = markdownItPlugins; }) @@ -847,7 +850,7 @@ const outputSummary = async ( modulePaths, logMessage, logError, - noRequire + noImport ) => { const errorsPresent = (summary.length > 0); if (errorsPresent || outputFormatters) { @@ -860,7 +863,7 @@ const outputSummary = async ( const dir = relativeDir || baseDir; const dirs = [ dir, ...modulePaths ]; const formattersAndParams = outputFormatters - ? await importModuleIdsAndParams(dirs, outputFormatters, noRequire) + ? await importModuleIdsAndParams(dirs, outputFormatters, noImport) // eslint-disable-next-line no-inline-comments, unicorn/no-await-expression-member : [ [ (await import(/* webpackMode: "eager" */ "markdownlint-cli2-formatter-default")).default ] ]; await Promise.all(formattersAndParams.map((formatterAndParams) => { @@ -880,7 +883,7 @@ export const main = async (params) => { optionsDefault, optionsOverride, fileContents, - noRequire, + noImport, allowStdin } = params; let { @@ -937,7 +940,7 @@ export const main = async (params) => { const resolvedConfigPath = posixPath(pathDefault.resolve(baseDirSystem, configPath)); optionsArgv = - await readOptionsOrConfig(resolvedConfigPath, fs, noRequire); + await readOptionsOrConfig(resolvedConfigPath, fs, noImport); relativeDir = pathPosix.dirname(resolvedConfigPath); } // Process arguments and get base options @@ -950,7 +953,7 @@ export const main = async (params) => { optionsArgv || optionsDefault, fixDefault, noGlobs, - noRequire + noImport ); } finally { if (!baseOptions?.baseMarkdownlintOptions.noBanner) { @@ -1009,7 +1012,7 @@ export const main = async (params) => { optionsOverride, gitignore, ignoreFiles, - noRequire + noImport ); // Output linting status if (showProgress) { @@ -1047,7 +1050,7 @@ export const main = async (params) => { modulePaths, logMessage, logError, - noRequire + noImport ); // Return result return errorsPresent ? 1 : 0; diff --git a/test/markdownlint-cli2-test-cases.mjs b/test/markdownlint-cli2-test-cases.mjs index ac654fa..41f1c50 100644 --- a/test/markdownlint-cli2-test-cases.mjs +++ b/test/markdownlint-cli2-test-cases.mjs @@ -19,7 +19,7 @@ const testCases = ({ host, invoke, absolute, - includeNoRequire, + includeNoImport, includeEnv, includeScript, includeRequire, @@ -38,7 +38,7 @@ const testCases = ({ stderrRe, pre, post, - noRequire, + noImport, usesRequire } = options; const usesEnv = Boolean(env); @@ -46,7 +46,7 @@ const testCases = ({ // eslint-disable-next-line unicorn/no-array-callback-reference const usesAbsolute = args.some(path.isAbsolute); if ( - (noRequire && !includeNoRequire) || + (noImport && !includeNoImport) || (usesEnv && !includeEnv) || (usesRequire && !includeRequire) || (usesScript && !includeScript) || @@ -58,7 +58,7 @@ const testCases = ({ t.plan(3); const directory = path.join(__dirname(import.meta), cwd || name); return ((pre || noop)(name, shadow) || Promise.resolve()). - then(invoke(directory, args, noRequire, env, script)). + then(invoke(directory, args, noImport, env, script)). then((result) => Promise.all([ result, fs.readFile( @@ -359,7 +359,7 @@ const testCases = ({ "name": "markdownlint-cjs-invalid", "args": [ ".*" ], "exitCode": 2, - "stderrRe": /Unable to require or import module '.*\.markdownlint\.cjs'/u, + "stderrRe": /Unable to import module '.*\.markdownlint\.cjs'/u, "usesRequire": true }); @@ -367,7 +367,7 @@ const testCases = ({ "name": "markdownlint-mjs-invalid", "args": [ ".*" ], "exitCode": 2, - "stderrRe": /Unable to require or import module '.*\.markdownlint\.mjs'/u, + "stderrRe": /Unable to import module '.*\.markdownlint\.mjs'/u, "usesRequire": true }); @@ -491,7 +491,7 @@ const testCases = ({ "name": "markdownlint-cli2-cjs-invalid", "args": [ ".*" ], "exitCode": 2, - "stderrRe": /'[^']*\.markdownlint-cli2\.cjs'.*Unable to require or import module '/u, + "stderrRe": /'[^']*\.markdownlint-cli2\.cjs'.*Unable to import module '/u, "usesRequire": true }); @@ -499,7 +499,7 @@ const testCases = ({ "name": "markdownlint-cli2-mjs-invalid", "args": [ ".*" ], "exitCode": 2, - "stderrRe": /'[^']*\.markdownlint-cli2\.mjs'.*Unable to require or import module '/u, + "stderrRe": /'[^']*\.markdownlint-cli2\.mjs'.*Unable to import module '/u, "usesRequire": true }); @@ -679,7 +679,7 @@ const testCases = ({ } const unableToParseJsonc = "Unable to parse JSONC content"; - const unableToRequireOrImport = "Unable to require or import module"; + const unableToRequireOrImport = "Unable to import module"; const invalidConfigFiles = [ [ "invalid.markdownlint-cli2.jsonc", unableToParseJsonc ], [ "invalid.markdownlint-cli2.cjs", unableToRequireOrImport ], @@ -813,7 +813,7 @@ const testCases = ({ "name": "customRules-missing", "args": [ ".*" ], "exitCode": 2, - "stderrRe": /Unable to require or import module 'missing-package'\./u, + "stderrRe": /Unable to import module 'missing-package'\./u, "usesRequire": true }); @@ -843,7 +843,7 @@ const testCases = ({ "name": "markdownItPlugins-missing", "args": [ ".*" ], "exitCode": 2, - "stderrRe": /Unable to require or import module 'missing-package'\./u, + "stderrRe": /Unable to import module 'missing-package'\./u, "usesRequire": true }); @@ -929,7 +929,7 @@ const testCases = ({ "name": "outputFormatters-missing", "args": [ ".*" ], "exitCode": 2, - "stderrRe": /Unable to require or import module 'missing-package'\./u, + "stderrRe": /Unable to import module 'missing-package'\./u, "usesRequire": true }); @@ -990,7 +990,7 @@ const testCases = ({ "args": [ "**/*.md" ], "exitCode": 1, "cwd": "markdownlint-cjs", - "noRequire": true + "noImport": true }); testCase({ @@ -998,7 +998,7 @@ const testCases = ({ "args": [ "**/*.md" ], "exitCode": 1, "cwd": "markdownlint-mjs", - "noRequire": true + "noImport": true }); testCase({ @@ -1006,7 +1006,7 @@ const testCases = ({ "args": [ "**/*.md" ], "exitCode": 1, "cwd": "markdownlint-cli2-cjs", - "noRequire": true + "noImport": true }); testCase({ @@ -1014,7 +1014,7 @@ const testCases = ({ "args": [ "**/*.md" ], "exitCode": 1, "cwd": "markdownlint-cli2-mjs", - "noRequire": true + "noImport": true }); testCase({ @@ -1022,7 +1022,7 @@ const testCases = ({ "args": [ "**/*.md" ], "exitCode": 1, "cwd": "customRules", - "noRequire": true + "noImport": true }); testCase({ @@ -1030,7 +1030,7 @@ const testCases = ({ "args": [ "**/*.md" ], "exitCode": 1, "cwd": "markdownItPlugins", - "noRequire": true + "noImport": true }); if (sameFileSystem) { diff --git a/test/markdownlint-cli2-test-exec.mjs b/test/markdownlint-cli2-test-exec.mjs index 2574921..bff481b 100644 --- a/test/markdownlint-cli2-test-exec.mjs +++ b/test/markdownlint-cli2-test-exec.mjs @@ -10,7 +10,7 @@ import { __dirname } from "./esm-helpers.mjs"; const absolute = (rootDir, file) => path.join(rootDir, file); const repositoryPath = (name) => path.join(__dirname(import.meta), "..", name); -const invoke = (directory, args, noRequire, env, script) => async () => { +const invoke = (directory, args, noImport, env, script) => async () => { await fs.access(directory); return spawn( "node", @@ -34,7 +34,7 @@ testCases({ "host": "exec", invoke, absolute, - "includeNoRequire": false, + "includeNoImport": false, "includeEnv": true, "includeScript": true, "includeRequire": true, diff --git a/test/markdownlint-cli2-test-fs.mjs b/test/markdownlint-cli2-test-fs.mjs index 8306a1c..8ca8453 100644 --- a/test/markdownlint-cli2-test-fs.mjs +++ b/test/markdownlint-cli2-test-fs.mjs @@ -9,7 +9,7 @@ const mockDirectory = "/mock"; const linesEndingWithNewLine = (lines) => lines.map((line) => `${line}\n`).join(""); -const invoke = (directory, args, noRequire) => () => { +const invoke = (directory, args, noImport) => () => { const stdouts = []; const stderrs = []; return markdownlintCli2({ @@ -17,7 +17,7 @@ const invoke = (directory, args, noRequire) => () => { "argv": args, "logMessage": (msg) => stdouts.push(msg), "logError": (msg) => stderrs.push(msg), - noRequire, + noImport, "fs": new FsMock(directory) }). then( @@ -40,7 +40,7 @@ testCases({ "host": "fs", invoke, absolute, - "includeNoRequire": true, + "includeNoImport": true, "includeEnv": false, "includeScript": false, "includeRequire": false, diff --git a/test/markdownlint-cli2-test-main.mjs b/test/markdownlint-cli2-test-main.mjs index 067e3be..2f17c55 100644 --- a/test/markdownlint-cli2-test-main.mjs +++ b/test/markdownlint-cli2-test-main.mjs @@ -7,7 +7,7 @@ import testCases from "./markdownlint-cli2-test-cases.mjs"; const linesEndingWithNewLine = (lines) => lines.map((line) => `${line}\n`).join(""); -const invoke = (directory, args, noRequire) => () => { +const invoke = (directory, args, noImport) => () => { const stdouts = []; const stderrs = []; return markdownlintCli2({ @@ -15,7 +15,7 @@ const invoke = (directory, args, noRequire) => () => { "argv": args, "logMessage": (msg) => stdouts.push(msg), "logError": (msg) => stderrs.push(msg), - noRequire + noImport }). then( (exitCode) => exitCode, @@ -37,7 +37,7 @@ testCases({ "host": "main", invoke, absolute, - "includeNoRequire": true, + "includeNoImport": true, "includeEnv": false, "includeScript": false, "includeRequire": true, diff --git a/test/markdownlint-cli2-test.mjs b/test/markdownlint-cli2-test.mjs index 5e56419..2f8dd6a 100644 --- a/test/markdownlint-cli2-test.mjs +++ b/test/markdownlint-cli2-test.mjs @@ -475,7 +475,7 @@ test("custom fs, extension scenario for untitled", (t) => { writeFile } }, - "noRequire": true + "noImport": true }). then((exitCode) => { t.is(exitCode, 1); @@ -570,7 +570,7 @@ test("custom fs, using node:fs", (t) => { }); }); -test("custom fs, using node:fs and noRequire=false", (t) => { +test("custom fs, using node:fs and noImport=false", (t) => { t.plan(2); return markdownlintCli2({ "directory": "test/markdownlint-cjs", @@ -579,14 +579,14 @@ test("custom fs, using node:fs and noRequire=false", (t) => { "outputFormatters": [ [ outputFormatterLengthIs(t, 11) ] ] }, "fs": nodeFs, - "noRequire": false + "noImport": false }). then((exitCode) => { t.is(exitCode, 1); }); }); -test("custom fs, using node:fs and noRequire=true", (t) => { +test("custom fs, using node:fs and noImport=true", (t) => { t.plan(2); return markdownlintCli2({ "directory": "test/markdownlint-cjs", @@ -595,7 +595,7 @@ test("custom fs, using node:fs and noRequire=true", (t) => { "outputFormatters": [ [ outputFormatterLengthIs(t, 14) ] ] }, "fs": nodeFs, - "noRequire": true + "noImport": true }). then((exitCode) => { t.is(exitCode, 1); @@ -611,7 +611,7 @@ test("custom fs, using fsMock", (t) => { "outputFormatters": [ [ outputFormatterLengthIs(t, 10) ] ] }, "fs": new FsMock(path.join(__dirname(import.meta), "markdownlint-cli2-jsonc")), - "noRequire": true + "noImport": true }). then((exitCode) => { t.is(exitCode, 1); @@ -627,7 +627,7 @@ test("custom fs, using fsMock simulating symbolic links", (t) => { "outputFormatters": [ [ outputFormatterLengthIs(t, 10) ] ] }, "fs": new FsMock(path.join(__dirname(import.meta), "markdownlint-cli2-jsonc"), true), - "noRequire": true + "noImport": true }). then((exitCode) => { t.is(exitCode, 1);