| 81 | } |
| 82 | |
| 83 | function check(file: string): Issue[] { |
| 84 | const src = readFileSync(path.join(ROOT, file), 'utf8'); |
| 85 | const lines = src.split('\n'); |
| 86 | const issues: Issue[] = []; |
| 87 | let fence: string | null = null; |
| 88 | for (let i = 0; i < lines.length; i++) { |
| 89 | const line = lines[i]; |
| 90 | const trim = line.trim(); |
| 91 | // Track fenced code blocks so we don't lint tables inside them. |
| 92 | const fenceMatch = trim.match(/^(`{3,}|~{3,})/); |
| 93 | if (fenceMatch) { |
| 94 | const marker = fenceMatch[1][0]; |
| 95 | if (fence === null) fence = marker; |
| 96 | else if (marker === fence) fence = null; |
| 97 | continue; |
| 98 | } |
| 99 | if (fence !== null) continue; |
| 100 | if (!line.trimStart().startsWith('|')) continue; |
| 101 | |
| 102 | if (isSep(line)) { |
| 103 | const cells = split(line.trim()); |
| 104 | for (const cell of cells) { |
| 105 | // Cells must be exactly ---, :---, ---: or :---: with no surrounding |
| 106 | // whitespace. Anything longer (or with space padding) is column-width |
| 107 | // alignment and re-pads on every content change. |
| 108 | if (!ok.has(cell)) { |
| 109 | issues.push({ |
| 110 | file, |
| 111 | line: i + 1, |
| 112 | kind: 'separator', |
| 113 | detail: `separator cell "${cell}" is padded or extended — use ---, :---, ---: or :---: with no surrounding spaces`, |
| 114 | }); |
| 115 | break; |
| 116 | } |
| 117 | } |
| 118 | continue; |
| 119 | } |
| 120 | |
| 121 | // Content row: detect padding (>1 space between content and pipe). |
| 122 | // Only inspect lines that look like table rows: starts and ends with `|`. |
| 123 | if (!line.trimStart().startsWith('|') || !line.trimEnd().endsWith('|')) continue; |
| 124 | const cells = split(line.trim()); |
| 125 | for (const cell of cells) { |
| 126 | if (cell.trim() === '') continue; |
| 127 | const leading = cell.match(/^ */)![0].length; |
| 128 | const trailing = cell.match(/ *$/)![0].length; |
| 129 | if (leading > 1 || trailing > 1) { |
| 130 | issues.push({ |
| 131 | file, |
| 132 | line: i + 1, |
| 133 | kind: 'content', |
| 134 | detail: `content cell "${cell}" has extra padding — use a single space on each side`, |
| 135 | }); |
| 136 | break; |
| 137 | } |
| 138 | } |
| 139 | } |
| 140 | return issues; |