mdrefine 0.2.1 → 0.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,5 @@
1
1
  import stringWidth from "string-width";
2
- import { frontMatterReading, range, startsWithMarker, unclosedFrontMatter, } from "../syntax/parse.js";
2
+ import { belowTomlFrontMatter, frontMatterReading, joinsTomlFrontMatter, range, startsWithMarker, unclosedFrontMatter, } from "../syntax/parse.js";
3
3
  import { walk } from "../syntax/walk.js";
4
4
  /** A JSON Schema for an options object with these properties and no others. */
5
5
  function schema(properties) {
@@ -101,6 +101,28 @@ export function takesLines(node) {
101
101
  }
102
102
  return unclosed(node) && (node.type === "obsidianComment" || !quoted);
103
103
  }
104
+ /**
105
+ * Whether a blank line added directly below `node`, at its own level, would be
106
+ * read by renderers as part of a fenced code block that ends a list item in
107
+ * `node` and has no closing fence. Such a block runs to the end of the item,
108
+ * and renderers count the item's last blank lines as its content, while the
109
+ * parser does not (issue #350). A block quote ends at a blank line, and so
110
+ * does the code in it.
111
+ */
112
+ export function endsInOpenFence(source, node) {
113
+ let item = false;
114
+ while (containers.has(node.type) && "children" in node && node.children.length) {
115
+ if (node.type === "blockquote")
116
+ return false;
117
+ if (node.type === "listItem")
118
+ item = true;
119
+ node = node.children.at(-1);
120
+ }
121
+ if (!item || node.type !== "code" || !located(node))
122
+ return false;
123
+ const fence = codeFence(source, node);
124
+ return fence !== undefined && !fence.close;
125
+ }
104
126
  /**
105
127
  * Whether a line ending added at the end of the document would change its
106
128
  * last block. Besides the blocks of `takesLines`, the parser counts a last
@@ -290,6 +312,12 @@ const thematicBreak = {
290
312
  lineStart(source, start) === start &&
291
313
  unclosedFrontMatter(source) === "---")
292
314
  return;
315
+ // Renderers without TOML front matter read its lines as a paragraph,
316
+ // which a line of `---` directly below underlines as a heading, as one
317
+ // written there already does (issue #333).
318
+ if ((marker === "---" && belowTomlFrontMatter(document.tree, node)) ||
319
+ joinsTomlFrontMatter(document.tree, node))
320
+ return;
293
321
  // On the line of list items whose markers are the new marker's character,
294
322
  // the items and the break would become one thematic break, as `- ---`,
295
323
  // `1. - ---`, and `* ***` are.
@@ -299,10 +327,11 @@ const thematicBreak = {
299
327
  return;
300
328
  if (marker === "---") {
301
329
  // Directly below a paragraph or a link reference definition, `---`
302
- // would underline it as a heading.
330
+ // would underline it as a heading, and so it would display math,
331
+ // which GitHub builds from a paragraph (issue #336).
303
332
  const above = index && parent ? lastBlock(parent.children[index - 1]) : undefined;
304
333
  if (above &&
305
- (above.type === "paragraph" || above.type === "definition") &&
334
+ (above.type === "paragraph" || above.type === "definition" || above.type === "math") &&
306
335
  above.position?.end.line === node.position.start.line - 1)
307
336
  return;
308
337
  }
@@ -1 +1 @@
1
- {"version":3,"file":"blocks.js","sourceRoot":"","sources":["../../src/rules/blocks.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Code, Heading, Nodes } from \"mdast\";\nimport stringWidth from \"string-width\";\nimport type { Document, Edit, Finding, Rule } from \"../core/types.js\";\nimport {\n frontMatterReading,\n range,\n startsWithMarker,\n unclosedFrontMatter,\n} from \"../syntax/parse.js\";\nimport { walk } from \"../syntax/walk.js\";\n\n/** A JSON Schema for an options object with these properties and no others. */\nfunction schema(properties: Record<string, unknown>) {\n return { type: \"object\", properties, additionalProperties: false };\n}\n/** Any CommonMark line ending, including a lone carriage return. */\nconst lineBreak = /\\r\\n|\\r|\\n/;\nfunction lineStart(source: string, at: number): number {\n while (at > 0 && source[at - 1] !== \"\\n\" && source[at - 1] !== \"\\r\") at--;\n return at;\n}\nfunction lineEnd(source: string, at: number): number {\n while (at < source.length && source[at] !== \"\\n\" && source[at] !== \"\\r\") at++;\n return at;\n}\n/** A physical line: where it starts, where its content ends, and where the next line starts. */\ninterface Line {\n start: number;\n end: number;\n next: number;\n}\nfunction physicalLines(source: string): Line[] {\n const lines: Line[] = [];\n let start = 0;\n for (const match of source.matchAll(/\\r\\n|\\r|\\n/g)) {\n lines.push({ start, end: match.index, next: match.index + match[0].length });\n start = match.index + match[0].length;\n }\n if (start < source.length) lines.push({ start, end: source.length, next: source.length });\n return lines;\n}\n/** Whether the parser gave a node, perhaps one of a plugin's syntax, a source position. */\nfunction located(node: Nodes): boolean {\n return node.position?.start.offset !== undefined && node.position.end.offset !== undefined;\n}\n/** Blocks whose lines hold other blocks, and blank lines between them. */\nconst containers = new Set([\"root\", \"blockquote\", \"list\", \"listItem\", \"footnoteDefinition\"]);\n/** Sort ranges and merge those that overlap or touch. */\nfunction merged(ranges: [number, number][]): [number, number][] {\n const result: [number, number][] = [];\n for (const [start, end] of ranges.filter(([a, b]) => a < b).sort((x, y) => x[0] - y[0])) {\n const last = result.at(-1);\n if (last && start <= last[1]) last[1] = Math.max(last[1], end);\n else result.push([start, end]);\n }\n return result;\n}\n\n/**\n * HTML blocks that end only at an end marker, by what starts them, with the\n * markers that end them, in lowercase, and the offset from which they are\n * searched: CommonMark's kinds 1 to 5. The other kinds end at a blank line.\n * These are CommonMark's markers, not HTML's: a comment's block ends only at\n * `-->`, not at `--!>`.\n */\nconst htmlEnds: [RegExp, string[], number][] = [\n [\n /^<(?:pre|script|style|textarea)(?:[\\t\\n\\r >]|$)/i,\n [\"</pre>\", \"</script>\", \"</style>\", \"</textarea>\"],\n 1,\n ],\n [/^<!--/, [\"-->\"], 2],\n [/^<\\?/, [\"?>\"], 1],\n [/^<!\\[CDATA\\[/, [\"]]>\"], 9],\n [/^<![A-Za-z]/, [\">\"], 2],\n];\n/**\n * Whether a block is an HTML block of a kind that ends only at its end marker,\n * or an Obsidian comment, and lacks that marker. Such a block runs to the end\n * of its container and takes in every line ending and blank line up to there.\n */\nfunction unclosed(node: Nodes): boolean {\n if (node.type === \"obsidianComment\") return node.value.indexOf(\"%%\", 2) < 0;\n if (node.type !== \"html\") return false;\n // The value keeps the block's indentation.\n const value = node.value.replace(/^[ \\t]+/, \"\");\n for (const [opening, ends, from] of htmlEnds) {\n if (!opening.test(value)) continue;\n const rest = value.slice(from).toLowerCase();\n return !ends.some((end) => rest.includes(end));\n }\n return false;\n}\n/**\n * Whether a line added directly below `node`, at its own level, would become\n * part of an HTML block or Obsidian comment that `node` ends with and that has\n * no end marker. The parser lets such an HTML block run on through the blank\n * lines of a list item or footnote, and through a final line ending, but a\n * block quote ends it. An Obsidian comment runs on to the end of the document,\n * whatever contains it.\n */\nexport function takesLines(node: Nodes): boolean {\n let quoted = false;\n while (containers.has(node.type) && \"children\" in node && node.children.length) {\n if (node.type === \"blockquote\") quoted = true;\n node = node.children.at(-1)!;\n }\n return unclosed(node) && (node.type === \"obsidianComment\" || !quoted);\n}\n/**\n * Whether a line ending added at the end of the document would change its\n * last block. Besides the blocks of `takesLines`, the parser counts a last\n * line of blank space in a code or math block that has no closing fence only\n * when a line ending follows it.\n */\nexport function takesFinalLineEnding(document: Document): boolean {\n if (takesLines(document.tree)) return true;\n if (!/(?:^|[\\r\\n])[ \\t]+$/.test(document.source)) return false;\n const last = lastBlock(document.tree);\n if ((last.type !== \"code\" && last.type !== \"math\") || !located(last)) return false;\n const fence = codeFence(document.source, last);\n return fence !== undefined && !fence.close;\n}\n\n/**\n * Whether `style/heading` writes headings of levels 1 and 2 underlined: with\n * `setext`, or with `consistent` when the document's first heading is.\n */\nexport function underlinedHeadings(document: Document, style: unknown): boolean {\n if (style !== \"consistent\") return style === \"setext\";\n let first: Heading | undefined;\n walk(document.tree, \"heading\", (node) => {\n if (!first && located(node)) first = node;\n });\n return first !== undefined && /[\\r\\n]/.test(document.source.slice(...range(first)));\n}\n/**\n * The start of a line that would not begin a paragraph after a blank line: a\n * list item, heading, block quote, thematic break, fence, HTML, math, or\n * Obsidian comment, a link reference definition, or a table row, which `---`\n * below it could make a table.\n */\nconst notParagraph =\n /^(?:[-+*](?:[ \\t]|$)|\\d{1,9}[.)](?:[ \\t]|$)|#{1,6}(?:[ \\t]|$)|>|([-*_])[ \\t]*(?:\\1[ \\t]*){2,}$|`{3,}|~{3,}|<|\\$\\$|%%|\\[[^]*\\]:)|\\|/;\n/**\n * The edit that writes the `#` heading `node`, of level 1 or 2, underlined\n * with `===` or `---`, or undefined where its text could not stand on a line\n * of its own as the same heading. Only headings at the start of a line of the\n * document itself, below a blank line or at the start, are underlined:\n * directly below text, the heading's line would continue a paragraph. On\n * Forgejo and Gitea, a heading with a `{` keeps its form, because their\n * attribute blocks depend on it.\n */\nexport function underlineEdit(document: Document, node: Heading): Edit | undefined {\n const { source } = document;\n const first = node.children[0];\n const last = node.children.at(-1);\n if (node.depth > 2 || !first || !last || !located(first) || !located(last)) return undefined;\n const [start] = range(node);\n if (lineStart(source, start) !== start) return undefined;\n if (start > 0) {\n const above = lineStart(source, start - (source.startsWith(\"\\r\\n\", start - 2) ? 2 : 1));\n if (!/^[ \\t]*$/.test(source.slice(above, lineEnd(source, above)))) return undefined;\n }\n const text = source.slice(range(first)[0], range(last)[1]);\n if (notParagraph.test(text) || text.endsWith(\"\\\\\")) return undefined;\n if ((document.dialect === \"forgejo\" || document.dialect === \"gitea\") && text.includes(\"{\"))\n return undefined;\n // Forgejo and Gitea open a definition or display math with these.\n if (/^(?::[ \\t]|\\\\\\[)/.test(text)) return undefined;\n const newline = /\\r\\n|\\r|\\n/.exec(source)?.[0] ?? \"\\n\";\n // Below a first line of `---` that opens no front matter, an underline of\n // `---` alone would close it (issue #278).\n const shortest = node.depth === 2 && unclosedFrontMatter(source) === \"---\" ? 4 : 3;\n const underline = (node.depth === 1 ? \"=\" : \"-\").repeat(Math.max(shortest, stringWidth(text)));\n return { start, end: lineEnd(source, start), text: `${text}${newline}${underline}` };\n}\n\n/** The fences of a fenced code or math block: the marker runs, as source ranges. */\ninterface Fence {\n marker: \"`\" | \"~\" | \"$\";\n open: [number, number];\n /** Absent when the block runs to the end of its container without a closing fence. */\n close?: [number, number];\n}\n/** The fences of a code or math block, or undefined for an indented code block. */\nfunction codeFence(\n source: string,\n node: Code | Extract<Nodes, { type: \"math\" }>,\n): Fence | undefined {\n const [start, end] = range(node);\n // A fenced block starts at its fence; an indented one at its indentation.\n const opening = /^(?:`{3,}|~{3,}|\\${2,})/.exec(source.slice(start, lineEnd(source, start)));\n if (!opening) return undefined;\n const marker = opening[0][0] as Fence[\"marker\"];\n const fence: Fence = { marker, open: [start, start + opening[0].length] };\n // The block's lines are the opening fence, the content, and the closing\n // fence if there is one. An empty value is no line or one blank line, and a\n // closing fence is never blank.\n const lines = source.slice(start, end).split(lineBreak);\n const last = lines.at(-1)!;\n const closing = new RegExp(\n `(?:${marker === \"$\" ? \"\\\\$\" : marker}){${opening[0].length},}(?=[ \\\\t]*$)`,\n ).exec(last);\n const content = node.value === \"\" ? undefined : node.value.split(lineBreak).length;\n if (closing && lines.length > 1 && (content === undefined || lines.length === content + 2)) {\n const at = end - last.length + closing.index;\n fence.close = [at, at + closing[0].length];\n }\n return fence;\n}\n\nconst codeFenceRule: Rule = {\n description: \"Write code fences with one marker and the length their content needs.\",\n kind: \"style\",\n phase: \"block\",\n schema: schema({ marker: { enum: [\"```\", \"~~~\", \"consistent\"] } }),\n check({ document, options }) {\n const { source } = document;\n const fences: { node: Code; fence: Fence }[] = [];\n walk(document.tree, \"code\", (node) => {\n const fence = located(node) ? codeFence(source, node) : undefined;\n if (fence) fences.push({ node, fence });\n });\n // `consistent` takes the marker of the first fence in the document.\n const marker =\n options.marker === \"~~~\"\n ? \"~\"\n : options.marker === \"consistent\"\n ? (fences[0]?.fence.marker ?? \"`\")\n : \"`\";\n const findings: Finding[] = [];\n for (const { node, fence } of fences) {\n // The info string of a backtick fence cannot contain a backtick.\n if (\n marker === \"`\" &&\n source.slice(fence.open[1], lineEnd(source, fence.open[1])).includes(\"`\")\n )\n continue;\n // A content line of the marker alone, at any indentation, could close a\n // fence that is not longer than it.\n let longest = 0;\n for (const line of node.value.split(lineBreak)) {\n const run = /^[ \\t]*(`+|~+)[ \\t]*$/.exec(line)?.[1];\n if (run?.[0] === marker) longest = Math.max(longest, run.length);\n }\n const text = marker.repeat(Math.max(3, longest + 1));\n for (const [start, end] of fence.close ? [fence.open, fence.close] : [fence.open])\n if (source.slice(start, end) !== text)\n findings.push({\n start,\n end,\n message: `Use ${text} for the code fence.`,\n edit: { start, end, text },\n });\n }\n return findings;\n },\n};\n\n/** The innermost last block of a container, where its text ends. */\nfunction lastBlock(node: Nodes): Nodes {\n while (containers.has(node.type) && \"children\" in node && node.children.length)\n node = node.children.at(-1)!;\n return node;\n}\nconst thematicBreak: Rule = {\n description: \"Write thematic breaks with one marker.\",\n kind: \"style\",\n phase: \"block\",\n schema: schema({ marker: { enum: [\"---\", \"***\", \"___\", \"consistent\"] } }),\n check({ document, options }) {\n const { source } = document;\n let marker = typeof options.marker === \"string\" ? options.marker : \"---\";\n // `consistent` takes the character of the first thematic break in the document.\n if (marker === \"consistent\") {\n let first: string | undefined;\n walk(document.tree, \"thematicBreak\", (node) => {\n if (first === undefined && located(node)) first = source[range(node)[0]];\n });\n marker = (first ?? \"-\").repeat(3);\n }\n const findings: Finding[] = [];\n walk(document.tree, \"thematicBreak\", (node, index, parent) => {\n if (!located(node)) return;\n const [start, last] = range(node);\n // The break's range includes blank space after its markers.\n const end = start + source.slice(start, last).replace(/[ \\t]+$/, \"\").length;\n if (source.slice(start, end) === marker) return;\n // At the start of the document, a break written `---` would open front\n // matter if a later line closed it, as a line of `---` alone does, also\n // one that this rule writes. A first-line `---` that the parser reads as a\n // break and site generators as front matter stays (issue #295).\n if (\n start === 0 &&\n (marker === \"---\" || (source.startsWith(\"---\") && frontMatterReading(document.tree)))\n )\n return;\n // Below a first line of `---` that opens no front matter, a line of `---`\n // alone would close it (issue #278).\n if (\n marker === \"---\" &&\n lineStart(source, start) === start &&\n unclosedFrontMatter(source) === \"---\"\n )\n return;\n // On the line of list items whose markers are the new marker's character,\n // the items and the break would become one thematic break, as `- ---`,\n // `1. - ---`, and `* ***` are.\n const items = new RegExp(`[ \\\\t${marker[0] === \"-\" ? \"\\\\-\" : marker[0]}]*$`);\n const prefix = source.slice(lineStart(source, start), start);\n if (items.exec(prefix)![0].includes(marker[0]!)) return;\n if (marker === \"---\") {\n // Directly below a paragraph or a link reference definition, `---`\n // would underline it as a heading.\n const above = index && parent ? lastBlock(parent.children[index - 1]!) : undefined;\n if (\n above &&\n (above.type === \"paragraph\" || above.type === \"definition\") &&\n above.position?.end.line === node.position!.start.line - 1\n )\n return;\n }\n findings.push({\n start,\n end,\n message: `Write the thematic break as ${marker}.`,\n edit: { start, end, text: marker },\n });\n });\n return findings;\n },\n};\n\n/** Where blank lines are content, or their number counts, as source ranges. */\nfunction contentBlocks(document: Document): [number, number][] {\n const blocks: [number, number][] = [];\n walk(document.tree, (node, _, parent) => {\n if (!located(node)) return;\n if (parent && containers.has(parent.type) && !containers.has(node.type))\n blocks.push(range(node));\n // In a block quote, a list, list item, or footnote can extend over the\n // blank lines below its last block. The parser then reads a list as loose,\n // or a list item as tight, by how many there are.\n const last =\n node.type === \"list\" || node.type === \"listItem\" || node.type === \"footnoteDefinition\"\n ? node.children.at(-1)\n : undefined;\n if (last && located(last) && range(last)[1] < range(node)[1])\n blocks.push([range(last)[1], range(node)[1]]);\n });\n return merged(blocks);\n}\nconst blankLines: Rule = {\n description: \"Limit blank lines in a row and remove those around the document.\",\n kind: \"style\",\n phase: \"document\",\n // Fewer than one blank line would join the blocks that it separates.\n schema: schema({ maximum: { type: \"integer\", minimum: 1 } }),\n check({ document, options }) {\n const { source } = document;\n const maximum = typeof options.maximum === \"number\" ? options.maximum : 1;\n const lines = physicalLines(source);\n const text = (line: Line) => source.slice(line.start, line.end);\n const empty = (line: Line) => /^[ \\t]*$/.test(text(line));\n // A line of blank space and block quote markers is blank inside its quotes.\n const blank = (line: Line) => /^[ \\t>]*$/.test(text(line));\n const blocks = contentBlocks(document);\n let block = 0;\n /** Whether a line lies inside a block that began above it; asked in document order. */\n const inside = (line: Line) => {\n while (block < blocks.length && blocks[block]![1] < line.end) block++;\n return block < blocks.length && blocks[block]![0] < line.start;\n };\n const findings: Finding[] = [];\n const remove = (from: number, to: number, message: string) =>\n findings.push({ start: from, end: to, message, edit: { start: from, end: to, text: \"\" } });\n let first = 0;\n while (first < lines.length && empty(lines[first]!)) first++;\n if (first === lines.length) {\n if (source) remove(0, source.length, \"Remove the blank lines.\");\n return findings;\n }\n let last = lines.length;\n // A block without its end, such as an unclosed fence, takes in the blank lines at the end.\n const inBlock = lines.map((line) => blank(line) && inside(line));\n while (empty(lines[last - 1]!) && !inBlock[last - 1]) last--;\n // Below blank lines, `---` or `+++` on the first line would open front matter.\n if (first > 0 && !/^(?:-{3}|\\+{3})/.test(text(lines[first]!)))\n remove(0, lines[first]!.start, \"Remove the blank lines at the start of the document.\");\n // Blank lines in a row with the same block quote markers and indentation\n // are one separation, however many there are.\n const trimmed = (line: Line) => text(line).replace(/[ \\t]+$/, \"\");\n const message =\n maximum === 1\n ? \"Remove the repeated blank line.\"\n : `Remove the blank lines beyond ${maximum} in a row.`;\n for (let index = first; index < last;) {\n const line = lines[index]!;\n let end = index + 1;\n if (blank(line) && !inBlock[index])\n while (\n end < last &&\n blank(lines[end]!) &&\n !inBlock[end] &&\n trimmed(lines[end]!) === trimmed(line)\n )\n end++;\n if (end - index > maximum)\n remove(lines[index + maximum]!.start, lines[end - 1]!.next, message);\n index = end;\n }\n if (last < lines.length)\n remove(\n lines[last]!.start,\n source.length,\n \"Remove the blank lines at the end of the document.\",\n );\n return findings;\n },\n};\n\n/** Nodes whose source between the lines of their text is ordinary prose. */\nconst prose = new Set([\n ...containers,\n \"paragraph\",\n \"heading\",\n \"thematicBreak\",\n \"table\",\n \"tableRow\",\n \"tableCell\",\n \"text\",\n \"emphasis\",\n \"strong\",\n \"delete\",\n]);\nconst trailingSpace: Rule = {\n description: \"Remove spaces and tabs at the end of lines outside code and HTML.\",\n kind: \"style\",\n phase: \"document\",\n schema: schema({ hardBreak: { enum: [\"keep\", \"backslash\"] } }),\n check({ document, options }) {\n const { source } = document;\n if (!/[ \\t](?:\\r|\\n|$)/.test(source)) return [];\n const backslash = options.hardBreak === \"backslash\";\n const forge = document.dialect === \"forgejo\" || document.dialect === \"gitea\";\n /** Source in which blank space at the end of a line is content. */\n const kept: [number, number][] = [];\n /**\n * Hard line breaks, with the paragraph or heading each one is in, and\n * whether that block starts like an alert's or callout's marker, `[!`.\n */\n const breaks: { start: number; end: number; block: [number, number]; marker: boolean }[] = [];\n const links: [number, number][] = [];\n let block: [number, number] = [0, 0];\n let marker = false;\n walk(document.tree, (node, _, parent) => {\n if (!located(node)) {\n // A plugin's node without a position keeps whatever its parent spans.\n if (parent && located(parent)) kept.push(range(parent));\n return;\n }\n const [start, end] = range(node);\n if (node.type === \"paragraph\" || node.type === \"heading\") {\n block = [start, end];\n const written = source.slice(start, end);\n marker =\n node.type === \"paragraph\"\n ? startsWithMarker(written, node, /^\\[!/)\n : written.startsWith(\"[!\");\n }\n if (node.type === \"link\") links.push([start, end]);\n if (node.type === \"break\") breaks.push({ start, end, block, marker });\n else if (node.type === \"link\" || node.type === \"linkReference\") {\n // The link text is prose; a title or label that spans lines is not.\n let at = start;\n for (const child of node.children) {\n if (!located(child)) continue;\n kept.push([at, range(child)[0]]);\n at = range(child)[1];\n }\n kept.push([at, end]);\n } else if (node.type === \"code\") {\n const fence = codeFence(source, node);\n // A fence line ends in syntax, unless an info string's text runs to its end.\n const from = fence && !node.meta ? lineEnd(source, start) : start;\n kept.push([from, fence?.close ? lineStart(source, fence.close[0]) : end]);\n } else if (!prose.has(node.type)) kept.push([start, end]);\n });\n const ranges = merged(kept);\n let next = 0;\n let following = 0;\n let link = 0;\n /**\n * Whether a backslash in place of the blank space of a hard line break,\n * which starts at `start`, would mean the same. One after another\n * backslash would be escaped. A literal autolink such as `www.example.com`\n * runs on to the next blank space, so it would take the backslash in. A\n * paragraph that starts like `[label]:` could become a link reference\n * definition with the backslash as its destination, and the title line of\n * an alert or callout, also one written as `\\[!NOTE]`, would end with it.\n * On Forgejo and Gitea, a backslash inside `\\(...\\)` math would be part of\n * the formula.\n */\n const backslashSafe = (start: number, paragraph: [number, number], marker: boolean) => {\n if (source[start - 1] === \"\\\\\") return false;\n let word = start;\n while (word > paragraph[0] && !/[ \\t\\r\\n]/.test(source[word - 1]!)) word--;\n while (link < links.length && links[link]![1] <= word) link++;\n if (link < links.length && links[link]![0] < start) return false;\n const before = source.slice(paragraph[0], start);\n if (/^\\[[^]*\\]:/.test(before) || (marker && !/[\\r\\n]/.test(before))) return false;\n return !(forge && source.slice(...paragraph).includes(\"\\\\(\"));\n };\n const findings: Finding[] = [];\n for (const line of physicalLines(source)) {\n const space = /[ \\t]+$/.exec(source.slice(line.start, line.end));\n if (!space) continue;\n const start = line.start + space.index;\n const end = line.end;\n while (next < ranges.length && ranges[next]![1] <= start) next++;\n if (next < ranges.length && ranges[next]![0] < end) continue;\n // Breaks are in document order, as lines are.\n while (following < breaks.length && breaks[following]!.end <= start) following++;\n const hard = breaks[following]?.start !== undefined && breaks[following]!.start < end;\n if (!hard) {\n findings.push({\n start,\n end,\n message: \"Remove the spaces and tabs at the end of the line.\",\n edit: { start, end, text: \"\" },\n });\n continue;\n }\n const brk = breaks[following]!;\n if (!backslash || brk.start !== start || !backslashSafe(start, brk.block, brk.marker))\n continue;\n findings.push({\n start,\n end,\n message: \"Write the hard line break as a backslash.\",\n edit: { start, end, text: \"\\\\\" },\n });\n }\n return findings;\n },\n};\n\nexport const blockRules: Record<string, Rule> = {\n \"style/blank-lines\": blankLines,\n \"style/code-fence\": codeFenceRule,\n \"style/thematic-break\": thematicBreak,\n \"style/trailing-space\": trailingSpace,\n};\n"]}
1
+ {"version":3,"file":"blocks.js","sourceRoot":"","sources":["../../src/rules/blocks.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Code, Heading, Nodes } from \"mdast\";\nimport stringWidth from \"string-width\";\nimport type { Document, Edit, Finding, Rule } from \"../core/types.js\";\nimport {\n belowTomlFrontMatter,\n frontMatterReading,\n joinsTomlFrontMatter,\n range,\n startsWithMarker,\n unclosedFrontMatter,\n} from \"../syntax/parse.js\";\nimport { walk } from \"../syntax/walk.js\";\n\n/** A JSON Schema for an options object with these properties and no others. */\nfunction schema(properties: Record<string, unknown>) {\n return { type: \"object\", properties, additionalProperties: false };\n}\n/** Any CommonMark line ending, including a lone carriage return. */\nconst lineBreak = /\\r\\n|\\r|\\n/;\nfunction lineStart(source: string, at: number): number {\n while (at > 0 && source[at - 1] !== \"\\n\" && source[at - 1] !== \"\\r\") at--;\n return at;\n}\nfunction lineEnd(source: string, at: number): number {\n while (at < source.length && source[at] !== \"\\n\" && source[at] !== \"\\r\") at++;\n return at;\n}\n/** A physical line: where it starts, where its content ends, and where the next line starts. */\ninterface Line {\n start: number;\n end: number;\n next: number;\n}\nfunction physicalLines(source: string): Line[] {\n const lines: Line[] = [];\n let start = 0;\n for (const match of source.matchAll(/\\r\\n|\\r|\\n/g)) {\n lines.push({ start, end: match.index, next: match.index + match[0].length });\n start = match.index + match[0].length;\n }\n if (start < source.length) lines.push({ start, end: source.length, next: source.length });\n return lines;\n}\n/** Whether the parser gave a node, perhaps one of a plugin's syntax, a source position. */\nfunction located(node: Nodes): boolean {\n return node.position?.start.offset !== undefined && node.position.end.offset !== undefined;\n}\n/** Blocks whose lines hold other blocks, and blank lines between them. */\nconst containers = new Set([\"root\", \"blockquote\", \"list\", \"listItem\", \"footnoteDefinition\"]);\n/** Sort ranges and merge those that overlap or touch. */\nfunction merged(ranges: [number, number][]): [number, number][] {\n const result: [number, number][] = [];\n for (const [start, end] of ranges.filter(([a, b]) => a < b).sort((x, y) => x[0] - y[0])) {\n const last = result.at(-1);\n if (last && start <= last[1]) last[1] = Math.max(last[1], end);\n else result.push([start, end]);\n }\n return result;\n}\n\n/**\n * HTML blocks that end only at an end marker, by what starts them, with the\n * markers that end them, in lowercase, and the offset from which they are\n * searched: CommonMark's kinds 1 to 5. The other kinds end at a blank line.\n * These are CommonMark's markers, not HTML's: a comment's block ends only at\n * `-->`, not at `--!>`.\n */\nconst htmlEnds: [RegExp, string[], number][] = [\n [\n /^<(?:pre|script|style|textarea)(?:[\\t\\n\\r >]|$)/i,\n [\"</pre>\", \"</script>\", \"</style>\", \"</textarea>\"],\n 1,\n ],\n [/^<!--/, [\"-->\"], 2],\n [/^<\\?/, [\"?>\"], 1],\n [/^<!\\[CDATA\\[/, [\"]]>\"], 9],\n [/^<![A-Za-z]/, [\">\"], 2],\n];\n/**\n * Whether a block is an HTML block of a kind that ends only at its end marker,\n * or an Obsidian comment, and lacks that marker. Such a block runs to the end\n * of its container and takes in every line ending and blank line up to there.\n */\nfunction unclosed(node: Nodes): boolean {\n if (node.type === \"obsidianComment\") return node.value.indexOf(\"%%\", 2) < 0;\n if (node.type !== \"html\") return false;\n // The value keeps the block's indentation.\n const value = node.value.replace(/^[ \\t]+/, \"\");\n for (const [opening, ends, from] of htmlEnds) {\n if (!opening.test(value)) continue;\n const rest = value.slice(from).toLowerCase();\n return !ends.some((end) => rest.includes(end));\n }\n return false;\n}\n/**\n * Whether a line added directly below `node`, at its own level, would become\n * part of an HTML block or Obsidian comment that `node` ends with and that has\n * no end marker. The parser lets such an HTML block run on through the blank\n * lines of a list item or footnote, and through a final line ending, but a\n * block quote ends it. An Obsidian comment runs on to the end of the document,\n * whatever contains it.\n */\nexport function takesLines(node: Nodes): boolean {\n let quoted = false;\n while (containers.has(node.type) && \"children\" in node && node.children.length) {\n if (node.type === \"blockquote\") quoted = true;\n node = node.children.at(-1)!;\n }\n return unclosed(node) && (node.type === \"obsidianComment\" || !quoted);\n}\n/**\n * Whether a blank line added directly below `node`, at its own level, would be\n * read by renderers as part of a fenced code block that ends a list item in\n * `node` and has no closing fence. Such a block runs to the end of the item,\n * and renderers count the item's last blank lines as its content, while the\n * parser does not (issue #350). A block quote ends at a blank line, and so\n * does the code in it.\n */\nexport function endsInOpenFence(source: string, node: Nodes): boolean {\n let item = false;\n while (containers.has(node.type) && \"children\" in node && node.children.length) {\n if (node.type === \"blockquote\") return false;\n if (node.type === \"listItem\") item = true;\n node = node.children.at(-1)!;\n }\n if (!item || node.type !== \"code\" || !located(node)) return false;\n const fence = codeFence(source, node);\n return fence !== undefined && !fence.close;\n}\n/**\n * Whether a line ending added at the end of the document would change its\n * last block. Besides the blocks of `takesLines`, the parser counts a last\n * line of blank space in a code or math block that has no closing fence only\n * when a line ending follows it.\n */\nexport function takesFinalLineEnding(document: Document): boolean {\n if (takesLines(document.tree)) return true;\n if (!/(?:^|[\\r\\n])[ \\t]+$/.test(document.source)) return false;\n const last = lastBlock(document.tree);\n if ((last.type !== \"code\" && last.type !== \"math\") || !located(last)) return false;\n const fence = codeFence(document.source, last);\n return fence !== undefined && !fence.close;\n}\n\n/**\n * Whether `style/heading` writes headings of levels 1 and 2 underlined: with\n * `setext`, or with `consistent` when the document's first heading is.\n */\nexport function underlinedHeadings(document: Document, style: unknown): boolean {\n if (style !== \"consistent\") return style === \"setext\";\n let first: Heading | undefined;\n walk(document.tree, \"heading\", (node) => {\n if (!first && located(node)) first = node;\n });\n return first !== undefined && /[\\r\\n]/.test(document.source.slice(...range(first)));\n}\n/**\n * The start of a line that would not begin a paragraph after a blank line: a\n * list item, heading, block quote, thematic break, fence, HTML, math, or\n * Obsidian comment, a link reference definition, or a table row, which `---`\n * below it could make a table.\n */\nconst notParagraph =\n /^(?:[-+*](?:[ \\t]|$)|\\d{1,9}[.)](?:[ \\t]|$)|#{1,6}(?:[ \\t]|$)|>|([-*_])[ \\t]*(?:\\1[ \\t]*){2,}$|`{3,}|~{3,}|<|\\$\\$|%%|\\[[^]*\\]:)|\\|/;\n/**\n * The edit that writes the `#` heading `node`, of level 1 or 2, underlined\n * with `===` or `---`, or undefined where its text could not stand on a line\n * of its own as the same heading. Only headings at the start of a line of the\n * document itself, below a blank line or at the start, are underlined:\n * directly below text, the heading's line would continue a paragraph. On\n * Forgejo and Gitea, a heading with a `{` keeps its form, because their\n * attribute blocks depend on it.\n */\nexport function underlineEdit(document: Document, node: Heading): Edit | undefined {\n const { source } = document;\n const first = node.children[0];\n const last = node.children.at(-1);\n if (node.depth > 2 || !first || !last || !located(first) || !located(last)) return undefined;\n const [start] = range(node);\n if (lineStart(source, start) !== start) return undefined;\n if (start > 0) {\n const above = lineStart(source, start - (source.startsWith(\"\\r\\n\", start - 2) ? 2 : 1));\n if (!/^[ \\t]*$/.test(source.slice(above, lineEnd(source, above)))) return undefined;\n }\n const text = source.slice(range(first)[0], range(last)[1]);\n if (notParagraph.test(text) || text.endsWith(\"\\\\\")) return undefined;\n if ((document.dialect === \"forgejo\" || document.dialect === \"gitea\") && text.includes(\"{\"))\n return undefined;\n // Forgejo and Gitea open a definition or display math with these.\n if (/^(?::[ \\t]|\\\\\\[)/.test(text)) return undefined;\n const newline = /\\r\\n|\\r|\\n/.exec(source)?.[0] ?? \"\\n\";\n // Below a first line of `---` that opens no front matter, an underline of\n // `---` alone would close it (issue #278).\n const shortest = node.depth === 2 && unclosedFrontMatter(source) === \"---\" ? 4 : 3;\n const underline = (node.depth === 1 ? \"=\" : \"-\").repeat(Math.max(shortest, stringWidth(text)));\n return { start, end: lineEnd(source, start), text: `${text}${newline}${underline}` };\n}\n\n/** The fences of a fenced code or math block: the marker runs, as source ranges. */\ninterface Fence {\n marker: \"`\" | \"~\" | \"$\";\n open: [number, number];\n /** Absent when the block runs to the end of its container without a closing fence. */\n close?: [number, number];\n}\n/** The fences of a code or math block, or undefined for an indented code block. */\nfunction codeFence(\n source: string,\n node: Code | Extract<Nodes, { type: \"math\" }>,\n): Fence | undefined {\n const [start, end] = range(node);\n // A fenced block starts at its fence; an indented one at its indentation.\n const opening = /^(?:`{3,}|~{3,}|\\${2,})/.exec(source.slice(start, lineEnd(source, start)));\n if (!opening) return undefined;\n const marker = opening[0][0] as Fence[\"marker\"];\n const fence: Fence = { marker, open: [start, start + opening[0].length] };\n // The block's lines are the opening fence, the content, and the closing\n // fence if there is one. An empty value is no line or one blank line, and a\n // closing fence is never blank.\n const lines = source.slice(start, end).split(lineBreak);\n const last = lines.at(-1)!;\n const closing = new RegExp(\n `(?:${marker === \"$\" ? \"\\\\$\" : marker}){${opening[0].length},}(?=[ \\\\t]*$)`,\n ).exec(last);\n const content = node.value === \"\" ? undefined : node.value.split(lineBreak).length;\n if (closing && lines.length > 1 && (content === undefined || lines.length === content + 2)) {\n const at = end - last.length + closing.index;\n fence.close = [at, at + closing[0].length];\n }\n return fence;\n}\n\nconst codeFenceRule: Rule = {\n description: \"Write code fences with one marker and the length their content needs.\",\n kind: \"style\",\n phase: \"block\",\n schema: schema({ marker: { enum: [\"```\", \"~~~\", \"consistent\"] } }),\n check({ document, options }) {\n const { source } = document;\n const fences: { node: Code; fence: Fence }[] = [];\n walk(document.tree, \"code\", (node) => {\n const fence = located(node) ? codeFence(source, node) : undefined;\n if (fence) fences.push({ node, fence });\n });\n // `consistent` takes the marker of the first fence in the document.\n const marker =\n options.marker === \"~~~\"\n ? \"~\"\n : options.marker === \"consistent\"\n ? (fences[0]?.fence.marker ?? \"`\")\n : \"`\";\n const findings: Finding[] = [];\n for (const { node, fence } of fences) {\n // The info string of a backtick fence cannot contain a backtick.\n if (\n marker === \"`\" &&\n source.slice(fence.open[1], lineEnd(source, fence.open[1])).includes(\"`\")\n )\n continue;\n // A content line of the marker alone, at any indentation, could close a\n // fence that is not longer than it.\n let longest = 0;\n for (const line of node.value.split(lineBreak)) {\n const run = /^[ \\t]*(`+|~+)[ \\t]*$/.exec(line)?.[1];\n if (run?.[0] === marker) longest = Math.max(longest, run.length);\n }\n const text = marker.repeat(Math.max(3, longest + 1));\n for (const [start, end] of fence.close ? [fence.open, fence.close] : [fence.open])\n if (source.slice(start, end) !== text)\n findings.push({\n start,\n end,\n message: `Use ${text} for the code fence.`,\n edit: { start, end, text },\n });\n }\n return findings;\n },\n};\n\n/** The innermost last block of a container, where its text ends. */\nfunction lastBlock(node: Nodes): Nodes {\n while (containers.has(node.type) && \"children\" in node && node.children.length)\n node = node.children.at(-1)!;\n return node;\n}\nconst thematicBreak: Rule = {\n description: \"Write thematic breaks with one marker.\",\n kind: \"style\",\n phase: \"block\",\n schema: schema({ marker: { enum: [\"---\", \"***\", \"___\", \"consistent\"] } }),\n check({ document, options }) {\n const { source } = document;\n let marker = typeof options.marker === \"string\" ? options.marker : \"---\";\n // `consistent` takes the character of the first thematic break in the document.\n if (marker === \"consistent\") {\n let first: string | undefined;\n walk(document.tree, \"thematicBreak\", (node) => {\n if (first === undefined && located(node)) first = source[range(node)[0]];\n });\n marker = (first ?? \"-\").repeat(3);\n }\n const findings: Finding[] = [];\n walk(document.tree, \"thematicBreak\", (node, index, parent) => {\n if (!located(node)) return;\n const [start, last] = range(node);\n // The break's range includes blank space after its markers.\n const end = start + source.slice(start, last).replace(/[ \\t]+$/, \"\").length;\n if (source.slice(start, end) === marker) return;\n // At the start of the document, a break written `---` would open front\n // matter if a later line closed it, as a line of `---` alone does, also\n // one that this rule writes. A first-line `---` that the parser reads as a\n // break and site generators as front matter stays (issue #295).\n if (\n start === 0 &&\n (marker === \"---\" || (source.startsWith(\"---\") && frontMatterReading(document.tree)))\n )\n return;\n // Below a first line of `---` that opens no front matter, a line of `---`\n // alone would close it (issue #278).\n if (\n marker === \"---\" &&\n lineStart(source, start) === start &&\n unclosedFrontMatter(source) === \"---\"\n )\n return;\n // Renderers without TOML front matter read its lines as a paragraph,\n // which a line of `---` directly below underlines as a heading, as one\n // written there already does (issue #333).\n if (\n (marker === \"---\" && belowTomlFrontMatter(document.tree, node)) ||\n joinsTomlFrontMatter(document.tree, node)\n )\n return;\n // On the line of list items whose markers are the new marker's character,\n // the items and the break would become one thematic break, as `- ---`,\n // `1. - ---`, and `* ***` are.\n const items = new RegExp(`[ \\\\t${marker[0] === \"-\" ? \"\\\\-\" : marker[0]}]*$`);\n const prefix = source.slice(lineStart(source, start), start);\n if (items.exec(prefix)![0].includes(marker[0]!)) return;\n if (marker === \"---\") {\n // Directly below a paragraph or a link reference definition, `---`\n // would underline it as a heading, and so it would display math,\n // which GitHub builds from a paragraph (issue #336).\n const above = index && parent ? lastBlock(parent.children[index - 1]!) : undefined;\n if (\n above &&\n (above.type === \"paragraph\" || above.type === \"definition\" || above.type === \"math\") &&\n above.position?.end.line === node.position!.start.line - 1\n )\n return;\n }\n findings.push({\n start,\n end,\n message: `Write the thematic break as ${marker}.`,\n edit: { start, end, text: marker },\n });\n });\n return findings;\n },\n};\n\n/** Where blank lines are content, or their number counts, as source ranges. */\nfunction contentBlocks(document: Document): [number, number][] {\n const blocks: [number, number][] = [];\n walk(document.tree, (node, _, parent) => {\n if (!located(node)) return;\n if (parent && containers.has(parent.type) && !containers.has(node.type))\n blocks.push(range(node));\n // In a block quote, a list, list item, or footnote can extend over the\n // blank lines below its last block. The parser then reads a list as loose,\n // or a list item as tight, by how many there are.\n const last =\n node.type === \"list\" || node.type === \"listItem\" || node.type === \"footnoteDefinition\"\n ? node.children.at(-1)\n : undefined;\n if (last && located(last) && range(last)[1] < range(node)[1])\n blocks.push([range(last)[1], range(node)[1]]);\n });\n return merged(blocks);\n}\nconst blankLines: Rule = {\n description: \"Limit blank lines in a row and remove those around the document.\",\n kind: \"style\",\n phase: \"document\",\n // Fewer than one blank line would join the blocks that it separates.\n schema: schema({ maximum: { type: \"integer\", minimum: 1 } }),\n check({ document, options }) {\n const { source } = document;\n const maximum = typeof options.maximum === \"number\" ? options.maximum : 1;\n const lines = physicalLines(source);\n const text = (line: Line) => source.slice(line.start, line.end);\n const empty = (line: Line) => /^[ \\t]*$/.test(text(line));\n // A line of blank space and block quote markers is blank inside its quotes.\n const blank = (line: Line) => /^[ \\t>]*$/.test(text(line));\n const blocks = contentBlocks(document);\n let block = 0;\n /** Whether a line lies inside a block that began above it; asked in document order. */\n const inside = (line: Line) => {\n while (block < blocks.length && blocks[block]![1] < line.end) block++;\n return block < blocks.length && blocks[block]![0] < line.start;\n };\n const findings: Finding[] = [];\n const remove = (from: number, to: number, message: string) =>\n findings.push({ start: from, end: to, message, edit: { start: from, end: to, text: \"\" } });\n let first = 0;\n while (first < lines.length && empty(lines[first]!)) first++;\n if (first === lines.length) {\n if (source) remove(0, source.length, \"Remove the blank lines.\");\n return findings;\n }\n let last = lines.length;\n // A block without its end, such as an unclosed fence, takes in the blank lines at the end.\n const inBlock = lines.map((line) => blank(line) && inside(line));\n while (empty(lines[last - 1]!) && !inBlock[last - 1]) last--;\n // Below blank lines, `---` or `+++` on the first line would open front matter.\n if (first > 0 && !/^(?:-{3}|\\+{3})/.test(text(lines[first]!)))\n remove(0, lines[first]!.start, \"Remove the blank lines at the start of the document.\");\n // Blank lines in a row with the same block quote markers and indentation\n // are one separation, however many there are.\n const trimmed = (line: Line) => text(line).replace(/[ \\t]+$/, \"\");\n const message =\n maximum === 1\n ? \"Remove the repeated blank line.\"\n : `Remove the blank lines beyond ${maximum} in a row.`;\n for (let index = first; index < last;) {\n const line = lines[index]!;\n let end = index + 1;\n if (blank(line) && !inBlock[index])\n while (\n end < last &&\n blank(lines[end]!) &&\n !inBlock[end] &&\n trimmed(lines[end]!) === trimmed(line)\n )\n end++;\n if (end - index > maximum)\n remove(lines[index + maximum]!.start, lines[end - 1]!.next, message);\n index = end;\n }\n if (last < lines.length)\n remove(\n lines[last]!.start,\n source.length,\n \"Remove the blank lines at the end of the document.\",\n );\n return findings;\n },\n};\n\n/** Nodes whose source between the lines of their text is ordinary prose. */\nconst prose = new Set([\n ...containers,\n \"paragraph\",\n \"heading\",\n \"thematicBreak\",\n \"table\",\n \"tableRow\",\n \"tableCell\",\n \"text\",\n \"emphasis\",\n \"strong\",\n \"delete\",\n]);\nconst trailingSpace: Rule = {\n description: \"Remove spaces and tabs at the end of lines outside code and HTML.\",\n kind: \"style\",\n phase: \"document\",\n schema: schema({ hardBreak: { enum: [\"keep\", \"backslash\"] } }),\n check({ document, options }) {\n const { source } = document;\n if (!/[ \\t](?:\\r|\\n|$)/.test(source)) return [];\n const backslash = options.hardBreak === \"backslash\";\n const forge = document.dialect === \"forgejo\" || document.dialect === \"gitea\";\n /** Source in which blank space at the end of a line is content. */\n const kept: [number, number][] = [];\n /**\n * Hard line breaks, with the paragraph or heading each one is in, and\n * whether that block starts like an alert's or callout's marker, `[!`.\n */\n const breaks: { start: number; end: number; block: [number, number]; marker: boolean }[] = [];\n const links: [number, number][] = [];\n let block: [number, number] = [0, 0];\n let marker = false;\n walk(document.tree, (node, _, parent) => {\n if (!located(node)) {\n // A plugin's node without a position keeps whatever its parent spans.\n if (parent && located(parent)) kept.push(range(parent));\n return;\n }\n const [start, end] = range(node);\n if (node.type === \"paragraph\" || node.type === \"heading\") {\n block = [start, end];\n const written = source.slice(start, end);\n marker =\n node.type === \"paragraph\"\n ? startsWithMarker(written, node, /^\\[!/)\n : written.startsWith(\"[!\");\n }\n if (node.type === \"link\") links.push([start, end]);\n if (node.type === \"break\") breaks.push({ start, end, block, marker });\n else if (node.type === \"link\" || node.type === \"linkReference\") {\n // The link text is prose; a title or label that spans lines is not.\n let at = start;\n for (const child of node.children) {\n if (!located(child)) continue;\n kept.push([at, range(child)[0]]);\n at = range(child)[1];\n }\n kept.push([at, end]);\n } else if (node.type === \"code\") {\n const fence = codeFence(source, node);\n // A fence line ends in syntax, unless an info string's text runs to its end.\n const from = fence && !node.meta ? lineEnd(source, start) : start;\n kept.push([from, fence?.close ? lineStart(source, fence.close[0]) : end]);\n } else if (!prose.has(node.type)) kept.push([start, end]);\n });\n const ranges = merged(kept);\n let next = 0;\n let following = 0;\n let link = 0;\n /**\n * Whether a backslash in place of the blank space of a hard line break,\n * which starts at `start`, would mean the same. One after another\n * backslash would be escaped. A literal autolink such as `www.example.com`\n * runs on to the next blank space, so it would take the backslash in. A\n * paragraph that starts like `[label]:` could become a link reference\n * definition with the backslash as its destination, and the title line of\n * an alert or callout, also one written as `\\[!NOTE]`, would end with it.\n * On Forgejo and Gitea, a backslash inside `\\(...\\)` math would be part of\n * the formula.\n */\n const backslashSafe = (start: number, paragraph: [number, number], marker: boolean) => {\n if (source[start - 1] === \"\\\\\") return false;\n let word = start;\n while (word > paragraph[0] && !/[ \\t\\r\\n]/.test(source[word - 1]!)) word--;\n while (link < links.length && links[link]![1] <= word) link++;\n if (link < links.length && links[link]![0] < start) return false;\n const before = source.slice(paragraph[0], start);\n if (/^\\[[^]*\\]:/.test(before) || (marker && !/[\\r\\n]/.test(before))) return false;\n return !(forge && source.slice(...paragraph).includes(\"\\\\(\"));\n };\n const findings: Finding[] = [];\n for (const line of physicalLines(source)) {\n const space = /[ \\t]+$/.exec(source.slice(line.start, line.end));\n if (!space) continue;\n const start = line.start + space.index;\n const end = line.end;\n while (next < ranges.length && ranges[next]![1] <= start) next++;\n if (next < ranges.length && ranges[next]![0] < end) continue;\n // Breaks are in document order, as lines are.\n while (following < breaks.length && breaks[following]!.end <= start) following++;\n const hard = breaks[following]?.start !== undefined && breaks[following]!.start < end;\n if (!hard) {\n findings.push({\n start,\n end,\n message: \"Remove the spaces and tabs at the end of the line.\",\n edit: { start, end, text: \"\" },\n });\n continue;\n }\n const brk = breaks[following]!;\n if (!backslash || brk.start !== start || !backslashSafe(start, brk.block, brk.marker))\n continue;\n findings.push({\n start,\n end,\n message: \"Write the hard line break as a backslash.\",\n edit: { start, end, text: \"\\\\\" },\n });\n }\n return findings;\n },\n};\n\nexport const blockRules: Record<string, Rule> = {\n \"style/blank-lines\": blankLines,\n \"style/code-fence\": codeFenceRule,\n \"style/thematic-break\": thematicBreak,\n \"style/trailing-space\": trailingSpace,\n};\n"]}
@@ -17,14 +17,24 @@ function calloutRule(obsidian) {
17
17
  if (obsidian ? document.dialect !== "obsidian" : !githubAlerts.has(document.dialect))
18
18
  return [];
19
19
  const findings = [];
20
- walk(document.tree, "blockquote", (node) => {
20
+ walk(document.tree, "blockquote", (node, _index, parent) => {
21
21
  const child = node.children[0];
22
22
  if (child?.type !== "paragraph")
23
23
  return;
24
- const start = range(child)[0];
24
+ const [start, end] = range(child);
25
25
  const match = /^\[!([\w-]+)\]/.exec(document.source.slice(start));
26
26
  if (!match)
27
27
  return;
28
+ // GitHub shows an alert only in a block quote at the top level, with
29
+ // the marker alone on its first line and content below it; elsewhere
30
+ // the marker is text, whose letters would change (issue #334).
31
+ if (!obsidian) {
32
+ const lineEnd = /\r\n|\r|\n|$/.exec(document.source.slice(start + match[0].length));
33
+ const rest = document.source.slice(start + match[0].length, start + match[0].length + lineEnd.index);
34
+ const below = start + match[0].length + lineEnd.index < end || node.children.length > 1;
35
+ if (parent?.type !== "root" || /[^ \t]/.test(rest) || !below)
36
+ return;
37
+ }
28
38
  const original = match[1];
29
39
  if (!obsidian &&
30
40
  !["NOTE", "TIP", "IMPORTANT", "WARNING", "CAUTION"].includes(original.toUpperCase()))
@@ -1 +1 @@
1
- {"version":3,"file":"dialects.js","sourceRoot":"","sources":["../../src/rules/dialects.ts"],"names":[],"mappings":"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","sourcesContent":["import { walk } from \"../syntax/walk.js\";\nimport type { Dialect, Finding, Rule } from \"../core/types.js\";\nimport { blockIdentifier } from \"../syntax/block-identifier.js\";\nimport { range } from \"../syntax/parse.js\";\nimport { headingAttributeBlock } from \"../workspace/heading-attributes.js\";\nimport { optionsSchema } from \"./style.js\";\n\nconst githubAlerts = new Set<Dialect>([\"github\", \"forgejo\", \"gitea\"]);\nfunction calloutRule(obsidian: boolean): Rule {\n return {\n description: obsidian\n ? \"Use lowercase Obsidian callout types.\"\n : \"Use uppercase GitHub alert types.\",\n kind: \"style\",\n phase: \"inline\",\n schema: optionsSchema({}),\n check({ document }) {\n // Forgejo and Gitea render the same five GitHub alert types, case-insensitively.\n if (obsidian ? document.dialect !== \"obsidian\" : !githubAlerts.has(document.dialect))\n return [];\n const findings: Finding[] = [];\n walk(document.tree, \"blockquote\", (node) => {\n const child = node.children[0];\n if (child?.type !== \"paragraph\") return;\n const start = range(child)[0];\n const match = /^\\[!([\\w-]+)\\]/.exec(document.source.slice(start));\n if (!match) return;\n const original = match[1]!;\n if (\n !obsidian &&\n ![\"NOTE\", \"TIP\", \"IMPORTANT\", \"WARNING\", \"CAUTION\"].includes(original.toUpperCase())\n )\n return;\n const replacement = obsidian ? original.toLowerCase() : original.toUpperCase();\n if (original !== replacement)\n findings.push({\n start: start + 2,\n end: start + 2 + original.length,\n message: `Use ${replacement} for the callout type.`,\n edit: { start: start + 2, end: start + 2 + original.length, text: replacement },\n });\n });\n return findings;\n },\n };\n}\nexport const dialectRules: Record<string, Rule> = {\n \"github/alert-marker\": calloutRule(false),\n \"obsidian/callout-marker\": calloutRule(true),\n \"github/task-marker\": {\n description: \"Use lowercase x in completed task markers.\",\n kind: \"style\",\n phase: \"inline\",\n schema: optionsSchema({}),\n check({ document }) {\n const findings: Finding[] = [];\n walk(document.tree, \"listItem\", (node) => {\n if (node.checked !== true) return;\n const start = range(node)[0];\n const match = /^(?:[-+*]|\\d+[.)])\\s+\\[X\\]/.exec(document.source.slice(start));\n if (!match) return;\n const offset = start + match[0].length - 2;\n findings.push({\n start: offset,\n message: \"Use lowercase x in task markers.\",\n edit: { start: offset, end: offset + 1, text: \"x\" },\n });\n });\n return findings;\n },\n },\n \"obsidian/block-reference\": {\n description: \"Report duplicate block identifiers.\",\n kind: \"problem\",\n schema: optionsSchema({}),\n check({ document }) {\n if (document.dialect !== \"obsidian\") return [];\n const seen = new Set<string>();\n const findings: Finding[] = [];\n walk(document.tree, (node) => {\n const found = blockIdentifier(document.source, node);\n if (!found) return;\n const { id } = found;\n if (seen.has(id))\n findings.push({\n start: range(found.node)[0],\n message: `Duplicate block identifier ^${id}.`,\n });\n seen.add(id);\n });\n return findings;\n },\n },\n \"forgejo/heading-id\": {\n description:\n \"Report heading attribute ids that are not text, which Forgejo and Gitea before 1.26 cannot render.\",\n kind: \"problem\",\n schema: optionsSchema({}),\n check({ document }) {\n if (document.dialect !== \"forgejo\" && document.dialect !== \"gitea\") return [];\n const findings: Finding[] = [];\n const { source } = document;\n walk(document.tree, \"heading\", (node) => {\n const [start, end] = range(node);\n // The block ends an ATX heading's line or the last text line of a\n // Setext heading, whose last line is its underline.\n const breaks = [...source.slice(start, end).matchAll(/\\r\\n?|\\n/g)];\n const underline = breaks.at(-1);\n const previous = breaks.at(-2);\n const lineStart = previous ? start + previous.index + previous[0].length : start;\n let lineEnd = underline ? start + underline.index : end;\n while (source[lineEnd - 1] === \" \" || source[lineEnd - 1] === \"\\t\") lineEnd--;\n let line = source.slice(lineStart, lineEnd);\n let block = headingAttributeBlock(line);\n // Gitea before 1.26 also reads a block followed by a closing `#` sequence.\n if (!block && !underline) {\n const closed = /[ \\t]+#+$/.exec(line);\n if (closed) {\n line = line.slice(0, closed.index);\n block = headingAttributeBlock(line);\n }\n }\n // goldmark hands a number, boolean, null, or list to the renderers,\n // which expect text: Gitea 1.26 and later give the heading an empty\n // id, Forgejo and earlier Gitea versions fail on the whole document.\n if (block?.id === null)\n findings.push({\n start: lineStart + block.start,\n end: lineStart + line.length,\n message:\n 'Heading id is not text: Forgejo, and Gitea before 1.26, cannot render a document containing it. Quote it: {id=\"5\"}.',\n });\n });\n return findings;\n },\n },\n \"obsidian/strict-line-breaks\": {\n description: \"Require verified soft-line-break behavior before reflowing an Obsidian document.\",\n kind: \"problem\",\n schema: optionsSchema({}),\n check({ document, workspace }) {\n return document.dialect === \"obsidian\" && workspace?.strictLineBreaks !== true\n ? [\n {\n start: 0,\n message:\n \"Obsidian's \\\"Strict line breaks\\\" setting is not known to be on, so paragraphs are not reflowed. Turn it on in the vault's settings, which keep it in .obsidian/app.json; a program that calls the library passes strictLineBreaks to createWorkspace.\",\n },\n ]\n : [];\n },\n },\n};\n"]}
1
+ {"version":3,"file":"dialects.js","sourceRoot":"","sources":["../../src/rules/dialects.ts"],"names":[],"mappings":"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","sourcesContent":["import { walk } from \"../syntax/walk.js\";\nimport type { Dialect, Finding, Rule } from \"../core/types.js\";\nimport { blockIdentifier } from \"../syntax/block-identifier.js\";\nimport { range } from \"../syntax/parse.js\";\nimport { headingAttributeBlock } from \"../workspace/heading-attributes.js\";\nimport { optionsSchema } from \"./style.js\";\n\nconst githubAlerts = new Set<Dialect>([\"github\", \"forgejo\", \"gitea\"]);\nfunction calloutRule(obsidian: boolean): Rule {\n return {\n description: obsidian\n ? \"Use lowercase Obsidian callout types.\"\n : \"Use uppercase GitHub alert types.\",\n kind: \"style\",\n phase: \"inline\",\n schema: optionsSchema({}),\n check({ document }) {\n // Forgejo and Gitea render the same five GitHub alert types, case-insensitively.\n if (obsidian ? document.dialect !== \"obsidian\" : !githubAlerts.has(document.dialect))\n return [];\n const findings: Finding[] = [];\n walk(document.tree, \"blockquote\", (node, _index, parent) => {\n const child = node.children[0];\n if (child?.type !== \"paragraph\") return;\n const [start, end] = range(child);\n const match = /^\\[!([\\w-]+)\\]/.exec(document.source.slice(start));\n if (!match) return;\n // GitHub shows an alert only in a block quote at the top level, with\n // the marker alone on its first line and content below it; elsewhere\n // the marker is text, whose letters would change (issue #334).\n if (!obsidian) {\n const lineEnd = /\\r\\n|\\r|\\n|$/.exec(document.source.slice(start + match[0].length))!;\n const rest = document.source.slice(\n start + match[0].length,\n start + match[0].length + lineEnd.index,\n );\n const below = start + match[0].length + lineEnd.index < end || node.children.length > 1;\n if (parent?.type !== \"root\" || /[^ \\t]/.test(rest) || !below) return;\n }\n const original = match[1]!;\n if (\n !obsidian &&\n ![\"NOTE\", \"TIP\", \"IMPORTANT\", \"WARNING\", \"CAUTION\"].includes(original.toUpperCase())\n )\n return;\n const replacement = obsidian ? original.toLowerCase() : original.toUpperCase();\n if (original !== replacement)\n findings.push({\n start: start + 2,\n end: start + 2 + original.length,\n message: `Use ${replacement} for the callout type.`,\n edit: { start: start + 2, end: start + 2 + original.length, text: replacement },\n });\n });\n return findings;\n },\n };\n}\nexport const dialectRules: Record<string, Rule> = {\n \"github/alert-marker\": calloutRule(false),\n \"obsidian/callout-marker\": calloutRule(true),\n \"github/task-marker\": {\n description: \"Use lowercase x in completed task markers.\",\n kind: \"style\",\n phase: \"inline\",\n schema: optionsSchema({}),\n check({ document }) {\n const findings: Finding[] = [];\n walk(document.tree, \"listItem\", (node) => {\n if (node.checked !== true) return;\n const start = range(node)[0];\n const match = /^(?:[-+*]|\\d+[.)])\\s+\\[X\\]/.exec(document.source.slice(start));\n if (!match) return;\n const offset = start + match[0].length - 2;\n findings.push({\n start: offset,\n message: \"Use lowercase x in task markers.\",\n edit: { start: offset, end: offset + 1, text: \"x\" },\n });\n });\n return findings;\n },\n },\n \"obsidian/block-reference\": {\n description: \"Report duplicate block identifiers.\",\n kind: \"problem\",\n schema: optionsSchema({}),\n check({ document }) {\n if (document.dialect !== \"obsidian\") return [];\n const seen = new Set<string>();\n const findings: Finding[] = [];\n walk(document.tree, (node) => {\n const found = blockIdentifier(document.source, node);\n if (!found) return;\n const { id } = found;\n if (seen.has(id))\n findings.push({\n start: range(found.node)[0],\n message: `Duplicate block identifier ^${id}.`,\n });\n seen.add(id);\n });\n return findings;\n },\n },\n \"forgejo/heading-id\": {\n description:\n \"Report heading attribute ids that are not text, which Forgejo and Gitea before 1.26 cannot render.\",\n kind: \"problem\",\n schema: optionsSchema({}),\n check({ document }) {\n if (document.dialect !== \"forgejo\" && document.dialect !== \"gitea\") return [];\n const findings: Finding[] = [];\n const { source } = document;\n walk(document.tree, \"heading\", (node) => {\n const [start, end] = range(node);\n // The block ends an ATX heading's line or the last text line of a\n // Setext heading, whose last line is its underline.\n const breaks = [...source.slice(start, end).matchAll(/\\r\\n?|\\n/g)];\n const underline = breaks.at(-1);\n const previous = breaks.at(-2);\n const lineStart = previous ? start + previous.index + previous[0].length : start;\n let lineEnd = underline ? start + underline.index : end;\n while (source[lineEnd - 1] === \" \" || source[lineEnd - 1] === \"\\t\") lineEnd--;\n let line = source.slice(lineStart, lineEnd);\n let block = headingAttributeBlock(line);\n // Gitea before 1.26 also reads a block followed by a closing `#` sequence.\n if (!block && !underline) {\n const closed = /[ \\t]+#+$/.exec(line);\n if (closed) {\n line = line.slice(0, closed.index);\n block = headingAttributeBlock(line);\n }\n }\n // goldmark hands a number, boolean, null, or list to the renderers,\n // which expect text: Gitea 1.26 and later give the heading an empty\n // id, Forgejo and earlier Gitea versions fail on the whole document.\n if (block?.id === null)\n findings.push({\n start: lineStart + block.start,\n end: lineStart + line.length,\n message:\n 'Heading id is not text: Forgejo, and Gitea before 1.26, cannot render a document containing it. Quote it: {id=\"5\"}.',\n });\n });\n return findings;\n },\n },\n \"obsidian/strict-line-breaks\": {\n description: \"Require verified soft-line-break behavior before reflowing an Obsidian document.\",\n kind: \"problem\",\n schema: optionsSchema({}),\n check({ document, workspace }) {\n return document.dialect === \"obsidian\" && workspace?.strictLineBreaks !== true\n ? [\n {\n start: 0,\n message:\n \"Obsidian's \\\"Strict line breaks\\\" setting is not known to be on, so paragraphs are not reflowed. Turn it on in the vault's settings, which keep it in .obsidian/app.json; a program that calls the library passes strictLineBreaks to createWorkspace.\",\n },\n ]\n : [];\n },\n },\n};\n"]}
@@ -269,6 +269,12 @@ function named(paths) {
269
269
  ? `${paths.slice(0, 3).join(", ")}, and ${paths.length - 3} more`
270
270
  : paths.join(", ");
271
271
  }
272
+ /** The nodes inside table cells, where a `|` that is not escaped ends the cell. */
273
+ function inTableCells(tree) {
274
+ const nodes = new Set();
275
+ walk(tree, "tableCell", (cell) => walk(cell, (child) => nodes.add(child)));
276
+ return nodes;
277
+ }
272
278
  export const linkRules = {
273
279
  "links/valid": {
274
280
  description: "Check local link destinations and dialect-specific heading/block references.",
@@ -333,6 +339,7 @@ export const linkRules = {
333
339
  }),
334
340
  check({ document, options, workspace }) {
335
341
  const findings = [];
342
+ let inCell;
336
343
  walk(document.tree, (node) => {
337
344
  const url = destination(node);
338
345
  if (url === undefined || !workspace)
@@ -414,8 +421,16 @@ export const linkRules = {
414
421
  return;
415
422
  if (!node.embed && node.label === undefined && replacement !== node.target)
416
423
  return;
417
- replacement = `${node.embed ? "!" : ""}[[${replacement}${node.label === undefined ? "" : `|${node.label}`}]]`;
418
- if (replacement !== document.source.slice(start, end))
424
+ // Only the destination changes. The divider stays as written, `|` or
425
+ // `\|`, which a table cell needs, and so do the label and an embed's size.
426
+ const raw = document.source.slice(start, end);
427
+ const open = node.embed ? 3 : 2;
428
+ const divider = raw.indexOf("|", open);
429
+ const targetEnd = divider < 0 ? raw.length - 2 : raw[divider - 1] === "\\" ? divider - 1 : divider;
430
+ if (raw.slice(open, targetEnd) !== node.target)
431
+ return;
432
+ replacement = raw.slice(0, open) + replacement + raw.slice(targetEnd);
433
+ if (replacement !== raw)
419
434
  findings.push({
420
435
  start,
421
436
  end,
@@ -442,6 +457,9 @@ export const linkRules = {
442
457
  .replaceAll(")", "%29")
443
458
  .replaceAll("<", "%3C")
444
459
  .replaceAll(">", "%3E");
460
+ // A file or folder name can hold a `|`, which would end a table cell.
461
+ if (replacement.includes("|") && (inCell ??= inTableCells(document.tree)).has(node))
462
+ replacement = replacement.replaceAll("|", "\\|");
445
463
  if (document.dialect === "gitea" &&
446
464
  (giteaPyLine(document, start, end) || replacement.includes("_.py")) &&
447
465
  giteaUnderscores(original) !== giteaUnderscores(replacement))
@@ -470,8 +488,10 @@ export const linkRules = {
470
488
  if (document.dialect !== "obsidian" || !workspace)
471
489
  return [];
472
490
  const findings = [];
491
+ let inCell;
473
492
  walk(document.tree, (node) => {
474
493
  const [start, end] = range(node);
494
+ const pipe = () => ((inCell ??= inTableCells(document.tree)).has(node) ? "\\|" : "|");
475
495
  let replacement;
476
496
  if (options.style === "markdown" &&
477
497
  node.type === "wikiLink" &&
@@ -479,7 +499,8 @@ export const linkRules = {
479
499
  node.label !== undefined) {
480
500
  if (/[[\]<>\\\r\n]/.test(node.target ?? "") || /[*_`[\]\\]/.test(node.label))
481
501
  return;
482
- replacement = `[${node.label}](<${node.target}>)`;
502
+ const label = node.label.includes("|") ? node.label.replaceAll("|", pipe()) : node.label;
503
+ replacement = `[${label}](<${node.target}>)`;
483
504
  }
484
505
  else if (options.style === "wiki" &&
485
506
  node.type === "link" &&
@@ -490,7 +511,7 @@ export const linkRules = {
490
511
  const target = wikiTarget(node.url);
491
512
  if (target === undefined || /[[\]|\r\n]/.test(label))
492
513
  return;
493
- replacement = `[[${target}|${label}]]`;
514
+ replacement = `[[${target}${pipe()}${label}]]`;
494
515
  }
495
516
  const url = destination(node);
496
517
  if (!replacement || url === undefined)