mdrefine 0.1.0-beta.3 → 0.1.0-beta.4

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.
package/README.md CHANGED
@@ -35,7 +35,7 @@ The CLI requires Node.js 22.12 or newer. The npm package is `mdrefine`; the
35
35
  executable is `mdtools`. To install the beta in your document workspace:
36
36
 
37
37
  ```sh
38
- npm install --save-dev --save-exact mdrefine@0.1.0-beta.3
38
+ npm install --save-dev --save-exact mdrefine@0.1.0-beta.4
39
39
  npx --no-install mdtools --help
40
40
  ```
41
41
 
@@ -1,6 +1,6 @@
1
1
  import { Ajv } from "ajv";
2
2
  import { resolveConfig, setting } from "../config/resolve.js";
3
- import { parse } from "../syntax/parse.js";
3
+ import { parse, range } from "../syntax/parse.js";
4
4
  import { styleRules } from "../rules/style.js";
5
5
  import { dialectRules } from "../rules/dialects.js";
6
6
  import { structureRules } from "../rules/structure.js";
@@ -133,6 +133,15 @@ export function semanticFingerprint(document, workspace) {
133
133
  };
134
134
  }
135
135
  const result = {};
136
+ if (calloutHeader && document.dialect === "obsidian" && node.type === "paragraph") {
137
+ const [start, end] = range(node);
138
+ const header = document.source.slice(start, end).split(/\r?\n/, 1)[0];
139
+ if (/^\[![\w-]+\]/.test(header)) {
140
+ // CommonMark merges title and body into one paragraph. Preserve their boundary too.
141
+ const title = header.replace(/^\[!([\w-]+)\]/, (_, marker) => `[!${marker.toLowerCase()}]`);
142
+ result.calloutTitle = normalize(parse(title, document.dialect, document.path).tree);
143
+ }
144
+ }
136
145
  for (const [key, value] of Object.entries(node)) {
137
146
  if (key === "position" || key === "data")
138
147
  continue;
@@ -1 +1 @@
1
- {"version":3,"file":"engine.js","sourceRoot":"","sources":["../../src/core/engine.ts"],"names":[],"mappings":"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","sourcesContent":["import { Ajv } from \"ajv\";\nimport type { Nodes } from \"mdast\";\nimport { resolveConfig, setting } from \"../config/resolve.js\";\nimport { parse } from \"../syntax/parse.js\";\nimport { styleRules } from \"../rules/style.js\";\nimport { dialectRules } from \"../rules/dialects.js\";\nimport { structureRules } from \"../rules/structure.js\";\nimport { linkRules } from \"../rules/links.js\";\nimport { suppressions } from \"./directives.js\";\nimport type {\n Diagnostic,\n Document,\n Edit,\n Finding,\n FormatResult,\n Plugin,\n ProcessOptions,\n ResolvedConfig,\n Rule,\n Workspace,\n} from \"./types.js\";\n\nexport const builtInRules: Record<string, Rule> = {\n ...styleRules,\n ...dialectRules,\n ...linkRules,\n ...structureRules,\n};\nexport function ruleRegistry(plugins: Plugin[] = []): Record<string, Rule> {\n const rules = { ...builtInRules };\n const names = new Set<string>();\n for (const plugin of plugins) {\n if (!/^[a-z][a-z\\d-]*$/.test(plugin.name) || names.has(plugin.name))\n throw new Error(`Invalid or duplicate plugin name: ${plugin.name}`);\n names.add(plugin.name);\n for (const [name, rule] of Object.entries(plugin.rules ?? {})) {\n const id = `${plugin.name}/${name}`;\n if (rules[id]) throw new Error(`Duplicate rule: ${id}`);\n rules[id] = rule;\n }\n }\n return rules;\n}\nconst ruleValidator = new Ajv({ allErrors: true });\nconst builtInSchemas = new Set(Object.values(builtInRules).map((rule) => rule.schema));\nfunction prepare(options: ProcessOptions) {\n const config = resolveConfig(options.config, options.path, options.plugins);\n const rules = ruleRegistry(options.plugins);\n let pluginValidator: Ajv | undefined;\n for (const [name, value] of Object.entries(config.rules)) {\n const rule = rules[name];\n if (!rule) throw new Error(`Unknown rule: ${name}`);\n const enabled = setting(value);\n if (rule.schema && enabled.severity !== \"off\") {\n // Plugin schema IDs are scoped to this call; distinct plugin instances\n // may legitimately reuse the same ID with different schemas.\n const validator = builtInSchemas.has(rule.schema)\n ? ruleValidator\n : (pluginValidator ??= new Ajv({ allErrors: true }));\n const validate = validator.compile(rule.schema);\n if (!validate(enabled.options))\n throw new Error(`Invalid options for ${name}: ${validator.errorsText(validate.errors)}`);\n }\n }\n return { config, rules };\n}\nfunction diagnostic(\n source: string,\n rule: string,\n severity: \"warn\" | \"error\",\n finding: Finding,\n): Diagnostic {\n const prefix = source.slice(0, finding.start);\n return {\n ...finding,\n rule,\n severity,\n line: prefix.split(\"\\n\").length,\n column: finding.start - prefix.lastIndexOf(\"\\n\"),\n };\n}\nfunction inspect(\n document: Document,\n config: ResolvedConfig,\n rules: Record<string, Rule>,\n workspace?: Workspace,\n phase?: string,\n): Diagnostic[] {\n const result: Diagnostic[] = [];\n const suppressed = suppressions(document);\n for (const [name, value] of Object.entries(config.rules)) {\n const enabled = setting(value);\n const rule = rules[name]!;\n if (\n enabled.severity === \"off\" ||\n (phase && (rule.kind !== \"style\" || (rule.phase ?? \"inline\") !== phase))\n )\n continue;\n const findings = rule.check({\n document,\n options: enabled.options,\n ...(workspace ? { workspace } : {}),\n });\n for (const finding of findings)\n if (!suppressed(name, finding))\n result.push(diagnostic(document.source, name, enabled.severity, finding));\n }\n return result.sort((a, b) => a.start - b.start || a.rule.localeCompare(b.rule));\n}\nexport function lint(source: string, options: ProcessOptions = {}): Diagnostic[] {\n const { config, rules } = prepare(options);\n const document = parse(source, config.dialect, options.path, options.plugins);\n return inspect(document, config, rules, options.workspace);\n}\nexport function applyEdits(source: string, edits: Edit[]): string {\n const sorted = [...edits].sort((a, b) => a.start - b.start || a.end - b.end);\n let previous: Edit | undefined;\n const accepted: Edit[] = [];\n for (const edit of sorted) {\n if (\n !Number.isInteger(edit.start) ||\n !Number.isInteger(edit.end) ||\n edit.start < 0 ||\n edit.end < edit.start ||\n edit.end > source.length\n )\n throw new Error(\"Rule returned an invalid edit range.\");\n if (\n previous &&\n edit.start === previous.start &&\n edit.end === previous.end &&\n edit.text === previous.text\n )\n continue;\n if (previous && (edit.start < previous.end || edit.start === previous.start))\n throw new Error(\n \"Enabled rules proposed overlapping edits; disable one of the conflicting rules.\",\n );\n accepted.push(edit);\n previous = edit;\n }\n let output = source;\n for (const edit of accepted.reverse())\n output = output.slice(0, edit.start) + edit.text + output.slice(edit.end);\n return output;\n}\n/** Compare semantic trees, with link identity supplied by the selected renderer's resolver. */\nexport function semanticFingerprint(document: Document, workspace?: Workspace): string {\n const canonicalUrl = (url: string, wiki = false) => {\n const resolution = workspace?.resolve(document.path, url, document.dialect, wiki);\n return resolution?.status === \"resolved\"\n ? `${resolution.target}#${resolution.fragment ?? \"\"}`\n : url;\n };\n function normalize(node: Nodes, calloutHeader = false): unknown {\n if (node.type === \"wikiLink\") {\n if (node.embed)\n return { type: \"embed\", url: canonicalUrl(node.target ?? \"\", true), label: node.label };\n return {\n type: \"link\",\n url: canonicalUrl(node.target ?? \"\", true),\n title: null,\n children: [{ type: \"text\", value: node.label ?? node.target }],\n };\n }\n const result: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(node)) {\n if (key === \"position\" || key === \"data\") continue;\n if (key === \"children\" && \"children\" in node) {\n result.children = node.children.map((child, index) =>\n normalize(child, index === 0 && (node.type === \"blockquote\" || calloutHeader)),\n );\n } else if (key === \"url\" && typeof value === \"string\") result[key] = canonicalUrl(value);\n else if (key === \"value\" && node.type === \"text\") {\n let text = node.value.replace(/[ \\t\\r\\n]+/g, \" \");\n if (calloutHeader && document.dialect !== \"commonmark\")\n text = text.replace(\n /^\\[!([\\w-]+)\\]/,\n (_, marker: string) => `[!${marker.toLowerCase()}]`,\n );\n result[key] = text;\n } else if (key === \"value\" && node.type === \"inlineCode\")\n result[key] = node.value.replace(/\\r\\n|\\r|\\n/g, \" \");\n else result[key] = value;\n }\n return result;\n }\n return JSON.stringify(normalize(document.tree), (_key, value: unknown) => {\n if (value && typeof value === \"object\" && !Array.isArray(value))\n return Object.fromEntries(Object.entries(value).sort(([a], [b]) => a.localeCompare(b)));\n return value;\n });\n}\nexport function format(source: string, options: ProcessOptions = {}): FormatResult {\n const { config, rules } = prepare(options);\n let output = source;\n let document = parse(source, config.dialect, options.path, options.plugins);\n const fingerprint = semanticFingerprint(document, options.workspace);\n const seen = new Set([source]);\n try {\n for (let pass = 0; pass < 8; pass++) {\n const before = output;\n for (const phase of [\"inline\", \"block\", \"document\"]) {\n const edits = inspect(document, config, rules, options.workspace, phase).flatMap((item) =>\n item.edit ? [item.edit] : [],\n );\n if (!edits.length) continue;\n const candidate = applyEdits(output, edits);\n if (candidate === output) continue;\n const candidateDocument = parse(candidate, config.dialect, options.path, options.plugins);\n if (semanticFingerprint(candidateDocument, options.workspace) !== fingerprint)\n throw new Error(\n `Formatting in the ${phase} phase would change parsed meaning; the document was left unchanged.`,\n );\n output = candidate;\n // Rules consume the document without mutating it. Reuse the validated\n // tree until another phase changes its source, including final diagnostics.\n document = candidateDocument;\n }\n if (output === before)\n return {\n output,\n changed: output !== source,\n diagnostics: inspect(document, config, rules, options.workspace),\n };\n if (seen.has(output))\n throw new Error(\"Formatting rules oscillate; the document was left unchanged.\");\n seen.add(output);\n }\n throw new Error(\n \"Formatting did not converge in eight passes; the document was left unchanged.\",\n );\n } catch (error) {\n return {\n output: source,\n changed: false,\n diagnostics: [\n diagnostic(source, \"engine/unsafe-format\", \"error\", {\n start: 0,\n message: error instanceof Error ? error.message : String(error),\n }),\n ],\n };\n }\n}\n"]}
1
+ {"version":3,"file":"engine.js","sourceRoot":"","sources":["../../src/core/engine.ts"],"names":[],"mappings":"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","sourcesContent":["import { Ajv } from \"ajv\";\nimport type { Nodes } from \"mdast\";\nimport { resolveConfig, setting } from \"../config/resolve.js\";\nimport { parse, range } from \"../syntax/parse.js\";\nimport { styleRules } from \"../rules/style.js\";\nimport { dialectRules } from \"../rules/dialects.js\";\nimport { structureRules } from \"../rules/structure.js\";\nimport { linkRules } from \"../rules/links.js\";\nimport { suppressions } from \"./directives.js\";\nimport type {\n Diagnostic,\n Document,\n Edit,\n Finding,\n FormatResult,\n Plugin,\n ProcessOptions,\n ResolvedConfig,\n Rule,\n Workspace,\n} from \"./types.js\";\n\nexport const builtInRules: Record<string, Rule> = {\n ...styleRules,\n ...dialectRules,\n ...linkRules,\n ...structureRules,\n};\nexport function ruleRegistry(plugins: Plugin[] = []): Record<string, Rule> {\n const rules = { ...builtInRules };\n const names = new Set<string>();\n for (const plugin of plugins) {\n if (!/^[a-z][a-z\\d-]*$/.test(plugin.name) || names.has(plugin.name))\n throw new Error(`Invalid or duplicate plugin name: ${plugin.name}`);\n names.add(plugin.name);\n for (const [name, rule] of Object.entries(plugin.rules ?? {})) {\n const id = `${plugin.name}/${name}`;\n if (rules[id]) throw new Error(`Duplicate rule: ${id}`);\n rules[id] = rule;\n }\n }\n return rules;\n}\nconst ruleValidator = new Ajv({ allErrors: true });\nconst builtInSchemas = new Set(Object.values(builtInRules).map((rule) => rule.schema));\nfunction prepare(options: ProcessOptions) {\n const config = resolveConfig(options.config, options.path, options.plugins);\n const rules = ruleRegistry(options.plugins);\n let pluginValidator: Ajv | undefined;\n for (const [name, value] of Object.entries(config.rules)) {\n const rule = rules[name];\n if (!rule) throw new Error(`Unknown rule: ${name}`);\n const enabled = setting(value);\n if (rule.schema && enabled.severity !== \"off\") {\n // Plugin schema IDs are scoped to this call; distinct plugin instances\n // may legitimately reuse the same ID with different schemas.\n const validator = builtInSchemas.has(rule.schema)\n ? ruleValidator\n : (pluginValidator ??= new Ajv({ allErrors: true }));\n const validate = validator.compile(rule.schema);\n if (!validate(enabled.options))\n throw new Error(`Invalid options for ${name}: ${validator.errorsText(validate.errors)}`);\n }\n }\n return { config, rules };\n}\nfunction diagnostic(\n source: string,\n rule: string,\n severity: \"warn\" | \"error\",\n finding: Finding,\n): Diagnostic {\n const prefix = source.slice(0, finding.start);\n return {\n ...finding,\n rule,\n severity,\n line: prefix.split(\"\\n\").length,\n column: finding.start - prefix.lastIndexOf(\"\\n\"),\n };\n}\nfunction inspect(\n document: Document,\n config: ResolvedConfig,\n rules: Record<string, Rule>,\n workspace?: Workspace,\n phase?: string,\n): Diagnostic[] {\n const result: Diagnostic[] = [];\n const suppressed = suppressions(document);\n for (const [name, value] of Object.entries(config.rules)) {\n const enabled = setting(value);\n const rule = rules[name]!;\n if (\n enabled.severity === \"off\" ||\n (phase && (rule.kind !== \"style\" || (rule.phase ?? \"inline\") !== phase))\n )\n continue;\n const findings = rule.check({\n document,\n options: enabled.options,\n ...(workspace ? { workspace } : {}),\n });\n for (const finding of findings)\n if (!suppressed(name, finding))\n result.push(diagnostic(document.source, name, enabled.severity, finding));\n }\n return result.sort((a, b) => a.start - b.start || a.rule.localeCompare(b.rule));\n}\nexport function lint(source: string, options: ProcessOptions = {}): Diagnostic[] {\n const { config, rules } = prepare(options);\n const document = parse(source, config.dialect, options.path, options.plugins);\n return inspect(document, config, rules, options.workspace);\n}\nexport function applyEdits(source: string, edits: Edit[]): string {\n const sorted = [...edits].sort((a, b) => a.start - b.start || a.end - b.end);\n let previous: Edit | undefined;\n const accepted: Edit[] = [];\n for (const edit of sorted) {\n if (\n !Number.isInteger(edit.start) ||\n !Number.isInteger(edit.end) ||\n edit.start < 0 ||\n edit.end < edit.start ||\n edit.end > source.length\n )\n throw new Error(\"Rule returned an invalid edit range.\");\n if (\n previous &&\n edit.start === previous.start &&\n edit.end === previous.end &&\n edit.text === previous.text\n )\n continue;\n if (previous && (edit.start < previous.end || edit.start === previous.start))\n throw new Error(\n \"Enabled rules proposed overlapping edits; disable one of the conflicting rules.\",\n );\n accepted.push(edit);\n previous = edit;\n }\n let output = source;\n for (const edit of accepted.reverse())\n output = output.slice(0, edit.start) + edit.text + output.slice(edit.end);\n return output;\n}\n/** Compare semantic trees, with link identity supplied by the selected renderer's resolver. */\nexport function semanticFingerprint(document: Document, workspace?: Workspace): string {\n const canonicalUrl = (url: string, wiki = false) => {\n const resolution = workspace?.resolve(document.path, url, document.dialect, wiki);\n return resolution?.status === \"resolved\"\n ? `${resolution.target}#${resolution.fragment ?? \"\"}`\n : url;\n };\n function normalize(node: Nodes, calloutHeader = false): unknown {\n if (node.type === \"wikiLink\") {\n if (node.embed)\n return { type: \"embed\", url: canonicalUrl(node.target ?? \"\", true), label: node.label };\n return {\n type: \"link\",\n url: canonicalUrl(node.target ?? \"\", true),\n title: null,\n children: [{ type: \"text\", value: node.label ?? node.target }],\n };\n }\n const result: Record<string, unknown> = {};\n if (calloutHeader && document.dialect === \"obsidian\" && node.type === \"paragraph\") {\n const [start, end] = range(node);\n const header = document.source.slice(start, end).split(/\\r?\\n/, 1)[0]!;\n if (/^\\[![\\w-]+\\]/.test(header)) {\n // CommonMark merges title and body into one paragraph. Preserve their boundary too.\n const title = header.replace(\n /^\\[!([\\w-]+)\\]/,\n (_, marker: string) => `[!${marker.toLowerCase()}]`,\n );\n result.calloutTitle = normalize(parse(title, document.dialect, document.path).tree);\n }\n }\n for (const [key, value] of Object.entries(node)) {\n if (key === \"position\" || key === \"data\") continue;\n if (key === \"children\" && \"children\" in node) {\n result.children = node.children.map((child, index) =>\n normalize(child, index === 0 && (node.type === \"blockquote\" || calloutHeader)),\n );\n } else if (key === \"url\" && typeof value === \"string\") result[key] = canonicalUrl(value);\n else if (key === \"value\" && node.type === \"text\") {\n let text = node.value.replace(/[ \\t\\r\\n]+/g, \" \");\n if (calloutHeader && document.dialect !== \"commonmark\")\n text = text.replace(\n /^\\[!([\\w-]+)\\]/,\n (_, marker: string) => `[!${marker.toLowerCase()}]`,\n );\n result[key] = text;\n } else if (key === \"value\" && node.type === \"inlineCode\")\n result[key] = node.value.replace(/\\r\\n|\\r|\\n/g, \" \");\n else result[key] = value;\n }\n return result;\n }\n return JSON.stringify(normalize(document.tree), (_key, value: unknown) => {\n if (value && typeof value === \"object\" && !Array.isArray(value))\n return Object.fromEntries(Object.entries(value).sort(([a], [b]) => a.localeCompare(b)));\n return value;\n });\n}\nexport function format(source: string, options: ProcessOptions = {}): FormatResult {\n const { config, rules } = prepare(options);\n let output = source;\n let document = parse(source, config.dialect, options.path, options.plugins);\n const fingerprint = semanticFingerprint(document, options.workspace);\n const seen = new Set([source]);\n try {\n for (let pass = 0; pass < 8; pass++) {\n const before = output;\n for (const phase of [\"inline\", \"block\", \"document\"]) {\n const edits = inspect(document, config, rules, options.workspace, phase).flatMap((item) =>\n item.edit ? [item.edit] : [],\n );\n if (!edits.length) continue;\n const candidate = applyEdits(output, edits);\n if (candidate === output) continue;\n const candidateDocument = parse(candidate, config.dialect, options.path, options.plugins);\n if (semanticFingerprint(candidateDocument, options.workspace) !== fingerprint)\n throw new Error(\n `Formatting in the ${phase} phase would change parsed meaning; the document was left unchanged.`,\n );\n output = candidate;\n // Rules consume the document without mutating it. Reuse the validated\n // tree until another phase changes its source, including final diagnostics.\n document = candidateDocument;\n }\n if (output === before)\n return {\n output,\n changed: output !== source,\n diagnostics: inspect(document, config, rules, options.workspace),\n };\n if (seen.has(output))\n throw new Error(\"Formatting rules oscillate; the document was left unchanged.\");\n seen.add(output);\n }\n throw new Error(\n \"Formatting did not converge in eight passes; the document was left unchanged.\",\n );\n } catch (error) {\n return {\n output: source,\n changed: false,\n diagnostics: [\n diagnostic(source, \"engine/unsafe-format\", \"error\", {\n start: 0,\n message: error instanceof Error ? error.message : String(error),\n }),\n ],\n };\n }\n}\n"]}
@@ -81,12 +81,46 @@ const wrap = {
81
81
  const width = Number(options.width ?? 80);
82
82
  const measure = options.measure === "codepoints" ? (text) => [...text].length : stringWidth;
83
83
  const unit = options.measure === "codepoints" ? "code points" : "columns";
84
- visit(document.tree, "paragraph", (node) => {
85
- const [start, end] = range(node);
86
- const original = document.source.slice(start, end);
84
+ visit(document.tree, "paragraph", (node, index, parent) => {
85
+ const [paragraphStart, end] = range(node);
86
+ let start = paragraphStart;
87
+ let original = document.source.slice(start, end);
88
+ let children = node.children;
89
+ let calloutHeader = document.dialect === "obsidian" &&
90
+ parent?.type === "blockquote" &&
91
+ index === 0 &&
92
+ /^\[![\w-]+\]/.test(original);
87
93
  const lineStart = document.source.lastIndexOf("\n", start - 1) + 1;
88
- const prefix = document.source.slice(lineStart, start);
94
+ let prefix = document.source.slice(lineStart, start);
89
95
  const continuation = prefix.replace(/(?:[-+*]|\d+[.)]|\[[xX ]\])(?=\s)/g, (value) => " ".repeat(value.length));
96
+ if (calloutHeader) {
97
+ const newline = original.indexOf("\n");
98
+ const headerEnd = newline < 0 ? end : start + newline;
99
+ const header = document.source.slice(start, headerEnd).replace(/\r$/, "");
100
+ const bodyStart = headerEnd + 1 + continuation.length;
101
+ const bodyLines = newline < 0 ? [] : original.slice(newline + 1).split(/\r?\n/);
102
+ const supported = bodyLines.every((line) => line.startsWith(continuation)) &&
103
+ !children.some((child) => {
104
+ const [a, b] = range(child);
105
+ return child.type !== "text" && a < bodyStart && b > bodyStart;
106
+ });
107
+ // Keep unusual continuations and inline syntax spanning the boundary untouched.
108
+ if (supported) {
109
+ if (options.reportUnbreakable === true && measure(prefix + header) > width)
110
+ findings.push({
111
+ start,
112
+ end: start + header.length,
113
+ message: `Paragraph exceeds ${width} ${unit} because of an unbreakable atom.`,
114
+ });
115
+ if (newline < 0)
116
+ return;
117
+ start = bodyStart;
118
+ original = document.source.slice(start, end);
119
+ children = children.filter((child) => range(child)[1] > start);
120
+ prefix = continuation;
121
+ calloutHeader = false;
122
+ }
123
+ }
90
124
  const reportUnbreakable = () => findings.push({
91
125
  start,
92
126
  end,
@@ -107,12 +141,18 @@ const wrap = {
107
141
  ? continuation
108
142
  : (content.match(/^[ \t>]+/)?.[0] ?? "");
109
143
  const linePrefix = offset === start ? prefix : container;
144
+ // An Obsidian title occupies one physical line, even when it contains spaces.
145
+ if (calloutHeader && offset === start) {
146
+ if (measure(prefix + content) > width)
147
+ unbreakable = true;
148
+ offset += line.length;
149
+ continue;
150
+ }
110
151
  const words = [];
111
- while (childIndex < node.children.length &&
112
- range(node.children[childIndex])[1] <= offset)
152
+ while (childIndex < children.length && range(children[childIndex])[1] <= offset)
113
153
  childIndex++;
114
- for (let i = childIndex; i < node.children.length; i++) {
115
- const child = node.children[i];
154
+ for (let i = childIndex; i < children.length; i++) {
155
+ const child = children[i];
116
156
  const [a, b] = range(child);
117
157
  if (a >= offset + content.length)
118
158
  break;
@@ -142,9 +182,9 @@ const wrap = {
142
182
  if (options.reportUnbreakable === true && unbreakable)
143
183
  reportUnbreakable();
144
184
  };
145
- const reason = node.children.some((child) => child.type === "break")
185
+ const reason = children.some((child) => child.type === "break")
146
186
  ? "hard line break"
147
- : node.children.some((child) => child.type === "html")
187
+ : children.some((child) => child.type === "html")
148
188
  ? "inline HTML"
149
189
  : /^\[![^\]]+\]/.test(original)
150
190
  ? "callout header"
@@ -159,9 +199,9 @@ const wrap = {
159
199
  }
160
200
  const words = [];
161
201
  let unsupported = false;
162
- for (const child of node.children) {
202
+ for (const child of children) {
163
203
  const [a, b] = range(child);
164
- const raw = document.source.slice(a, b);
204
+ const raw = document.source.slice(Math.max(a, start), b);
165
205
  const lines = raw.split(/\r?\n/);
166
206
  for (let i = 1; i < lines.length; i++) {
167
207
  const line = lines[i];
@@ -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\n// Whitespace inside an inline node is protected; only text-node whitespace can wrap.\nfunction wrappingAtoms(words: string[]): string[] {\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 // Keep syntax-like markers with the preceding atom to preserve paragraph meaning.\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 return atoms;\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 continuation = prefix.replace(/(?:[-+*]|\\d+[.)]|\\[[xX ]\\])(?=\\s)/g, (value) =>\n \" \".repeat(value.length),\n );\n const reportUnbreakable = () =>\n findings.push({\n start,\n end,\n message: `Paragraph exceeds ${width} ${unit} because of an unbreakable atom.`,\n });\n const reportSkipped = (reason: string) => {\n if (options.reportUnreflowed !== true && options.reportUnbreakable !== true) return;\n let breakable = false;\n let unbreakable = false;\n let offset = start;\n let childIndex = 0;\n for (const line of original.split(/(?<=\\n)/)) {\n const content = line.replace(/\\r?\\n$/, \"\");\n const container =\n offset === start\n ? \"\"\n : continuation && content.startsWith(continuation)\n ? continuation\n : (content.match(/^[ \\t>]+/)?.[0] ?? \"\");\n const linePrefix = offset === start ? prefix : container;\n const words: string[] = [];\n while (\n childIndex < node.children.length &&\n range(node.children[childIndex]!)[1] <= offset\n )\n childIndex++;\n for (let i = childIndex; i < node.children.length; i++) {\n const child = node.children[i]!;\n const [a, b] = range(child);\n if (a >= offset + content.length) break;\n if (child.type === \"break\") continue;\n const raw = document.source.slice(\n Math.max(a, offset + container.length),\n Math.min(b, offset + content.length),\n );\n if (!raw) continue;\n words.push(...(child.type === \"text\" ? raw.split(/([ \\t]+)/).filter(Boolean) : [raw]));\n }\n const atoms = wrappingAtoms(words);\n const available = width - measure(linePrefix);\n if (measure(words.join(\"\").trimEnd()) > available) {\n if (atoms.length > 1) breakable = true;\n if (atoms.some((atom) => measure(atom) > available)) unbreakable = true;\n }\n offset += line.length;\n }\n if (options.reportUnreflowed === true && breakable)\n findings.push({\n start,\n end,\n message: `Paragraph not reflowed: ${reason} (width ${width} ${unit}).`,\n });\n if (options.reportUnbreakable === true && unbreakable) reportUnbreakable();\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 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 const atoms = wrappingAtoms(words);\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 reportUnbreakable();\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"]}
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\n// Whitespace inside an inline node is protected; only text-node whitespace can wrap.\nfunction wrappingAtoms(words: string[]): string[] {\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 // Keep syntax-like markers with the preceding atom to preserve paragraph meaning.\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 return atoms;\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, index, parent) => {\n const [paragraphStart, end] = range(node);\n let start = paragraphStart;\n let original = document.source.slice(start, end);\n let children = node.children;\n let calloutHeader =\n document.dialect === \"obsidian\" &&\n parent?.type === \"blockquote\" &&\n index === 0 &&\n /^\\[![\\w-]+\\]/.test(original);\n const lineStart = document.source.lastIndexOf(\"\\n\", start - 1) + 1;\n let prefix = document.source.slice(lineStart, start);\n const continuation = prefix.replace(/(?:[-+*]|\\d+[.)]|\\[[xX ]\\])(?=\\s)/g, (value) =>\n \" \".repeat(value.length),\n );\n if (calloutHeader) {\n const newline = original.indexOf(\"\\n\");\n const headerEnd = newline < 0 ? end : start + newline;\n const header = document.source.slice(start, headerEnd).replace(/\\r$/, \"\");\n const bodyStart = headerEnd + 1 + continuation.length;\n const bodyLines = newline < 0 ? [] : original.slice(newline + 1).split(/\\r?\\n/);\n const supported =\n bodyLines.every((line) => line.startsWith(continuation)) &&\n !children.some((child) => {\n const [a, b] = range(child);\n return child.type !== \"text\" && a < bodyStart && b > bodyStart;\n });\n // Keep unusual continuations and inline syntax spanning the boundary untouched.\n if (supported) {\n if (options.reportUnbreakable === true && measure(prefix + header) > width)\n findings.push({\n start,\n end: start + header.length,\n message: `Paragraph exceeds ${width} ${unit} because of an unbreakable atom.`,\n });\n if (newline < 0) return;\n start = bodyStart;\n original = document.source.slice(start, end);\n children = children.filter((child) => range(child)[1] > start);\n prefix = continuation;\n calloutHeader = false;\n }\n }\n const reportUnbreakable = () =>\n findings.push({\n start,\n end,\n message: `Paragraph exceeds ${width} ${unit} because of an unbreakable atom.`,\n });\n const reportSkipped = (reason: string) => {\n if (options.reportUnreflowed !== true && options.reportUnbreakable !== true) return;\n let breakable = false;\n let unbreakable = false;\n let offset = start;\n let childIndex = 0;\n for (const line of original.split(/(?<=\\n)/)) {\n const content = line.replace(/\\r?\\n$/, \"\");\n const container =\n offset === start\n ? \"\"\n : continuation && content.startsWith(continuation)\n ? continuation\n : (content.match(/^[ \\t>]+/)?.[0] ?? \"\");\n const linePrefix = offset === start ? prefix : container;\n // An Obsidian title occupies one physical line, even when it contains spaces.\n if (calloutHeader && offset === start) {\n if (measure(prefix + content) > width) unbreakable = true;\n offset += line.length;\n continue;\n }\n const words: string[] = [];\n while (childIndex < children.length && range(children[childIndex]!)[1] <= offset)\n childIndex++;\n for (let i = childIndex; i < children.length; i++) {\n const child = children[i]!;\n const [a, b] = range(child);\n if (a >= offset + content.length) break;\n if (child.type === \"break\") continue;\n const raw = document.source.slice(\n Math.max(a, offset + container.length),\n Math.min(b, offset + content.length),\n );\n if (!raw) continue;\n words.push(...(child.type === \"text\" ? raw.split(/([ \\t]+)/).filter(Boolean) : [raw]));\n }\n const atoms = wrappingAtoms(words);\n const available = width - measure(linePrefix);\n if (measure(words.join(\"\").trimEnd()) > available) {\n if (atoms.length > 1) breakable = true;\n if (atoms.some((atom) => measure(atom) > available)) unbreakable = true;\n }\n offset += line.length;\n }\n if (options.reportUnreflowed === true && breakable)\n findings.push({\n start,\n end,\n message: `Paragraph not reflowed: ${reason} (width ${width} ${unit}).`,\n });\n if (options.reportUnbreakable === true && unbreakable) reportUnbreakable();\n };\n const reason = children.some((child) => child.type === \"break\")\n ? \"hard line break\"\n : 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 words: string[] = [];\n let unsupported = false;\n for (const child of children) {\n const [a, b] = range(child);\n const raw = document.source.slice(Math.max(a, start), 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 const atoms = wrappingAtoms(words);\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 reportUnbreakable();\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"]}
@@ -108,6 +108,9 @@ Whitespace inside a link, code span, or other protected inline node is not a
108
108
  wrapping opportunity. A protected paragraph with both breakable prose and an
109
109
  over-width atom can report both causes; an atom-only overflow does not trigger
110
110
  `reportUnreflowed`. Hard-break markers are excluded from protected-line width.
111
+ An Obsidian callout title is one indivisible physical line: an over-width title
112
+ follows `reportUnbreakable`, even when it contains spaces. Body prose is
113
+ classified separately. A block ID does not make its whole paragraph indivisible.
111
114
  Both options default to false, propose no edits, and use the rule's severity.
112
115
  Use severity `error` or `--max-warnings 0` to make these diagnostics fail a
113
116
  check; `--check` does not change rule settings.
package/docs/design.md CHANGED
@@ -32,11 +32,13 @@ preservation. Tests use synthetic documents, deterministic property checks, and
32
32
  filesystem/CLI integration cases, including the list-collapse failure that
33
33
  motivated replacing heuristic reflow.
34
34
 
35
- Obsidian callout headers remain intact; their body paragraphs can reflow when
36
- supported. Highlight, comment, math, code, HTML, and front-matter contents are
37
- preserved. Standalone Obsidian comment blocks may span blank lines. Inline
38
- comments spanning multiple paragraphs are not fully modeled; suppress formatting
39
- around those constructs or use standalone comment blocks.
35
+ Obsidian callout headers remain intact; supported body prose can reflow directly
36
+ below the header or in later paragraphs. The semantic fingerprint also protects
37
+ the title/body boundary. Lazy quote continuations and inline syntax spanning
38
+ that boundary remain untouched. Highlight, comment, math, code, HTML, and
39
+ front-matter contents are preserved. Standalone Obsidian comment blocks may span
40
+ blank lines. Inline comments spanning multiple paragraphs are not fully modeled;
41
+ suppress formatting around those constructs or use standalone comment blocks.
40
42
 
41
43
  The source-preserving wrapper supports ordinary paragraphs, list items, and
42
44
  blockquote containers. It preserves explicit hard-break paragraphs, lazy/unusual
package/docs/obsidian.md CHANGED
@@ -34,6 +34,18 @@ and never edits the settings file itself.
34
34
  If that setting is not appropriate for your vault, disable `style/wrap`. Other
35
35
  enabled rules can still run.
36
36
 
37
+ ## Wrap callout bodies
38
+
39
+ With strict line breaks verified, `style/wrap` reflows supported body prose even
40
+ when it directly follows the callout header without a blank quote line. The
41
+ header stays on its original physical line, including its title and folding
42
+ marker. Existing quote and list-container prefixes are retained.
43
+
44
+ Hard breaks, block IDs, inline HTML, and unsupported multiline syntax still
45
+ protect body paragraphs. Lazy or inconsistent quote continuations and inline
46
+ syntax spanning the title/body boundary remain untouched. Long headers follow
47
+ `reportUnbreakable`; skipped breakable body prose follows `reportUnreflowed`.
48
+
37
49
  ## Choose link policies deliberately
38
50
 
39
51
  The recommended preset validates local links. To normalize verified destinations
@@ -9,7 +9,7 @@ The CLI requires Node.js 22.12 or newer. Install the package in your document
9
9
  workspace:
10
10
 
11
11
  ```sh
12
- npm install --save-dev --save-exact mdrefine@0.1.0-beta.3
12
+ npm install --save-dev --save-exact mdrefine@0.1.0-beta.4
13
13
  npx --no-install mdtools --help
14
14
  ```
15
15
 
@@ -0,0 +1,50 @@
1
+ # mdrefine 0.1.0-beta.4
2
+
3
+ Fourth public beta of Markdown Tools. npm package: `mdrefine`; executable:
4
+ `mdtools`. Requires Node.js 22.12 or newer. Upgrade with:
5
+
6
+ ```sh
7
+ npm install --save-dev --save-exact mdrefine@0.1.0-beta.4
8
+ ```
9
+
10
+ ## Callout header diagnostics
11
+
12
+ An Obsidian callout title occupies one physical line. Over-width titles now
13
+ follow `style/wrap.reportUnbreakable`, even when they contain spaces, instead of
14
+ triggering `reportUnreflowed`. Body overflow is evaluated separately. A block
15
+ identifier does not make its entire paragraph indivisible; existing atom-aware
16
+ classification for those paragraphs is retained.
17
+
18
+ Fixed in [PR #42](https://github.com/viell-dev/slop-markdown-tools/pull/42),
19
+ resolving [#40](https://github.com/viell-dev/slop-markdown-tools/issues/40).
20
+
21
+ ## Direct callout body wrapping
22
+
23
+ `style/wrap` now reflows supported Obsidian body prose directly below the
24
+ callout header, without requiring or inserting a blank quote line. The header's
25
+ physical line, title, folding marker, and container prefix remain intact. Body
26
+ reflow retains quote and list prefixes, protected inline atoms, and line
27
+ endings.
28
+
29
+ The semantic fingerprint now distinguishes the title from body text, rejecting
30
+ edits that move words across their boundary. Supported inline title formatting
31
+ still works. Hard breaks, block identifiers, inline HTML, unsupported multiline
32
+ syntax, and lazy or inconsistent quote continuations remain conservative cases.
33
+ Inline syntax spanning the title/body boundary is left untouched by wrapping.
34
+
35
+ Implemented in
36
+ [PR #43](https://github.com/viell-dev/slop-markdown-tools/pull/43), resolving
37
+ [#41](https://github.com/viell-dev/slop-markdown-tools/issues/41).
38
+
39
+ ## Compatibility and verification
40
+
41
+ No dependency, public API, configuration-schema, or Node.js minimum changes.
42
+ Existing beta.3 configurations remain valid. Both diagnostic options remain
43
+ false by default and propose no edits. Consumers enabling them may see header
44
+ findings move to `reportUnbreakable`. Obsidian wrapping still requires verified
45
+ `strictLineBreaks: true`; CommonMark and GitHub behavior is unchanged.
46
+
47
+ Regression coverage includes nested callouts, list containers, folding markers,
48
+ LF/CRLF, both diagnostic flags, width modes, inline atoms, protected source,
49
+ rule isolation, semantic preservation, idempotence, unsafe boundary edits, and
50
+ CLI preview/write/check behavior. The API and configuration remain provisional.
package/docs/releases.md CHANGED
@@ -2,16 +2,16 @@
2
2
 
3
3
  ## Versions and availability
4
4
 
5
- These documents cover `mdrefine@0.1.0-beta.3`. The executable is `mdtools`;
5
+ These documents cover `mdrefine@0.1.0-beta.4`. The executable is `mdtools`;
6
6
  prereleases use npm's `beta` channel. Read the
7
- [beta.3 release notes](releases/0.1.0-beta.3.md) for changes and limitations.
8
- Previous releases: [beta.2](releases/0.1.0-beta.2.md) and
9
- [beta.1](releases/0.1.0-beta.1.md).
7
+ [beta.4 release notes](releases/0.1.0-beta.4.md) for changes and limitations.
8
+ Previous releases: [beta.3](releases/0.1.0-beta.3.md),
9
+ [beta.2](releases/0.1.0-beta.2.md), and [beta.1](releases/0.1.0-beta.1.md).
10
10
 
11
11
  The registry is the source of truth for package availability:
12
12
 
13
13
  ```sh
14
- npm view mdrefine@0.1.0-beta.3 version --registry=https://registry.npmjs.org/
14
+ npm view mdrefine@0.1.0-beta.4 version --registry=https://registry.npmjs.org/
15
15
  ```
16
16
 
17
17
  An `E404` means the requested package or version is unavailable. A version in
@@ -32,7 +32,7 @@ Use Node.js 24 and npm 10 or newer from a clean checkout:
32
32
  ```sh
33
33
  npm ci
34
34
  npm run release:prepare
35
- npm publish ./artifacts/mdrefine-0.1.0-beta.3.tgz --dry-run --ignore-scripts --access public --tag beta
35
+ npm publish ./artifacts/mdrefine-0.1.0-beta.4.tgz --dry-run --ignore-scripts --access public --tag beta
36
36
  ```
37
37
 
38
38
  Preparation runs all checks, packs the allowlisted files, installs that exact
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mdrefine",
3
- "version": "0.1.0-beta.3",
3
+ "version": "0.1.0-beta.4",
4
4
  "description": "Configurable Markdown linting and formatting for CommonMark, GitHub, and Obsidian",
5
5
  "type": "module",
6
6
  "license": "MIT",