mdrefine 0.1.0-beta.1 → 0.1.0-beta.2

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 (40) hide show
  1. package/CONTRIBUTING.md +6 -0
  2. package/README.md +10 -6
  3. package/dist/cli/main.js +9 -2
  4. package/dist/cli/main.js.map +1 -1
  5. package/dist/config/resolve.d.ts +12 -0
  6. package/dist/config/resolve.js +7 -1
  7. package/dist/config/resolve.js.map +1 -1
  8. package/dist/core/engine.js +19 -4
  9. package/dist/core/engine.js.map +1 -1
  10. package/dist/core/types.d.ts +7 -1
  11. package/dist/core/types.js.map +1 -1
  12. package/dist/index.d.ts +1 -1
  13. package/dist/index.js.map +1 -1
  14. package/dist/rules/links.js +28 -5
  15. package/dist/rules/links.js.map +1 -1
  16. package/dist/rules/structure.d.ts +2 -0
  17. package/dist/rules/structure.js +24 -0
  18. package/dist/rules/structure.js.map +1 -0
  19. package/dist/rules/style.js +78 -15
  20. package/dist/rules/style.js.map +1 -1
  21. package/dist/syntax/obsidian.js +17 -0
  22. package/dist/syntax/obsidian.js.map +1 -1
  23. package/dist/workspace/files.d.ts +5 -2
  24. package/dist/workspace/files.js +15 -6
  25. package/dist/workspace/files.js.map +1 -1
  26. package/dist/workspace/index.d.ts +4 -1
  27. package/dist/workspace/index.js +53 -15
  28. package/dist/workspace/index.js.map +1 -1
  29. package/dist/workspace/selection.d.ts +2 -0
  30. package/dist/workspace/selection.js +31 -0
  31. package/dist/workspace/selection.js.map +1 -0
  32. package/docs/cli.md +18 -0
  33. package/docs/configuration.md +86 -25
  34. package/docs/contributing.md +87 -5
  35. package/docs/design.md +15 -5
  36. package/docs/plugins.md +11 -4
  37. package/docs/quick-start.md +1 -1
  38. package/docs/releases/0.1.0-beta.2.md +83 -0
  39. package/docs/releases.md +33 -10
  40. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"links.js","sourceRoot":"","sources":["../../src/rules/links.ts"],"names":[],"mappings":"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","sourcesContent":["import path from \"node:path\";\nimport { visit } from \"unist-util-visit\";\nimport type { Nodes } from \"mdast\";\nimport type { Finding, Rule } from \"../core/types.js\";\nimport { range } from \"../syntax/parse.js\";\nimport { splitDestination } from \"../workspace/index.js\";\nimport { optionsSchema } from \"./style.js\";\n\nfunction destination(node: Nodes): string | undefined {\n if (node.type === \"wikiLink\") return node.target;\n if (node.type === \"link\" || node.type === \"image\" || node.type === \"definition\") return node.url;\n return undefined;\n}\n/** Locate an inline destination within a parsed link, retaining labels and optional titles. */\nfunction destinationRange(raw: string): [number, number] | undefined {\n let bracket = 0;\n let opening = -1;\n for (let i = raw.startsWith(\"!\") ? 1 : 0; i < raw.length; i++) {\n if (raw[i] === \"\\\\\") {\n i++;\n continue;\n }\n if (raw[i] === \"[\") bracket++;\n if (raw[i] === \"]\" && --bracket === 0 && raw[i + 1] === \"(\") {\n opening = i + 2;\n break;\n }\n }\n if (opening < 0) return undefined;\n while (/\\s/.test(raw[opening] ?? \"\")) opening++;\n if (raw[opening] === \"<\") {\n for (let i = opening + 1; i < raw.length; i++) {\n if (raw[i] === \"\\\\\") {\n i++;\n continue;\n }\n if (raw[i] === \">\") return [opening, i + 1];\n }\n return undefined;\n }\n let depth = 0;\n for (let i = opening; i < raw.length; i++) {\n const char = raw[i]!;\n if (char === \"\\\\\") {\n i++;\n continue;\n }\n if (char === \"(\") depth++;\n if ((char === \")\" && depth-- === 0) || /\\s/.test(char)) return [opening, i];\n }\n return undefined;\n}\n\nexport const linkRules: Record<string, Rule> = {\n \"links/valid\": {\n description: \"Check local link destinations and dialect-specific heading/block references.\",\n kind: \"problem\",\n schema: optionsSchema({}),\n check({ document, workspace }) {\n const findings: Finding[] = [];\n const definitions = new Set<string>();\n visit(document.tree, \"definition\", (node) => {\n definitions.add(node.identifier);\n });\n visit(document.tree, (node) => {\n if (\n (node.type === \"linkReference\" || node.type === \"imageReference\") &&\n !definitions.has(node.identifier)\n )\n findings.push({\n start: range(node)[0],\n message: `Missing link definition: ${node.identifier}.`,\n });\n const url = destination(node);\n if (url === undefined || !workspace) return;\n const result = workspace.resolve(\n document.path,\n url,\n document.dialect,\n node.type === \"wikiLink\",\n );\n if (result.status === \"missing\" || result.status === \"ambiguous\")\n findings.push({\n start: range(node)[0],\n message: `${result.status === \"missing\" ? \"Missing\" : \"Ambiguous\"} local target: ${url}.`,\n });\n else if (result.status === \"resolved\" && !result.fragmentExists)\n findings.push({ start: range(node)[0], message: `Missing fragment in ${url}.` });\n });\n return findings;\n },\n },\n \"links/path\": {\n description: \"Rewrite verified local destinations using the configured path and bracket style.\",\n kind: \"style\",\n phase: \"inline\",\n schema: optionsSchema({\n style: { enum: [\"relative\", \"root\", \"shortest\", \"preserve\"] },\n brackets: { enum: [\"angle\", \"bare\", \"preserve\"] },\n extension: { enum: [\"include\", \"omit\", \"preserve\"] },\n leadingDot: { type: \"boolean\" },\n }),\n check({ document, options, workspace }) {\n const findings: Finding[] = [];\n visit(document.tree, (node) => {\n const url = destination(node);\n if (url === undefined || !workspace) return;\n const result = workspace.resolve(\n document.path,\n url,\n document.dialect,\n node.type === \"wikiLink\",\n );\n if (result.status !== \"resolved\" || !result.target || !result.fragmentExists) return;\n const parts = splitDestination(url);\n let target = parts.path;\n const style = options.style ?? \"preserve\";\n // Vault roots and extensionless Markdown are renderer-specific; don't change other dialects.\n if (\n document.dialect !== \"obsidian\" &&\n (style === \"root\" || style === \"shortest\" || options.extension === \"omit\")\n )\n return;\n if (parts.path) {\n if (style === \"root\") target = result.target;\n else if (style === \"relative\")\n target = path.posix.relative(path.posix.dirname(document.path), result.target);\n else if (style === \"shortest\") {\n const basename = path.posix.basename(result.target);\n const resolved = workspace.resolve(document.path, basename, document.dialect, true);\n target =\n resolved.status === \"resolved\" && resolved.target === result.target\n ? basename\n : result.target;\n }\n if (document.dialect === \"obsidian\" && result.target.endsWith(\".md\")) {\n if (\n options.extension === \"omit\" ||\n ((options.extension ?? \"preserve\") === \"preserve\" && !parts.path.endsWith(\".md\"))\n )\n target = target.replace(/\\.md$/, \"\");\n else if (options.extension === \"include\" && !target.endsWith(\".md\")) target += \".md\";\n }\n if (style === \"relative\" && options.leadingDot === true && !target.startsWith(\".\"))\n target = `./${target}`;\n }\n // Encode reserved path characters before reattaching a separately parsed fragment.\n const encodedPath = target\n .replaceAll(\"%\", \"%25\")\n .replaceAll(\"#\", \"%23\")\n .replaceAll(\"?\", \"%3F\");\n let replacement =\n encodedPath + (parts.fragment ? `#${parts.fragment.replaceAll(\"%\", \"%25\")}` : \"\");\n const [start, end] = range(node);\n if (node.type === \"wikiLink\") {\n if (/[[\\]|\\r\\n]/.test(replacement)) return;\n if (!node.embed && node.label === undefined && replacement !== node.target) return;\n replacement = `${node.embed ? \"!\" : \"\"}[[${replacement}${node.label === undefined ? \"\" : `|${node.label}`}]]`;\n if (replacement !== document.source.slice(start, end))\n findings.push({\n start,\n end,\n message: \"Normalize wikilink destination.\",\n edit: { start, end, text: replacement },\n });\n return;\n }\n if (node.type === \"definition\") return; // Definitions are validated; retain their exact layout in this release.\n const raw = document.source.slice(start, end);\n const span = destinationRange(raw);\n if (!span) return; // Autolinks have no parenthesized destination.\n const original = raw.slice(...span);\n const angle =\n options.brackets === \"angle\" ||\n ((options.brackets ?? \"preserve\") === \"preserve\" && original.startsWith(\"<\"));\n if (angle)\n replacement = `<${replacement.replaceAll(\"<\", \"%3C\").replaceAll(\">\", \"%3E\").replaceAll(\"\\\\\", \"%5C\")}>`;\n else\n replacement = replacement\n .replaceAll(\" \", \"%20\")\n .replaceAll(\"(\", \"%28\")\n .replaceAll(\")\", \"%29\")\n .replaceAll(\"<\", \"%3C\")\n .replaceAll(\">\", \"%3E\");\n if (original !== replacement)\n findings.push({\n start: start + span[0],\n end: start + span[1],\n message: \"Normalize link destination.\",\n edit: { start: start + span[0], end: start + span[1], text: replacement },\n });\n });\n return findings;\n },\n },\n \"links/notation\": {\n description: \"Convert plain-label Obsidian links between Markdown and wikilink notation.\",\n kind: \"style\",\n phase: \"inline\",\n schema: optionsSchema({ style: { enum: [\"markdown\", \"wiki\"] } }),\n check({ document, options, workspace }) {\n if (document.dialect !== \"obsidian\" || !workspace) return [];\n const findings: Finding[] = [];\n visit(document.tree, (node) => {\n const [start, end] = range(node);\n let replacement: string | undefined;\n if (\n options.style === \"markdown\" &&\n node.type === \"wikiLink\" &&\n !node.embed &&\n node.label !== undefined\n ) {\n if (/[[\\]<>\\\\\\r\\n]/.test(node.target ?? \"\") || /[*_`[\\]\\\\]/.test(node.label)) return;\n replacement = `[${node.label}](<${node.target}>)`;\n } else if (\n options.style === \"wiki\" &&\n node.type === \"link\" &&\n !node.title &&\n node.children.length === 1 &&\n node.children[0]?.type === \"text\"\n ) {\n const label = node.children[0].value;\n if (/[[\\]|\\r\\n]/.test(node.url + label)) return;\n replacement = `[[${node.url}|${label}]]`;\n }\n const url = destination(node);\n if (\n !replacement ||\n url === undefined ||\n workspace.resolve(document.path, url, document.dialect, node.type === \"wikiLink\")\n .status !== \"resolved\"\n )\n return;\n findings.push({\n start,\n end,\n message: `Use ${String(options.style)} link notation.`,\n edit: { start, end, text: replacement },\n });\n });\n return findings;\n },\n },\n};\n"]}
1
+ {"version":3,"file":"links.js","sourceRoot":"","sources":["../../src/rules/links.ts"],"names":[],"mappings":"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","sourcesContent":["import path from \"node:path\";\nimport { visit } from \"unist-util-visit\";\nimport type { Nodes } from \"mdast\";\nimport type { Finding, Rule } from \"../core/types.js\";\nimport { range } from \"../syntax/parse.js\";\nimport { splitDestination } from \"../workspace/index.js\";\nimport { optionsSchema } from \"./style.js\";\n\nfunction destination(node: Nodes): string | undefined {\n if (node.type === \"wikiLink\") return node.target;\n if (node.type === \"link\" || node.type === \"image\" || node.type === \"definition\") return node.url;\n return undefined;\n}\n/** Locate an inline destination within a parsed link, retaining labels and optional titles. */\nfunction destinationRange(raw: string): [number, number] | undefined {\n let bracket = 0;\n let opening = -1;\n for (let i = raw.startsWith(\"!\") ? 1 : 0; i < raw.length; i++) {\n if (raw[i] === \"\\\\\") {\n i++;\n continue;\n }\n if (raw[i] === \"[\") bracket++;\n if (raw[i] === \"]\" && --bracket === 0 && raw[i + 1] === \"(\") {\n opening = i + 2;\n break;\n }\n }\n if (opening < 0) return undefined;\n while (/\\s/.test(raw[opening] ?? \"\")) opening++;\n if (raw[opening] === \"<\") {\n for (let i = opening + 1; i < raw.length; i++) {\n if (raw[i] === \"\\\\\") {\n i++;\n continue;\n }\n if (raw[i] === \">\") return [opening, i + 1];\n }\n return undefined;\n }\n let depth = 0;\n for (let i = opening; i < raw.length; i++) {\n const char = raw[i]!;\n if (char === \"\\\\\") {\n i++;\n continue;\n }\n if (char === \"(\") depth++;\n if ((char === \")\" && depth-- === 0) || /\\s/.test(char)) return [opening, i];\n }\n return undefined;\n}\n\nexport const linkRules: Record<string, Rule> = {\n \"links/valid\": {\n description: \"Check local link destinations and dialect-specific heading/block references.\",\n kind: \"problem\",\n schema: optionsSchema({}),\n check({ document, workspace }) {\n const findings: Finding[] = [];\n const definitions = new Set<string>();\n visit(document.tree, \"definition\", (node) => {\n definitions.add(node.identifier);\n });\n visit(document.tree, (node) => {\n if (\n (node.type === \"linkReference\" || node.type === \"imageReference\") &&\n !definitions.has(node.identifier)\n )\n findings.push({\n start: range(node)[0],\n message: `Missing link definition: ${node.identifier}.`,\n });\n const url = destination(node);\n if (url === undefined || !workspace) return;\n const result = workspace.resolve(\n document.path,\n url,\n document.dialect,\n node.type === \"wikiLink\",\n );\n if (result.status === \"missing\" || result.status === \"ambiguous\")\n findings.push({\n start: range(node)[0],\n message: `${result.status === \"missing\" ? \"Missing\" : \"Ambiguous\"} local target: ${url}.`,\n });\n else if (result.status === \"directory\" && document.dialect === \"obsidian\")\n findings.push({ start: range(node)[0], message: `Local target is a directory: ${url}.` });\n else if (result.status === \"resolved\" && !result.fragmentExists)\n findings.push({ start: range(node)[0], message: `Missing fragment in ${url}.` });\n });\n return findings;\n },\n },\n \"links/path\": {\n description: \"Rewrite verified local destinations using the configured path and bracket style.\",\n kind: \"style\",\n phase: \"inline\",\n schema: optionsSchema({\n style: { enum: [\"relative\", \"root\", \"shortest\", \"preserve\"] },\n brackets: { enum: [\"angle\", \"bare\", \"preserve\"] },\n extension: { enum: [\"include\", \"omit\", \"preserve\"] },\n leadingDot: { type: \"boolean\" },\n }),\n check({ document, options, workspace }) {\n const findings: Finding[] = [];\n visit(document.tree, (node) => {\n const url = destination(node);\n if (url === undefined || !workspace) return;\n const result = workspace.resolve(\n document.path,\n url,\n document.dialect,\n node.type === \"wikiLink\",\n );\n if (result.status !== \"resolved\" || !result.target || !result.fragmentExists) return;\n const parts = splitDestination(url);\n let target = parts.path;\n const style = options.style ?? \"preserve\";\n // Vault roots and extensionless Markdown are renderer-specific; don't change other dialects.\n if (\n document.dialect !== \"obsidian\" &&\n (style === \"root\" || style === \"shortest\" || options.extension === \"omit\")\n )\n return;\n if (parts.path) {\n if (style === \"root\") target = result.target;\n else if (style === \"relative\")\n target = path.posix.relative(path.posix.dirname(document.path), result.target);\n else if (style === \"shortest\") {\n const basename = path.posix.basename(result.target);\n const resolved = workspace.resolve(document.path, basename, document.dialect, true);\n target =\n resolved.status === \"resolved\" && resolved.target === result.target\n ? basename\n : result.target;\n }\n if (document.dialect === \"obsidian\" && result.target.endsWith(\".md\")) {\n if (\n options.extension === \"omit\" ||\n ((options.extension ?? \"preserve\") === \"preserve\" && !parts.path.endsWith(\".md\"))\n )\n target = target.replace(/\\.md$/, \"\");\n else if (options.extension === \"include\" && !target.endsWith(\".md\")) target += \".md\";\n }\n if (style === \"relative\" && options.leadingDot === true && !target.startsWith(\".\"))\n target = `./${target}`;\n }\n // Encode reserved path characters before reattaching a separately parsed fragment.\n const hash = url.indexOf(\"#\");\n const encodedPath =\n target === parts.path\n ? hash < 0\n ? url\n : url.slice(0, hash)\n : target.replaceAll(\"%\", \"%25\").replaceAll(\"#\", \"%23\");\n let replacement =\n encodedPath +\n (hash < 0\n ? \"\"\n : target === parts.path\n ? url.slice(hash)\n : `#${parts.fragment.replaceAll(\"%\", \"%25\")}`);\n // A relative basename can collide with a vault-root path. Make the\n // relative spelling explicit before proposing an identity-changing edit.\n let verified = workspace.resolve(\n document.path,\n replacement,\n document.dialect,\n node.type === \"wikiLink\",\n );\n if (\n style === \"relative\" &&\n parts.path &&\n !replacement.startsWith(\".\") &&\n (verified.status !== \"resolved\" || verified.target !== result.target)\n ) {\n replacement = `./${replacement}`;\n verified = workspace.resolve(\n document.path,\n replacement,\n document.dialect,\n node.type === \"wikiLink\",\n );\n }\n if (\n verified.status !== \"resolved\" ||\n verified.target !== result.target ||\n verified.fragment !== result.fragment\n )\n return;\n const [start, end] = range(node);\n if (node.type === \"wikiLink\") {\n if (/[[\\]|\\r\\n]/.test(replacement)) return;\n if (!node.embed && node.label === undefined && replacement !== node.target) return;\n replacement = `${node.embed ? \"!\" : \"\"}[[${replacement}${node.label === undefined ? \"\" : `|${node.label}`}]]`;\n if (replacement !== document.source.slice(start, end))\n findings.push({\n start,\n end,\n message: \"Normalize wikilink destination.\",\n edit: { start, end, text: replacement },\n });\n return;\n }\n if (node.type === \"definition\") return; // Definitions are validated; retain their exact layout in this release.\n const raw = document.source.slice(start, end);\n const span = destinationRange(raw);\n if (!span) return; // Autolinks have no parenthesized destination.\n const original = raw.slice(...span);\n const angle =\n options.brackets === \"angle\" ||\n ((options.brackets ?? \"preserve\") === \"preserve\" && original.startsWith(\"<\"));\n if (angle)\n replacement = `<${replacement.replaceAll(\"<\", \"%3C\").replaceAll(\">\", \"%3E\").replaceAll(\"\\\\\", \"%5C\")}>`;\n else\n replacement = replacement\n .replaceAll(\" \", \"%20\")\n .replaceAll(\"(\", \"%28\")\n .replaceAll(\")\", \"%29\")\n .replaceAll(\"<\", \"%3C\")\n .replaceAll(\">\", \"%3E\");\n if (original !== replacement)\n findings.push({\n start: start + span[0],\n end: start + span[1],\n message: \"Normalize link destination.\",\n edit: { start: start + span[0], end: start + span[1], text: replacement },\n });\n });\n return findings;\n },\n },\n \"links/notation\": {\n description: \"Convert plain-label Obsidian links between Markdown and wikilink notation.\",\n kind: \"style\",\n phase: \"inline\",\n schema: optionsSchema({ style: { enum: [\"markdown\", \"wiki\"] } }),\n check({ document, options, workspace }) {\n if (document.dialect !== \"obsidian\" || !workspace) return [];\n const findings: Finding[] = [];\n visit(document.tree, (node) => {\n const [start, end] = range(node);\n let replacement: string | undefined;\n if (\n options.style === \"markdown\" &&\n node.type === \"wikiLink\" &&\n !node.embed &&\n node.label !== undefined\n ) {\n if (/[[\\]<>\\\\\\r\\n]/.test(node.target ?? \"\") || /[*_`[\\]\\\\]/.test(node.label)) return;\n replacement = `[${node.label}](<${node.target}>)`;\n } else if (\n options.style === \"wiki\" &&\n node.type === \"link\" &&\n !node.title &&\n node.children.length === 1 &&\n node.children[0]?.type === \"text\"\n ) {\n const label = node.children[0].value;\n if (/[[\\]|\\r\\n]/.test(node.url + label)) return;\n replacement = `[[${node.url}|${label}]]`;\n }\n const url = destination(node);\n if (\n !replacement ||\n url === undefined ||\n workspace.resolve(document.path, url, document.dialect, node.type === \"wikiLink\")\n .status !== \"resolved\"\n )\n return;\n findings.push({\n start,\n end,\n message: `Use ${String(options.style)} link notation.`,\n edit: { start, end, text: replacement },\n });\n });\n return findings;\n },\n },\n};\n"]}
@@ -0,0 +1,2 @@
1
+ import type { Rule } from "../core/types.js";
2
+ export declare const structureRules: Record<string, Rule>;
@@ -0,0 +1,24 @@
1
+ import { range } from "../syntax/parse.js";
2
+ import { optionsSchema } from "./style.js";
3
+ function content(nodes) {
4
+ return nodes.filter((node) => !["yaml", "toml"].includes(node.type));
5
+ }
6
+ export const structureRules = {
7
+ "structure/initial-heading": {
8
+ description: "Require the first content block to be a level-1 heading.",
9
+ kind: "problem",
10
+ schema: optionsSchema({}),
11
+ check({ document }) {
12
+ const first = content(document.tree.children)[0];
13
+ return first?.type === "heading" && first.depth === 1
14
+ ? []
15
+ : [
16
+ {
17
+ start: first ? range(first)[0] : 0,
18
+ message: "Start the document with a level-1 heading after optional front matter.",
19
+ },
20
+ ];
21
+ },
22
+ },
23
+ };
24
+ //# sourceMappingURL=structure.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"structure.js","sourceRoot":"","sources":["../../src/rules/structure.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAE3C,SAAS,OAAO,CAAC,KAAoB;IACnC,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;AACvE,CAAC;AACD,MAAM,CAAC,MAAM,cAAc,GAAyB;IAClD,2BAA2B,EAAE;QAC3B,WAAW,EAAE,0DAA0D;QACvE,IAAI,EAAE,SAAS;QACf,MAAM,EAAE,aAAa,CAAC,EAAE,CAAC;QACzB,KAAK,CAAC,EAAE,QAAQ,EAAE;YAChB,MAAM,KAAK,GAAG,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;YACjD,OAAO,KAAK,EAAE,IAAI,KAAK,SAAS,IAAI,KAAK,CAAC,KAAK,KAAK,CAAC;gBACnD,CAAC,CAAC,EAAE;gBACJ,CAAC,CAAC;oBACE;wBACE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;wBAClC,OAAO,EAAE,wEAAwE;qBAClF;iBACF,CAAC;QACR,CAAC;KACF;CACF,CAAC","sourcesContent":["import type { RootContent } from \"mdast\";\nimport type { Rule } from \"../core/types.js\";\nimport { range } from \"../syntax/parse.js\";\nimport { optionsSchema } from \"./style.js\";\n\nfunction content(nodes: RootContent[]): RootContent[] {\n return nodes.filter((node) => ![\"yaml\", \"toml\"].includes(node.type));\n}\nexport const structureRules: Record<string, Rule> = {\n \"structure/initial-heading\": {\n description: \"Require the first content block to be a level-1 heading.\",\n kind: \"problem\",\n schema: optionsSchema({}),\n check({ document }) {\n const first = content(document.tree.children)[0];\n return first?.type === \"heading\" && first.depth === 1\n ? []\n : [\n {\n start: first ? range(first)[0] : 0,\n message: \"Start the document with a level-1 heading after optional front matter.\",\n },\n ];\n },\n },\n};\n"]}
@@ -41,27 +41,51 @@ function markerRule(type, fallback) {
41
41
  };
42
42
  }
43
43
  const wrap = {
44
- description: "Reflow paragraphs using display-column width and protected inline atoms.",
44
+ description: "Reflow paragraphs using configurable width and protected inline atoms.",
45
45
  kind: "style",
46
46
  phase: "block",
47
- schema: optionsSchema({ width: { type: "integer", minimum: 20, maximum: 500 } }),
47
+ schema: optionsSchema({
48
+ width: { type: "integer", minimum: 20, maximum: 500 },
49
+ measure: { enum: ["columns", "codepoints"] },
50
+ reportUnreflowed: { type: "boolean" },
51
+ reportUnbreakable: { type: "boolean" },
52
+ }),
48
53
  check({ document, options, workspace }) {
49
54
  if (document.dialect === "obsidian" && workspace?.strictLineBreaks !== true)
50
55
  return [];
51
56
  const findings = [];
52
57
  const width = Number(options.width ?? 80);
58
+ const measure = options.measure === "codepoints" ? (text) => [...text].length : stringWidth;
59
+ const unit = options.measure === "codepoints" ? "code points" : "columns";
53
60
  visit(document.tree, "paragraph", (node) => {
54
61
  const [start, end] = range(node);
55
62
  const original = document.source.slice(start, end);
56
- // Explicit breaks, callout headers, block IDs, multiline opaque syntax, and HTML are protected.
57
- if (node.children.some((child) => child.type === "break" || child.type === "html") ||
58
- /^\[![^\]]+\]/.test(original) ||
59
- /(?:^|\s)\^[\w-]+\s*$/.test(original))
60
- return;
61
63
  const lineStart = document.source.lastIndexOf("\n", start - 1) + 1;
62
64
  const prefix = document.source.slice(lineStart, start);
63
- if (!/^[\s>\-*+\d.[\]xX)]*$/.test(prefix))
65
+ const reportSkipped = (reason) => {
66
+ if (options.reportUnreflowed === true &&
67
+ (prefix + original).split(/\r?\n/).some((line) => measure(line) > width))
68
+ findings.push({
69
+ start,
70
+ end,
71
+ message: `Paragraph not reflowed: ${reason} (width ${width} ${unit}).`,
72
+ });
73
+ };
74
+ const reason = node.children.some((child) => child.type === "break")
75
+ ? "hard line break"
76
+ : node.children.some((child) => child.type === "html")
77
+ ? "inline HTML"
78
+ : /^\[![^\]]+\]/.test(original)
79
+ ? "callout header"
80
+ : /(?:^|\s)\^[\w-]+\s*$/.test(original)
81
+ ? "block identifier"
82
+ : !/^[\s>\-*+\d.[\]xX)]*$/.test(prefix)
83
+ ? "unsupported container prefix"
84
+ : undefined;
85
+ if (reason) {
86
+ reportSkipped(reason);
64
87
  return;
88
+ }
65
89
  const continuation = prefix.replace(/(?:[-+*]|\d+[.)]|\[[xX ]\])(?=\s)/g, (value) => " ".repeat(value.length));
66
90
  const words = [];
67
91
  let unsupported = false;
@@ -87,8 +111,10 @@ const wrap = {
87
111
  words.push(value);
88
112
  }
89
113
  }
90
- if (unsupported)
114
+ if (unsupported) {
115
+ reportSkipped("multiline inline syntax or unsupported continuation");
91
116
  return;
117
+ }
92
118
  // Adjacent inline nodes without source whitespace form a single wrapping atom.
93
119
  const atoms = [];
94
120
  let current = "";
@@ -103,17 +129,22 @@ const wrap = {
103
129
  }
104
130
  if (current)
105
131
  atoms.push(current);
132
+ // Decide breaks with a marker and its preceding atom already grouped.
133
+ for (let i = 1; i < atoms.length; i++) {
134
+ if (/^(?:[-+*]|\d+[.)]|#{1,6}|>|[-*_]{3,})$/.test(atoms[i])) {
135
+ atoms.splice(i - 1, 2, `${atoms[i - 1]} ${atoms[i]}`);
136
+ i--;
137
+ }
138
+ }
106
139
  const output = [];
107
140
  let line = "";
108
- let available = width - stringWidth(prefix);
141
+ let available = width - measure(prefix);
109
142
  for (const atom of atoms) {
110
143
  const candidate = line ? `${line} ${atom}` : atom;
111
- // Never introduce a Markdown block by placing its marker at a physical line start.
112
- const marker = /^(?:[-+*]|\d+[.)]|#{1,6}|>|[-*_]{3,})$/.test(atom);
113
- if (line && stringWidth(candidate) > available && !marker) {
144
+ if (line && measure(candidate) > available) {
114
145
  output.push(line);
115
146
  line = atom;
116
- available = width - stringWidth(continuation);
147
+ available = width - measure(continuation);
117
148
  }
118
149
  else
119
150
  line = candidate;
@@ -126,9 +157,16 @@ const wrap = {
126
157
  findings.push({
127
158
  start,
128
159
  end,
129
- message: `Reflow paragraph to ${width} columns.`,
160
+ message: `Reflow paragraph to ${width} ${unit}.`,
130
161
  edit: { start, end, text: replacement },
131
162
  });
163
+ if (options.reportUnbreakable === true &&
164
+ (prefix + replacement).split(/\r?\n/).some((line) => measure(line) > width))
165
+ findings.push({
166
+ start,
167
+ end,
168
+ message: `Paragraph exceeds ${width} ${unit} because of an unbreakable atom.`,
169
+ });
132
170
  });
133
171
  return findings;
134
172
  },
@@ -179,6 +217,31 @@ const table = {
179
217
  };
180
218
  export const styleRules = {
181
219
  "style/wrap": wrap,
220
+ "style/inline-code": {
221
+ description: "Join multiline code spans using their CommonMark rendered value.",
222
+ kind: "style",
223
+ phase: "inline",
224
+ schema: optionsSchema({}),
225
+ check({ document }) {
226
+ const findings = [];
227
+ visit(document.tree, "inlineCode", (node) => {
228
+ const [start, end] = range(node);
229
+ if (!/[\r\n]/.test(document.source.slice(start, end)))
230
+ return;
231
+ const value = node.value.replace(/\r\n|\r|\n/g, " ");
232
+ const longest = Math.max(0, ...(value.match(/`+/g) ?? []).map((run) => run.length));
233
+ const marker = "`".repeat(longest + 1);
234
+ const pad = /^`|`$/.test(value) || (/^ .* $/.test(value) && /[^ ]/.test(value)) ? " " : "";
235
+ findings.push({
236
+ start,
237
+ end,
238
+ message: "Join the code span onto one line.",
239
+ edit: { start, end, text: `${marker}${pad}${value}${pad}${marker}` },
240
+ });
241
+ });
242
+ return findings;
243
+ },
244
+ },
182
245
  "style/emphasis": markerRule("emphasis", "_"),
183
246
  "style/strong": markerRule("strong", "*"),
184
247
  "style/table": table,
@@ -1 +1 @@
1
- {"version":3,"file":"style.js","sourceRoot":"","sources":["../../src/rules/style.ts"],"names":[],"mappings":"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","sourcesContent":["import { visit } from \"unist-util-visit\";\nimport stringWidth from \"string-width\";\nimport type { Nodes } from \"mdast\";\nimport type { Finding, Rule } from \"../core/types.js\";\nimport { range } from \"../syntax/parse.js\";\n\nexport function optionsSchema(properties: Record<string, unknown>) {\n return { type: \"object\", properties, additionalProperties: false };\n}\nfunction markerRule(type: \"emphasis\" | \"strong\", fallback: string): Rule {\n return {\n description: `Choose ${type} delimiters without reprinting their contents.`,\n kind: \"style\",\n phase: \"inline\",\n schema: optionsSchema({ marker: { enum: [\"*\", \"_\"] } }),\n check({ document, options }) {\n const findings: Finding[] = [];\n visit(document.tree, type, (node) => {\n const [start, end] = range(node);\n const size = type === \"strong\" ? 2 : 1;\n const marker = String(options.marker ?? fallback).repeat(size);\n const original = document.source.slice(start, end);\n if (original.startsWith(marker)) return;\n // Underscores cannot delimit intraword emphasis. Preserve these valid forms.\n if (\n marker.startsWith(\"_\") &&\n (/\\p{L}|\\p{N}/u.test(document.source[start - 1] ?? \"\") ||\n /\\p{L}|\\p{N}/u.test(document.source[end] ?? \"\"))\n )\n return;\n for (const [a, b] of [\n [start, start + size],\n [end - size, end],\n ] as const) {\n findings.push({\n start: a,\n end: b,\n message: `Use ${JSON.stringify(marker)} for ${type}.`,\n edit: { start: a, end: b, text: marker },\n });\n }\n });\n return findings;\n },\n };\n}\n\nconst wrap: Rule = {\n description: \"Reflow paragraphs using display-column width and protected inline atoms.\",\n kind: \"style\",\n phase: \"block\",\n schema: optionsSchema({ width: { type: \"integer\", minimum: 20, maximum: 500 } }),\n check({ document, options, workspace }) {\n if (document.dialect === \"obsidian\" && workspace?.strictLineBreaks !== true) return [];\n const findings: Finding[] = [];\n const width = Number(options.width ?? 80);\n visit(document.tree, \"paragraph\", (node) => {\n const [start, end] = range(node);\n const original = document.source.slice(start, end);\n // Explicit breaks, callout headers, block IDs, multiline opaque syntax, and HTML are protected.\n if (\n node.children.some((child) => child.type === \"break\" || child.type === \"html\") ||\n /^\\[![^\\]]+\\]/.test(original) ||\n /(?:^|\\s)\\^[\\w-]+\\s*$/.test(original)\n )\n return;\n const lineStart = document.source.lastIndexOf(\"\\n\", start - 1) + 1;\n const prefix = document.source.slice(lineStart, start);\n if (!/^[\\s>\\-*+\\d.[\\]xX)]*$/.test(prefix)) return;\n const continuation = prefix.replace(/(?:[-+*]|\\d+[.)]|\\[[xX ]\\])(?=\\s)/g, (value) =>\n \" \".repeat(value.length),\n );\n const words: string[] = [];\n let unsupported = false;\n for (const child of node.children) {\n const [a, b] = range(child);\n const raw = document.source.slice(a, b);\n const lines = raw.split(/\\r?\\n/);\n for (let i = 1; i < lines.length; i++) {\n const line = lines[i]!;\n if (continuation && line.startsWith(continuation))\n lines[i] = line.slice(continuation.length);\n else if (continuation && /^[\\s>]/.test(line)) unsupported = true;\n }\n const value = lines.join(\" \");\n if (child.type === \"text\") {\n // Preserve escaping and entities. Split only ordinary source whitespace.\n words.push(...value.split(/([ \\t]+)/).filter(Boolean));\n } else {\n if (raw.includes(\"\\n\")) unsupported = true;\n words.push(value);\n }\n }\n if (unsupported) return;\n // Adjacent inline nodes without source whitespace form a single wrapping atom.\n const atoms: string[] = [];\n let current = \"\";\n for (const word of words) {\n if (/^[ \\t]+$/.test(word)) {\n if (current) atoms.push(current);\n current = \"\";\n } else current += word;\n }\n if (current) atoms.push(current);\n const output: string[] = [];\n let line = \"\";\n let available = width - stringWidth(prefix);\n for (const atom of atoms) {\n const candidate = line ? `${line} ${atom}` : atom;\n // Never introduce a Markdown block by placing its marker at a physical line start.\n const marker = /^(?:[-+*]|\\d+[.)]|#{1,6}|>|[-*_]{3,})$/.test(atom);\n if (line && stringWidth(candidate) > available && !marker) {\n output.push(line);\n line = atom;\n available = width - stringWidth(continuation);\n } else line = candidate;\n }\n if (line) output.push(line);\n const newline = document.source.includes(\"\\r\\n\") ? \"\\r\\n\" : \"\\n\";\n const replacement = output.join(newline + continuation);\n if (replacement !== original)\n findings.push({\n start,\n end,\n message: `Reflow paragraph to ${width} columns.`,\n edit: { start, end, text: replacement },\n });\n });\n return findings;\n },\n};\n\nconst table: Rule = {\n description: \"Align GFM table cells while preserving their inline source.\",\n kind: \"style\",\n phase: \"block\",\n schema: optionsSchema({}),\n check({ document }) {\n const findings: Finding[] = [];\n visit(document.tree, \"table\", (node) => {\n const [start, end] = range(node);\n // Nested tables retain container prefixes until a dedicated container printer handles them.\n if (node.position!.start.column !== 1) return;\n const rows = node.children.map((row) =>\n row.children.map((cell) => {\n if (!cell.children.length) return \"\";\n const first = range(cell.children[0]!)[0];\n const last = range(cell.children.at(-1)!)[1];\n return document.source.slice(first, last);\n }),\n );\n const count = node.align?.length ?? rows[0]?.length ?? 0;\n if (rows.some((row) => row.length > count)) return;\n const widths = Array.from({ length: count }, (_, i) =>\n Math.max(3, ...rows.map((row) => stringWidth(row[i] ?? \"\"))),\n );\n const rendered = rows.map(\n (row) =>\n `| ${widths.map((width, i) => (row[i] ?? \"\") + \" \".repeat(width - stringWidth(row[i] ?? \"\"))).join(\" | \")} |`,\n );\n rendered.splice(\n 1,\n 0,\n `| ${widths\n .map((width, i) => {\n const align = node.align?.[i];\n return (\n (align === \"left\" || align === \"center\" ? \":\" : \"-\") +\n \"-\".repeat(width - 2) +\n (align === \"right\" || align === \"center\" ? \":\" : \"-\")\n );\n })\n .join(\" | \")} |`,\n );\n const replacement = rendered.join(document.source.includes(\"\\r\\n\") ? \"\\r\\n\" : \"\\n\");\n if (replacement !== document.source.slice(start, end))\n findings.push({\n start,\n end,\n message: \"Align table cells.\",\n edit: { start, end, text: replacement },\n });\n });\n return findings;\n },\n};\n\nexport const styleRules: Record<string, Rule> = {\n \"style/wrap\": wrap,\n \"style/emphasis\": markerRule(\"emphasis\", \"_\"),\n \"style/strong\": markerRule(\"strong\", \"*\"),\n \"style/table\": table,\n \"style/final-newline\": {\n description: \"End nonempty documents with a newline.\",\n kind: \"style\",\n phase: \"document\",\n schema: optionsSchema({}),\n check({ document: { source } }) {\n if (!source || source.endsWith(\"\\n\")) return [];\n return [\n {\n start: source.length,\n message: \"Add a final newline.\",\n edit: {\n start: source.length,\n end: source.length,\n text: source.includes(\"\\r\\n\") ? \"\\r\\n\" : \"\\n\",\n },\n },\n ];\n },\n },\n \"style/heading\": {\n description: \"Use ATX headings.\",\n kind: \"style\",\n phase: \"block\",\n schema: optionsSchema({}),\n check({ document }) {\n const findings: Finding[] = [];\n visit(document.tree, \"heading\", (node) => {\n const [start, end] = range(node);\n if (document.source[start] === \"#\" || node.position!.start.column !== 1) return;\n const first = node.children[0];\n const last = node.children.at(-1);\n if (!first || !last) return;\n const text = document.source.slice(range(first)[0], range(last)[1]);\n if (text.includes(\"\\n\")) return;\n findings.push({\n start,\n end,\n message: \"Use an ATX heading.\",\n edit: { start, end, text: `${\"#\".repeat(node.depth)} ${text}` },\n });\n });\n return findings;\n },\n },\n};\n\n/** Collect source-positioned nodes for rule/plugin consumers. */\nexport function nodesOfType(\n document: { tree: import(\"mdast\").Root },\n type: Nodes[\"type\"],\n): Nodes[] {\n const result: Nodes[] = [];\n visit(document.tree, (node) => {\n if (node.type === type) result.push(node);\n });\n return result;\n}\n"]}
1
+ {"version":3,"file":"style.js","sourceRoot":"","sources":["../../src/rules/style.ts"],"names":[],"mappings":"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","sourcesContent":["import { visit } from \"unist-util-visit\";\nimport stringWidth from \"string-width\";\nimport type { Nodes } from \"mdast\";\nimport type { Finding, Rule } from \"../core/types.js\";\nimport { range } from \"../syntax/parse.js\";\n\nexport function optionsSchema(properties: Record<string, unknown>) {\n return { type: \"object\", properties, additionalProperties: false };\n}\nfunction markerRule(type: \"emphasis\" | \"strong\", fallback: string): Rule {\n return {\n description: `Choose ${type} delimiters without reprinting their contents.`,\n kind: \"style\",\n phase: \"inline\",\n schema: optionsSchema({ marker: { enum: [\"*\", \"_\"] } }),\n check({ document, options }) {\n const findings: Finding[] = [];\n visit(document.tree, type, (node) => {\n const [start, end] = range(node);\n const size = type === \"strong\" ? 2 : 1;\n const marker = String(options.marker ?? fallback).repeat(size);\n const original = document.source.slice(start, end);\n if (original.startsWith(marker)) return;\n // Underscores cannot delimit intraword emphasis. Preserve these valid forms.\n if (\n marker.startsWith(\"_\") &&\n (/\\p{L}|\\p{N}/u.test(document.source[start - 1] ?? \"\") ||\n /\\p{L}|\\p{N}/u.test(document.source[end] ?? \"\"))\n )\n return;\n for (const [a, b] of [\n [start, start + size],\n [end - size, end],\n ] as const) {\n findings.push({\n start: a,\n end: b,\n message: `Use ${JSON.stringify(marker)} for ${type}.`,\n edit: { start: a, end: b, text: marker },\n });\n }\n });\n return findings;\n },\n };\n}\n\nconst wrap: Rule = {\n description: \"Reflow paragraphs using configurable width and protected inline atoms.\",\n kind: \"style\",\n phase: \"block\",\n schema: optionsSchema({\n width: { type: \"integer\", minimum: 20, maximum: 500 },\n measure: { enum: [\"columns\", \"codepoints\"] },\n reportUnreflowed: { type: \"boolean\" },\n reportUnbreakable: { type: \"boolean\" },\n }),\n check({ document, options, workspace }) {\n if (document.dialect === \"obsidian\" && workspace?.strictLineBreaks !== true) return [];\n const findings: Finding[] = [];\n const width = Number(options.width ?? 80);\n const measure =\n options.measure === \"codepoints\" ? (text: string) => [...text].length : stringWidth;\n const unit = options.measure === \"codepoints\" ? \"code points\" : \"columns\";\n visit(document.tree, \"paragraph\", (node) => {\n const [start, end] = range(node);\n const original = document.source.slice(start, end);\n const lineStart = document.source.lastIndexOf(\"\\n\", start - 1) + 1;\n const prefix = document.source.slice(lineStart, start);\n const reportSkipped = (reason: string) => {\n if (\n options.reportUnreflowed === true &&\n (prefix + original).split(/\\r?\\n/).some((line) => measure(line) > width)\n )\n findings.push({\n start,\n end,\n message: `Paragraph not reflowed: ${reason} (width ${width} ${unit}).`,\n });\n };\n const reason = node.children.some((child) => child.type === \"break\")\n ? \"hard line break\"\n : node.children.some((child) => child.type === \"html\")\n ? \"inline HTML\"\n : /^\\[![^\\]]+\\]/.test(original)\n ? \"callout header\"\n : /(?:^|\\s)\\^[\\w-]+\\s*$/.test(original)\n ? \"block identifier\"\n : !/^[\\s>\\-*+\\d.[\\]xX)]*$/.test(prefix)\n ? \"unsupported container prefix\"\n : undefined;\n if (reason) {\n reportSkipped(reason);\n return;\n }\n const continuation = prefix.replace(/(?:[-+*]|\\d+[.)]|\\[[xX ]\\])(?=\\s)/g, (value) =>\n \" \".repeat(value.length),\n );\n const words: string[] = [];\n let unsupported = false;\n for (const child of node.children) {\n const [a, b] = range(child);\n const raw = document.source.slice(a, b);\n const lines = raw.split(/\\r?\\n/);\n for (let i = 1; i < lines.length; i++) {\n const line = lines[i]!;\n if (continuation && line.startsWith(continuation))\n lines[i] = line.slice(continuation.length);\n else if (continuation && /^[\\s>]/.test(line)) unsupported = true;\n }\n const value = lines.join(\" \");\n if (child.type === \"text\") {\n // Preserve escaping and entities. Split only ordinary source whitespace.\n words.push(...value.split(/([ \\t]+)/).filter(Boolean));\n } else {\n if (raw.includes(\"\\n\")) unsupported = true;\n words.push(value);\n }\n }\n if (unsupported) {\n reportSkipped(\"multiline inline syntax or unsupported continuation\");\n return;\n }\n // Adjacent inline nodes without source whitespace form a single wrapping atom.\n const atoms: string[] = [];\n let current = \"\";\n for (const word of words) {\n if (/^[ \\t]+$/.test(word)) {\n if (current) atoms.push(current);\n current = \"\";\n } else current += word;\n }\n if (current) atoms.push(current);\n // Decide breaks with a marker and its preceding atom already grouped.\n for (let i = 1; i < atoms.length; i++) {\n if (/^(?:[-+*]|\\d+[.)]|#{1,6}|>|[-*_]{3,})$/.test(atoms[i]!)) {\n atoms.splice(i - 1, 2, `${atoms[i - 1]} ${atoms[i]}`);\n i--;\n }\n }\n const output: string[] = [];\n let line = \"\";\n let available = width - measure(prefix);\n for (const atom of atoms) {\n const candidate = line ? `${line} ${atom}` : atom;\n if (line && measure(candidate) > available) {\n output.push(line);\n line = atom;\n available = width - measure(continuation);\n } else line = candidate;\n }\n if (line) output.push(line);\n const newline = document.source.includes(\"\\r\\n\") ? \"\\r\\n\" : \"\\n\";\n const replacement = output.join(newline + continuation);\n if (replacement !== original)\n findings.push({\n start,\n end,\n message: `Reflow paragraph to ${width} ${unit}.`,\n edit: { start, end, text: replacement },\n });\n if (\n options.reportUnbreakable === true &&\n (prefix + replacement).split(/\\r?\\n/).some((line) => measure(line) > width)\n )\n findings.push({\n start,\n end,\n message: `Paragraph exceeds ${width} ${unit} because of an unbreakable atom.`,\n });\n });\n return findings;\n },\n};\n\nconst table: Rule = {\n description: \"Align GFM table cells while preserving their inline source.\",\n kind: \"style\",\n phase: \"block\",\n schema: optionsSchema({}),\n check({ document }) {\n const findings: Finding[] = [];\n visit(document.tree, \"table\", (node) => {\n const [start, end] = range(node);\n // Nested tables retain container prefixes until a dedicated container printer handles them.\n if (node.position!.start.column !== 1) return;\n const rows = node.children.map((row) =>\n row.children.map((cell) => {\n if (!cell.children.length) return \"\";\n const first = range(cell.children[0]!)[0];\n const last = range(cell.children.at(-1)!)[1];\n return document.source.slice(first, last);\n }),\n );\n const count = node.align?.length ?? rows[0]?.length ?? 0;\n if (rows.some((row) => row.length > count)) return;\n const widths = Array.from({ length: count }, (_, i) =>\n Math.max(3, ...rows.map((row) => stringWidth(row[i] ?? \"\"))),\n );\n const rendered = rows.map(\n (row) =>\n `| ${widths.map((width, i) => (row[i] ?? \"\") + \" \".repeat(width - stringWidth(row[i] ?? \"\"))).join(\" | \")} |`,\n );\n rendered.splice(\n 1,\n 0,\n `| ${widths\n .map((width, i) => {\n const align = node.align?.[i];\n return (\n (align === \"left\" || align === \"center\" ? \":\" : \"-\") +\n \"-\".repeat(width - 2) +\n (align === \"right\" || align === \"center\" ? \":\" : \"-\")\n );\n })\n .join(\" | \")} |`,\n );\n const replacement = rendered.join(document.source.includes(\"\\r\\n\") ? \"\\r\\n\" : \"\\n\");\n if (replacement !== document.source.slice(start, end))\n findings.push({\n start,\n end,\n message: \"Align table cells.\",\n edit: { start, end, text: replacement },\n });\n });\n return findings;\n },\n};\n\nexport const styleRules: Record<string, Rule> = {\n \"style/wrap\": wrap,\n \"style/inline-code\": {\n description: \"Join multiline code spans using their CommonMark rendered value.\",\n kind: \"style\",\n phase: \"inline\",\n schema: optionsSchema({}),\n check({ document }) {\n const findings: Finding[] = [];\n visit(document.tree, \"inlineCode\", (node) => {\n const [start, end] = range(node);\n if (!/[\\r\\n]/.test(document.source.slice(start, end))) return;\n const value = node.value.replace(/\\r\\n|\\r|\\n/g, \" \");\n const longest = Math.max(0, ...(value.match(/`+/g) ?? []).map((run) => run.length));\n const marker = \"`\".repeat(longest + 1);\n const pad = /^`|`$/.test(value) || (/^ .* $/.test(value) && /[^ ]/.test(value)) ? \" \" : \"\";\n findings.push({\n start,\n end,\n message: \"Join the code span onto one line.\",\n edit: { start, end, text: `${marker}${pad}${value}${pad}${marker}` },\n });\n });\n return findings;\n },\n },\n \"style/emphasis\": markerRule(\"emphasis\", \"_\"),\n \"style/strong\": markerRule(\"strong\", \"*\"),\n \"style/table\": table,\n \"style/final-newline\": {\n description: \"End nonempty documents with a newline.\",\n kind: \"style\",\n phase: \"document\",\n schema: optionsSchema({}),\n check({ document: { source } }) {\n if (!source || source.endsWith(\"\\n\")) return [];\n return [\n {\n start: source.length,\n message: \"Add a final newline.\",\n edit: {\n start: source.length,\n end: source.length,\n text: source.includes(\"\\r\\n\") ? \"\\r\\n\" : \"\\n\",\n },\n },\n ];\n },\n },\n \"style/heading\": {\n description: \"Use ATX headings.\",\n kind: \"style\",\n phase: \"block\",\n schema: optionsSchema({}),\n check({ document }) {\n const findings: Finding[] = [];\n visit(document.tree, \"heading\", (node) => {\n const [start, end] = range(node);\n if (document.source[start] === \"#\" || node.position!.start.column !== 1) return;\n const first = node.children[0];\n const last = node.children.at(-1);\n if (!first || !last) return;\n const text = document.source.slice(range(first)[0], range(last)[1]);\n if (text.includes(\"\\n\")) return;\n findings.push({\n start,\n end,\n message: \"Use an ATX heading.\",\n edit: { start, end, text: `${\"#\".repeat(node.depth)} ${text}` },\n });\n });\n return findings;\n },\n },\n};\n\n/** Collect source-positioned nodes for rule/plugin consumers. */\nexport function nodesOfType(\n document: { tree: import(\"mdast\").Root },\n type: Nodes[\"type\"],\n): Nodes[] {\n const result: Nodes[] = [];\n visit(document.tree, (node) => {\n if (node.type === type) result.push(node);\n });\n return result;\n}\n"]}
@@ -9,6 +9,7 @@ const tokenize = function (effects, ok, nok) {
9
9
  opening = code === 33 ? "![[" : code === 91 ? "[[" : code === 37 ? "%%" : "==";
10
10
  closing = opening.endsWith("[[") ? "]]" : opening;
11
11
  effects.enter("obsidianLiteral");
12
+ effects.enter("obsidianCommentData");
12
13
  return open(code);
13
14
  };
14
15
  const open = (code) => {
@@ -21,17 +22,33 @@ const tokenize = function (effects, ok, nok) {
21
22
  const body = (code) => {
22
23
  if (code === null || (opening !== "%%" && code < 0 && code !== -1 && code !== -2))
23
24
  return nok(code);
25
+ if (code < -2) {
26
+ // Micromark subtokenizes each physical line separately. Expose every
27
+ // line ending so a multiline inline comment can span more than two chunks.
28
+ effects.exit("obsidianCommentData");
29
+ effects.enter("lineEnding");
30
+ effects.consume(code);
31
+ effects.exit("lineEnding");
32
+ previous = null;
33
+ count++;
34
+ return resume;
35
+ }
24
36
  effects.consume(code);
25
37
  count++;
26
38
  if (code === closing.charCodeAt(1) && previous === closing.charCodeAt(0)) {
27
39
  if (count <= 2)
28
40
  return nok(code);
41
+ effects.exit("obsidianCommentData");
29
42
  effects.exit("obsidianLiteral");
30
43
  return ok;
31
44
  }
32
45
  previous = code;
33
46
  return body;
34
47
  };
48
+ const resume = (code) => {
49
+ effects.enter("obsidianCommentData");
50
+ return body(code);
51
+ };
35
52
  return start;
36
53
  };
37
54
  // Standalone comment blocks may cross blank lines. Keep their complete source opaque.
@@ -1 +1 @@
1
- {"version":3,"file":"obsidian.js","sourceRoot":"","sources":["../../src/syntax/obsidian.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Literal } from \"mdast\";\nimport type { Extension, State, Tokenizer } from \"micromark-util-types\";\nimport type { Extension as TreeExtension } from \"mdast-util-from-markdown\";\n\nexport interface ObsidianLiteral extends Literal {\n type: \"wikiLink\" | \"obsidianComment\" | \"obsidianHighlight\";\n embed?: boolean;\n target?: string;\n label?: string;\n}\ndeclare module \"mdast\" {\n interface RootContentMap {\n wikiLink: ObsidianLiteral;\n obsidianComment: ObsidianLiteral;\n obsidianHighlight: ObsidianLiteral;\n }\n interface PhrasingContentMap {\n wikiLink: ObsidianLiteral;\n obsidianComment: ObsidianLiteral;\n obsidianHighlight: ObsidianLiteral;\n }\n interface BlockContentMap {\n obsidianComment: ObsidianLiteral;\n }\n}\ndeclare module \"micromark-util-types\" {\n interface TokenTypeMap {\n obsidianLiteral: \"obsidianLiteral\";\n obsidianBlockComment: \"obsidianBlockComment\";\n obsidianCommentData: \"obsidianCommentData\";\n }\n}\n\n/** A tokenizer, not a pre-parse replacement: code, escapes, and fenced blocks stay opaque. */\nconst tokenize: Tokenizer = function (effects, ok, nok) {\n let opening = \"\";\n let closing = \"\";\n let index = 0;\n let previous: number | null = null;\n let count = 0;\n const start: State = (code) => {\n opening = code === 33 ? \"![[\" : code === 91 ? \"[[\" : code === 37 ? \"%%\" : \"==\";\n closing = opening.endsWith(\"[[\") ? \"]]\" : opening;\n effects.enter(\"obsidianLiteral\");\n return open(code);\n };\n const open: State = (code) => {\n if (code !== opening.charCodeAt(index)) return nok(code);\n effects.consume(code);\n index++;\n return index === opening.length ? body : open;\n };\n const body: State = (code) => {\n if (code === null || (opening !== \"%%\" && code < 0 && code !== -1 && code !== -2))\n return nok(code);\n effects.consume(code);\n count++;\n if (code === closing.charCodeAt(1) && previous === closing.charCodeAt(0)) {\n if (count <= 2) return nok(code);\n effects.exit(\"obsidianLiteral\");\n return ok;\n }\n previous = code;\n return body;\n };\n return start;\n};\n\n// Standalone comment blocks may cross blank lines. Keep their complete source opaque.\nconst tokenizeBlockComment: Tokenizer = function (effects, ok, nok) {\n let opened = 0;\n let previous: number | null = null;\n let closed = false;\n const start: State = (code) => {\n if (code !== 37) return nok(code);\n if (opened === 0) {\n effects.enter(\"obsidianBlockComment\");\n effects.enter(\"obsidianCommentData\");\n }\n effects.consume(code);\n opened++;\n return opened === 2 ? body : start;\n };\n const body: State = (code) => {\n if (code === null || (closed && code < -2)) {\n effects.exit(\"obsidianCommentData\");\n effects.exit(\"obsidianBlockComment\");\n return ok(code);\n }\n if (code < -2) {\n effects.exit(\"obsidianCommentData\");\n effects.enter(\"lineEnding\");\n effects.consume(code);\n effects.exit(\"lineEnding\");\n previous = null;\n return before;\n }\n effects.consume(code);\n if (code === 37 && previous === 37) closed = true;\n previous = code;\n return body;\n };\n const before: State = (code) => {\n if (code === null) {\n effects.exit(\"obsidianBlockComment\");\n return ok(code);\n }\n if (code < -2) {\n effects.enter(\"lineEnding\");\n effects.consume(code);\n effects.exit(\"lineEnding\");\n return before;\n }\n effects.enter(\"obsidianCommentData\");\n return body(code);\n };\n return start;\n};\n\nexport const obsidianSyntax: Extension = {\n flow: { 37: { name: \"obsidianBlockComment\", tokenize: tokenizeBlockComment, concrete: true } },\n text: Object.fromEntries(\n [33, 91, 37, 61].map((code) => [code, { name: \"obsidianLiteral\", tokenize }]),\n ),\n};\nexport const obsidianTree: TreeExtension = {\n enter: {\n obsidianBlockComment(token) {\n this.enter({ type: \"obsidianComment\", value: this.sliceSerialize(token) }, token);\n },\n obsidianLiteral(token) {\n const raw = this.sliceSerialize(token);\n const wiki = raw.startsWith(\"[[\") || raw.startsWith(\"![[\");\n const embed = raw.startsWith(\"!\");\n const value = raw.slice(wiki && embed ? 3 : 2, -2).replaceAll(\"\\\\|\", \"|\");\n const divider = value.indexOf(\"|\");\n const node: ObsidianLiteral = {\n type: wiki ? \"wikiLink\" : raw.startsWith(\"%%\") ? \"obsidianComment\" : \"obsidianHighlight\",\n value,\n };\n if (wiki) {\n node.embed = embed;\n node.target = divider < 0 ? value : value.slice(0, divider);\n if (divider >= 0) node.label = value.slice(divider + 1);\n }\n this.enter(node, token);\n },\n },\n exit: {\n obsidianBlockComment(token) {\n this.exit(token);\n },\n obsidianLiteral(token) {\n this.exit(token);\n },\n },\n};\n"]}
1
+ {"version":3,"file":"obsidian.js","sourceRoot":"","sources":["../../src/syntax/obsidian.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Literal } from \"mdast\";\nimport type { Extension, State, Tokenizer } from \"micromark-util-types\";\nimport type { Extension as TreeExtension } from \"mdast-util-from-markdown\";\n\nexport interface ObsidianLiteral extends Literal {\n type: \"wikiLink\" | \"obsidianComment\" | \"obsidianHighlight\";\n embed?: boolean;\n target?: string;\n label?: string;\n}\ndeclare module \"mdast\" {\n interface RootContentMap {\n wikiLink: ObsidianLiteral;\n obsidianComment: ObsidianLiteral;\n obsidianHighlight: ObsidianLiteral;\n }\n interface PhrasingContentMap {\n wikiLink: ObsidianLiteral;\n obsidianComment: ObsidianLiteral;\n obsidianHighlight: ObsidianLiteral;\n }\n interface BlockContentMap {\n obsidianComment: ObsidianLiteral;\n }\n}\ndeclare module \"micromark-util-types\" {\n interface TokenTypeMap {\n obsidianLiteral: \"obsidianLiteral\";\n obsidianBlockComment: \"obsidianBlockComment\";\n obsidianCommentData: \"obsidianCommentData\";\n }\n}\n\n/** A tokenizer, not a pre-parse replacement: code, escapes, and fenced blocks stay opaque. */\nconst tokenize: Tokenizer = function (effects, ok, nok) {\n let opening = \"\";\n let closing = \"\";\n let index = 0;\n let previous: number | null = null;\n let count = 0;\n const start: State = (code) => {\n opening = code === 33 ? \"![[\" : code === 91 ? \"[[\" : code === 37 ? \"%%\" : \"==\";\n closing = opening.endsWith(\"[[\") ? \"]]\" : opening;\n effects.enter(\"obsidianLiteral\");\n effects.enter(\"obsidianCommentData\");\n return open(code);\n };\n const open: State = (code) => {\n if (code !== opening.charCodeAt(index)) return nok(code);\n effects.consume(code);\n index++;\n return index === opening.length ? body : open;\n };\n const body: State = (code) => {\n if (code === null || (opening !== \"%%\" && code < 0 && code !== -1 && code !== -2))\n return nok(code);\n if (code < -2) {\n // Micromark subtokenizes each physical line separately. Expose every\n // line ending so a multiline inline comment can span more than two chunks.\n effects.exit(\"obsidianCommentData\");\n effects.enter(\"lineEnding\");\n effects.consume(code);\n effects.exit(\"lineEnding\");\n previous = null;\n count++;\n return resume;\n }\n effects.consume(code);\n count++;\n if (code === closing.charCodeAt(1) && previous === closing.charCodeAt(0)) {\n if (count <= 2) return nok(code);\n effects.exit(\"obsidianCommentData\");\n effects.exit(\"obsidianLiteral\");\n return ok;\n }\n previous = code;\n return body;\n };\n const resume: State = (code) => {\n effects.enter(\"obsidianCommentData\");\n return body(code);\n };\n return start;\n};\n\n// Standalone comment blocks may cross blank lines. Keep their complete source opaque.\nconst tokenizeBlockComment: Tokenizer = function (effects, ok, nok) {\n let opened = 0;\n let previous: number | null = null;\n let closed = false;\n const start: State = (code) => {\n if (code !== 37) return nok(code);\n if (opened === 0) {\n effects.enter(\"obsidianBlockComment\");\n effects.enter(\"obsidianCommentData\");\n }\n effects.consume(code);\n opened++;\n return opened === 2 ? body : start;\n };\n const body: State = (code) => {\n if (code === null || (closed && code < -2)) {\n effects.exit(\"obsidianCommentData\");\n effects.exit(\"obsidianBlockComment\");\n return ok(code);\n }\n if (code < -2) {\n effects.exit(\"obsidianCommentData\");\n effects.enter(\"lineEnding\");\n effects.consume(code);\n effects.exit(\"lineEnding\");\n previous = null;\n return before;\n }\n effects.consume(code);\n if (code === 37 && previous === 37) closed = true;\n previous = code;\n return body;\n };\n const before: State = (code) => {\n if (code === null) {\n effects.exit(\"obsidianBlockComment\");\n return ok(code);\n }\n if (code < -2) {\n effects.enter(\"lineEnding\");\n effects.consume(code);\n effects.exit(\"lineEnding\");\n return before;\n }\n effects.enter(\"obsidianCommentData\");\n return body(code);\n };\n return start;\n};\n\nexport const obsidianSyntax: Extension = {\n flow: { 37: { name: \"obsidianBlockComment\", tokenize: tokenizeBlockComment, concrete: true } },\n text: Object.fromEntries(\n [33, 91, 37, 61].map((code) => [code, { name: \"obsidianLiteral\", tokenize }]),\n ),\n};\nexport const obsidianTree: TreeExtension = {\n enter: {\n obsidianBlockComment(token) {\n this.enter({ type: \"obsidianComment\", value: this.sliceSerialize(token) }, token);\n },\n obsidianLiteral(token) {\n const raw = this.sliceSerialize(token);\n const wiki = raw.startsWith(\"[[\") || raw.startsWith(\"![[\");\n const embed = raw.startsWith(\"!\");\n const value = raw.slice(wiki && embed ? 3 : 2, -2).replaceAll(\"\\\\|\", \"|\");\n const divider = value.indexOf(\"|\");\n const node: ObsidianLiteral = {\n type: wiki ? \"wikiLink\" : raw.startsWith(\"%%\") ? \"obsidianComment\" : \"obsidianHighlight\",\n value,\n };\n if (wiki) {\n node.embed = embed;\n node.target = divider < 0 ? value : value.slice(0, divider);\n if (divider >= 0) node.label = value.slice(divider + 1);\n }\n this.enter(node, token);\n },\n },\n exit: {\n obsidianBlockComment(token) {\n this.exit(token);\n },\n obsidianLiteral(token) {\n this.exit(token);\n },\n },\n};\n"]}
@@ -1,8 +1,11 @@
1
+ import type { ResolveOptions } from "../core/types.js";
2
+ import type { WorkspaceSource } from "./index.js";
1
3
  export interface FileSet {
2
4
  root: string;
3
- files: Record<string, string | null>;
5
+ files: Record<string, WorkspaceSource>;
6
+ directories: string[];
4
7
  selected: string[];
5
8
  strictLineBreaks?: boolean;
6
9
  }
7
- export declare function discover(rootPath: string, supplied: string[], excluded: string[]): Promise<FileSet>;
10
+ export declare function discover(rootPath: string, supplied: string[], excluded: string[], resolve?: ResolveOptions): Promise<FileSet>;
8
11
  export declare function writeAtomic(file: string, before: string, after: string): Promise<void>;
@@ -1,12 +1,14 @@
1
1
  import { lstat, readdir, readFile, realpath, open, rename, unlink } from "node:fs/promises";
2
2
  import path from "node:path";
3
+ import { readFileSync } from "node:fs";
3
4
  import { randomUUID } from "node:crypto";
4
5
  import ignore from "ignore";
5
6
  import { minimatch } from "minimatch";
6
7
  import { exists } from "../config/load.js";
7
- export async function discover(rootPath, supplied, excluded) {
8
+ export async function discover(rootPath, supplied, excluded, resolve = {}) {
8
9
  const root = await realpath(rootPath);
9
10
  const files = {};
11
+ const directories = [];
10
12
  const selected = [];
11
13
  const requests = [];
12
14
  for (const input of supplied.length ? supplied : [root]) {
@@ -19,7 +21,7 @@ export async function discover(rootPath, supplied, excluded) {
19
21
  throw new Error(`Input is outside the workspace: ${input}`);
20
22
  requests.push(relative);
21
23
  }
22
- async function walk(relative, inherited) {
24
+ async function walk(relative, inherited, targetOnly = false) {
23
25
  const directory = path.join(root, relative);
24
26
  const layers = [...inherited];
25
27
  if (await exists(path.join(directory, ".gitignore")))
@@ -32,17 +34,23 @@ export async function discover(rootPath, supplied, excluded) {
32
34
  entry.isSymbolicLink())
33
35
  continue;
34
36
  const name = relative ? `${relative}/${entry.name}` : entry.name;
35
- if (layers.some((layer) => layer.matcher.ignores(name.slice(layer.base ? layer.base.length + 1 : 0) + (entry.isDirectory() ? "/" : ""))))
37
+ const gitIgnored = layers.some((layer) => layer.matcher.ignores(name.slice(layer.base ? layer.base.length + 1 : 0) + (entry.isDirectory() ? "/" : "")));
38
+ if (gitIgnored && resolve.gitIgnored !== true)
36
39
  continue;
37
40
  const full = path.join(root, name);
38
41
  if (entry.isDirectory()) {
39
- if (!(await exists(path.join(full, ".git"))))
40
- await walk(name, layers);
42
+ directories.push(name);
43
+ const nested = await exists(path.join(full, ".git"));
44
+ if (!nested || resolve.nestedRepositories === true)
45
+ await walk(name, layers, targetOnly || gitIgnored || nested);
41
46
  }
42
47
  else if (entry.isFile()) {
43
48
  const markdown = /\.md$/i.test(name);
44
- files[name] = markdown ? await readFile(full, "utf8") : null;
49
+ let cached;
50
+ files[name] = markdown ? () => (cached ??= readFileSync(full, "utf8")) : null;
45
51
  if (markdown &&
52
+ !targetOnly &&
53
+ !gitIgnored &&
46
54
  requests.some((request) => !request || name === request || name.startsWith(`${request}/`)) &&
47
55
  !excluded.some((pattern) => minimatch(name, pattern, { dot: true })))
48
56
  selected.push(name);
@@ -63,6 +71,7 @@ export async function discover(rootPath, supplied, excluded) {
63
71
  return {
64
72
  root,
65
73
  files,
74
+ directories,
66
75
  selected: selected.sort(),
67
76
  ...(strictLineBreaks !== undefined ? { strictLineBreaks } : {}),
68
77
  };