mdrefine 0.2.0-rc.2 → 0.2.0

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 (130) hide show
  1. package/CHANGELOG.md +577 -0
  2. package/CODE_OF_CONDUCT.md +30 -0
  3. package/CONTRIBUTING.md +189 -16
  4. package/README.md +100 -154
  5. package/SECURITY.md +15 -13
  6. package/config.schema.json +91 -0
  7. package/dist/cli/diff.d.ts +10 -0
  8. package/dist/cli/diff.js +247 -0
  9. package/dist/cli/diff.js.map +1 -0
  10. package/dist/cli/main.js +270 -150
  11. package/dist/cli/main.js.map +1 -1
  12. package/dist/config/load.js +67 -6
  13. package/dist/config/load.js.map +1 -1
  14. package/dist/config/problems.d.ts +7 -0
  15. package/dist/config/problems.js +208 -0
  16. package/dist/config/problems.js.map +1 -0
  17. package/dist/config/resolve.d.ts +42 -109
  18. package/dist/config/resolve.js +193 -52
  19. package/dist/config/resolve.js.map +1 -1
  20. package/dist/core/directives.d.ts +7 -0
  21. package/dist/core/directives.js +25 -13
  22. package/dist/core/directives.js.map +1 -1
  23. package/dist/core/engine.d.ts +42 -4
  24. package/dist/core/engine.js +518 -79
  25. package/dist/core/engine.js.map +1 -1
  26. package/dist/core/frozen.d.ts +6 -0
  27. package/dist/core/frozen.js +15 -0
  28. package/dist/core/frozen.js.map +1 -0
  29. package/dist/core/scope.d.ts +30 -0
  30. package/dist/core/scope.js +122 -0
  31. package/dist/core/scope.js.map +1 -0
  32. package/dist/core/types.d.ts +202 -23
  33. package/dist/core/types.js.map +1 -1
  34. package/dist/index.d.ts +2 -2
  35. package/dist/index.js.map +1 -1
  36. package/dist/node.d.ts +3 -0
  37. package/dist/node.js +4 -0
  38. package/dist/node.js.map +1 -0
  39. package/dist/rules/blocks.d.ts +34 -0
  40. package/dist/rules/blocks.js +550 -0
  41. package/dist/rules/blocks.js.map +1 -0
  42. package/dist/rules/content.d.ts +2 -0
  43. package/dist/rules/content.js +85 -0
  44. package/dist/rules/content.js.map +1 -0
  45. package/dist/rules/dialects.js +10 -6
  46. package/dist/rules/dialects.js.map +1 -1
  47. package/dist/rules/links.js +302 -6
  48. package/dist/rules/links.js.map +1 -1
  49. package/dist/rules/lists.d.ts +2 -0
  50. package/dist/rules/lists.js +924 -0
  51. package/dist/rules/lists.js.map +1 -0
  52. package/dist/rules/structure.js +127 -1
  53. package/dist/rules/structure.js.map +1 -1
  54. package/dist/rules/style.d.ts +8 -2
  55. package/dist/rules/style.js +1137 -165
  56. package/dist/rules/style.js.map +1 -1
  57. package/dist/syntax/block-identifier.d.ts +18 -0
  58. package/dist/syntax/block-identifier.js +24 -0
  59. package/dist/syntax/block-identifier.js.map +1 -0
  60. package/dist/syntax/obsidian.d.ts +29 -11
  61. package/dist/syntax/obsidian.js +9 -10
  62. package/dist/syntax/obsidian.js.map +1 -1
  63. package/dist/syntax/parse.d.ts +87 -3
  64. package/dist/syntax/parse.js +247 -19
  65. package/dist/syntax/parse.js.map +1 -1
  66. package/dist/workspace/access.d.ts +12 -3
  67. package/dist/workspace/access.js +33 -5
  68. package/dist/workspace/access.js.map +1 -1
  69. package/dist/workspace/discovery.d.ts +85 -0
  70. package/dist/workspace/discovery.js +155 -0
  71. package/dist/workspace/discovery.js.map +1 -0
  72. package/dist/workspace/encoding.d.ts +24 -0
  73. package/dist/workspace/encoding.js +113 -0
  74. package/dist/workspace/encoding.js.map +1 -0
  75. package/dist/workspace/files.d.ts +92 -6
  76. package/dist/workspace/files.js +715 -59
  77. package/dist/workspace/files.js.map +1 -1
  78. package/dist/workspace/git.d.ts +54 -0
  79. package/dist/workspace/git.js +198 -0
  80. package/dist/workspace/git.js.map +1 -0
  81. package/dist/workspace/index.d.ts +58 -3
  82. package/dist/workspace/index.js +136 -37
  83. package/dist/workspace/index.js.map +1 -1
  84. package/dist/workspace/selection.d.ts +2 -2
  85. package/dist/workspace/selection.js +3 -3
  86. package/dist/workspace/selection.js.map +1 -1
  87. package/dist/workspace/slug.js +8 -1
  88. package/dist/workspace/slug.js.map +1 -1
  89. package/dist/workspace/vault.js +3 -1
  90. package/dist/workspace/vault.js.map +1 -1
  91. package/docs/api.md +239 -0
  92. package/docs/benchmarks.md +140 -200
  93. package/docs/changelog.md +1 -0
  94. package/docs/cli.md +281 -89
  95. package/docs/configuration.md +193 -480
  96. package/docs/design.md +163 -284
  97. package/docs/dialects.md +169 -0
  98. package/docs/examples.md +151 -109
  99. package/docs/index.md +21 -37
  100. package/docs/integrations.md +144 -0
  101. package/docs/obsidian.md +91 -115
  102. package/docs/plugins.md +147 -212
  103. package/docs/quick-start.md +68 -74
  104. package/docs/rules.md +1237 -0
  105. package/docs/versions.md +56 -0
  106. package/examples/README.md +17 -14
  107. package/examples/automation/summarize-report.mjs +5 -2
  108. package/examples/library/lint-folder.mjs +5 -4
  109. package/examples/library/lint-workspace.mjs +32 -0
  110. package/examples/plugin/notes/release-checklist.md +2 -2
  111. package/examples/plugin/rules.mjs +17 -23
  112. package/examples/workspaces/obsidian-vault/after/mdtools.config.jsonc +2 -2
  113. package/examples/workspaces/obsidian-vault/before/mdtools.config.jsonc +2 -2
  114. package/examples/workspaces/repository-docs/after/README.md +2 -2
  115. package/examples/workspaces/repository-docs/after/mdtools.config.jsonc +0 -2
  116. package/examples/workspaces/repository-docs/before/README.md +2 -2
  117. package/examples/workspaces/repository-docs/before/docs/guide.md +7 -7
  118. package/examples/workspaces/repository-docs/before/docs/reference.md +3 -1
  119. package/examples/workspaces/repository-docs/before/mdtools.config.jsonc +0 -2
  120. package/package.json +38 -12
  121. package/docs/contributing.md +0 -218
  122. package/docs/releases/0.1.0-beta.1.md +0 -39
  123. package/docs/releases/0.1.0-beta.2.md +0 -83
  124. package/docs/releases/0.1.0-beta.3.md +0 -61
  125. package/docs/releases/0.1.0-beta.4.md +0 -50
  126. package/docs/releases/0.1.0-rc.1.md +0 -99
  127. package/docs/releases/0.2.0-rc.1.md +0 -141
  128. package/docs/releases/0.2.0-rc.2.md +0 -225
  129. package/docs/releases.md +0 -144
  130. package/docs/testing.md +0 -93
@@ -1 +1 @@
1
- {"version":3,"file":"files.js","sourceRoot":"","sources":["../../src/workspace/files.ts"],"names":[],"mappings":"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","sourcesContent":["import { lstat, readdir, readFile, realpath, open, rename, unlink } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { readFileSync } from \"node:fs\";\nimport type { Dirent } from \"node:fs\";\nimport type { ResolveOptions } from \"../core/types.js\";\nimport type { WorkspaceSource } from \"./index.js\";\nimport { randomUUID } from \"node:crypto\";\nimport ignore from \"ignore\";\nimport { minimatch } from \"minimatch\";\nimport { exists, pathError, refusal, refusalText } from \"./access.js\";\nimport type { RefusalCode } from \"./access.js\";\nimport { enclosingVault, isVault, lineBreakSetting } from \"./vault.js\";\nimport type { SettingsProblem, Vault } from \"./vault.js\";\n\n/** A path that discovery could not use and left out of the run. */\nexport interface Skipped {\n /** The directory or settings file, relative to the workspace root. */\n path: string;\n type: \"directory\" | \"file\";\n /** The system's error code, or `INVALID` for a settings file with unusable content. */\n code: RefusalCode | \"INVALID\";\n /** What was skipped, why, and what follows from it. */\n message: string;\n}\nexport interface FileSet {\n root: string;\n files: Record<string, WorkspaceSource>;\n directories: string[];\n /** What discovery could not read or use, sorted by path. */\n skipped: Skipped[];\n selected: string[];\n /**\n * The Obsidian vaults that hold documents of the workspace, sorted by path:\n * the one at or above the root, and each one in a folder that discovery\n * visited.\n */\n vaults: Vault[];\n}\n/** The workspace's record of the vault in `directory`, and of its settings file if unusable. */\nasync function describeVault(\n root: string,\n part: string,\n directory: string,\n): Promise<{ vault: Vault; skipped?: Skipped }> {\n const setting = await lineBreakSetting(directory);\n // Only the vault that holds the root can lie above it.\n const below = part ? \"\" : path.relative(directory, root).split(path.sep).join(\"/\");\n const vault: Vault = {\n path: part,\n ...(setting.value !== undefined ? { strictLineBreaks: setting.value } : {}),\n ...(below ? { rootInVault: below } : {}),\n };\n if (!setting.problem) return { vault };\n const problem: SettingsProblem = setting.problem;\n const file = path\n .relative(root, path.join(directory, \".obsidian\", \"app.json\"))\n .split(path.sep)\n .join(\"/\");\n return {\n vault,\n skipped: {\n path: file,\n type: \"file\",\n code: problem.code,\n message: `Skipped ${problem.code === \"INVALID\" ? \"unusable\" : \"unreadable\"} settings file: ${file} (${problem.reason}). Obsidian's strictLineBreaks setting is not verified for that vault, so its documents are not reflowed.`,\n },\n };\n}\n/**\n * The vault that holds the document `name` of the workspace, which need not\n * exist on disk: text read from stdin can be named into a folder that discovery\n * did not visit. The vault is found by searching upward from the document's\n * folder and is added to the set when it is new.\n */\nexport async function vaultFor(set: FileSet, name: string): Promise<Vault | undefined> {\n const directory = await enclosingVault(path.join(set.root, name));\n if (!directory) return undefined;\n const relative = path.relative(set.root, directory).split(path.sep).join(\"/\");\n const part =\n relative === \"..\" || relative.startsWith(\"../\") || path.isAbsolute(relative) ? \"\" : relative;\n const known = set.vaults.find((vault) => vault.path === part);\n if (known) return known;\n const described = await describeVault(set.root, part, directory);\n set.vaults.push(described.vault);\n if (described.skipped) set.skipped.push(described.skipped);\n return described.vault;\n}\nexport async function discover(\n rootPath: string,\n supplied: string[],\n excluded: string[],\n resolve: ResolveOptions = {},\n): Promise<FileSet> {\n const root = await realpath(rootPath);\n const files: Record<string, WorkspaceSource> = {};\n const directories: string[] = [];\n const selected: string[] = [];\n const requests: string[] = [];\n /** The folders that are vaults, by the part of the workspace that each holds. */\n const vaultFolders = new Map<string, string>();\n for (const input of supplied.length ? supplied : [root]) {\n const absolute = path.resolve(input);\n let resolved: string;\n try {\n if ((await lstat(absolute)).isSymbolicLink())\n throw new Error(`Refusing symbolic-link input: ${input}`);\n resolved = await realpath(absolute);\n } catch (error) {\n throw pathError(\"Input\", input, error);\n }\n const relative = path.relative(root, resolved).split(path.sep).join(\"/\");\n if (relative.startsWith(\"../\") || relative === \"..\" || path.isAbsolute(relative))\n throw new Error(`Input is outside the workspace: ${input}`);\n requests.push(relative);\n }\n interface IgnoreLayer {\n base: string;\n matcher: ReturnType<typeof ignore>;\n }\n /** Directories left out, with the path whose read the system refused. */\n const refused: { directory: string; reading: string; code: RefusalCode }[] = [];\n const reason = (item: { reading: string; code: RefusalCode }, subject: string) =>\n refusalText(item.code) + (item.reading === subject ? \"\" : ` for ${item.reading}`);\n /**\n * Leave out a directory that the system refuses to let the tool read. Any\n * other error is a fault and stops the run, and so does a refusal for the\n * workspace root, without which there is nothing to do.\n */\n function leaveOut(directory: string, reading: string, error: unknown): void {\n const code = refusal(error);\n if (!code) throw error;\n if (!directory)\n throw new Error(\n `Workspace root cannot be read: ${rootPath} (${reason({ reading, code }, \"\")})`,\n { cause: error },\n );\n refused.push({ directory, reading, code });\n }\n async function walk(relative: string, inherited: IgnoreLayer[], targetOnly = false) {\n const directory = path.join(root, relative);\n const layers = [...inherited];\n const rules = path.join(directory, \".gitignore\");\n let entries: Dirent[];\n // What is being read: the directory itself, or its `.gitignore`. Without the\n // ignore rules nothing tells which of the directory's files may be touched.\n let reading = relative;\n try {\n if (await exists(rules)) {\n reading = relative ? `${relative}/.gitignore` : \".gitignore\";\n layers.push({ base: relative, matcher: ignore().add(await readFile(rules, \"utf8\")) });\n reading = relative;\n }\n entries = await readdir(directory, { withFileTypes: true });\n } catch (error) {\n leaveOut(relative, reading, error);\n return;\n }\n // Obsidian creates the settings folder itself; a link to one shares a vault's settings.\n const settings = entries.find((entry) => entry.name === \".obsidian\");\n if (settings?.isDirectory() || (settings?.isSymbolicLink() && (await isVault(directory))))\n vaultFolders.set(relative, directory);\n for (const entry of entries) {\n if (\n [\".git\", \".obsidian\", \"node_modules\", \".npm-cache\", \"dist\", \"coverage\"].includes(\n entry.name,\n ) ||\n entry.isSymbolicLink()\n )\n continue;\n const name = relative ? `${relative}/${entry.name}` : entry.name;\n const gitIgnored = layers.some((layer) =>\n layer.matcher.ignores(\n name.slice(layer.base ? layer.base.length + 1 : 0) + (entry.isDirectory() ? \"/\" : \"\"),\n ),\n );\n if (gitIgnored && resolve.gitIgnored !== true) continue;\n const full = path.join(root, name);\n if (entry.isDirectory()) {\n directories.push(name);\n let nested: boolean;\n try {\n nested = await exists(path.join(full, \".git\"));\n } catch (error) {\n // A directory that cannot be entered: nothing in it can be read.\n leaveOut(name, name, error);\n continue;\n }\n if (!nested || resolve.nestedRepositories === true)\n await walk(name, layers, targetOnly || gitIgnored || nested);\n } else if (entry.isFile()) {\n const markdown = /\\.md$/i.test(name);\n let cached: string | undefined;\n files[name] = markdown ? () => (cached ??= readFileSync(full, \"utf8\")) : null;\n if (\n markdown &&\n !targetOnly &&\n !gitIgnored &&\n requests.some(\n (request) => !request || name === request || name.startsWith(`${request}/`),\n ) &&\n !excluded.some((pattern) => minimatch(name, pattern, { dot: true }))\n )\n selected.push(name);\n }\n }\n }\n await walk(\"\", []);\n // An input in a directory that was left out is an error: the user asked for it.\n for (const [index, request] of requests.entries()) {\n const item = refused.find(\n ({ directory }) => request === directory || request.startsWith(`${directory}/`),\n );\n if (item)\n throw new Error(`Input cannot be read: ${supplied[index]!} (${reason(item, request)})`);\n }\n const skipped: Skipped[] = refused.map((item) => ({\n path: item.directory,\n type: \"directory\",\n code: item.code,\n message: `Skipped unreadable directory: ${item.directory} (${reason(item, item.directory)}). Its files are not processed, and links into it cannot be checked.`,\n }));\n // A root that is no vault itself can be a folder of one.\n if (!vaultFolders.has(\"\")) {\n const outer = await enclosingVault(root);\n if (outer) vaultFolders.set(\"\", outer);\n }\n const vaults: Vault[] = [];\n for (const [part, directory] of vaultFolders) {\n const described = await describeVault(root, part, directory);\n vaults.push(described.vault);\n if (described.skipped) skipped.push(described.skipped);\n }\n const byPath = (a: { path: string }, b: { path: string }) =>\n a.path < b.path ? -1 : a.path > b.path ? 1 : 0;\n return {\n root,\n files,\n directories,\n skipped: skipped.sort(byPath),\n selected: selected.sort(),\n vaults: vaults.sort(byPath),\n };\n}\nexport async function writeAtomic(file: string, before: string, after: string): Promise<void> {\n const info = await lstat(file);\n if (!info.isFile() || info.isSymbolicLink())\n throw new Error(`Refusing non-regular file: ${file}`);\n if ((await readFile(file, \"utf8\")) !== before)\n throw new Error(`File changed during formatting: ${file}`);\n const temporary = path.join(path.dirname(file), `.mdtools-${randomUUID()}.tmp`);\n const handle = await open(temporary, \"wx\", info.mode);\n try {\n await handle.writeFile(after, \"utf8\");\n await handle.chmod(info.mode);\n await handle.sync();\n await handle.close();\n const current = await lstat(file);\n if (\n current.isSymbolicLink() ||\n current.ino !== info.ino ||\n (await readFile(file, \"utf8\")) !== before\n )\n throw new Error(`File changed before replacement: ${file}`);\n await rename(temporary, file);\n } finally {\n await handle.close();\n await unlink(temporary).catch((error: NodeJS.ErrnoException) => {\n if (error.code !== \"ENOENT\") throw error;\n });\n }\n}\n"]}
1
+ {"version":3,"file":"files.js","sourceRoot":"","sources":["../../src/workspace/files.ts"],"names":[],"mappings":"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","sourcesContent":["import { access, lstat, readdir, readFile, realpath, open, unlink } from \"node:fs/promises\";\nimport type { FileHandle } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { constants, lstatSync, readFileSync, realpathSync, statSync } from \"node:fs\";\nimport type { Dirent, Stats } from \"node:fs\";\nimport type { ResolveOptions } from \"../core/types.js\";\nimport type { LookupResult, WorkspaceSource } from \"./index.js\";\nimport { randomBytes, randomUUID } from \"node:crypto\";\nimport ignore from \"ignore\";\nimport type { Ignore } from \"ignore\";\nimport { minimatch, Minimatch } from \"minimatch\";\nimport { exists, pathError, refusal, refusalText, systemErrorText } from \"./access.js\";\nimport type { RefusalCode } from \"./access.js\";\nimport { decodeText } from \"./encoding.js\";\nimport { excludesFile, ignoreSettings, optionalText, repositoryTop, trackedFiles } from \"./git.js\";\nimport { isMarkdownName } from \"./index.js\";\nimport { enclosingVault, isVault, lineBreakSetting } from \"./vault.js\";\nimport type { SettingsProblem, Vault } from \"./vault.js\";\n\n/** A path that discovery could not use and left out of the run. */\nexport interface Skipped {\n /** The directory or file, relative to the workspace root. */\n path: string;\n /** Whether a directory or a file was left out. */\n type: \"directory\" | \"file\";\n /**\n * The system's error code, `INVALID` for a settings file with unusable\n * content, or `IGNORED` for an input that was named but is ignored.\n */\n code: RefusalCode | \"INVALID\" | \"IGNORED\";\n /** What was skipped, why, and what follows from it. */\n message: string;\n}\n/** Names a path of the workspace, given relative to the root, as a message shows it. */\ntype PathText = (file: string) => string;\n/** The words of each skipped entry's message, with the paths it names left to the caller. */\nconst wording = new WeakMap<Skipped, (show: PathText) => string>();\n/** A skipped entry whose message names paths relative to the root. */\nfunction skip(entry: Omit<Skipped, \"message\">, words: (show: PathText) => string): Skipped {\n const item = { ...entry, message: words((file) => file) };\n wording.set(item, words);\n return item;\n}\n/**\n * The message of a skipped entry with each path of the workspace that it names\n * given by `show`, which receives the path relative to the root. The CLI's text\n * names them from the current directory.\n */\nexport function skippedMessage(item: Skipped, show: PathText): string {\n return wording.get(item)?.(show) ?? item.message;\n}\n/** The skipped entries of named inputs that ignore rules leave out. */\nconst ignoredInputs = new WeakSet<Skipped>();\n/**\n * Whether a skipped entry reports a named file or folder that discovery leaves\n * out as ignored, a warning that the CLI's `--no-warn-ignored` leaves out. An\n * ignored workspace root is not one: no path named it, and none of its files is\n * processed.\n */\nexport function isIgnoredInput(item: Skipped): boolean {\n return ignoredInputs.has(item);\n}\n/** A file of ignore rules as a message shows it: one outside the repository by its full path. */\nfunction showFile(show: PathText, file: string): string {\n return path.isAbsolute(file) ? file : show(file);\n}\n/**\n * Names of folders and files that discovery never enters or selects, wherever\n * they are. A link can still name what is in them; `unlistedLookup` finds it.\n */\nconst alwaysSkipped = new Set([\".git\", \".obsidian\", \"node_modules\", \"dist\", \"coverage\"]);\n/**\n * Whether letter case is ignored where the file system usually ignores it, as\n * those of Windows and macOS do by default. Git turns `core.ignorecase` on when\n * it creates a repository on such a file system, and `.gitignore` patterns\n * match accordingly; where Git cannot say, this stands in for the setting.\n */\nconst caseInsensitive = process.platform === \"win32\" || process.platform === \"darwin\";\n/**\n * Characters that make an input a pattern when no path of its name exists:\n * wildcards, a character class, a brace list, or an extended group.\n */\nconst patternCharacters = /[*?[{]|[!@+]\\(/;\n/**\n * How input patterns match, on every system: `/` separates folders and `\\`\n * escapes the next character; a name starting with a dot is matched like any\n * other, as discovery finds it; letter case is ignored where the file system\n * usually ignores it, as the `glob` package does.\n */\nconst patternOptions = { dot: true, nocomment: true, nonegate: true, nocase: caseInsensitive };\n/**\n * A file of Git ignore rules for the folder whose paths its patterns match: a\n * `.gitignore` for the folder that holds it, and a repository's\n * `info/exclude` or the global excludes file for the repository's top level.\n */\ninterface IgnoreLayer {\n /**\n * The folder, relative to the top level of the repository that holds the\n * workspace root, or to the root outside a repository; empty for that folder.\n */\n base: string;\n /** The file, as messages name it. */\n file: string;\n /** The file's text. */\n text: string;\n /** Whether its patterns match without regard to letter case, as its repository says. */\n ignoreCase: boolean;\n matcher: Ignore;\n}\n/** A gitignore pattern that matches exactly one folder, at a path relative to the file's folder. */\nfunction folderOnly(folder: string): string {\n return `/${folder.replace(/[\\\\*?[]/g, \"\\\\$&\")}/`;\n}\n/**\n * The matchers for the entries of the folder `at`, relative to where the\n * layers' folders are, one for each file of rules above them, nearest last,\n * with the path from that file's folder. Git asks each file only whether its\n * patterns match the path itself; that nothing below an excluded folder counts\n * is settled by the walk, which never enters one. The `ignore` package also\n * answers that a path is ignored when the file's patterns exclude a folder\n * above it, which is wrong when a deeper `.gitignore` included that folder\n * again. For such a folder, the file's patterns are tested with each folder on\n * the way marked as included.\n */\nfunction ignoreScopes(at: string, layers: IgnoreLayer[]) {\n return layers.map((layer) => {\n const inner = at.slice(layer.base ? layer.base.length + 1 : 0);\n let { matcher } = layer;\n if (inner && matcher.test(`${inner}/`).ignored) {\n const folders = inner\n .split(\"/\")\n .map((_, index, parts) => parts.slice(0, index + 1).join(\"/\"));\n matcher = ignore({ ignorecase: layer.ignoreCase })\n .add(layer.text)\n .add(folders.map((folder) => `!${folderOnly(folder)}`));\n }\n return { layer, matcher, prefix: inner ? `${inner}/` : \"\" };\n });\n}\n/**\n * The file and pattern that exclude an entry, or undefined when none does: the\n * nearest file whose patterns match the entry decides, and a negated pattern\n * includes it.\n */\nfunction gitIgnoreRule(\n scopes: ReturnType<typeof ignoreScopes>,\n entry: string,\n directory: boolean,\n): { file: string; pattern: string } | undefined {\n for (let index = scopes.length - 1; index >= 0; index--) {\n const { layer, matcher, prefix } = scopes[index]!;\n const result = matcher.test(prefix + entry + (directory ? \"/\" : \"\"));\n if (result.ignored) return { file: layer.file, pattern: result.rule?.pattern ?? \"\" };\n if (result.unignored) return undefined;\n }\n return undefined;\n}\n/**\n * The layer of the rules `text`, read from `file`, for the folder `base`, in a\n * repository that ignores letter case or not.\n */\nfunction ignoreLayer(base: string, file: string, text: string, ignoreCase: boolean): IgnoreLayer {\n return { base, file, text, ignoreCase, matcher: ignore({ ignorecase: ignoreCase }).add(text) };\n}\n/** A path that the user named among the inputs. */\ninterface NamedInput {\n /** The real path, relative to the root. */\n path: string;\n directory: boolean;\n /** Whether it is only a supplied document's path, which selects nothing on disk. */\n document?: boolean;\n /** Why discovery leaves it out, when it does, naming paths through `show`. */\n reason?: (show: PathText) => string;\n}\n/** An input that is a pattern, with one matcher of paths from the root for each brace alternative. */\ninterface PatternInput {\n input: string;\n matchers: Minimatch[];\n /** The folders, relative to the root, that the alternatives' literal parts name. */\n folders: string[];\n matched: boolean;\n}\n/**\n * An input that names no existing path, read as a pattern relative to `base`.\n * The literal folders at the start of each alternative are located as a path\n * is, so the pattern can match paths from the workspace root. Undefined for an\n * input without pattern characters.\n */\nasync function patternInput(\n input: string,\n root: string,\n base: string,\n): Promise<PatternInput | undefined> {\n if (!patternCharacters.test(input)) return undefined;\n const result: PatternInput = { input, matchers: [], folders: [], matched: false };\n for (const alternative of minimatch.braceExpand(input)) {\n const parts = alternative.split(\"/\");\n let literal = 0;\n while (\n literal < parts.length - 1 &&\n !patternCharacters.test(parts[literal]!) &&\n !parts[literal]!.includes(\"\\\\\")\n )\n literal++;\n const prefix = parts.slice(0, literal).join(\"/\");\n // A pattern that starts with `/` or with a drive and `/`, such as `C:/`,\n // starts at that root: `C:` alone names the drive's current folder.\n const start = literal && /^(?:[A-Za-z]:)?$/.test(prefix) ? `${prefix}/` : prefix || \".\";\n let folder: string;\n try {\n folder = await realpath(path.resolve(base, start));\n } catch (error) {\n const code = (error as NodeJS.ErrnoException).code;\n // A folder that is not there holds nothing that could match.\n if (code === \"ENOENT\" || code === \"ENOTDIR\") continue;\n throw pathError(\"Input\", input, error);\n }\n const relative = path.relative(root, folder).split(path.sep).join(\"/\");\n if (relative.startsWith(\"../\") || relative === \"..\" || path.isAbsolute(relative))\n throw new Error(`Input is outside the workspace: ${input}`);\n const rest = parts.slice(literal).join(\"/\");\n result.folders.push(relative);\n result.matchers.push(\n new Minimatch(relative ? `${relative.replace(/[\\\\*?[\\](){}!+@]/g, \"\\\\$&\")}/${rest}` : rest, {\n ...patternOptions,\n // The braces were expanded already; a folder's name may hold one.\n nobrace: true,\n }),\n );\n }\n return result;\n}\nexport interface FileSet {\n root: string;\n files: Record<string, WorkspaceSource>;\n directories: string[];\n /**\n * The entries below the root that discovery did not enter and that Git does\n * not ignore: folders and files of the names that it always leaves out, and\n * symbolic links and junctions. Their files are not in `files`, but a link\n * can name one.\n */\n unlisted: string[];\n /** What discovery could not read or use, sorted by path. */\n skipped: Skipped[];\n selected: string[];\n /**\n * The Obsidian vaults that hold documents of the workspace, sorted by path:\n * the one at or above the root, and each one in a folder that discovery\n * visited.\n */\n vaults: Vault[];\n}\n/**\n * The workspace's lookup of a path at or below one of the set's `unlisted`\n * entries, on disk: a link that names such a path is checked there instead of\n * being called missing. The workspace root still bounds what is read, so a\n * path whose real location lies outside it, through a symbolic link or a\n * junction, is reported as such and not read.\n */\nexport function unlistedLookup(\n set: FileSet,\n): (name: string, folded: boolean) => LookupResult | undefined {\n const exact = new Set(set.unlisted);\n // Obsidian matches paths without regard to case.\n const folded = new Map(set.unlisted.map((name) => [name.toLowerCase(), name]));\n return (name, fold) => {\n if (!set.unlisted.length) return undefined;\n const parts = name.split(\"/\");\n for (let count = 1; count <= parts.length; count++) {\n const prefix = parts.slice(0, count).join(\"/\");\n const entry = fold\n ? folded.get(prefix.toLowerCase())\n : exact.has(prefix)\n ? prefix\n : undefined;\n if (entry !== undefined) return onDisk(set.root, [entry, ...parts.slice(count)].join(\"/\"));\n }\n return undefined;\n };\n}\n/** What is at the path `name` below `root`, following links as far as the root allows. */\nfunction onDisk(root: string, name: string): LookupResult | undefined {\n const parts = name.split(\"/\");\n // Each step on the way, so that what stands in the way can be named.\n for (let count = 1; count <= parts.length; count++) {\n const step = parts.slice(0, count).join(\"/\");\n let actual: string;\n try {\n if (!lstatSync(path.join(root, step)).isSymbolicLink()) continue;\n actual = realpathSync.native(path.join(root, step));\n } catch (error) {\n const code = (error as NodeJS.ErrnoException).code;\n // A path through something that is not there, or a link that leads nowhere.\n if (code === \"ENOENT\" || code === \"ENOTDIR\" || code === \"ELOOP\") return undefined;\n if (refusal(error))\n return { type: \"unreadable\", at: count > 1 ? parts.slice(0, count - 1).join(\"/\") : step };\n throw error;\n }\n const relative = path.relative(root, actual);\n if (relative === \"..\" || relative.startsWith(`..${path.sep}`) || path.isAbsolute(relative))\n return { type: \"outside\", through: step };\n }\n let info: Stats;\n try {\n info = statSync(path.join(root, name));\n } catch (error) {\n const code = (error as NodeJS.ErrnoException).code;\n if (code === \"ENOENT\" || code === \"ENOTDIR\" || code === \"ELOOP\") return undefined;\n if (refusal(error)) return { type: \"unreadable\", at: name };\n throw error;\n }\n if (info.isDirectory()) return { type: \"directory\" };\n const full = path.join(root, name);\n let cached: string | undefined;\n return {\n type: \"file\",\n path: name,\n source: isMarkdownName(name) ? () => (cached ??= decodeText(readFileSync(full), name)) : null,\n };\n}\n/** The workspace's record of the vault in `directory`, and of its settings file if unusable. */\nasync function describeVault(\n root: string,\n part: string,\n directory: string,\n): Promise<{ vault: Vault; skipped?: Skipped }> {\n const setting = await lineBreakSetting(directory);\n // Only the vault that holds the root can lie above it.\n const below = part ? \"\" : path.relative(directory, root).split(path.sep).join(\"/\");\n const vault: Vault = {\n path: part,\n ...(setting.value !== undefined ? { strictLineBreaks: setting.value } : {}),\n ...(below ? { rootInVault: below } : {}),\n };\n if (!setting.problem) return { vault };\n const problem: SettingsProblem = setting.problem;\n const file = path\n .relative(root, path.join(directory, \".obsidian\", \"app.json\"))\n .split(path.sep)\n .join(\"/\");\n return {\n vault,\n skipped: skip(\n { path: file, type: \"file\", code: problem.code },\n (show) =>\n `Skipped ${problem.code === \"INVALID\" ? \"unusable\" : \"unreadable\"} settings file: ${show(file)} (${problem.reason}). Obsidian's strictLineBreaks setting is not verified for that vault, so its documents are not reflowed.`,\n ),\n };\n}\n/**\n * The vault that holds the document `name` of the workspace, which need not\n * exist on disk: text read from stdin can be named into a folder that discovery\n * did not visit. The vault is found by searching upward from the document's\n * folder and is added to the set when it is new.\n */\nexport async function vaultFor(set: FileSet, name: string): Promise<Vault | undefined> {\n const directory = await enclosingVault(path.join(set.root, name));\n if (!directory) return undefined;\n const relative = path.relative(set.root, directory).split(path.sep).join(\"/\");\n const part =\n relative === \"..\" || relative.startsWith(\"../\") || path.isAbsolute(relative) ? \"\" : relative;\n const known = set.vaults.find((vault) => vault.path === part);\n if (known) return known;\n const described = await describeVault(set.root, part, directory);\n set.vaults.push(described.vault);\n if (described.skipped) set.skipped.push(described.skipped);\n return described.vault;\n}\n/**\n * Where Git's ignore rules for the workspace at `root` come from. They start at\n * `top`, the top level of the repository that holds the root, which can lie\n * above it; in each repository nested in the workspace, only its own rules\n * apply. What a repository tracks is never ignored.\n */\nfunction gitRules(root: string, top: string | undefined) {\n /** The root, relative to the repository's top level. */\n const lead = top ? path.relative(top, root).split(path.sep).join(\"/\") : \"\";\n /** A path relative to the root, relative to the repository's top level instead. */\n const fromTop = (relative: string) =>\n lead && relative ? `${lead}/${relative}` : lead || relative;\n /** How messages name a file of rules: from the root, or in full outside the repository. */\n function shown(file: string): string {\n const inside = path.relative(top ?? root, file);\n if (inside === \"..\" || inside.startsWith(`..${path.sep}`) || path.isAbsolute(inside))\n return file;\n return path.relative(root, file).split(path.sep).join(\"/\");\n }\n /** The file whose read failed, as messages name it. */\n const failed = (error: unknown, fallback: string) =>\n shown((error as NodeJS.ErrnoException).path ?? fallback);\n /**\n * The tracked files, from the top level, and the folders that hold them,\n * each kept as its repository compares letter case: as they are, or in lower\n * case.\n */\n const exact = { tracked: new Set<string>(), holding: new Set<string>() };\n const folded = { tracked: new Set<string>(), holding: new Set<string>() };\n /**\n * The rules for the top level of the repository in `directory`, `base` from\n * the outer repository's top level, with the lowest precedence first: the\n * global excludes file that the repository's settings name, then its\n * `info/exclude`; and whether its patterns ignore letter case. What the\n * repository tracks is recorded on the way.\n */\n async function repositoryLayers(\n directory: string,\n base: string,\n ): Promise<{ layers: IgnoreLayer[]; ignoreCase: boolean }> {\n const settings = ignoreSettings(directory).then(async (found) => ({\n ...found,\n text: found.excludesFile === undefined ? undefined : await optionalText(found.excludesFile),\n }));\n const listed = trackedFiles(directory);\n let text: string | undefined;\n let exclude: string | undefined;\n try {\n exclude = await excludesFile(directory);\n text = exclude === undefined ? undefined : await optionalText(exclude);\n } finally {\n // Git runs in the repository's folder, which Windows does not let anyone\n // remove until it is done, so discovery waits for it also after a failure.\n await Promise.allSettled([settings, listed]);\n }\n const global = await settings;\n // Where Git cannot say, case is compared as the file system usually does.\n const ignoreCase = global.ignoreCase ?? caseInsensitive;\n const sets = ignoreCase ? folded : exact;\n for (const name of (await listed) ?? []) {\n let at = base ? `${base}/${name}` : name;\n if (ignoreCase) at = at.toLowerCase();\n sets.tracked.add(at);\n for (\n at = path.posix.dirname(at);\n at !== \".\" && !sets.holding.has(at);\n at = path.posix.dirname(at)\n )\n sets.holding.add(at);\n }\n const layers: IgnoreLayer[] = [];\n if (global.text !== undefined)\n layers.push(ignoreLayer(base, shown(global.excludesFile!), global.text, ignoreCase));\n if (text !== undefined) layers.push(ignoreLayer(base, shown(exclude!), text, ignoreCase));\n return { layers, ignoreCase };\n }\n /** Whether a repository tracks the path `at`, from the top level, or a file in that folder. */\n function isTracked(at: string): boolean {\n if (exact.tracked.has(at) || exact.holding.has(at)) return true;\n if (!folded.tracked.size) return false;\n const lower = at.toLowerCase();\n return folded.tracked.has(lower) || folded.holding.has(lower);\n }\n return { lead, fromTop, shown, failed, repositoryLayers, isTracked };\n}\n/**\n * The files of the workspace at `rootPath`, and the documents that `supplied`\n * files, folders, and patterns select, or all of them when `supplied` is\n * empty. Relative inputs are resolved from `base`.\n *\n * A folder or pattern selects the Markdown files in it or matching it, by\n * name (`isMarkdownName`), that nothing ignores. A file named on its own is\n * selected whatever its name: naming it is the request. When ignore rules\n * leave out a named file or folder, `skipped` says so and why.\n *\n * `documents` are paths from the root of documents whose text a caller\n * supplies, which need not exist. They are not selected here, but ignore rules\n * leave them out as named files, as far as their folders exist. With\n * `selectNone`, the caller selects nothing from disk, and an ignored root is\n * not reported.\n */\nexport async function discover(\n rootPath: string,\n supplied: string[],\n excluded: string[],\n resolve: ResolveOptions = {},\n base = process.cwd(),\n { documents = [], selectNone = false }: { documents?: string[]; selectNone?: boolean } = {},\n): Promise<FileSet> {\n const root = await realpath(rootPath);\n let top: string | undefined;\n try {\n top = await repositoryTop(root);\n } catch (error) {\n const code = refusal(error);\n if (!code) throw error;\n // Only the root itself can refuse it: each folder above leads to the root.\n throw new Error(`Workspace root cannot be read: ${rootPath} (${refusalText(code)})`, {\n cause: error,\n });\n }\n const { lead, fromTop, shown, failed, repositoryLayers, isTracked } = gitRules(root, top);\n // Compiled once: compiling a pattern costs more than matching it.\n const ignorePatterns = excluded.map((pattern) => ({\n pattern,\n matcher: new Minimatch(pattern, { dot: true }),\n }));\n const files: Record<string, WorkspaceSource> = {};\n const directories: string[] = [];\n const unlisted: string[] = [];\n const selected: string[] = [];\n /** The folders that select their Markdown files, relative to the root. */\n const requests: string[] = [];\n /** The paths named as inputs, by their own path and that of each folder above them. */\n const named = new Map<string, NamedInput[]>();\n const namedInputs = new Map<string, NamedInput>();\n const patterns: PatternInput[] = [];\n /** Each input as given, with a path from the root that it names or searches. */\n const located: { input: string; path: string }[] = [];\n /** The folders that are vaults, by the part of the workspace that each holds. */\n const vaultFolders = new Map<string, string>();\n for (const input of supplied.length ? supplied : [root]) {\n const absolute = path.resolve(base, input);\n let resolved: string;\n let directory: boolean;\n try {\n const info = await lstat(absolute);\n if (info.isSymbolicLink()) throw new Error(`Refusing symbolic-link input: ${input}`);\n directory = info.isDirectory();\n resolved = await realpath(absolute);\n } catch (error) {\n const code = (error as NodeJS.ErrnoException).code;\n const pattern =\n code === \"ENOENT\" || code === \"ENOTDIR\" ? await patternInput(input, root, base) : undefined;\n if (pattern) {\n patterns.push(pattern);\n for (const folder of pattern.folders) located.push({ input, path: folder });\n continue;\n }\n throw pathError(\"Input\", input, error);\n }\n const relative = path.relative(root, resolved).split(path.sep).join(\"/\");\n if (relative.startsWith(\"../\") || relative === \"..\" || path.isAbsolute(relative))\n throw new Error(`Input is outside the workspace: ${input}`);\n located.push({ input, path: relative });\n if (directory) requests.push(relative);\n if (!relative || namedInputs.has(relative)) continue;\n const request: NamedInput = { path: relative, directory };\n namedInputs.set(relative, request);\n for (let at = relative; at !== \".\"; at = path.posix.dirname(at)) {\n const list = named.get(at);\n if (list) list.push(request);\n else named.set(at, [request]);\n }\n }\n /** The supplied documents, which ignore rules leave out as they do named files. */\n const documentInputs: NamedInput[] = [];\n for (const name of documents) {\n const existing = namedInputs.get(name);\n if (existing) {\n if (!existing.directory) documentInputs.push(existing);\n continue;\n }\n const request: NamedInput = { path: name, directory: false, document: true };\n namedInputs.set(name, request);\n documentInputs.push(request);\n for (let at = name; at !== \".\"; at = path.posix.dirname(at)) {\n const list = named.get(at);\n if (list) list.push(request);\n else named.set(at, [request]);\n }\n }\n /**\n * Record why the entry `name` leaves out the named inputs at or below it for\n * which `applies` holds, unless something above it did already.\n */\n function leaveNamed(\n name: string,\n why: (input: NamedInput) => (show: PathText) => string,\n applies: (input: NamedInput) => boolean = () => true,\n ) {\n for (const request of named.get(name) ?? [])\n if (applies(request)) request.reason ??= why(request);\n }\n /** Whether Git's rules can leave out a named input: Git ignores nothing that it tracks. */\n const untracked = (input: NamedInput) => !isTracked(fromTop(input.path));\n /** Directories left out, with the path whose read the system refused. */\n const refused: { directory: string; reading: string; code: RefusalCode }[] = [];\n const reason = (item: { reading: string; code: RefusalCode }, subject: string) =>\n refusalText(item.code) + (item.reading === subject ? \"\" : ` for ${item.reading}`);\n /**\n * Leave out a directory that the system refuses to let the tool read. Any\n * other error is a fault and stops the run, and so does a refusal for the\n * workspace root, without which there is nothing to do.\n */\n function leaveOut(directory: string, reading: string, error: unknown): void {\n const code = refusal(error);\n if (!code) throw error;\n if (!directory)\n throw new Error(\n `Workspace root cannot be read: ${rootPath} (${reason({ reading, code }, \"\")})`,\n { cause: error },\n );\n refused.push({ directory, reading, code });\n }\n /** The rules that apply at the root, from the repository's top level down. */\n let rootLayers: IgnoreLayer[] = [];\n /** Whether the rules of the repository that holds the root ignore letter case. */\n let rootIgnoreCase = caseInsensitive;\n /** The folder at or above the root that Git ignores, from the top level, and the rule. */\n let ignoredRoot: { folder: string; file: string; pattern: string } | undefined;\n if (top) {\n try {\n ({ layers: rootLayers, ignoreCase: rootIgnoreCase } = await repositoryLayers(top, \"\"));\n const parts = lead ? lead.split(\"/\") : [];\n for (let index = 0; index < parts.length && !ignoredRoot; index++) {\n const at = parts.slice(0, index).join(\"/\");\n const file = path.join(top, ...parts.slice(0, index), \".gitignore\");\n const text = await optionalText(file);\n if (text !== undefined) rootLayers.push(ignoreLayer(at, shown(file), text, rootIgnoreCase));\n const rule = gitIgnoreRule(ignoreScopes(at, rootLayers), parts[index]!, true);\n if (rule) ignoredRoot = { folder: parts.slice(0, index + 1).join(\"/\"), ...rule };\n }\n } catch (error) {\n leaveOut(\"\", failed(error, path.join(top, \".git\")), error);\n }\n }\n /**\n * Visit a directory, whose repository's rules ignore letter case or not.\n * Below a folder that Git's rules exclude, nothing can be included again, as\n * in Git, except what Git tracks. Such a folder is visited for what it\n * tracks, and otherwise only for link targets.\n */\n async function walk(\n relative: string,\n inherited: IgnoreLayer[],\n ignoreCase: boolean,\n targetOnly = false,\n gitIgnoredAbove = false,\n ) {\n const directory = path.join(root, relative);\n const layers = [...inherited];\n const rules = path.join(directory, \".gitignore\");\n let entries: Dirent[];\n // What is being read: the directory itself, or its `.gitignore`. Without the\n // ignore rules nothing tells which of the directory's files may be touched.\n let reading = relative;\n try {\n if (!gitIgnoredAbove && (await exists(rules))) {\n reading = relative ? `${relative}/.gitignore` : \".gitignore\";\n const text = await readFile(rules, \"utf8\");\n layers.push(ignoreLayer(fromTop(relative), reading, text, ignoreCase));\n reading = relative;\n }\n entries = await readdir(directory, { withFileTypes: true });\n } catch (error) {\n leaveOut(relative, reading, error);\n return;\n }\n // Obsidian creates the settings folder itself; a link to one shares a vault's settings.\n const settings = entries.find((entry) => entry.name === \".obsidian\");\n if (settings?.isDirectory() || (settings?.isSymbolicLink() && (await isVault(directory))))\n vaultFolders.set(relative, directory);\n const scopes = gitIgnoredAbove ? [] : ignoreScopes(fromTop(relative), layers);\n for (const entry of entries) {\n const name = relative ? `${relative}/${entry.name}` : entry.name;\n const rule = gitIgnoredAbove\n ? undefined\n : gitIgnoreRule(scopes, entry.name, entry.isDirectory());\n const gitExcluded = gitIgnoredAbove || rule !== undefined;\n // Git ignores no file that it tracks, and no folder that holds one,\n // though the folder's other files stay ignored.\n const gitIgnored = gitExcluded && !isTracked(fromTop(name));\n const skippedName = alwaysSkipped.has(entry.name);\n if (skippedName || entry.isSymbolicLink()) {\n if (skippedName)\n leaveNamed(\n name,\n (input) => (show) =>\n input.path === name\n ? `discovery always leaves out ${entry.name}`\n : `in ${show(name)}, which discovery always leaves out`,\n );\n // Not entered, but a link can name what is in it or behind it, unless\n // Git ignores it and so its files are no link targets.\n if (!gitIgnored || resolve.gitIgnored === true) unlisted.push(name);\n continue;\n }\n if (rule)\n leaveNamed(\n name,\n (input) => (show) =>\n input.path === name\n ? `matched by \"${rule.pattern}\" in ${showFile(show, rule.file)}`\n : `in ${show(name)}, which \"${rule.pattern}\" in ${showFile(show, rule.file)} matches`,\n untracked,\n );\n if (gitIgnored && resolve.gitIgnored !== true) continue;\n const full = path.join(root, name);\n if (entry.isDirectory()) {\n directories.push(name);\n let nested: boolean;\n try {\n nested = await exists(path.join(full, \".git\"));\n } catch (error) {\n // A directory that cannot be entered: nothing in it can be read.\n leaveOut(name, name, error);\n continue;\n }\n // A nested repository is another project, not one that a rule leaves\n // alone: text supplied for one of its documents is read as its own.\n if (nested)\n leaveNamed(\n name,\n (input) => (show) =>\n input.path === name ? \"a nested repository\" : `in ${show(name)}, a nested repository`,\n (input) => !input.document,\n );\n if (nested && resolve.nestedRepositories !== true) continue;\n // Inside a nested repository, only its own rules and settings apply, as in Git.\n let inner = { layers, ignoreCase };\n if (nested && !gitIgnored)\n try {\n inner = await repositoryLayers(full, fromTop(name));\n } catch (error) {\n leaveOut(name, failed(error, path.join(full, \".git\")), error);\n continue;\n }\n await walk(\n name,\n inner.layers,\n inner.ignoreCase,\n targetOnly || gitIgnored || nested,\n nested && !gitIgnored ? false : gitExcluded,\n );\n } else if (entry.isFile()) {\n const request = named.get(name)?.find((input) => input.path === name && !input.directory);\n const markdown = isMarkdownName(name);\n let cached: string | undefined;\n files[name] =\n markdown || request ? () => (cached ??= decodeText(readFileSync(full), name)) : null;\n if (!(markdown || request) || targetOnly || gitIgnored) continue;\n const pattern = ignorePatterns.find((item) => item.matcher.match(name))?.pattern;\n if (pattern !== undefined) {\n if (request)\n request.reason ??= () => `matched by the configuration's ignore pattern \"${pattern}\"`;\n continue;\n }\n let chosen = request !== undefined && !request.document;\n if (markdown) {\n chosen ||= requests.some(\n (folder) => !folder || name === folder || name.startsWith(`${folder}/`),\n );\n for (const item of patterns)\n if (item.matchers.some((matcher) => matcher.match(name))) chosen = item.matched = true;\n }\n if (chosen) selected.push(name);\n }\n }\n // A supplied document that no file holds yet is left out by the rules of\n // its folder as a file there would be.\n for (const request of documentInputs) {\n if (request.reason || request.path in files) continue;\n if (path.posix.dirname(request.path) !== (relative || \".\")) continue;\n const entry = path.posix.basename(request.path);\n if (alwaysSkipped.has(entry)) request.reason = () => `discovery always leaves out ${entry}`;\n const rule = gitIgnoredAbove ? undefined : gitIgnoreRule(scopes, entry, false);\n if (rule && untracked(request))\n request.reason ??= (show) => `matched by \"${rule.pattern}\" in ${showFile(show, rule.file)}`;\n }\n }\n await walk(\"\", rootLayers, rootIgnoreCase, false, ignoredRoot !== undefined);\n // The names that discovery always leaves out, and the configuration's\n // patterns, apply to a supplied document's path also where no folder of it\n // exists.\n for (const request of documentInputs) {\n if (request.reason) continue;\n const parts = request.path.split(\"/\");\n const at = parts.findIndex((part) => alwaysSkipped.has(part));\n if (at >= 0) {\n const folder = parts.slice(0, at + 1).join(\"/\");\n request.reason =\n folder === request.path\n ? () => `discovery always leaves out ${parts[at]}`\n : (show) => `in ${show(folder)}, which discovery always leaves out`;\n continue;\n }\n const pattern = ignorePatterns.find((item) => item.matcher.match(request.path))?.pattern;\n if (pattern !== undefined)\n request.reason = () => `matched by the configuration's ignore pattern \"${pattern}\"`;\n }\n // Nothing that Git does not track is processed in a root that Git ignores.\n let rootIgnored: ((show: PathText) => string) | undefined;\n if (ignoredRoot) {\n const { file, pattern } = ignoredRoot;\n // The root itself, or a folder above it.\n const folder = path.posix.relative(lead, ignoredRoot.folder);\n const why = (show: PathText) =>\n folder\n ? `in ${show(folder)}, which \"${pattern}\" in ${showFile(show, file)} matches`\n : `matched by \"${pattern}\" in ${showFile(show, file)}`;\n for (const input of namedInputs.values())\n if (untracked(input))\n input.reason ??= folder ? why : (show) => `in the workspace root, which is ${why(show)}`;\n if (!namedInputs.size && !selectNone && !isTracked(lead)) rootIgnored = why;\n }\n // An input in a directory that was left out is an error: the user asked for it.\n for (const { input, path: request } of located) {\n const item = refused.find(\n ({ directory }) => request === directory || request.startsWith(`${directory}/`),\n );\n if (item) throw new Error(`Input cannot be read: ${input} (${reason(item, request)})`);\n }\n // A pattern stands for the documents it matches, so one that matches none is\n // an error, as a path that does not exist is.\n for (const item of patterns)\n if (!item.matched)\n throw new Error(\n `Input pattern matches no document: ${item.input}${\n item.input.includes(\"\\\\\") ? \" (patterns separate folders with /)\" : \"\"\n }`,\n );\n const skipped: Skipped[] = refused.map((item) =>\n skip(\n { path: item.directory, type: \"directory\", code: item.code },\n (show) =>\n `Skipped unreadable directory: ${show(item.directory)} (${refusalText(item.code)}${item.reading === item.directory ? \"\" : ` for ${showFile(show, item.reading)}`}). Its files are not processed, and links into it cannot be checked.`,\n ),\n );\n if (rootIgnored) {\n const why = rootIgnored;\n skipped.push(\n skip(\n { path: \".\", type: \"directory\", code: \"IGNORED\" },\n (show) =>\n `Skipped ignored workspace root: ${show(\".\") || \".\"} (${why(show)}). Its files are not processed.`,\n ),\n );\n }\n // A named input that ignore rules leave out is not an error, but the user asked for it.\n for (const input of namedInputs.values()) {\n const why = input.reason;\n if (!why) continue;\n const item = skip(\n { path: input.path, type: input.directory ? \"directory\" : \"file\", code: \"IGNORED\" },\n (show) =>\n `Skipped ignored input: ${show(input.path)} (${why(show)}). ${input.directory ? \"Its files are\" : \"It is\"} not processed.`,\n );\n ignoredInputs.add(item);\n skipped.push(item);\n }\n // A root that is no vault itself can be a folder of one.\n if (!vaultFolders.has(\"\")) {\n const outer = await enclosingVault(root);\n if (outer) vaultFolders.set(\"\", outer);\n }\n const vaults: Vault[] = [];\n for (const [part, directory] of vaultFolders) {\n const described = await describeVault(root, part, directory);\n vaults.push(described.vault);\n if (described.skipped) skipped.push(described.skipped);\n }\n const byPath = (a: { path: string }, b: { path: string }) =>\n a.path < b.path ? -1 : a.path > b.path ? 1 : 0;\n return {\n root,\n files,\n directories,\n unlisted,\n skipped: skipped.sort(byPath),\n selected: selected.sort(),\n vaults: vaults.sort(byPath),\n };\n}\n/**\n * A file that `writeFormatted` would not write, or did not write completely,\n * with the reason in words that do not name it.\n */\nexport class ReplacementRefused extends Error {\n constructor(\n readonly reason: string,\n message: string,\n options?: ErrorOptions,\n ) {\n super(message, options);\n }\n}\n/**\n * Why `file` cannot be written, or undefined when nothing stands in the way\n * that can be seen before writing: the file may not be written, or its folder\n * does not let the trial file be created beside it. A read-only file is refused\n * on every platform: the flag marks a file that is not to be edited.\n */\nexport async function replacementProblem(file: string): Promise<string | undefined> {\n for (const [target, subject] of [\n [file, \"The file\"],\n [path.dirname(file), \"The file's folder\"],\n ] as const) {\n try {\n await access(target, constants.W_OK);\n } catch (error) {\n const text = systemErrorText(error);\n if (!text) throw error;\n return `${subject} may not be written (${text})`;\n }\n }\n return undefined;\n}\n/**\n * What went wrong when `writeFormatted` failed for a file, in words that do\n * not name it, or undefined for an error that is a fault of the tool.\n */\nexport function replacementFailure(error: unknown): string | undefined {\n if (error instanceof ReplacementRefused) return error.reason;\n const text = systemErrorText(error);\n return text ? `The file could not be written (${text}) and is unchanged` : undefined;\n}\n/** The refusal for a file whose bytes are no longer those that were read. */\nfunction changedOnDisk(file: string, when: string): ReplacementRefused {\n return new ReplacementRefused(\n \"The file changed on disk during formatting and was not written\",\n `File changed ${when}: ${file}`,\n );\n}\n/**\n * Show that `size` more bytes fit on the disk of `folder`, by writing a file\n * of that size there and removing it. It holds random bytes, not the\n * document's text: a file left behind by a crash then reveals nothing, and a\n * disk that compresses what it stores cannot make the trial smaller than the\n * write. Common file systems set aside the room when the bytes are written, so\n * the trial is not flushed to the disk; a file system that runs out of room only\n * then makes the write itself fail, and the file's content is written back.\n */\nasync function trialWrite(folder: string, size: number): Promise<void> {\n const trial = path.join(folder, `.mdtools-${randomUUID()}.tmp`);\n const handle = await open(trial, \"wx\", 0o600);\n try {\n await handle.writeFile(randomBytes(size));\n } finally {\n await handle.close();\n await unlink(trial).catch((error: NodeJS.ErrnoException) => {\n if (error.code !== \"ENOENT\") throw error;\n });\n }\n}\n/** Make the open file hold exactly `content`. */\nasync function overwrite(handle: FileHandle, content: Buffer): Promise<void> {\n for (let at = 0; at < content.length;)\n at += (await handle.write(content, at, content.length - at, at)).bytesWritten;\n await handle.truncate(content.length);\n await handle.sync();\n}\n/**\n * Write the formatted text `after` into `file`, whose text was read as\n * `before`, if the file still holds exactly the bytes that were read. The file\n * itself is written, not replaced by a new one, so that it keeps its\n * permissions, attributes, owner, creation time, and hard links, which Node.js\n * cannot all carry over to a new file. A trial write beside the file first shows that\n * the new content fits on the disk. The file is then checked through the open\n * file, just before writing. If writing fails part way, the bytes that were read\n * are written back, and the reason says whether that worked. A file that already\n * holds `after`, as the second name of a hard link written earlier in the batch\n * does, is left as it is.\n */\nexport async function writeFormatted(file: string, before: string, after: string): Promise<void> {\n const info = await lstat(file);\n if (!info.isFile() || info.isSymbolicLink())\n throw new ReplacementRefused(\n \"The file is not a regular file and was not written\",\n `Refusing non-regular file: ${file}`,\n );\n // The text was decoded from valid UTF-8, so encoding it again gives the bytes\n // that were read; comparing the text instead would miss a change to bytes that\n // decode to the same text.\n const expected = Buffer.from(before, \"utf8\");\n const content = Buffer.from(after, \"utf8\");\n const found = await readFile(file);\n if (found.equals(content)) return;\n if (!found.equals(expected)) throw changedOnDisk(file, \"during formatting\");\n await trialWrite(path.dirname(file), content.length);\n const handle = await open(file, \"r+\");\n try {\n // The path may lead to another file by now, such as through a link put in its place.\n const current = await handle.stat();\n if (current.ino !== info.ino || !(await handle.readFile()).equals(expected))\n throw changedOnDisk(file, \"before writing\");\n try {\n await overwrite(handle, content);\n } catch (error) {\n const text = systemErrorText(error);\n if (!text) throw error;\n let undone: string | undefined;\n try {\n await overwrite(handle, expected);\n } catch (again) {\n undone = systemErrorText(again);\n if (!undone) throw again;\n }\n throw new ReplacementRefused(\n undone === undefined\n ? `The file could not be written (${text}), and its content from before formatting was written back`\n : `The file could not be written (${text}), and writing its content from before formatting back failed too (${undone}); it may be incomplete`,\n `File written in part: ${file}`,\n { cause: error },\n );\n }\n } finally {\n await handle.close();\n }\n}\n"]}
@@ -0,0 +1,54 @@
1
+ /**
2
+ * The text of a file that need not be there, or undefined when nothing, or a
3
+ * folder, is at its path. A refusal, or any other error, is thrown.
4
+ */
5
+ export declare function optionalText(file: string): Promise<string | undefined>;
6
+ /**
7
+ * The top level of the Git repository that holds `directory`: the nearest
8
+ * folder at or above it that contains `.git`, a folder or, in a linked worktree
9
+ * or a submodule, a file. Undefined outside a repository; a refusal, or any
10
+ * other error, is thrown.
11
+ */
12
+ export declare function repositoryTop(directory: string): Promise<string | undefined>;
13
+ /**
14
+ * The repository's own excludes file, `info/exclude` in its common Git
15
+ * folder: `.git` itself, or the folder that a `.git` file names, as a
16
+ * submodule's does, and for a linked worktree the main repository's folder,
17
+ * which its `commondir` file names. Undefined when the `.git` file is not one
18
+ * that Git reads.
19
+ */
20
+ export declare function excludesFile(top: string): Promise<string | undefined>;
21
+ /** The settings of Git's configuration that decide how a repository's ignore rules apply. */
22
+ export interface IgnoreSettings {
23
+ /**
24
+ * The global excludes file: `core.excludesFile`, else
25
+ * `$XDG_CONFIG_HOME/git/ignore`, by default `~/.config/git/ignore`.
26
+ * Undefined where Git is not installed or cannot read its configuration,
27
+ * since which file Git would read is then unknown.
28
+ */
29
+ excludesFile?: string;
30
+ /**
31
+ * Whether patterns match without regard to letter case: `core.ignorecase`,
32
+ * which Git turns on when it creates a repository on a file system that
33
+ * ignores case, and which is off where it is not set. Undefined where Git is
34
+ * not installed or cannot read it.
35
+ */
36
+ ignoreCase?: boolean;
37
+ }
38
+ /**
39
+ * The settings that Git reads for the repository at `top`: the repository's
40
+ * own over the user's and the system's, so they can differ from one
41
+ * repository to the next. Only Git itself can read its configuration, with
42
+ * its included files, so this runs `git config`, in the usual case once for
43
+ * both settings, since each run of Git takes time, with both read as paths.
44
+ * Git gives `true` and `false` unchanged as paths, but refuses a setting
45
+ * written without a value, which means true; where it does, or where a value
46
+ * takes another form such as `yes`, each setting is read again in its own form.
47
+ */
48
+ export declare function ignoreSettings(top: string): Promise<IgnoreSettings>;
49
+ /**
50
+ * The files that the repository at `top` tracks, relative to its top level,
51
+ * which Git's ignore rules never apply to, or undefined where Git is not
52
+ * installed or cannot list them. Git lists a submodule as one entry.
53
+ */
54
+ export declare function trackedFiles(top: string): Promise<string[] | undefined>;
@@ -0,0 +1,198 @@
1
+ import { execFile } from "node:child_process";
2
+ import { statSync } from "node:fs";
3
+ import { readFile } from "node:fs/promises";
4
+ import { homedir } from "node:os";
5
+ import path from "node:path";
6
+ import { exists } from "./access.js";
7
+ /**
8
+ * The text of a file that need not be there, or undefined when nothing, or a
9
+ * folder, is at its path. A refusal, or any other error, is thrown.
10
+ */
11
+ export async function optionalText(file) {
12
+ try {
13
+ return await readFile(file, "utf8");
14
+ }
15
+ catch (error) {
16
+ const code = error.code;
17
+ if (code === "ENOENT" || code === "ENOTDIR" || code === "EISDIR")
18
+ return undefined;
19
+ throw error;
20
+ }
21
+ }
22
+ /**
23
+ * The top level of the Git repository that holds `directory`: the nearest
24
+ * folder at or above it that contains `.git`, a folder or, in a linked worktree
25
+ * or a submodule, a file. Undefined outside a repository; a refusal, or any
26
+ * other error, is thrown.
27
+ */
28
+ export async function repositoryTop(directory) {
29
+ for (let current = directory;; current = path.dirname(current)) {
30
+ if (await exists(path.join(current, ".git")))
31
+ return current;
32
+ if (path.dirname(current) === current)
33
+ return undefined;
34
+ }
35
+ }
36
+ /**
37
+ * The repository's own excludes file, `info/exclude` in its common Git
38
+ * folder: `.git` itself, or the folder that a `.git` file names, as a
39
+ * submodule's does, and for a linked worktree the main repository's folder,
40
+ * which its `commondir` file names. Undefined when the `.git` file is not one
41
+ * that Git reads.
42
+ */
43
+ export async function excludesFile(top) {
44
+ const dotGit = path.join(top, ".git");
45
+ // A folder reads as nothing.
46
+ const link = await optionalText(dotGit);
47
+ let gitDirectory = dotGit;
48
+ if (link !== undefined) {
49
+ if (!link.startsWith("gitdir: "))
50
+ return undefined;
51
+ const named = link.slice("gitdir: ".length).replace(/[\r\n]+$/, "");
52
+ if (!named)
53
+ return undefined;
54
+ gitDirectory = path.resolve(top, named);
55
+ }
56
+ const common = await optionalText(path.join(gitDirectory, "commondir"));
57
+ const commonDirectory = common === undefined
58
+ ? gitDirectory
59
+ : path.resolve(gitDirectory, common.replace(/[\r\n]+$/, ""));
60
+ return path.join(commonDirectory, "info", "exclude");
61
+ }
62
+ /**
63
+ * The Git program to run. Windows, and Node.js on Windows, look for a program
64
+ * in the folder that it is started in before the folders of `PATH`, so a
65
+ * `git.exe` in a workspace would run in place of Git. There the program is
66
+ * found in the absolute folders of `PATH` alone.
67
+ */
68
+ function gitProgram() {
69
+ if (process.platform !== "win32")
70
+ return "git";
71
+ for (const entry of (process.env.PATH ?? "").split(path.delimiter)) {
72
+ const folder = entry.replace(/^"(.*)"$/, "$1");
73
+ if (!path.isAbsolute(folder))
74
+ continue;
75
+ const file = path.join(folder, "git.exe");
76
+ try {
77
+ if (statSync(file).isFile())
78
+ return file;
79
+ }
80
+ catch {
81
+ // Not in this folder.
82
+ }
83
+ }
84
+ return undefined;
85
+ }
86
+ /**
87
+ * Variables that make Git use another repository than the one that holds its
88
+ * working folder. A Git hook, which can run the tool, sets some of them for
89
+ * its own repository, and Git's advice for a hook that works in another one is
90
+ * to clear them.
91
+ */
92
+ const repositoryVariables = [
93
+ "GIT_DIR",
94
+ "GIT_WORK_TREE",
95
+ "GIT_COMMON_DIR",
96
+ "GIT_INDEX_FILE",
97
+ "GIT_OBJECT_DIRECTORY",
98
+ "GIT_ALTERNATE_OBJECT_DIRECTORIES",
99
+ "GIT_PREFIX",
100
+ ];
101
+ /**
102
+ * Run Git in the repository at `top`, for its exit status and what it
103
+ * printed, or undefined where Git is not installed or does not start. The
104
+ * repository's configuration can name a file system monitor, a program that
105
+ * Git runs when it reads the index; a workspace that the tool lints need not
106
+ * be trusted, so the monitor is turned off for every call.
107
+ */
108
+ function runGit(top, args) {
109
+ const program = gitProgram();
110
+ if (!program)
111
+ return Promise.resolve(undefined);
112
+ const env = { ...process.env };
113
+ for (const name of repositoryVariables)
114
+ delete env[name];
115
+ return new Promise((resolve) => {
116
+ execFile(program, ["-c", "core.fsmonitor=false", ...args], { cwd: top, env, encoding: "utf8", maxBuffer: Infinity, windowsHide: true }, (error, stdout) => {
117
+ if (!error)
118
+ resolve({ status: 0, stdout });
119
+ else
120
+ resolve(typeof error.code === "number" ? { status: error.code, stdout } : undefined);
121
+ });
122
+ });
123
+ }
124
+ /**
125
+ * A setting's value as Git gives it in the form that `type` names, such as
126
+ * `--bool`, null where it is not set, or undefined where Git is not installed
127
+ * or cannot read it.
128
+ */
129
+ async function setting(top, type, name) {
130
+ const result = await runGit(top, ["config", "-z", type, "--get", name]);
131
+ if (result?.status === 0)
132
+ return result.stdout.replace(/\0$/, "");
133
+ // Status 1: the setting is not there, and Git uses its default.
134
+ return result?.status === 1 ? null : undefined;
135
+ }
136
+ /**
137
+ * The settings that Git reads for the repository at `top`: the repository's
138
+ * own over the user's and the system's, so they can differ from one
139
+ * repository to the next. Only Git itself can read its configuration, with
140
+ * its included files, so this runs `git config`, in the usual case once for
141
+ * both settings, since each run of Git takes time, with both read as paths.
142
+ * Git gives `true` and `false` unchanged as paths, but refuses a setting
143
+ * written without a value, which means true; where it does, or where a value
144
+ * takes another form such as `yes`, each setting is read again in its own form.
145
+ */
146
+ export async function ignoreSettings(top) {
147
+ const both = await runGit(top, [
148
+ "config",
149
+ "-z",
150
+ "--path",
151
+ "--get-regexp",
152
+ "^core\\.(excludesfile|ignorecase)$",
153
+ ]);
154
+ if (!both)
155
+ return {};
156
+ let excludes = null;
157
+ let ignoreCase = null;
158
+ if (both.status === 0)
159
+ // Each entry is the setting's name in lower case, a line ending, and the
160
+ // value, or the name alone for a setting without one; the last one counts.
161
+ for (const entry of both.stdout.split("\0")) {
162
+ const end = entry.indexOf("\n");
163
+ const name = end === -1 ? entry : entry.slice(0, end);
164
+ const value = end === -1 ? "" : entry.slice(end + 1);
165
+ if (name === "core.excludesfile")
166
+ excludes = value;
167
+ else if (name === "core.ignorecase")
168
+ ignoreCase = value;
169
+ }
170
+ else if (both.status !== 1)
171
+ [excludes, ignoreCase] = await Promise.all([
172
+ setting(top, "--path", "core.excludesFile"),
173
+ setting(top, "--bool", "core.ignorecase"),
174
+ ]);
175
+ if (typeof ignoreCase === "string" && ignoreCase !== "true" && ignoreCase !== "false")
176
+ ignoreCase = await setting(top, "--bool", "core.ignorecase");
177
+ const settings = {};
178
+ if (ignoreCase !== undefined)
179
+ settings.ignoreCase = ignoreCase === "true";
180
+ // Git reads a relative path from the repository's top level, and an empty one as no file.
181
+ if (excludes)
182
+ settings.excludesFile = path.resolve(top, excludes);
183
+ else if (excludes === null) {
184
+ const home = process.env.XDG_CONFIG_HOME || path.join(process.env.HOME || homedir(), ".config");
185
+ settings.excludesFile = path.join(home, "git", "ignore");
186
+ }
187
+ return settings;
188
+ }
189
+ /**
190
+ * The files that the repository at `top` tracks, relative to its top level,
191
+ * which Git's ignore rules never apply to, or undefined where Git is not
192
+ * installed or cannot list them. Git lists a submodule as one entry.
193
+ */
194
+ export async function trackedFiles(top) {
195
+ const result = await runGit(top, ["ls-files", "-z"]);
196
+ return result?.status === 0 ? result.stdout.split("\0").filter(Boolean) : undefined;
197
+ }
198
+ //# sourceMappingURL=git.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git.js","sourceRoot":"","sources":["../../src/workspace/git.ts"],"names":[],"mappings":"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","sourcesContent":["import { execFile } from \"node:child_process\";\nimport { statSync } from \"node:fs\";\nimport { readFile } from \"node:fs/promises\";\nimport { homedir } from \"node:os\";\nimport path from \"node:path\";\nimport { exists } from \"./access.js\";\n\n/**\n * The text of a file that need not be there, or undefined when nothing, or a\n * folder, is at its path. A refusal, or any other error, is thrown.\n */\nexport async function optionalText(file: string): Promise<string | undefined> {\n try {\n return await readFile(file, \"utf8\");\n } catch (error) {\n const code = (error as NodeJS.ErrnoException).code;\n if (code === \"ENOENT\" || code === \"ENOTDIR\" || code === \"EISDIR\") return undefined;\n throw error;\n }\n}\n/**\n * The top level of the Git repository that holds `directory`: the nearest\n * folder at or above it that contains `.git`, a folder or, in a linked worktree\n * or a submodule, a file. Undefined outside a repository; a refusal, or any\n * other error, is thrown.\n */\nexport async function repositoryTop(directory: string): Promise<string | undefined> {\n for (let current = directory; ; current = path.dirname(current)) {\n if (await exists(path.join(current, \".git\"))) return current;\n if (path.dirname(current) === current) return undefined;\n }\n}\n/**\n * The repository's own excludes file, `info/exclude` in its common Git\n * folder: `.git` itself, or the folder that a `.git` file names, as a\n * submodule's does, and for a linked worktree the main repository's folder,\n * which its `commondir` file names. Undefined when the `.git` file is not one\n * that Git reads.\n */\nexport async function excludesFile(top: string): Promise<string | undefined> {\n const dotGit = path.join(top, \".git\");\n // A folder reads as nothing.\n const link = await optionalText(dotGit);\n let gitDirectory = dotGit;\n if (link !== undefined) {\n if (!link.startsWith(\"gitdir: \")) return undefined;\n const named = link.slice(\"gitdir: \".length).replace(/[\\r\\n]+$/, \"\");\n if (!named) return undefined;\n gitDirectory = path.resolve(top, named);\n }\n const common = await optionalText(path.join(gitDirectory, \"commondir\"));\n const commonDirectory =\n common === undefined\n ? gitDirectory\n : path.resolve(gitDirectory, common.replace(/[\\r\\n]+$/, \"\"));\n return path.join(commonDirectory, \"info\", \"exclude\");\n}\n/**\n * The Git program to run. Windows, and Node.js on Windows, look for a program\n * in the folder that it is started in before the folders of `PATH`, so a\n * `git.exe` in a workspace would run in place of Git. There the program is\n * found in the absolute folders of `PATH` alone.\n */\nfunction gitProgram(): string | undefined {\n if (process.platform !== \"win32\") return \"git\";\n for (const entry of (process.env.PATH ?? \"\").split(path.delimiter)) {\n const folder = entry.replace(/^\"(.*)\"$/, \"$1\");\n if (!path.isAbsolute(folder)) continue;\n const file = path.join(folder, \"git.exe\");\n try {\n if (statSync(file).isFile()) return file;\n } catch {\n // Not in this folder.\n }\n }\n return undefined;\n}\n/**\n * Variables that make Git use another repository than the one that holds its\n * working folder. A Git hook, which can run the tool, sets some of them for\n * its own repository, and Git's advice for a hook that works in another one is\n * to clear them.\n */\nconst repositoryVariables = [\n \"GIT_DIR\",\n \"GIT_WORK_TREE\",\n \"GIT_COMMON_DIR\",\n \"GIT_INDEX_FILE\",\n \"GIT_OBJECT_DIRECTORY\",\n \"GIT_ALTERNATE_OBJECT_DIRECTORIES\",\n \"GIT_PREFIX\",\n];\n/**\n * Run Git in the repository at `top`, for its exit status and what it\n * printed, or undefined where Git is not installed or does not start. The\n * repository's configuration can name a file system monitor, a program that\n * Git runs when it reads the index; a workspace that the tool lints need not\n * be trusted, so the monitor is turned off for every call.\n */\nfunction runGit(\n top: string,\n args: string[],\n): Promise<{ status: number; stdout: string } | undefined> {\n const program = gitProgram();\n if (!program) return Promise.resolve(undefined);\n const env = { ...process.env };\n for (const name of repositoryVariables) delete env[name];\n return new Promise((resolve) => {\n execFile(\n program,\n [\"-c\", \"core.fsmonitor=false\", ...args],\n { cwd: top, env, encoding: \"utf8\", maxBuffer: Infinity, windowsHide: true },\n (error, stdout) => {\n if (!error) resolve({ status: 0, stdout });\n else resolve(typeof error.code === \"number\" ? { status: error.code, stdout } : undefined);\n },\n );\n });\n}\n/** The settings of Git's configuration that decide how a repository's ignore rules apply. */\nexport interface IgnoreSettings {\n /**\n * The global excludes file: `core.excludesFile`, else\n * `$XDG_CONFIG_HOME/git/ignore`, by default `~/.config/git/ignore`.\n * Undefined where Git is not installed or cannot read its configuration,\n * since which file Git would read is then unknown.\n */\n excludesFile?: string;\n /**\n * Whether patterns match without regard to letter case: `core.ignorecase`,\n * which Git turns on when it creates a repository on a file system that\n * ignores case, and which is off where it is not set. Undefined where Git is\n * not installed or cannot read it.\n */\n ignoreCase?: boolean;\n}\n/**\n * A setting's value as Git gives it in the form that `type` names, such as\n * `--bool`, null where it is not set, or undefined where Git is not installed\n * or cannot read it.\n */\nasync function setting(top: string, type: string, name: string) {\n const result = await runGit(top, [\"config\", \"-z\", type, \"--get\", name]);\n if (result?.status === 0) return result.stdout.replace(/\\0$/, \"\");\n // Status 1: the setting is not there, and Git uses its default.\n return result?.status === 1 ? null : undefined;\n}\n/**\n * The settings that Git reads for the repository at `top`: the repository's\n * own over the user's and the system's, so they can differ from one\n * repository to the next. Only Git itself can read its configuration, with\n * its included files, so this runs `git config`, in the usual case once for\n * both settings, since each run of Git takes time, with both read as paths.\n * Git gives `true` and `false` unchanged as paths, but refuses a setting\n * written without a value, which means true; where it does, or where a value\n * takes another form such as `yes`, each setting is read again in its own form.\n */\nexport async function ignoreSettings(top: string): Promise<IgnoreSettings> {\n const both = await runGit(top, [\n \"config\",\n \"-z\",\n \"--path\",\n \"--get-regexp\",\n \"^core\\\\.(excludesfile|ignorecase)$\",\n ]);\n if (!both) return {};\n let excludes: string | null | undefined = null;\n let ignoreCase: string | null | undefined = null;\n if (both.status === 0)\n // Each entry is the setting's name in lower case, a line ending, and the\n // value, or the name alone for a setting without one; the last one counts.\n for (const entry of both.stdout.split(\"\\0\")) {\n const end = entry.indexOf(\"\\n\");\n const name = end === -1 ? entry : entry.slice(0, end);\n const value = end === -1 ? \"\" : entry.slice(end + 1);\n if (name === \"core.excludesfile\") excludes = value;\n else if (name === \"core.ignorecase\") ignoreCase = value;\n }\n else if (both.status !== 1)\n [excludes, ignoreCase] = await Promise.all([\n setting(top, \"--path\", \"core.excludesFile\"),\n setting(top, \"--bool\", \"core.ignorecase\"),\n ]);\n if (typeof ignoreCase === \"string\" && ignoreCase !== \"true\" && ignoreCase !== \"false\")\n ignoreCase = await setting(top, \"--bool\", \"core.ignorecase\");\n const settings: IgnoreSettings = {};\n if (ignoreCase !== undefined) settings.ignoreCase = ignoreCase === \"true\";\n // Git reads a relative path from the repository's top level, and an empty one as no file.\n if (excludes) settings.excludesFile = path.resolve(top, excludes);\n else if (excludes === null) {\n const home = process.env.XDG_CONFIG_HOME || path.join(process.env.HOME || homedir(), \".config\");\n settings.excludesFile = path.join(home, \"git\", \"ignore\");\n }\n return settings;\n}\n/**\n * The files that the repository at `top` tracks, relative to its top level,\n * which Git's ignore rules never apply to, or undefined where Git is not\n * installed or cannot list them. Git lists a submodule as one entry.\n */\nexport async function trackedFiles(top: string): Promise<string[] | undefined> {\n const result = await runGit(top, [\"ls-files\", \"-z\"]);\n return result?.status === 0 ? result.stdout.split(\"\\0\").filter(Boolean) : undefined;\n}\n"]}
@@ -1,14 +1,54 @@
1
1
  import type { Dialect, Workspace } from "../core/types.js";
2
2
  /**
3
3
  * A Markdown file's text, null for a file that is not Markdown, or a loader
4
- * that returns the text when a fragment check needs it. A loader that throws an
5
- * error whose `code` is `EACCES` or `EPERM` marks the file as unreadable; any
6
- * other error propagates.
4
+ * that returns the text when a fragment check needs it. Only a file that
5
+ * `isMarkdownName` accepts for the link's dialect is read for anchors. A
6
+ * loader that throws an error whose `code` is `EACCES`, `EPERM`, or `EBUSY`,
7
+ * or `ERR_ENCODING_INVALID_ENCODED_DATA` for a file that is not UTF-8 text,
8
+ * marks the file as unreadable; any other error propagates.
7
9
  */
8
10
  export type WorkspaceSource = string | null | (() => string);
11
+ /** What `WorkspaceOptions.lookup` found at a path. */
12
+ export type LookupResult =
13
+ /** A file, with its path as found from the root and its source as in `files`. */
14
+ {
15
+ type: "file";
16
+ path: string;
17
+ source: WorkspaceSource;
18
+ } | {
19
+ type: "directory";
20
+ }
21
+ /**
22
+ * Something whose real location lies outside the workspace root, reached
23
+ * through the symbolic link or junction `through`, which the host does not
24
+ * follow: the root bounds what is read.
25
+ */
26
+ | {
27
+ type: "outside";
28
+ through: string;
29
+ }
30
+ /** Something that the system does not let the host examine; `at` names it. */
31
+ | {
32
+ type: "unreadable";
33
+ at: string;
34
+ };
35
+ /**
36
+ * Whether a file is Markdown by its name: one ending in `.md` or `.markdown`,
37
+ * in any letter case, both of which GitHub, Forgejo, and Gitea render.
38
+ * Discovery selects such files in folders, and their headings are link
39
+ * targets. For the Obsidian dialect only `.md` counts: Obsidian opens no
40
+ * other file as a note.
41
+ */
42
+ export declare function isMarkdownName(name: string, dialect?: Dialect): boolean;
43
+ /** The options of `createWorkspace`. */
9
44
  export interface WorkspaceOptions {
10
45
  /** The dialect that link targets are parsed in; `github` when omitted. */
11
46
  dialect?: Dialect;
47
+ /**
48
+ * `true` when the vault's "Strict line breaks" setting is verified on, which
49
+ * the workspace then reports as `Workspace.strictLineBreaks`. Obsidian notes
50
+ * are wrapped only then.
51
+ */
12
52
  strictLineBreaks?: boolean;
13
53
  /** Existing directories, including empty ones; never treated as note targets. */
14
54
  directories?: string[];
@@ -18,6 +58,14 @@ export interface WorkspaceOptions {
18
58
  * `unreadable` instead of `missing`.
19
59
  */
20
60
  unreadable?: string[];
61
+ /**
62
+ * Looks for a path that `files` and `directories` do not hold, when a link
63
+ * names it: a host that leaves some folders or links out of the index, such
64
+ * as the CLI, finds there what a link names. It returns what is at the path,
65
+ * or undefined when nothing is. `folded` asks for Obsidian's matching,
66
+ * without regard to letter case. A search by note name does not use it.
67
+ */
68
+ lookup?: (path: string, folded: boolean) => LookupResult | undefined;
21
69
  /**
22
70
  * Folders below the workspace root that are Obsidian vaults of their own. An
23
71
  * Obsidian link in a note of such a vault reaches only the vault's files: a
@@ -38,4 +86,11 @@ export declare function splitDestination(destination: string): {
38
86
  path: string;
39
87
  fragment: string;
40
88
  };
89
+ /**
90
+ * The workspace of `files`, which maps each path, relative to the workspace
91
+ * root with forward slashes, to a `WorkspaceSource`. Link checks, link
92
+ * rewriting, and Obsidian wrapping need one. A Markdown target is parsed in
93
+ * `options.dialect` when a link's fragment needs its anchors, which are kept
94
+ * and its text is not.
95
+ */
41
96
  export declare function createWorkspace(files: Record<string, WorkspaceSource>, options?: WorkspaceOptions): Workspace;