mdrefine 0.2.0-rc.2 → 0.2.0-rc.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (127) hide show
  1. package/CHANGELOG.md +509 -0
  2. package/CODE_OF_CONDUCT.md +30 -0
  3. package/CONTRIBUTING.md +188 -16
  4. package/README.md +100 -154
  5. package/SECURITY.md +15 -13
  6. package/config.schema.json +91 -0
  7. package/dist/cli/main.js +261 -148
  8. package/dist/cli/main.js.map +1 -1
  9. package/dist/config/load.js +67 -6
  10. package/dist/config/load.js.map +1 -1
  11. package/dist/config/problems.d.ts +7 -0
  12. package/dist/config/problems.js +208 -0
  13. package/dist/config/problems.js.map +1 -0
  14. package/dist/config/resolve.d.ts +42 -109
  15. package/dist/config/resolve.js +193 -52
  16. package/dist/config/resolve.js.map +1 -1
  17. package/dist/core/directives.d.ts +7 -0
  18. package/dist/core/directives.js +25 -13
  19. package/dist/core/directives.js.map +1 -1
  20. package/dist/core/engine.d.ts +42 -4
  21. package/dist/core/engine.js +518 -79
  22. package/dist/core/engine.js.map +1 -1
  23. package/dist/core/frozen.d.ts +6 -0
  24. package/dist/core/frozen.js +15 -0
  25. package/dist/core/frozen.js.map +1 -0
  26. package/dist/core/scope.d.ts +30 -0
  27. package/dist/core/scope.js +122 -0
  28. package/dist/core/scope.js.map +1 -0
  29. package/dist/core/types.d.ts +202 -23
  30. package/dist/core/types.js.map +1 -1
  31. package/dist/index.d.ts +2 -2
  32. package/dist/index.js.map +1 -1
  33. package/dist/node.d.ts +3 -0
  34. package/dist/node.js +4 -0
  35. package/dist/node.js.map +1 -0
  36. package/dist/rules/blocks.d.ts +34 -0
  37. package/dist/rules/blocks.js +538 -0
  38. package/dist/rules/blocks.js.map +1 -0
  39. package/dist/rules/content.d.ts +2 -0
  40. package/dist/rules/content.js +85 -0
  41. package/dist/rules/content.js.map +1 -0
  42. package/dist/rules/dialects.js +10 -6
  43. package/dist/rules/dialects.js.map +1 -1
  44. package/dist/rules/links.js +302 -6
  45. package/dist/rules/links.js.map +1 -1
  46. package/dist/rules/lists.d.ts +2 -0
  47. package/dist/rules/lists.js +924 -0
  48. package/dist/rules/lists.js.map +1 -0
  49. package/dist/rules/structure.js +127 -1
  50. package/dist/rules/structure.js.map +1 -1
  51. package/dist/rules/style.d.ts +8 -2
  52. package/dist/rules/style.js +1118 -165
  53. package/dist/rules/style.js.map +1 -1
  54. package/dist/syntax/block-identifier.d.ts +18 -0
  55. package/dist/syntax/block-identifier.js +24 -0
  56. package/dist/syntax/block-identifier.js.map +1 -0
  57. package/dist/syntax/obsidian.d.ts +29 -11
  58. package/dist/syntax/obsidian.js +9 -10
  59. package/dist/syntax/obsidian.js.map +1 -1
  60. package/dist/syntax/parse.d.ts +74 -3
  61. package/dist/syntax/parse.js +227 -19
  62. package/dist/syntax/parse.js.map +1 -1
  63. package/dist/workspace/access.d.ts +12 -3
  64. package/dist/workspace/access.js +33 -5
  65. package/dist/workspace/access.js.map +1 -1
  66. package/dist/workspace/discovery.d.ts +80 -0
  67. package/dist/workspace/discovery.js +143 -0
  68. package/dist/workspace/discovery.js.map +1 -0
  69. package/dist/workspace/encoding.d.ts +24 -0
  70. package/dist/workspace/encoding.js +113 -0
  71. package/dist/workspace/encoding.js.map +1 -0
  72. package/dist/workspace/files.d.ts +76 -6
  73. package/dist/workspace/files.js +639 -59
  74. package/dist/workspace/files.js.map +1 -1
  75. package/dist/workspace/git.d.ts +54 -0
  76. package/dist/workspace/git.js +198 -0
  77. package/dist/workspace/git.js.map +1 -0
  78. package/dist/workspace/index.d.ts +58 -3
  79. package/dist/workspace/index.js +136 -37
  80. package/dist/workspace/index.js.map +1 -1
  81. package/dist/workspace/selection.d.ts +2 -2
  82. package/dist/workspace/selection.js +3 -3
  83. package/dist/workspace/selection.js.map +1 -1
  84. package/dist/workspace/slug.js +8 -1
  85. package/dist/workspace/slug.js.map +1 -1
  86. package/dist/workspace/vault.js +3 -1
  87. package/dist/workspace/vault.js.map +1 -1
  88. package/docs/api.md +237 -0
  89. package/docs/benchmarks.md +139 -199
  90. package/docs/changelog.md +1 -0
  91. package/docs/cli.md +271 -89
  92. package/docs/configuration.md +193 -480
  93. package/docs/design.md +158 -284
  94. package/docs/dialects.md +169 -0
  95. package/docs/examples.md +151 -109
  96. package/docs/index.md +21 -37
  97. package/docs/integrations.md +138 -0
  98. package/docs/obsidian.md +91 -115
  99. package/docs/plugins.md +147 -212
  100. package/docs/quick-start.md +68 -74
  101. package/docs/rules.md +1230 -0
  102. package/docs/versions.md +56 -0
  103. package/examples/README.md +17 -14
  104. package/examples/automation/summarize-report.mjs +5 -2
  105. package/examples/library/lint-folder.mjs +5 -4
  106. package/examples/library/lint-workspace.mjs +32 -0
  107. package/examples/plugin/notes/release-checklist.md +2 -2
  108. package/examples/plugin/rules.mjs +17 -23
  109. package/examples/workspaces/obsidian-vault/after/mdtools.config.jsonc +2 -2
  110. package/examples/workspaces/obsidian-vault/before/mdtools.config.jsonc +2 -2
  111. package/examples/workspaces/repository-docs/after/README.md +2 -2
  112. package/examples/workspaces/repository-docs/after/mdtools.config.jsonc +0 -2
  113. package/examples/workspaces/repository-docs/before/README.md +2 -2
  114. package/examples/workspaces/repository-docs/before/docs/guide.md +7 -7
  115. package/examples/workspaces/repository-docs/before/docs/reference.md +3 -1
  116. package/examples/workspaces/repository-docs/before/mdtools.config.jsonc +0 -2
  117. package/package.json +37 -11
  118. package/docs/contributing.md +0 -218
  119. package/docs/releases/0.1.0-beta.1.md +0 -39
  120. package/docs/releases/0.1.0-beta.2.md +0 -83
  121. package/docs/releases/0.1.0-beta.3.md +0 -61
  122. package/docs/releases/0.1.0-beta.4.md +0 -50
  123. package/docs/releases/0.1.0-rc.1.md +0 -99
  124. package/docs/releases/0.2.0-rc.1.md +0 -141
  125. package/docs/releases/0.2.0-rc.2.md +0 -225
  126. package/docs/releases.md +0 -144
  127. package/docs/testing.md +0 -93
@@ -1 +1 @@
1
- {"version":3,"file":"main.js","sourceRoot":"","sources":["../../src/cli/main.ts"],"names":[],"mappings":"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","sourcesContent":["#!/usr/bin/env node\nimport { Command } from \"commander\";\nimport { createTwoFilesPatch } from \"diff\";\nimport { access, constants, readFile, realpath, stat } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { format, lint, ruleRegistry } from \"../core/engine.js\";\nimport { loadConfig } from \"../config/load.js\";\nimport { resolveConfig } from \"../config/resolve.js\";\nimport { discover, vaultFor, writeAtomic } from \"../workspace/files.js\";\nimport { enclosingVault, vaultOf } from \"../workspace/vault.js\";\nimport { excludeSelection } from \"../workspace/selection.js\";\nimport { createWorkspace } from \"../workspace/index.js\";\nimport { pathError, refusal, refusalText } from \"../workspace/access.js\";\nimport type { Diagnostic, Dialect, DialectName, ProcessOptions, Workspace } from \"../core/types.js\";\nimport type { Vault } from \"../workspace/vault.js\";\n\ninterface Flags {\n config?: string;\n root?: string;\n dialect?: DialectName;\n json?: boolean;\n check?: boolean;\n diff?: boolean;\n write?: boolean;\n stdinFilepath?: string;\n maxWarnings?: number;\n exclude?: string[];\n}\nconst manifest = JSON.parse(\n await readFile(fileURLToPath(new URL(\"../../package.json\", import.meta.url)), \"utf8\"),\n) as { version: string };\nconst program = new Command()\n .name(\"mdtools\")\n .description(\"Lint and format Markdown with explicit dialects and configurable rules.\")\n .version(manifest.version);\nfunction common(command: Command): Command {\n return command\n .option(\"--config <file>\", \"Explicit JSON, JSONC, or .mjs configuration\")\n .option(\"--root <directory>\", \"Workspace root (default: configuration directory or cwd)\")\n .option(\n \"--dialect <dialect>\",\n \"commonmark, github, forgejo (alias: codeberg), gitea, or obsidian (when none is named: github, or obsidian inside a vault)\",\n )\n .option(\n \"--exclude <path>\",\n \"Exclude an exact file or directory (repeatable)\",\n (value: string, previous: string[]) => [...previous, value],\n [],\n )\n .option(\"--json\", \"Machine-readable output\")\n .option(\"--stdin-filepath <file>\", \"Filename context for stdin\")\n .option(\n \"--max-warnings <count>\",\n \"Fail when warning count exceeds this nonnegative integer\",\n (value: string) => {\n const number = Number(value);\n if (!Number.isInteger(number) || number < 0)\n throw new Error(\"--max-warnings must be a nonnegative integer.\");\n return number;\n },\n );\n}\ninterface Report {\n path: string;\n changed?: boolean;\n diagnostics: Diagnostic[];\n output?: string;\n}\n/**\n * The dialect to assume for a document when nothing names one, or undefined for\n * the library's own default. An Obsidian vault shows a single line break as a\n * line break and holds wikilinks, both of which any other dialect lets reflow\n * change, so a document that a vault holds is read as a note.\n */\nfunction assumedDialect(vault: Vault | string | undefined): Dialect | undefined {\n return vault ? \"obsidian\" : undefined;\n}\n/**\n * Stops when the folder given as `--root` cannot serve as a workspace root.\n * Without this check the first thing to fail would be the search for a\n * configuration file in it, with a message about a file the user never named.\n */\nasync function checkRoot(given: string | undefined): Promise<void> {\n if (given === undefined) return;\n const root = path.resolve(given);\n try {\n if (!(await stat(root)).isDirectory())\n throw new Error(`Workspace root is not a directory: ${root}`);\n await access(root, constants.R_OK | constants.X_OK);\n } catch (error) {\n throw pathError(\"Workspace root\", root, error);\n }\n}\nasync function run(mode: \"lint\" | \"format\", inputs: string[], flags: Flags) {\n if ([flags.check, flags.diff, flags.write].filter(Boolean).length > 1)\n throw new Error(\"Choose only one of --check, --diff, and --write.\");\n if (inputs.includes(\"-\") && flags.exclude?.length)\n throw new Error(\"--exclude cannot be combined with stdin.\");\n await checkRoot(flags.root);\n const loaded = await loadConfig(path.resolve(flags.root ?? \".\"), flags.config);\n const root = path.resolve(flags.root ?? loaded.root);\n if (flags.dialect) loaded.config.dialect = flags.dialect;\n // Which files to leave out does not depend on a document's dialect.\n const resolved = resolveConfig(loaded.config, \"document.md\", loaded.plugins);\n const stdin = inputs.includes(\"-\");\n if (stdin && (inputs.length !== 1 || flags.write))\n throw new Error(\"stdin must be the only input and cannot be combined with --write.\");\n const set = await discover(root, stdin ? [] : inputs, resolved.ignore, resolved.resolve);\n set.selected = await excludeSelection(set.root, set.selected, flags.exclude ?? []);\n /** The vault of the document read from stdin, found by a search of its own. */\n let named: Vault | undefined;\n if (stdin) {\n const name = path\n .relative(root, path.resolve(flags.stdinFilepath ?? path.join(root, \"stdin.md\")))\n .split(path.sep)\n .join(\"/\");\n if (name.startsWith(\"../\") || path.isAbsolute(name))\n throw new Error(\"--stdin-filepath must be within the workspace.\");\n let source = \"\";\n process.stdin.setEncoding(\"utf8\");\n for await (const chunk of process.stdin) source += String(chunk);\n set.files[name] = source;\n set.selected = [name];\n // The name can lead into a folder that discovery did not visit.\n named = await vaultFor(set, name);\n }\n // Links into a directory that could not be read are reported as unchecked, not as missing.\n const unreadable = set.skipped.flatMap((item) => (item.type === \"directory\" ? [item.path] : []));\n const reports: Report[] = [];\n const changes: { file: string; before: string; after: string }[] = [];\n // Selected files that the system refused to let the tool read.\n const unread: string[] = [];\n // The vault that the root is a folder of, if it is one: links may lead out of sight.\n const enclosing = set.vaults.find((item) => item.rootInVault);\n // One index per active dialect; build lazily for mixed documentation workspaces.\n const indexes = new Map<Dialect, Workspace>();\n // The same index with the line-break setting of each vault that has documents in it.\n const views = new Map<Dialect, Map<Vault, Workspace>>();\n for (const name of set.selected) {\n const vault = stdin ? named : vaultOf(set.vaults, name);\n const assumed = assumedDialect(vault);\n const config = resolveConfig(loaded.config, name, loaded.plugins, assumed);\n let workspace = indexes.get(config.dialect);\n if (!workspace)\n indexes.set(\n config.dialect,\n (workspace = createWorkspace(set.files, {\n dialect: config.dialect,\n directories: set.directories,\n unreadable,\n // The vault at or above the root holds the whole workspace and needs no entry.\n vaults: set.vaults.flatMap((item) => (item.path ? [item.path] : [])),\n ...(enclosing?.rootInVault ? { rootInVault: enclosing.rootInVault } : {}),\n })),\n );\n // Whether a note may be reflowed is a setting of its own vault.\n if (vault?.strictLineBreaks !== undefined) {\n let ofDialect = views.get(config.dialect);\n if (!ofDialect) views.set(config.dialect, (ofDialect = new Map()));\n const index = workspace;\n workspace = ofDialect.get(vault);\n if (!workspace)\n ofDialect.set(vault, (workspace = { ...index, strictLineBreaks: vault.strictLineBreaks }));\n }\n const options: ProcessOptions = {\n path: name,\n config: loaded.config,\n plugins: loaded.plugins,\n workspace,\n ...(assumed ? { defaultDialect: assumed } : {}),\n };\n const value = set.files[name]!;\n let source: string | null;\n try {\n source = typeof value === \"function\" ? value() : value;\n } catch (error) {\n // Report the file and carry on with the others; any other error is a fault.\n const code = refusal(error);\n if (!code) throw error;\n unread.push(name);\n reports.push({\n path: name,\n ...(mode === \"format\" ? { changed: false } : {}),\n diagnostics: [\n {\n start: 0,\n message: `The file could not be read (${refusalText(code)}) and was not ${mode === \"lint\" ? \"linted\" : \"formatted\"}.`,\n rule: \"engine/unreadable-file\",\n severity: \"error\",\n line: 1,\n column: 1,\n },\n ],\n });\n continue;\n }\n if (source === null) continue;\n if (mode === \"lint\") reports.push({ path: name, diagnostics: lint(source, options) });\n else {\n const result = format(source, options);\n reports.push({\n path: name,\n changed: result.changed,\n diagnostics: result.diagnostics,\n ...(stdin && !flags.check ? { output: result.output } : {}),\n });\n if (result.changed) changes.push({ file: name, before: source, after: result.output });\n }\n }\n // A file that could not be formatted safely, or not be read at all, is a failure\n // to operate: nothing of the batch is written, and the run ends with status 2.\n const diagnostics = reports.flatMap((report) => report.diagnostics);\n const count = (severity: Diagnostic[\"severity\"]) =>\n diagnostics.filter((item) => item.severity === severity).length;\n const unsafe =\n unread.length > 0 ||\n reports.some((report) =>\n report.diagnostics.some((item) => item.rule === \"engine/unsafe-format\"),\n );\n if (flags.write && !unsafe)\n for (const change of changes)\n await writeAtomic(path.join(set.root, change.file), change.before, change.after);\n if (flags.json)\n process.stdout.write(\n JSON.stringify(\n {\n version: manifest.version,\n mode,\n files: reports,\n written: flags.write === true && !unsafe,\n ...(set.skipped.length ? { skipped: set.skipped } : {}),\n },\n null,\n 2,\n ) + \"\\n\",\n );\n else {\n // Warnings about the run, not about a document: they do not change the exit status.\n for (const item of set.skipped) process.stderr.write(`mdtools: warning: ${item.message}\\n`);\n if (stdin && mode === \"format\" && !flags.check && !flags.diff)\n process.stdout.write(reports[0]?.output ?? \"\");\n else if (mode === \"format\" && !flags.check && !flags.write)\n for (const change of changes)\n process.stdout.write(\n createTwoFilesPatch(`a/${change.file}`, `b/${change.file}`, change.before, change.after),\n );\n for (const report of reports)\n for (const item of report.diagnostics)\n process.stderr.write(\n `${report.path}:${item.line}:${item.column}: ${item.severity} ${item.rule}: ${item.message}\\n`,\n );\n if (!stdin) {\n // Lint changes nothing, so its summary counts what it reported instead.\n const outcome =\n mode === \"lint\"\n ? `${count(\"error\")} error(s), ${count(\"warn\")} warning(s)`\n : `${changes.length} ${flags.write && !unsafe ? \"written\" : \"would change\"}`;\n process.stderr.write(\n `${set.selected.length - unread.length} file(s) ${mode === \"lint\" ? \"linted\" : \"processed\"}; ${outcome}${unread.length ? `; ${unread.length} could not be read` : \"\"}.\\n`,\n );\n }\n }\n const errors = count(\"error\") > 0;\n const tooManyWarnings = flags.maxWarnings !== undefined && count(\"warn\") > flags.maxWarnings;\n process.exitCode = unsafe\n ? 2\n : errors || tooManyWarnings || (flags.check && changes.length > 0)\n ? 1\n : 0;\n}\ncommon(\n program.command(\"lint\").argument(\"[paths...]\", \"Markdown files/directories, or - for stdin\"),\n).action((inputs: string[], flags: Flags) => run(\"lint\", inputs, flags));\ncommon(\n program.command(\"format\").argument(\"[paths...]\", \"Markdown files/directories, or - for stdin\"),\n)\n .option(\"--check\", \"Fail if formatting changes would be needed\")\n .option(\"--diff\", \"Preview the complete diff (default for file inputs)\")\n .option(\"--write\", \"Write validated formatting changes\")\n .action((inputs: string[], flags: Flags) => run(\"format\", inputs, flags));\ncommon(program.command(\"config\").description(\"Inspect effective configuration\"))\n .command(\"explain <file>\")\n .action(async (file: string, _flags: unknown, command: Command) => {\n const flags = command.parent!.opts<Flags>();\n await checkRoot(flags.root);\n const loaded = await loadConfig(path.resolve(flags.root ?? \".\"), flags.config);\n if (flags.dialect) loaded.config.dialect = flags.dialect;\n const root = path.resolve(flags.root ?? loaded.root);\n const name = path.relative(root, path.resolve(file)).split(path.sep).join(\"/\");\n // The file need not exist. It is located through the root's real path, as\n // discovery locates it, so that a root reached through a link is searched\n // upward from where it really is.\n const actual = await realpath(root).catch(() => root);\n process.stdout.write(\n JSON.stringify(\n {\n root,\n file: loaded.file ?? null,\n effective: resolveConfig(\n loaded.config,\n name,\n loaded.plugins,\n assumedDialect(await enclosingVault(path.join(actual, name))),\n ),\n },\n null,\n 2,\n ) + \"\\n\",\n );\n });\nprogram\n .command(\"rules\")\n .description(\"List built-in rules\")\n .action(() => {\n for (const [name, rule] of Object.entries(ruleRegistry()))\n process.stdout.write(`${name}\\t${rule.kind}\\t${rule.description}\\n`);\n });\ntry {\n await program.parseAsync();\n} catch (error) {\n process.stderr.write(`mdtools: ${error instanceof Error ? error.message : String(error)}\\n`);\n process.exitCode = 2;\n}\n"]}
1
+ {"version":3,"file":"main.js","sourceRoot":"","sources":["../../src/cli/main.ts"],"names":[],"mappings":"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","sourcesContent":["#!/usr/bin/env node\nimport { Command, CommanderError, InvalidArgumentError, Option } from \"commander\";\nimport { createTwoFilesPatch } from \"diff\";\nimport { readFile, realpath } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { format, lint, ruleRegistry } from \"../core/engine.js\";\nimport { loadConfig } from \"../config/load.js\";\nimport { dialectAliases, dialects, resolveConfig } from \"../config/resolve.js\";\nimport {\n replacementFailure,\n replacementProblem,\n skippedMessage,\n writeFormatted,\n} from \"../workspace/files.js\";\nimport { assumedDialect, checkRoot, discoverFrom } from \"../workspace/discovery.js\";\nimport { enclosingVault } from \"../workspace/vault.js\";\nimport { refusal, refusalText } from \"../workspace/access.js\";\nimport { decodeText, NotUtf8Error } from \"../workspace/encoding.js\";\nimport type { Diagnostic, DialectName } from \"../core/types.js\";\n\ninterface Flags {\n config?: string;\n root?: string;\n dialect?: DialectName;\n json?: boolean;\n check?: boolean;\n diff?: boolean;\n write?: boolean;\n stdinFilepath?: string;\n maxWarnings?: number;\n exclude?: string[];\n quiet?: boolean;\n fix?: boolean;\n}\nconst manifest = JSON.parse(\n await readFile(fileURLToPath(new URL(\"../../package.json\", import.meta.url)), \"utf8\"),\n) as { version: string };\n// Subcommands inherit these settings, so they come before the commands.\nconst program = new Command()\n .name(\"mdtools\")\n .description(\"Lint and format Markdown with explicit dialects and configurable rules.\")\n .version(manifest.version, \"-V, --version\", \"Print the version\")\n .helpOption(\"-h, --help\", \"Print help for the command\")\n .helpCommand(\"help [command]\", \"Print help for a command\")\n // Commander starts its messages with \"error: \", the tool with its name.\n .configureOutput({\n outputError: (text, write) => write(`mdtools: ${text.replace(/^error: /, \"\")}`),\n })\n // Throw instead of exiting, so that a usage error can end with code 2.\n .exitOverride();\nconst configOption = [\n \"--config <file>\",\n \"Use this JSON, JSONC, or JavaScript configuration file instead of searching for one\",\n] as const;\n/** The dialects, each with its other names, as in \"forgejo (alias: codeberg)\". */\nconst dialectList = dialects\n .map((dialect) => {\n const aliases = Object.entries(dialectAliases).flatMap(([name, of]) =>\n of === dialect ? [name] : [],\n );\n return aliases.length ? `${dialect} (alias: ${aliases.join(\", \")})` : dialect;\n })\n .join(\", \");\n/** The options that choose the configuration, the workspace, and the dialect. */\nfunction workspaceOptions(command: Command): Command {\n return command\n .option(...configOption)\n .option(\n \"--root <directory>\",\n \"Workspace root (default: the configuration file's directory; without one, the Git repository or vault where the search stopped, else the current directory)\",\n )\n .option(\n \"--dialect <dialect>\",\n `${dialectList} (when none is named: github, or obsidian inside a vault)`,\n (value: string) => {\n if (!Object.hasOwn(dialectAliases, value) && !(dialects as string[]).includes(value))\n throw new InvalidArgumentError(`The dialects are ${dialectList}.`);\n return value as DialectName;\n },\n );\n}\nfunction common(command: Command): Command {\n return (\n workspaceOptions(command)\n .option(\n \"--exclude <path>\",\n \"Exclude an exact file or directory (repeatable)\",\n (value: string, previous: string[] = []) => [...previous, value],\n )\n .option(\"--json\", \"Machine-readable output\")\n .option(\"--quiet\", \"Report errors only: leave warnings out of the report and its counts\")\n .option(\"--stdin-filepath <file>\", \"Filename context for stdin\")\n .option(\n \"--max-warnings <count>\",\n \"Fail when warning count exceeds this nonnegative integer\",\n (value: string) => {\n const number = Number(value);\n if (!Number.isInteger(number) || number < 0)\n throw new Error(\"--max-warnings must be a nonnegative integer.\");\n return number;\n },\n )\n // Not an option: `run` answers it with the option that does what it asks for.\n .addOption(new Option(\"--fix\").hideHelp())\n );\n}\n/**\n * The configuration and workspace root that the options name. `--dialect` is\n * applied to a copy, because an .mjs configuration may export a frozen object.\n */\nasync function workspace(flags: Flags) {\n // Without this check the first thing to fail would be the search for a\n // configuration file in the root, with a message about a file the user never named.\n if (flags.root !== undefined) await checkRoot(flags.root);\n const loaded = await loadConfig(path.resolve(flags.root ?? \".\"), flags.config);\n return {\n ...loaded,\n root: path.resolve(flags.root ?? loaded.root),\n config: flags.dialect ? { ...loaded.config, dialect: flags.dialect } : loaded.config,\n };\n}\n/**\n * The real path of `file`, which need not exist: the real path of the nearest\n * directory above it that does, with the rest of `file` appended.\n */\nasync function located(file: string): Promise<string> {\n const rest: string[] = [];\n for (let current = path.resolve(file); ;) {\n try {\n return path.join(await realpath(current), ...rest);\n } catch {\n const parent = path.dirname(current);\n if (parent === current) return path.resolve(file);\n rest.unshift(path.basename(current));\n current = parent;\n }\n }\n}\n/**\n * The path of `file`, which need not exist, from the workspace root, with\n * forward slashes, or undefined when it lies outside. Both are located through\n * their real paths, as discovery locates files, so that a root reached through\n * a link still holds the files below it.\n */\nasync function workspacePath(root: string, file: string): Promise<string | undefined> {\n const actual = await realpath(root).catch(() => root);\n const name = path\n .relative(actual, await located(file))\n .split(path.sep)\n .join(\"/\");\n return name === \"..\" || name.startsWith(\"../\") || path.isAbsolute(name) ? undefined : name;\n}\n/** The library's diagnostics for a document that it could not process as configured. */\nconst failures = new Set([\"engine/unsafe-format\", \"engine/rule-error\"]);\ninterface Report {\n path: string;\n changed?: boolean;\n diagnostics: Diagnostic[];\n output?: string;\n}\nasync function run(mode: \"lint\" | \"format\", inputs: string[], flags: Flags) {\n // ESLint and markdownlint-cli2 fix with --fix, Prettier with --write.\n if (flags.fix)\n throw new Error(\n mode === \"lint\"\n ? \"unknown option '--fix': lint never changes files; 'mdtools format --write' applies the fixes.\"\n : \"unknown option '--fix': format writes its changes with --write.\",\n );\n if ([flags.check, flags.diff, flags.write].filter(Boolean).length > 1)\n throw new Error(\"Choose only one of --check, --diff, and --write.\");\n if (inputs.includes(\"-\") && flags.exclude?.length)\n throw new Error(\"--exclude cannot be combined with stdin.\");\n const { root, ...loaded } = await workspace(flags);\n const stdin = inputs.includes(\"-\");\n if (stdin && (inputs.length !== 1 || flags.write))\n throw new Error(\"stdin must be the only input and cannot be combined with --write.\");\n /** The text read from stdin, by the name it is given in the workspace. */\n let documents: Record<string, string> | undefined;\n if (stdin) {\n const name = await workspacePath(root, flags.stdinFilepath ?? path.join(root, \"stdin.md\"));\n if (name === undefined) throw new Error(\"--stdin-filepath must be within the workspace.\");\n const chunks: Buffer[] = [];\n for await (const chunk of process.stdin) chunks.push(chunk as Buffer);\n try {\n documents = { [name]: decodeText(Buffer.concat(chunks), \"stdin\") };\n } catch (error) {\n // There is no file to report it for, and nothing else to process.\n if (error instanceof NotUtf8Error)\n throw new Error(`stdin is not UTF-8 text (${error.reason})`, { cause: error });\n throw error;\n }\n }\n // Paths on the command line are relative to the working directory, and no\n // path selects the whole workspace; stdin is the only document then.\n const discovery = await discoverFrom(\n {\n root,\n ...(stdin ? { inputs: [] } : inputs.length ? { inputs } : {}),\n exclude: flags.exclude ?? [],\n config: loaded.config,\n plugins: loaded.plugins,\n ...(documents ? { documents } : {}),\n },\n process.cwd(),\n );\n const reports: Report[] = [];\n const changes: { file: string; before: string; after: string }[] = [];\n // Selected files that the system refused to let the tool read, or that are not UTF-8 text.\n const unread: string[] = [];\n for (const name of discovery.selected) {\n const options = discovery.options(name);\n let source: string;\n try {\n source = discovery.read(name);\n } catch (error) {\n // Report the file and carry on with the others; any other error is a fault.\n const code = refusal(error);\n const problem = code\n ? `could not be read (${refusalText(code)})`\n : error instanceof NotUtf8Error\n ? `is not UTF-8 text (${error.reason})`\n : undefined;\n if (!problem) throw error;\n unread.push(name);\n reports.push({\n path: name,\n ...(mode === \"format\" ? { changed: false } : {}),\n diagnostics: [\n {\n start: 0,\n message: `The file ${problem} and was not ${mode === \"lint\" ? \"linted\" : \"formatted\"}.`,\n rule: \"engine/unreadable-file\",\n severity: \"error\",\n line: 1,\n column: 1,\n },\n ],\n });\n continue;\n }\n if (mode === \"lint\") reports.push({ path: name, diagnostics: lint(source, options) });\n else {\n const result = format(source, options);\n reports.push({\n path: name,\n changed: result.changed,\n diagnostics: result.diagnostics,\n ...(stdin && !flags.check ? { output: result.output } : {}),\n });\n if (result.changed) changes.push({ file: name, before: source, after: result.output });\n }\n }\n // A document that could not be read, had a rule refused or failing on it, or\n // could not be written is a failure to operate, reported for its own file,\n // and the run ends with status 2. Files do not depend on one another's\n // content, so every other changed document is still written, and so is the\n // result of one with a refused or failing rule, which the engine checked.\n const failed =\n unread.length > 0 ||\n reports.some((report) => report.diagnostics.some((item) => failures.has(item.rule)));\n // Changed files that could not be written, each reported for its file.\n const unwritten: string[] = [];\n const refuse = (file: string, message: string) => {\n unwritten.push(file);\n reports\n .find((report) => report.path === file)!\n .diagnostics.unshift({\n start: 0,\n message: `${message}.`,\n rule: \"engine/unwritable-file\",\n severity: \"error\",\n line: 1,\n column: 1,\n });\n };\n // The files that were written, in the order of the report.\n const written: string[] = [];\n if (flags.write)\n for (const change of changes) {\n const file = path.join(discovery.root, change.file);\n // A file that may not be written, such as a read-only one, is left alone.\n const problem = await replacementProblem(file);\n if (problem) {\n refuse(change.file, `${problem}; the file is unchanged`);\n continue;\n }\n try {\n await writeFormatted(file, change.before, change.after);\n written.push(change.file);\n } catch (error) {\n const failure = replacementFailure(error);\n if (!failure) throw error;\n refuse(change.file, failure);\n }\n }\n // As in ESLint, --quiet leaves warnings out of the report and of what counts them.\n if (flags.quiet)\n for (const report of reports)\n report.diagnostics = report.diagnostics.filter((item) => item.severity !== \"warn\");\n const diagnostics = reports.flatMap((report) => report.diagnostics);\n const count = (severity: Diagnostic[\"severity\"]) =>\n diagnostics.filter((item) => item.severity === severity).length;\n if (flags.json)\n process.stdout.write(\n JSON.stringify(\n {\n version: manifest.version,\n mode,\n // The files' paths are relative to it, for programs to join.\n root,\n files: reports,\n written,\n ...(discovery.skipped.length ? { skipped: discovery.skipped } : {}),\n },\n null,\n 2,\n ) + \"\\n\",\n );\n else {\n // Text names documents from the current directory, as Prettier does, so\n // that a terminal or an editor opens them from where the command ran.\n const here = await realpath(process.cwd()).catch(() => process.cwd());\n const shown = (name: string) =>\n path.relative(here, path.join(discovery.root, name)).split(path.sep).join(\"/\");\n // Warnings about the run, not about a document: they do not change the exit status.\n for (const item of discovery.skipped)\n process.stderr.write(`mdtools: warning: ${skippedMessage(item, shown)}\\n`);\n if (stdin && mode === \"format\" && !flags.check && !flags.diff)\n process.stdout.write(reports[0]?.output ?? \"\");\n else if (mode === \"format\" && !flags.check && !flags.write)\n for (const change of changes)\n process.stdout.write(\n createTwoFilesPatch(\n `a/${shown(change.file)}`,\n `b/${shown(change.file)}`,\n change.before,\n change.after,\n ),\n );\n for (const report of reports)\n for (const item of report.diagnostics)\n process.stderr.write(\n `${shown(report.path)}:${item.line}:${item.column}: ${item.severity} ${item.rule}: ${item.message}\\n`,\n );\n // The files to fix when a check fails, as Prettier's --check lists them.\n if (mode === \"format\" && flags.check && !stdin)\n for (const change of changes) process.stderr.write(`${shown(change.file)}\\n`);\n if (!stdin) {\n // Lint changes nothing, so its summary counts what it reported instead.\n const outcome =\n mode === \"lint\"\n ? `${count(\"error\")} error(s), ${count(\"warn\")} warning(s)`\n : flags.write\n ? `${written.length} written`\n : `${changes.length} would change`;\n process.stderr.write(\n `${discovery.selected.length - unread.length} file(s) ${mode === \"lint\" ? \"linted\" : \"processed\"}; ${outcome}${unread.length ? `; ${unread.length} could not be read` : \"\"}${unwritten.length ? `; ${unwritten.length} could not be written` : \"\"}.\\n`,\n );\n }\n }\n const errors = count(\"error\") > 0;\n const tooManyWarnings = flags.maxWarnings !== undefined && count(\"warn\") > flags.maxWarnings;\n process.exitCode =\n failed || unwritten.length > 0\n ? 2\n : errors || tooManyWarnings || (flags.check && changes.length > 0)\n ? 1\n : 0;\n}\ncommon(\n program\n .command(\"lint\")\n .argument(\"[paths...]\", \"Files, directories, or glob patterns to select, or - for stdin\"),\n)\n .description(\"Report the findings of the enabled rules; never writes\")\n .action((inputs: string[], flags: Flags) => run(\"lint\", inputs, flags));\ncommon(\n program\n .command(\"format\")\n .argument(\"[paths...]\", \"Files, directories, or glob patterns to select, or - for stdin\"),\n)\n .description(\"Format documents: print a diff (the default), check, or write\")\n .option(\"--check\", \"Fail if formatting changes would be needed, and name the files\")\n .option(\"--diff\", \"Preview the complete diff (default for file inputs)\")\n .option(\"--write\", \"Write validated formatting changes\")\n .action((inputs: string[], flags: Flags) => run(\"format\", inputs, flags));\n// The options belong to `config`, which reads them before or after `explain`;\n// `explain` repeats them so that its help lists them.\nworkspaceOptions(\n workspaceOptions(program.command(\"config\").description(\"Inspect the configuration\"))\n .command(\"explain\")\n .description(\"Print, as JSON, the configuration in effect for one document\")\n .argument(\"<file>\", \"The document, which need not exist\"),\n).action(async (file: string, _flags: unknown, command: Command) => {\n const flags = command.optsWithGlobals<Flags>();\n const { root, config, plugins, file: source } = await workspace(flags);\n const name = await workspacePath(root, file);\n if (name === undefined) throw new Error(`Input is outside the workspace: ${file}`);\n // The search for the document's vault starts from the root's real path too.\n const actual = await realpath(root).catch(() => root);\n process.stdout.write(\n JSON.stringify(\n {\n root,\n config: source ?? null,\n path: name,\n effective: resolveConfig({\n config,\n path: name,\n plugins,\n defaultDialect: assumedDialect(await enclosingVault(path.join(actual, name))),\n }),\n },\n null,\n 2,\n ) + \"\\n\",\n );\n});\nprogram\n .command(\"rules\")\n .description(\"List the built-in rules and those of the configuration's plugins\")\n .option(...configOption)\n .option(\"--json\", \"Print the list as JSON\")\n .action(async (flags: Flags) => {\n const { plugins } = await loadConfig(path.resolve(\".\"), flags.config);\n const rules = Object.entries(ruleRegistry(plugins)).map(([id, rule]) => ({\n id,\n kind: rule.kind,\n description: rule.description,\n }));\n if (flags.json) process.stdout.write(JSON.stringify({ rules }, null, 2) + \"\\n\");\n else\n for (const rule of rules)\n // One line per rule, even when a plugin's description has line breaks or tabs.\n process.stdout.write(\n `${rule.id}\\t${rule.kind}\\t${rule.description.replace(/\\s+/g, \" \")}\\n`,\n );\n });\ntry {\n await program.parseAsync();\n} catch (error) {\n // Commander has printed the help, the version, or what is wrong with the\n // command line. Help and the version succeed; a usage error ends with code 2,\n // as in ESLint and Prettier, so that it does not pass for findings.\n if (error instanceof CommanderError) process.exitCode = error.exitCode === 0 ? 0 : 2;\n else {\n process.stderr.write(`mdtools: ${error instanceof Error ? error.message : String(error)}\\n`);\n process.exitCode = 2;\n }\n}\n"]}
@@ -4,8 +4,59 @@ import { pathToFileURL } from "node:url";
4
4
  import { createRequire } from "node:module";
5
5
  import { parse, printParseErrorCode } from "jsonc-parser";
6
6
  import { configProblem, validateConfig } from "./resolve.js";
7
+ import { reservedPluginName } from "../core/engine.js";
7
8
  import { exists, pathError, refusal, refusalText } from "../workspace/access.js";
8
9
  import { isVault } from "../workspace/vault.js";
10
+ import { splitByteOrderMark } from "../syntax/parse.js";
11
+ /** The names of the configuration files that the search finds; one directory may hold one. */
12
+ const configFiles = [
13
+ "mdtools.config.jsonc",
14
+ "mdtools.config.json",
15
+ "mdtools.config.mjs",
16
+ "mdtools.config.js",
17
+ "mdtools.config.cjs",
18
+ ];
19
+ /**
20
+ * Whether Node.js loads `file` as JavaScript. A `.js` file is an ES module or
21
+ * CommonJS as Node.js decides from the nearest `package.json`; either way,
22
+ * importing it gives its default export or its `module.exports`.
23
+ */
24
+ const isScript = (file) => /\.[cm]?js$/i.test(file);
25
+ /** The 1-based line and column, in UTF-16 code units, of `offset` in `text`. */
26
+ function position(text, offset) {
27
+ let line = 1;
28
+ let start = 0;
29
+ for (const match of text.slice(0, offset).matchAll(/\r\n|\r|\n/g)) {
30
+ line++;
31
+ start = match.index + match[0].length;
32
+ }
33
+ return { line, column: offset - start + 1 };
34
+ }
35
+ const syntaxProblems = {
36
+ InvalidNumberFormat: "the number is not written as JSON writes numbers",
37
+ PropertyNameExpected: "a property name in double quotes is expected",
38
+ ValueExpected: "a value is expected",
39
+ ColonExpected: "a colon is expected",
40
+ CommaExpected: "a comma is expected",
41
+ CloseBraceExpected: "a closing brace is expected",
42
+ CloseBracketExpected: "a closing bracket is expected",
43
+ EndOfFileExpected: "the file should end here",
44
+ InvalidCommentToken: "a .json file cannot hold comments; name it .jsonc to keep them",
45
+ UnexpectedEndOfComment: "the comment is not closed",
46
+ UnexpectedEndOfString: "the string is not closed on its line",
47
+ UnexpectedEndOfNumber: "the number is incomplete",
48
+ InvalidUnicode: "the Unicode escape is invalid",
49
+ InvalidEscapeCharacter: "the escape sequence is invalid",
50
+ InvalidCharacter: "a control character in a string must be escaped",
51
+ };
52
+ /** A JSON syntax error in plain words. */
53
+ function syntaxProblem(text, error) {
54
+ const code = printParseErrorCode(error.error);
55
+ // Text such as an unquoted name or a single-quoted string, which JSON does not have.
56
+ if (code === "InvalidSymbol")
57
+ return `${JSON.stringify(text.slice(error.offset, error.offset + Math.min(error.length, 40)))} is not valid JSON here`;
58
+ return syntaxProblems[code] ?? code;
59
+ }
9
60
  export async function loadConfig(start, explicit) {
10
61
  let file = explicit ? path.resolve(explicit) : undefined;
11
62
  let fallbackRoot = path.resolve(start);
@@ -15,7 +66,7 @@ export async function loadConfig(start, explicit) {
15
66
  const found = [];
16
67
  let boundary;
17
68
  try {
18
- for (const name of ["mdtools.config.jsonc", "mdtools.config.json", "mdtools.config.mjs"])
69
+ for (const name of configFiles)
19
70
  if (await exists(path.join(directory, name)))
20
71
  found.push(path.join(directory, name));
21
72
  // A repository or an Obsidian vault is a workspace of its own.
@@ -50,11 +101,12 @@ export async function loadConfig(start, explicit) {
50
101
  let value = {};
51
102
  if (file && shown) {
52
103
  let text = "";
104
+ const script = isScript(file);
53
105
  try {
54
106
  if (!(await stat(file)).isFile())
55
107
  throw new Error(`Configuration file is not a file: ${shown}`);
56
108
  // A script is read by Node.js itself; its refusal would not name the file.
57
- if (file.endsWith(".mjs"))
109
+ if (script)
58
110
  await access(file, constants.R_OK);
59
111
  else
60
112
  text = await readFile(file, "utf8");
@@ -62,7 +114,7 @@ export async function loadConfig(start, explicit) {
62
114
  catch (error) {
63
115
  throw pathError("Configuration file", shown, error);
64
116
  }
65
- if (file.endsWith(".mjs")) {
117
+ if (script) {
66
118
  try {
67
119
  value = (await import(pathToFileURL(file).href)).default;
68
120
  }
@@ -72,12 +124,19 @@ export async function loadConfig(start, explicit) {
72
124
  }
73
125
  else {
74
126
  const errors = [];
75
- value = parse(text, errors, {
127
+ // RFC 8259 lets a parser ignore a byte order mark, which some Windows
128
+ // programs write at the start of a UTF-8 file; error offsets count after it.
129
+ const json = splitByteOrderMark(text)[1];
130
+ value = parse(json, errors, {
76
131
  allowTrailingComma: true,
77
132
  disallowComments: file.endsWith(".json"),
78
133
  });
79
- if (errors.length)
80
- throw new Error(`Invalid JSON configuration in ${shown}: ${errors.map((error) => `${printParseErrorCode(error.error)} at offset ${error.offset}`).join(", ")}`);
134
+ // The errors after the first mostly follow from it, as the parser recovers.
135
+ const [first] = errors;
136
+ if (first) {
137
+ const { line, column } = position(json, first.offset);
138
+ throw new Error(`Invalid JSON configuration in ${shown} at line ${line}, column ${column}: ${syntaxProblem(json, first)}`);
139
+ }
81
140
  }
82
141
  const problem = configProblem(value);
83
142
  if (problem)
@@ -190,6 +249,8 @@ async function loadPlugin(specifier, file) {
190
249
  !("name" in plugin) ||
191
250
  typeof plugin.name !== "string")
192
251
  throw new Error(`Invalid plugin "${specifier}" named in ${file}: its default export must be an object with a string "name".`);
252
+ if (plugin.name === reservedPluginName)
253
+ throw new Error(`Invalid plugin "${specifier}" named in ${file}: its name, ${reservedPluginName}, is reserved for the engine's own diagnostics.`);
193
254
  return plugin;
194
255
  }
195
256
  //# sourceMappingURL=load.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"load.js","sourceRoot":"","sources":["../../src/config/load.ts"],"names":[],"mappings":"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","sourcesContent":["import { access, constants, readFile, stat } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { pathToFileURL } from \"node:url\";\nimport { createRequire } from \"node:module\";\nimport { parse, printParseErrorCode } from \"jsonc-parser\";\nimport type { ParseError } from \"jsonc-parser\";\nimport type { Config, Plugin } from \"../core/types.js\";\nimport { configProblem, validateConfig } from \"./resolve.js\";\nimport { exists, pathError, refusal, refusalText } from \"../workspace/access.js\";\nimport { isVault } from \"../workspace/vault.js\";\n\nexport interface LoadedConfig {\n config: Config;\n plugins: Plugin[];\n root: string;\n file?: string;\n}\nexport async function loadConfig(start: string, explicit?: string): Promise<LoadedConfig> {\n let file = explicit ? path.resolve(explicit) : undefined;\n let fallbackRoot = path.resolve(start);\n if (!file) {\n let directory = path.resolve(start);\n for (;;) {\n const found: string[] = [];\n let boundary: boolean;\n try {\n for (const name of [\"mdtools.config.jsonc\", \"mdtools.config.json\", \"mdtools.config.mjs\"])\n if (await exists(path.join(directory, name))) found.push(path.join(directory, name));\n // A repository or an Obsidian vault is a workspace of its own.\n boundary =\n !found.length &&\n ((await exists(path.join(directory, \".git\"))) || (await isVault(directory)));\n } catch (error) {\n // Default rules must not take the place of a configuration that may be there.\n const code = refusal(error);\n if (!code) throw error;\n throw new Error(\n `Cannot look for a configuration file in ${directory} (${refusalText(code)})`,\n { cause: error },\n );\n }\n if (found.length > 1)\n throw new Error(`Multiple mdtools configuration files in ${directory}. Use --config.`);\n if (found.length) {\n file = found[0];\n break;\n }\n if (boundary) {\n fallbackRoot = directory;\n break;\n }\n if (path.dirname(directory) === directory) break;\n directory = path.dirname(directory);\n }\n }\n // The file as the user named it, or where the search found it.\n const shown = explicit ?? file;\n let value: unknown = {};\n if (file && shown) {\n let text = \"\";\n try {\n if (!(await stat(file)).isFile())\n throw new Error(`Configuration file is not a file: ${shown}`);\n // A script is read by Node.js itself; its refusal would not name the file.\n if (file.endsWith(\".mjs\")) await access(file, constants.R_OK);\n else text = await readFile(file, \"utf8\");\n } catch (error) {\n throw pathError(\"Configuration file\", shown, error);\n }\n if (file.endsWith(\".mjs\")) {\n try {\n value = ((await import(pathToFileURL(file).href)) as { default: unknown }).default;\n } catch (error) {\n throw new Error(\n `Cannot load configuration file ${shown}: ${error instanceof Error ? error.message : String(error)}`,\n { cause: error },\n );\n }\n } else {\n const errors: ParseError[] = [];\n value = parse(text, errors, {\n allowTrailingComma: true,\n disallowComments: file.endsWith(\".json\"),\n });\n if (errors.length)\n throw new Error(\n `Invalid JSON configuration in ${shown}: ${errors.map((error) => `${printParseErrorCode(error.error)} at offset ${error.offset}`).join(\", \")}`,\n );\n }\n const problem = configProblem(value);\n if (problem) throw new Error(`Invalid configuration in ${shown}: ${problem}`);\n }\n validateConfig(value);\n const root = file ? path.dirname(file) : fallbackRoot;\n const plugins: Plugin[] = [];\n // Only a configuration file can name plugins, so there is a file to resolve them from.\n if (file)\n for (const specifier of value.plugins ?? []) plugins.push(await loadPlugin(specifier, file));\n return { config: value, plugins, root, ...(file ? { file } : {}) };\n}\n\n/**\n * The options of `NODE_OPTIONS`, split as Node.js splits them: at spaces, except inside double\n * quotes, where a backslash takes the next character literally.\n */\nfunction splitNodeOptions(value: string): string[] {\n const options: string[] = [];\n let quoted = false;\n let fresh = true;\n for (let index = 0; index < value.length; index++) {\n let character = value[index]!;\n if (quoted && character === \"\\\\\" && index + 1 < value.length) character = value[++index]!;\n else if (character === \" \" && !quoted) {\n fresh = true;\n continue;\n } else if (character === '\"') {\n quoted = !quoted;\n continue;\n }\n // Like Node.js, an option starts with its first character, so `\"\"` alone is none.\n if (fresh) options.push(character);\n else options[options.length - 1] += character;\n fresh = false;\n }\n return options;\n}\n/**\n * The conditions Node.js applies to the `exports` of a package it imports: its defaults, as of\n * Node.js 22.12, changed by the options the process was started with. `--conditions` (`-C`)\n * adds one and `--no-addons` takes `node-addons` away, on the command line or in\n * `NODE_OPTIONS`. Node.js has no supported way to ask for the conditions in effect or to\n * resolve from another file, so they are worked out here.\n */\nexport function importConditions(\n execArgv: readonly string[] = process.execArgv,\n nodeOptions: string | undefined = process.env.NODE_OPTIONS,\n): Set<string> {\n const conditions = new Set([\"node\", \"import\", \"module-sync\", \"node-addons\"]);\n const options = [...splitNodeOptions(nodeOptions ?? \"\"), ...execArgv];\n for (let index = 0; index < options.length; index++) {\n const option = options[index]!;\n // Node.js takes the value after `=` or as the next option; `-C` only as the next.\n const named = /^--conditions(?:=(.*))?$/s.exec(option);\n if (named || option === \"-C\") {\n const condition = named?.[1] ?? options[++index];\n if (condition) conditions.add(condition);\n } else if (option === \"--no-addons\") conditions.delete(\"node-addons\");\n else if (option === \"--addons\") conditions.add(\"node-addons\");\n }\n return conditions;\n}\n\n/** The URL of the module that `specifier` names in the configuration file `file`. */\nasync function locatePlugin(specifier: string, file: string): Promise<string> {\n // A path is taken as written, not as a URL, so \"%\", \"#\", and \"?\" in a file name stay literal.\n if (specifier.startsWith(\".\") || path.isAbsolute(specifier)) {\n const named = path.resolve(path.dirname(file), specifier);\n // Node.js's reason for a file that is not there ends with the importing file, which\n // here is this one and means nothing to the user.\n // The check's own failure, such as a refusal, names the path and is reported as it is.\n if (!(await exists(named)) || !(await stat(named)).isFile())\n throw new Error(`no file at ${named}`);\n return pathToFileURL(named).href;\n }\n // Loaded only here, so that a run that names no package does not pay for the resolver.\n const { moduleResolve } = await import(\"import-meta-resolve\");\n try {\n // The module is imported, so its name is resolved as an import written in the\n // configuration file would be: a package's `import` entry wins over its `require` entry.\n return moduleResolve(specifier, pathToFileURL(file), importConditions()).href;\n } catch (error) {\n // CommonJS resolution finds what an import does not: an entry that is only declared for\n // `require`, a file named without its extension, a directory, and NODE_PATH.\n try {\n return pathToFileURL(createRequire(file).resolve(specifier)).href;\n } catch {\n throw error;\n }\n }\n}\n\nasync function loadPlugin(specifier: string, file: string): Promise<Plugin> {\n let plugin: unknown;\n try {\n plugin = ((await import(await locatePlugin(specifier, file))) as { default?: unknown }).default;\n } catch (error) {\n throw new Error(\n `Cannot load plugin \"${specifier}\" named in ${file}: ${error instanceof Error ? error.message : String(error)}`,\n { cause: error },\n );\n }\n if (\n !plugin ||\n typeof plugin !== \"object\" ||\n !(\"name\" in plugin) ||\n typeof plugin.name !== \"string\"\n )\n throw new Error(\n `Invalid plugin \"${specifier}\" named in ${file}: its default export must be an object with a string \"name\".`,\n );\n return plugin as Plugin;\n}\n"]}
1
+ {"version":3,"file":"load.js","sourceRoot":"","sources":["../../src/config/load.ts"],"names":[],"mappings":"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","sourcesContent":["import { access, constants, readFile, stat } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { pathToFileURL } from \"node:url\";\nimport { createRequire } from \"node:module\";\nimport { parse, printParseErrorCode } from \"jsonc-parser\";\nimport type { ParseError } from \"jsonc-parser\";\nimport type { Config, Plugin } from \"../core/types.js\";\nimport { configProblem, validateConfig } from \"./resolve.js\";\nimport { reservedPluginName } from \"../core/engine.js\";\nimport { exists, pathError, refusal, refusalText } from \"../workspace/access.js\";\nimport { isVault } from \"../workspace/vault.js\";\nimport { splitByteOrderMark } from \"../syntax/parse.js\";\n\nexport interface LoadedConfig {\n config: Config;\n plugins: Plugin[];\n root: string;\n file?: string;\n}\n/** The names of the configuration files that the search finds; one directory may hold one. */\nconst configFiles = [\n \"mdtools.config.jsonc\",\n \"mdtools.config.json\",\n \"mdtools.config.mjs\",\n \"mdtools.config.js\",\n \"mdtools.config.cjs\",\n];\n/**\n * Whether Node.js loads `file` as JavaScript. A `.js` file is an ES module or\n * CommonJS as Node.js decides from the nearest `package.json`; either way,\n * importing it gives its default export or its `module.exports`.\n */\nconst isScript = (file: string) => /\\.[cm]?js$/i.test(file);\n/** The 1-based line and column, in UTF-16 code units, of `offset` in `text`. */\nfunction position(text: string, offset: number): { line: number; column: number } {\n let line = 1;\n let start = 0;\n for (const match of text.slice(0, offset).matchAll(/\\r\\n|\\r|\\n/g)) {\n line++;\n start = match.index + match[0].length;\n }\n return { line, column: offset - start + 1 };\n}\nconst syntaxProblems: Partial<Record<ReturnType<typeof printParseErrorCode>, string>> = {\n InvalidNumberFormat: \"the number is not written as JSON writes numbers\",\n PropertyNameExpected: \"a property name in double quotes is expected\",\n ValueExpected: \"a value is expected\",\n ColonExpected: \"a colon is expected\",\n CommaExpected: \"a comma is expected\",\n CloseBraceExpected: \"a closing brace is expected\",\n CloseBracketExpected: \"a closing bracket is expected\",\n EndOfFileExpected: \"the file should end here\",\n InvalidCommentToken: \"a .json file cannot hold comments; name it .jsonc to keep them\",\n UnexpectedEndOfComment: \"the comment is not closed\",\n UnexpectedEndOfString: \"the string is not closed on its line\",\n UnexpectedEndOfNumber: \"the number is incomplete\",\n InvalidUnicode: \"the Unicode escape is invalid\",\n InvalidEscapeCharacter: \"the escape sequence is invalid\",\n InvalidCharacter: \"a control character in a string must be escaped\",\n};\n/** A JSON syntax error in plain words. */\nfunction syntaxProblem(text: string, error: ParseError): string {\n const code = printParseErrorCode(error.error);\n // Text such as an unquoted name or a single-quoted string, which JSON does not have.\n if (code === \"InvalidSymbol\")\n return `${JSON.stringify(text.slice(error.offset, error.offset + Math.min(error.length, 40)))} is not valid JSON here`;\n return syntaxProblems[code] ?? code;\n}\nexport async function loadConfig(start: string, explicit?: string): Promise<LoadedConfig> {\n let file = explicit ? path.resolve(explicit) : undefined;\n let fallbackRoot = path.resolve(start);\n if (!file) {\n let directory = path.resolve(start);\n for (;;) {\n const found: string[] = [];\n let boundary: boolean;\n try {\n for (const name of configFiles)\n if (await exists(path.join(directory, name))) found.push(path.join(directory, name));\n // A repository or an Obsidian vault is a workspace of its own.\n boundary =\n !found.length &&\n ((await exists(path.join(directory, \".git\"))) || (await isVault(directory)));\n } catch (error) {\n // Default rules must not take the place of a configuration that may be there.\n const code = refusal(error);\n if (!code) throw error;\n throw new Error(\n `Cannot look for a configuration file in ${directory} (${refusalText(code)})`,\n { cause: error },\n );\n }\n if (found.length > 1)\n throw new Error(`Multiple mdtools configuration files in ${directory}. Use --config.`);\n if (found.length) {\n file = found[0];\n break;\n }\n if (boundary) {\n fallbackRoot = directory;\n break;\n }\n if (path.dirname(directory) === directory) break;\n directory = path.dirname(directory);\n }\n }\n // The file as the user named it, or where the search found it.\n const shown = explicit ?? file;\n let value: unknown = {};\n if (file && shown) {\n let text = \"\";\n const script = isScript(file);\n try {\n if (!(await stat(file)).isFile())\n throw new Error(`Configuration file is not a file: ${shown}`);\n // A script is read by Node.js itself; its refusal would not name the file.\n if (script) await access(file, constants.R_OK);\n else text = await readFile(file, \"utf8\");\n } catch (error) {\n throw pathError(\"Configuration file\", shown, error);\n }\n if (script) {\n try {\n value = ((await import(pathToFileURL(file).href)) as { default: unknown }).default;\n } catch (error) {\n throw new Error(\n `Cannot load configuration file ${shown}: ${error instanceof Error ? error.message : String(error)}`,\n { cause: error },\n );\n }\n } else {\n const errors: ParseError[] = [];\n // RFC 8259 lets a parser ignore a byte order mark, which some Windows\n // programs write at the start of a UTF-8 file; error offsets count after it.\n const json = splitByteOrderMark(text)[1];\n value = parse(json, errors, {\n allowTrailingComma: true,\n disallowComments: file.endsWith(\".json\"),\n });\n // The errors after the first mostly follow from it, as the parser recovers.\n const [first] = errors;\n if (first) {\n const { line, column } = position(json, first.offset);\n throw new Error(\n `Invalid JSON configuration in ${shown} at line ${line}, column ${column}: ${syntaxProblem(json, first)}`,\n );\n }\n }\n const problem = configProblem(value);\n if (problem) throw new Error(`Invalid configuration in ${shown}: ${problem}`);\n }\n validateConfig(value);\n const root = file ? path.dirname(file) : fallbackRoot;\n const plugins: Plugin[] = [];\n // Only a configuration file can name plugins, so there is a file to resolve them from.\n if (file)\n for (const specifier of value.plugins ?? []) plugins.push(await loadPlugin(specifier, file));\n return { config: value, plugins, root, ...(file ? { file } : {}) };\n}\n\n/**\n * The options of `NODE_OPTIONS`, split as Node.js splits them: at spaces, except inside double\n * quotes, where a backslash takes the next character literally.\n */\nfunction splitNodeOptions(value: string): string[] {\n const options: string[] = [];\n let quoted = false;\n let fresh = true;\n for (let index = 0; index < value.length; index++) {\n let character = value[index]!;\n if (quoted && character === \"\\\\\" && index + 1 < value.length) character = value[++index]!;\n else if (character === \" \" && !quoted) {\n fresh = true;\n continue;\n } else if (character === '\"') {\n quoted = !quoted;\n continue;\n }\n // Like Node.js, an option starts with its first character, so `\"\"` alone is none.\n if (fresh) options.push(character);\n else options[options.length - 1] += character;\n fresh = false;\n }\n return options;\n}\n/**\n * The conditions Node.js applies to the `exports` of a package it imports: its defaults, as of\n * Node.js 22.12, changed by the options the process was started with. `--conditions` (`-C`)\n * adds one and `--no-addons` takes `node-addons` away, on the command line or in\n * `NODE_OPTIONS`. Node.js has no supported way to ask for the conditions in effect or to\n * resolve from another file, so they are worked out here.\n */\nexport function importConditions(\n execArgv: readonly string[] = process.execArgv,\n nodeOptions: string | undefined = process.env.NODE_OPTIONS,\n): Set<string> {\n const conditions = new Set([\"node\", \"import\", \"module-sync\", \"node-addons\"]);\n const options = [...splitNodeOptions(nodeOptions ?? \"\"), ...execArgv];\n for (let index = 0; index < options.length; index++) {\n const option = options[index]!;\n // Node.js takes the value after `=` or as the next option; `-C` only as the next.\n const named = /^--conditions(?:=(.*))?$/s.exec(option);\n if (named || option === \"-C\") {\n const condition = named?.[1] ?? options[++index];\n if (condition) conditions.add(condition);\n } else if (option === \"--no-addons\") conditions.delete(\"node-addons\");\n else if (option === \"--addons\") conditions.add(\"node-addons\");\n }\n return conditions;\n}\n\n/** The URL of the module that `specifier` names in the configuration file `file`. */\nasync function locatePlugin(specifier: string, file: string): Promise<string> {\n // A path is taken as written, not as a URL, so \"%\", \"#\", and \"?\" in a file name stay literal.\n if (specifier.startsWith(\".\") || path.isAbsolute(specifier)) {\n const named = path.resolve(path.dirname(file), specifier);\n // Node.js's reason for a file that is not there ends with the importing file, which\n // here is this one and means nothing to the user.\n // The check's own failure, such as a refusal, names the path and is reported as it is.\n if (!(await exists(named)) || !(await stat(named)).isFile())\n throw new Error(`no file at ${named}`);\n return pathToFileURL(named).href;\n }\n // Loaded only here, so that a run that names no package does not pay for the resolver.\n const { moduleResolve } = await import(\"import-meta-resolve\");\n try {\n // The module is imported, so its name is resolved as an import written in the\n // configuration file would be: a package's `import` entry wins over its `require` entry.\n return moduleResolve(specifier, pathToFileURL(file), importConditions()).href;\n } catch (error) {\n // CommonJS resolution finds what an import does not: an entry that is only declared for\n // `require`, a file named without its extension, a directory, and NODE_PATH.\n try {\n return pathToFileURL(createRequire(file).resolve(specifier)).href;\n } catch {\n throw error;\n }\n }\n}\n\nasync function loadPlugin(specifier: string, file: string): Promise<Plugin> {\n let plugin: unknown;\n try {\n plugin = ((await import(await locatePlugin(specifier, file))) as { default?: unknown }).default;\n } catch (error) {\n throw new Error(\n `Cannot load plugin \"${specifier}\" named in ${file}: ${error instanceof Error ? error.message : String(error)}`,\n { cause: error },\n );\n }\n if (\n !plugin ||\n typeof plugin !== \"object\" ||\n !(\"name\" in plugin) ||\n typeof plugin.name !== \"string\"\n )\n throw new Error(\n `Invalid plugin \"${specifier}\" named in ${file}: its default export must be an object with a string \"name\".`,\n );\n if (plugin.name === reservedPluginName)\n throw new Error(\n `Invalid plugin \"${specifier}\" named in ${file}: its name, ${reservedPluginName}, is reserved for the engine's own diagnostics.`,\n );\n return plugin as Plugin;\n}\n"]}
@@ -0,0 +1,7 @@
1
+ import type { ErrorObject } from "ajv";
2
+ /** A short description of a value that was given where something else belongs. */
3
+ export declare function shown(value: unknown): string;
4
+ /** The configuration's validation errors in plain words, naming each setting as it is written. */
5
+ export declare function configErrors(errors: readonly ErrorObject[], value: unknown, dialects: readonly string[]): string;
6
+ /** A rule's option errors in plain words, naming each option as it is written. */
7
+ export declare function optionErrors(errors: readonly ErrorObject[], value: unknown): string;
@@ -0,0 +1,208 @@
1
+ /** A short description of a value that was given where something else belongs. */
2
+ export function shown(value) {
3
+ switch (typeof value) {
4
+ case "string":
5
+ return JSON.stringify(value.length > 40 ? `${value.slice(0, 40)}…` : value);
6
+ case "number":
7
+ case "bigint":
8
+ case "boolean":
9
+ case "undefined":
10
+ return String(value);
11
+ case "function":
12
+ return "a function";
13
+ case "symbol":
14
+ return "a symbol";
15
+ default:
16
+ return value === null ? "null" : Array.isArray(value) ? "a list" : "an object";
17
+ }
18
+ }
19
+ /** Alternatives in prose: `"a", "b", or "c"`. */
20
+ function either(items) {
21
+ return items.length < 3
22
+ ? items.join(" or ")
23
+ : `${items.slice(0, -1).join(", ")}, or ${items.at(-1)}`;
24
+ }
25
+ /** The keys of a JSON pointer, such as `/rules/style~1wrap`, unescaped. */
26
+ function keys(pointer) {
27
+ return pointer
28
+ ? pointer
29
+ .slice(1)
30
+ .split("/")
31
+ .map((key) => key.replaceAll("~1", "/").replaceAll("~0", "~"))
32
+ : [];
33
+ }
34
+ /** Keys as a path written the way a reader finds them in a file: `overrides[0].files`. */
35
+ function written(path) {
36
+ let text = "";
37
+ for (const key of path)
38
+ text += /^\d+$/.test(key) ? `[${key}]` : text ? `.${key}` : key;
39
+ return text;
40
+ }
41
+ /** The part of `value` at `path`. */
42
+ function at(value, path) {
43
+ for (const key of path)
44
+ value =
45
+ value && typeof value === "object" && Object.hasOwn(value, key)
46
+ ? value[key]
47
+ : undefined;
48
+ return value;
49
+ }
50
+ const typeWords = {
51
+ string: "a string",
52
+ number: "a number",
53
+ integer: "an integer",
54
+ boolean: "true or false",
55
+ object: "an object",
56
+ array: "a list",
57
+ null: "null",
58
+ };
59
+ /** Limits in plain words, by keyword. */
60
+ const limits = {
61
+ minimum: (limit) => `must be at least ${String(limit)}`,
62
+ maximum: (limit) => `must be at most ${String(limit)}`,
63
+ exclusiveMinimum: (limit) => `must be more than ${String(limit)}`,
64
+ exclusiveMaximum: (limit) => `must be less than ${String(limit)}`,
65
+ minItems: (limit) => `must hold at least ${String(limit)} item(s)`,
66
+ maxItems: (limit) => `must hold at most ${String(limit)} item(s)`,
67
+ minLength: (limit) => `must be at least ${String(limit)} character(s) long`,
68
+ maxLength: (limit) => `must be at most ${String(limit)} character(s) long`,
69
+ };
70
+ /** Keywords whose failure means that the value itself is of the wrong kind, so naming it helps. */
71
+ const kinds = new Set(["type", "enum", "const"]);
72
+ const severities = either(['"off"', '"warn"', '"error"']);
73
+ /** Where `path` lies in a configuration, or in the override `scope` when it is set. */
74
+ function place(path, dialects, scope) {
75
+ const [key, ...rest] = path;
76
+ const name = (keys) => `"${scope ? `${scope}.` : ""}${written(keys)}"`;
77
+ const setting = written(scope ? [scope, ...path.slice(0, 1)] : path.slice(0, 1));
78
+ const item = (whole, one) => rest.length
79
+ ? { setting, label: name(path.slice(0, 2)), expected: one }
80
+ : { setting, label: name(path), expected: whole };
81
+ switch (key) {
82
+ case undefined:
83
+ return scope
84
+ ? { setting: scope, label: `"${scope}"`, expected: 'an object with "files"' }
85
+ : { setting: "", label: "the configuration", expected: "an object" };
86
+ case "$schema":
87
+ return { setting, label: name(path), expected: "a string" };
88
+ case "resolve":
89
+ return rest.length
90
+ ? {
91
+ setting: written(path.slice(0, 2)),
92
+ label: name(path.slice(0, 2)),
93
+ expected: "true or false",
94
+ }
95
+ : { setting, label: name(path), expected: "an object" };
96
+ case "extends":
97
+ return item("a preset name or a list of preset names", "a preset name");
98
+ case "dialect":
99
+ return { setting, label: name(path), expected: either(dialects.map((item) => `"${item}"`)) };
100
+ case "ignore":
101
+ return item("a list of path patterns", "a path pattern");
102
+ case "plugins":
103
+ return item("a list of file or package names", "a file or package name");
104
+ case "files":
105
+ return item("a list of one or more path patterns", "a path pattern");
106
+ case "rules": {
107
+ const [id, part] = rest;
108
+ if (id === undefined)
109
+ return { setting, label: name(path), expected: "an object of rule IDs and their settings" };
110
+ const of = `"${id}"${scope ? ` in "${scope}"` : ""}`;
111
+ const rule = `${setting}/${id}`;
112
+ if (part === "0")
113
+ return { setting: rule, label: `the severity of ${of}`, expected: severities };
114
+ if (part === "1")
115
+ return { setting: rule, label: `the options of ${of}`, expected: "an object" };
116
+ return {
117
+ setting: rule,
118
+ label: `the setting of ${of}`,
119
+ expected: `${severities}, or a list of a severity and, optionally, the rule's options`,
120
+ };
121
+ }
122
+ case "overrides": {
123
+ const [index, ...inside] = rest;
124
+ if (index === undefined)
125
+ return { setting, label: name(path), expected: 'a list of objects with "files"' };
126
+ return place(inside, dialects, `overrides[${index}]`);
127
+ }
128
+ default:
129
+ return { setting: written(path), label: name(path) };
130
+ }
131
+ }
132
+ /**
133
+ * Validation errors of a JSON Schema as one message in plain words, with each
134
+ * part named as it is written in the file: `"extends[1]" must be a preset name,
135
+ * not 5`. `describe` names a part and says what it must be; without
136
+ * `expected`, the validator's own words say it. Of the errors of one setting,
137
+ * only those deepest in the value are kept: they are the ones that a list or
138
+ * an object allowed as a whole still breaks.
139
+ */
140
+ function phrased(errors, value, describe, unknown) {
141
+ const messages = new Set();
142
+ /** The remaining errors of each setting, at the depth that counts. */
143
+ const settings = new Map();
144
+ for (const error of errors) {
145
+ const path = keys(error.instancePath);
146
+ if (error.keyword === "additionalProperties") {
147
+ const extra = String(error.params.additionalProperty);
148
+ messages.add(`unknown ${unknown} "${written([...path, extra])}"`);
149
+ continue;
150
+ }
151
+ if (error.keyword === "required") {
152
+ const missing = String(error.params.missingProperty);
153
+ messages.add(`${describe(path).label} must have "${missing}"`);
154
+ continue;
155
+ }
156
+ // A summary of alternatives that each failed; the alternatives say how.
157
+ if (error.keyword === "anyOf" || error.keyword === "oneOf")
158
+ continue;
159
+ const { setting } = describe(path);
160
+ const held = settings.get(setting);
161
+ if (!held || path.length > held.depth)
162
+ settings.set(setting, { depth: path.length, errors: [error] });
163
+ else if (path.length === held.depth)
164
+ held.errors.push(error);
165
+ }
166
+ for (const { errors: kept } of settings.values()) {
167
+ const byPath = new Map();
168
+ for (const error of kept)
169
+ byPath.set(error.instancePath, [...(byPath.get(error.instancePath) ?? []), error]);
170
+ for (const [pointer, group] of byPath) {
171
+ const path = keys(pointer);
172
+ const { label, expected } = describe(path);
173
+ const given = group.every((error) => kinds.has(error.keyword))
174
+ ? `, not ${shown(at(value, path))}`
175
+ : "";
176
+ if (expected)
177
+ messages.add(`${label} must be ${expected}${given}`);
178
+ else {
179
+ const types = group.flatMap((error) => error.keyword === "type" ? [error.params] : []);
180
+ if (types.length === group.length)
181
+ messages.add(`${label} must be ${either(types.flatMap(({ type }) => type).map((type) => typeWords[type] ?? type))}${given}`);
182
+ else
183
+ for (const error of group) {
184
+ const { allowedValues, limit } = error.params;
185
+ const limited = limits[error.keyword];
186
+ messages.add(error.keyword === "enum" && allowedValues
187
+ ? `${label} must be ${either(allowedValues.map((item) => JSON.stringify(item)))}${given}`
188
+ : limited && limit !== undefined
189
+ ? `${label} ${limited(limit)}`
190
+ : `${label} ${error.message ?? "is not valid"}${kinds.has(error.keyword) ? given : ""}`);
191
+ }
192
+ }
193
+ }
194
+ }
195
+ return [...messages].join("; ");
196
+ }
197
+ /** The configuration's validation errors in plain words, naming each setting as it is written. */
198
+ export function configErrors(errors, value, dialects) {
199
+ return phrased(errors, value, (path) => place(path, dialects), "setting");
200
+ }
201
+ /** A rule's option errors in plain words, naming each option as it is written. */
202
+ export function optionErrors(errors, value) {
203
+ return phrased(errors, value, (path) => ({
204
+ setting: written(path),
205
+ label: path.length ? `"${written(path)}"` : "the options",
206
+ }), "option");
207
+ }
208
+ //# sourceMappingURL=problems.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"problems.js","sourceRoot":"","sources":["../../src/config/problems.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ErrorObject } from \"ajv\";\n\n/** A short description of a value that was given where something else belongs. */\nexport function shown(value: unknown): string {\n switch (typeof value) {\n case \"string\":\n return JSON.stringify(value.length > 40 ? `${value.slice(0, 40)}…` : value);\n case \"number\":\n case \"bigint\":\n case \"boolean\":\n case \"undefined\":\n return String(value);\n case \"function\":\n return \"a function\";\n case \"symbol\":\n return \"a symbol\";\n default:\n return value === null ? \"null\" : Array.isArray(value) ? \"a list\" : \"an object\";\n }\n}\n/** Alternatives in prose: `\"a\", \"b\", or \"c\"`. */\nfunction either(items: readonly string[]): string {\n return items.length < 3\n ? items.join(\" or \")\n : `${items.slice(0, -1).join(\", \")}, or ${items.at(-1)}`;\n}\n/** The keys of a JSON pointer, such as `/rules/style~1wrap`, unescaped. */\nfunction keys(pointer: string): string[] {\n return pointer\n ? pointer\n .slice(1)\n .split(\"/\")\n .map((key) => key.replaceAll(\"~1\", \"/\").replaceAll(\"~0\", \"~\"))\n : [];\n}\n/** Keys as a path written the way a reader finds them in a file: `overrides[0].files`. */\nfunction written(path: readonly string[]): string {\n let text = \"\";\n for (const key of path) text += /^\\d+$/.test(key) ? `[${key}]` : text ? `.${key}` : key;\n return text;\n}\n/** The part of `value` at `path`. */\nfunction at(value: unknown, path: readonly string[]): unknown {\n for (const key of path)\n value =\n value && typeof value === \"object\" && Object.hasOwn(value, key)\n ? (value as Record<string, unknown>)[key]\n : undefined;\n return value;\n}\nconst typeWords: Record<string, string> = {\n string: \"a string\",\n number: \"a number\",\n integer: \"an integer\",\n boolean: \"true or false\",\n object: \"an object\",\n array: \"a list\",\n null: \"null\",\n};\n/** Limits in plain words, by keyword. */\nconst limits: Record<string, (limit: unknown) => string> = {\n minimum: (limit) => `must be at least ${String(limit)}`,\n maximum: (limit) => `must be at most ${String(limit)}`,\n exclusiveMinimum: (limit) => `must be more than ${String(limit)}`,\n exclusiveMaximum: (limit) => `must be less than ${String(limit)}`,\n minItems: (limit) => `must hold at least ${String(limit)} item(s)`,\n maxItems: (limit) => `must hold at most ${String(limit)} item(s)`,\n minLength: (limit) => `must be at least ${String(limit)} character(s) long`,\n maxLength: (limit) => `must be at most ${String(limit)} character(s) long`,\n};\n/** Keywords whose failure means that the value itself is of the wrong kind, so naming it helps. */\nconst kinds = new Set([\"type\", \"enum\", \"const\"]);\n\n/** What a part of the configuration is called in a message, and what it must be. */\ninterface Place {\n /** Places of one setting, whose errors are reported together. */\n setting: string;\n label: string;\n expected?: string;\n}\nconst severities = either(['\"off\"', '\"warn\"', '\"error\"']);\n/** Where `path` lies in a configuration, or in the override `scope` when it is set. */\nfunction place(path: readonly string[], dialects: readonly string[], scope?: string): Place {\n const [key, ...rest] = path;\n const name = (keys: readonly string[]) => `\"${scope ? `${scope}.` : \"\"}${written(keys)}\"`;\n const setting = written(scope ? [scope, ...path.slice(0, 1)] : path.slice(0, 1));\n const item = (whole: string, one: string): Place =>\n rest.length\n ? { setting, label: name(path.slice(0, 2)), expected: one }\n : { setting, label: name(path), expected: whole };\n switch (key) {\n case undefined:\n return scope\n ? { setting: scope, label: `\"${scope}\"`, expected: 'an object with \"files\"' }\n : { setting: \"\", label: \"the configuration\", expected: \"an object\" };\n case \"$schema\":\n return { setting, label: name(path), expected: \"a string\" };\n case \"resolve\":\n return rest.length\n ? {\n setting: written(path.slice(0, 2)),\n label: name(path.slice(0, 2)),\n expected: \"true or false\",\n }\n : { setting, label: name(path), expected: \"an object\" };\n case \"extends\":\n return item(\"a preset name or a list of preset names\", \"a preset name\");\n case \"dialect\":\n return { setting, label: name(path), expected: either(dialects.map((item) => `\"${item}\"`)) };\n case \"ignore\":\n return item(\"a list of path patterns\", \"a path pattern\");\n case \"plugins\":\n return item(\"a list of file or package names\", \"a file or package name\");\n case \"files\":\n return item(\"a list of one or more path patterns\", \"a path pattern\");\n case \"rules\": {\n const [id, part] = rest;\n if (id === undefined)\n return { setting, label: name(path), expected: \"an object of rule IDs and their settings\" };\n const of = `\"${id}\"${scope ? ` in \"${scope}\"` : \"\"}`;\n const rule = `${setting}/${id}`;\n if (part === \"0\")\n return { setting: rule, label: `the severity of ${of}`, expected: severities };\n if (part === \"1\")\n return { setting: rule, label: `the options of ${of}`, expected: \"an object\" };\n return {\n setting: rule,\n label: `the setting of ${of}`,\n expected: `${severities}, or a list of a severity and, optionally, the rule's options`,\n };\n }\n case \"overrides\": {\n const [index, ...inside] = rest;\n if (index === undefined)\n return { setting, label: name(path), expected: 'a list of objects with \"files\"' };\n return place(inside, dialects, `overrides[${index}]`);\n }\n default:\n return { setting: written(path), label: name(path) };\n }\n}\n\n/**\n * Validation errors of a JSON Schema as one message in plain words, with each\n * part named as it is written in the file: `\"extends[1]\" must be a preset name,\n * not 5`. `describe` names a part and says what it must be; without\n * `expected`, the validator's own words say it. Of the errors of one setting,\n * only those deepest in the value are kept: they are the ones that a list or\n * an object allowed as a whole still breaks.\n */\nfunction phrased(\n errors: readonly ErrorObject[],\n value: unknown,\n describe: (path: readonly string[]) => Place,\n unknown: string,\n): string {\n const messages = new Set<string>();\n /** The remaining errors of each setting, at the depth that counts. */\n const settings = new Map<string, { depth: number; errors: ErrorObject[] }>();\n for (const error of errors) {\n const path = keys(error.instancePath);\n if (error.keyword === \"additionalProperties\") {\n const extra = String((error.params as { additionalProperty: string }).additionalProperty);\n messages.add(`unknown ${unknown} \"${written([...path, extra])}\"`);\n continue;\n }\n if (error.keyword === \"required\") {\n const missing = String((error.params as { missingProperty: string }).missingProperty);\n messages.add(`${describe(path).label} must have \"${missing}\"`);\n continue;\n }\n // A summary of alternatives that each failed; the alternatives say how.\n if (error.keyword === \"anyOf\" || error.keyword === \"oneOf\") continue;\n const { setting } = describe(path);\n const held = settings.get(setting);\n if (!held || path.length > held.depth)\n settings.set(setting, { depth: path.length, errors: [error] });\n else if (path.length === held.depth) held.errors.push(error);\n }\n for (const { errors: kept } of settings.values()) {\n const byPath = new Map<string, ErrorObject[]>();\n for (const error of kept)\n byPath.set(error.instancePath, [...(byPath.get(error.instancePath) ?? []), error]);\n for (const [pointer, group] of byPath) {\n const path = keys(pointer);\n const { label, expected } = describe(path);\n const given = group.every((error) => kinds.has(error.keyword))\n ? `, not ${shown(at(value, path))}`\n : \"\";\n if (expected) messages.add(`${label} must be ${expected}${given}`);\n else {\n const types = group.flatMap((error) =>\n error.keyword === \"type\" ? [error.params as { type: string | string[] }] : [],\n );\n if (types.length === group.length)\n messages.add(\n `${label} must be ${either(types.flatMap(({ type }) => type).map((type) => typeWords[type] ?? type))}${given}`,\n );\n else\n for (const error of group) {\n const { allowedValues, limit } = error.params as {\n allowedValues?: unknown[];\n limit?: unknown;\n };\n const limited = limits[error.keyword];\n messages.add(\n error.keyword === \"enum\" && allowedValues\n ? `${label} must be ${either(allowedValues.map((item) => JSON.stringify(item)))}${given}`\n : limited && limit !== undefined\n ? `${label} ${limited(limit)}`\n : `${label} ${error.message ?? \"is not valid\"}${kinds.has(error.keyword) ? given : \"\"}`,\n );\n }\n }\n }\n }\n return [...messages].join(\"; \");\n}\n\n/** The configuration's validation errors in plain words, naming each setting as it is written. */\nexport function configErrors(\n errors: readonly ErrorObject[],\n value: unknown,\n dialects: readonly string[],\n): string {\n return phrased(errors, value, (path) => place(path, dialects), \"setting\");\n}\n/** A rule's option errors in plain words, naming each option as it is written. */\nexport function optionErrors(errors: readonly ErrorObject[], value: unknown): string {\n return phrased(\n errors,\n value,\n (path) => ({\n setting: written(path),\n label: path.length ? `\"${written(path)}\"` : \"the options\",\n }),\n \"option\",\n );\n}\n"]}