Skip to content

Commit 8eb700b

Browse files
jedudenclaude
andauthored
Fold table structure (MD055/056/058) into MDS025 table-format (#353)
* Add MDS060 table-structure rule (plan 181) New default-enabled rule covering markdownlint MD055 (table-pipe-style), MD056 (table-column-count), and MD058 (blanks-around-tables). MD055 and MD058 are autofixed; MD056 is flagged only since a missing cell's content is unknown. Uses line-based GFM table detection (edge pipes optional) so it sees the borderless and mixed-pipe tables MDS025's tablefmt parser cannot. The default `consistent` style is loop-stable with MDS025 enabled, since MDS025's canonical bordered output already satisfies it. Generated catalog/include table bodies are skipped so the source file stays the owner. Closes the MD055/MD056/MD058 gap in the linter comparison. https://claude.ai/code/session_012X1wVbY7u9DNMpGRhNurzT * MDS060: insert CRLF-matching blank lines in fix The MD058 blank-line insertion emitted a bare "" line, which on a CRLF file produced a lone-LF blank among CRLF rows (mixed endings). Detect the file's newline style and insert a matching blank line, mirroring the edge-normalization path that already preserves trailing carriage returns. https://claude.ai/code/session_012X1wVbY7u9DNMpGRhNurzT * MDS060: lint blockquoted and indented tables Extend prefix detection to consume a `>` blockquote-marker chain (mirroring MDS025's tablefmt), so MD055/MD056/MD058 apply to blockquoted and list-indented tables instead of being silently skipped. The MD058 blank line inside a blockquote is the bare `>` marker, not an empty line, so the blockquote is not broken; CRLF newline style is preserved. Adds blockquote fixtures and brings the package to 100% statement coverage (addresses the codecov/patch gate). Addresses Copilot review feedback on PR #353. https://claude.ai/code/session_012X1wVbY7u9DNMpGRhNurzT * MDS060: handle escaped trailing pipe; correct MDS025 note Edge detection treated a literal `\|` at the end of the last cell as a trailing edge pipe, producing a false MD055/MD056 diagnostic and corrupting the cell on fix. Trailing-pipe detection, cell counting, and edge normalization now strip a final `|` only when it is unescaped (even backslash run). Also correct the README guidance: no_leading_or_trailing does not oscillate with MDS025. Once MDS060 strips the edges, MDS025 (bordered-only) stops formatting the table; the real tradeoff is lost column alignment, not a per-pass disagreement. Backed by a loop-stability test. Addresses Copilot review feedback on PR #353. https://claude.ai/code/session_012X1wVbY7u9DNMpGRhNurzT * MDS060: respect backslash parity for unescaped pipes Three call sites treated every literal `|` as a delimiter regardless of escaping. A paragraph like `A \| B` could be mistaken for a table header; a paragraph after a table whose only pipe was escaped was absorbed as a body row (hiding the MD058 "missing blank line after" diagnostic); and `splitCells` treated `\\|` as a single literal pipe rather than an escaped backslash followed by a real delimiter, miscounting cells for MD056. Introduce `containsUnescapedPipe` (used in `isHeader`, `isSeparator`, `continuesTable`) and rewrite `splitCells` to toggle an escape state byte by byte. Cell counts and table boundaries now match the same backslash-parity rule as `endsWithUnescapedPipe`. Addresses Copilot review feedback on PR #353. https://claude.ai/code/session_012X1wVbY7u9DNMpGRhNurzT * MDS060: declare markdownlint frontmatter rules The rule-readme schema (internal/rules/proto.md) now requires each README to list the markdownlint rule(s) it covers, so MDS020 can validate the coverage matrix from front matter instead of free-form prose. https://claude.ai/code/session_012X1wVbY7u9DNMpGRhNurzT * MDS060: tighten ATX-heading guard and post-prefix indent Two header-detection bugs surfaced by Copilot review: - `isHeader` rejected any line whose trimmed content started with `#`, but `#1 | Title` is a valid first cell, not an ATX heading. Limit the guard to actual ATX shape — one to six `#` followed by space, tab, or end of line — via a new `isATXHeading` helper. - `parseRow` checked `HasPrefix(c, "|")` against the un-trimmed row content, so a row like `> | a | b |` (extra indent after the blockquote marker) had `leading` come out false even though `logicalCells` already trimmed and treated it as a real edge. Trim the same way before edge detection. Addresses Copilot review feedback on PR #353. https://claude.ai/code/session_012X1wVbY7u9DNMpGRhNurzT * fold table structure into MDS025 table-format Merge MDS060 (table-structure) into MDS025 so a single rule owns GFM table parsing, the structure checks (MD055 pipe style, MD056 column count, MD058 blanks-around-tables), and the prettier-style alignment pass. Users now configure one `table-format` block; a `mdsmith fix` run is inherently single-pass with no inter-rule oscillation window. - Port the GFM parser and MD055/056/058 logic into internal/rules/tableformat/structure.go. - Extend tableformat.Rule with a `style` setting (consistent / leading_and_trailing / no_leading_or_trailing) and chain the structure fix before the alignment fix on the same Fix call. - Bring the alignment pass's skip set to parity with the structure pass via formatSkipLines (code blocks + PI blocks + generated ranges). The helper builds a fresh map; lint.Collect*BlockLines return a shared read-only cache. - Migrate the structure fixtures into internal/rules/MDS025-table-format/{good,bad,fixed}/ with merged-rule diagnostic lists. The short-row fixture now expects both a format diag and the MD056 structure diag; the alignment pass pads the short cell on Fix. - Delete the tablestructure package and MDS060 fixture dir; drop the registrations in internal/rules/all and the integration test. - Update the MDS025 README, the markdownlint-coverage research doc, and the linter-comparison background page for the merged scope. - Refresh plan/181_table-structure.md to describe the merged design and tasks. https://claude.ai/code/session_012X1wVbY7u9DNMpGRhNurzT * recompute GeneratedRanges after structure fix The structure pass inserts blank lines around tables that need MD058 fix. Those insertions shift every downstream generated section by N lines. Fix previously copied f.GeneratedRanges onto the reparsed buffer, so the alignment pass's skip set pointed at pre-fix line numbers; tablefmt would then iterate past the shifted body and rewrite a non-canonical table living inside an `<?include?>` or `<?catalog?>` directive. Call gensection.FindAllGeneratedRanges on the reparsed buffer instead. The new TestFix_RecomputesGeneratedRangesAfterStructure Insert reproduces the bug (verified by temporarily reverting to the copy — the body table got reformatted) and gates the fix. Also rephrase the plan: "inherently single-pass" was imprecise. The fix engine still loops fixable rules to stability; the new wording says one Rule.Fix call runs structure + alignment, and that MDS025 has no second rule to oscillate against. The package-comment "retired MDS060" is dropped in favor of naming the markdownlint coverage directly. https://claude.ai/code/session_012X1wVbY7u9DNMpGRhNurzT * post-rebase fixups: gofmt and README include regen After rebasing onto main, gofmt collapses the Pad field's comment alignment and `mdsmith fix` updates the README's `<?include?>` bodies to pick up the spaced separators main introduced in good/default.md and good/alignment.md. https://claude.ai/code/session_012X1wVbY7u9DNMpGRhNurzT * address copilot review: sort, dedupe, CRLF, escape, skip cache Five correctness/consistency fixes from Copilot's second pass: 1. Check sorts the combined diagnostic slice by (line, column) after appending structure diagnostics to the format-pass output. With multiple tables in one file the two streams interleave by line, and fixture tests compare diagnostics in source order. 2. applyStructureFix dedupes adjacent-table MD058 insertions: two tables with different prefixes can each schedule a blank at the same gap (table1's blankAfter[K] + table2's blankBefore[K+1]). Emitting both produces consecutive blank lines that then trip MDS008 no-multiple-blanks. Test: TestMD058_NoDoubleBlankBetweenAdjacentTables. 3. Fix re-normalises line endings to CRLF when the source used it. tablefmt joins rewritten table lines with bare `\n`, dropping each row's `\r`, which on CRLF documents leaves the table with bare-LF endings while every surrounding line keeps `\r\n` — a mixed-ending output. Test: TestFix_CRLF_RoundTrips_TableLines. 4. Structure escape semantics drop backslash parity and match tablefmt's GFM rule directly: `\|` is the only escape, so `\\|` reads as a literal backslash plus an escaped pipe (one cell), not "escaped backslash + unescaped delimiter" (two cells). The earlier parity behavior put the structure pass and tablefmt at odds on inputs containing `\\|`. Updated tests: TestSplitCells_EscapedPipe, TestEndsWithUnescapedPipe, TestContainsUnescapedPipe. 5. formatSkipLines returns the cached code-block map directly when there are no PI blocks and no generated ranges, avoiding a per-Check allocation on the hot path. The merged map is built only when one of the other inputs is non-empty. https://claude.ai/code/session_012X1wVbY7u9DNMpGRhNurzT * markdownlint-coverage: use legend's "partial" for MD056 The coverage matrix used a one-off "⚠️" status marker for MD056 that the file's status legend (✅ / partial / 🔲 plan N) does not define. Switch to the existing "partial" label so the table is self-consistent. https://claude.ai/code/session_012X1wVbY7u9DNMpGRhNurzT * docs: qualify the MD056 "alignment pads short rows" claim Both the rule README and plan 181 said a fixed file is structurally clean even when a cell is missing, on the assumption that the alignment pass would pad the short row. That only holds for *bordered* tables: tablefmt requires edge pipes on every row, so a borderless short row survives the fix untouched and MD056 keeps firing. Qualify the claim and tell the user how to resolve the borderless case (add edges or fill the cell). https://claude.ai/code/session_012X1wVbY7u9DNMpGRhNurzT * docs: MD056 covers the delimiter row too The README said only "body row" cell counts are compared, but the implementation iterates `t.rows[1:]` so the delimiter row is also matched against the header. Catching a delimiter row with the wrong cell count is intentional — a malformed delimiter would otherwise pass MD056 silently. Reword the spec line to match the behaviour. https://claude.ai/code/session_012X1wVbY7u9DNMpGRhNurzT * structure: reject bare-pipe lines as table headers isHeader accepted a single `|` (no logical cell) as a valid header because it only checked for an unescaped pipe and a non-separator shape. That produces false-positive table detection — e.g. `|` followed by a delimiter-looking line — and diverges from tablefmt, which requires a row to start/end with `|` and have length >= 2. Require `countCells(c) > 0` before accepting the line as a header. Guarded by TestBarePipeNotHeader (red without the guard). https://claude.ai/code/session_012X1wVbY7u9DNMpGRhNurzT * perf: stream structure fix + push CRLF into tablefmt Two perf fixes for Copilot's second-pass review: - applyStructureFix used to materialise every line as a string, modify the slice, then rebuild via strings.Join. On a typical file that's N+5 allocations even when the file has no tables to rewrite. Replace with a bytes.Buffer pre-sized to the source, writing untouched rows directly from f.Lines as []byte and only string-converting the rows that actually need edge-normalisation. Split into collectStructureEdits + renderStructureFix to keep each function under the gocognit budget. - Rule.Fix used to scan the whole output buffer twice (`bytes.ReplaceAll(\r\n -> \n)` then `\n -> \r\n`) so the CRLF endings tablefmt stripped from rewritten table rows came back. Push CRLF awareness into tablefmt.rebuildWithFormattedTables instead: if any source line ends with `\r`, re-append it to each formatted row. Drop the post-pass from Fix. The existing CRLF round-trip test and adjacent-tables dedupe test still pass. https://claude.ai/code/session_012X1wVbY7u9DNMpGRhNurzT * post-rebase: regen rule catalog to include MDS067 origin/main added MDS067 (callout-type) while this branch was open. The rebase took the local catalog body during conflict resolution; re-running `mdsmith fix` rebuilds the row. --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent 3cf569c commit 8eb700b

23 files changed

Lines changed: 1710 additions & 98 deletions

PLAN.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ footer: |
107107
| 178 || sonnet | [List marker space rule](plan/178_list-marker-space.md) |
108108
| 179 || opus | [Reversed and empty link rule](plan/179_link-validity.md) |
109109
| 180 || sonnet | [Descriptive link text rule](plan/180_descriptive-link-text.md) |
110-
| 181 | 🔲 | opus | [Table structure rules](plan/181_table-structure.md) |
110+
| 181 | | opus | [Table structure rules](plan/181_table-structure.md) |
111111
| 182 | 🔲 | sonnet | [Code block convention rules](plan/182_code-block-conventions.md) |
112112
| 183 || sonnet | [Skip DedupeDiagnostics via an audited rule.RepoScoped marker](plan/183_dedupe-diagnostics-repo-scoped-skip.md) |
113113
| 184 || opus | [Automate the cross-tool benchmark on merge to main and publish numbers to the assets branch](plan/184_release-benchmark-automation.md) |

docs/background/markdown-linters.md

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -362,9 +362,9 @@ the broadest set. The full rule-by-rule mapping lives in the
362362
[markdownlint coverage matrix][mdcov]: every markdownlint
363363
`MDxxx`, the mdsmith rule that covers it or the plan that
364364
schedules it, and the mdsmith-only rules. As of 2026-05
365-
mdsmith implements 46 of 52 active markdownlint rules (44
366-
fully, 2 partial); the other 6 are scheduled in plans 172
367-
and 181-182.
365+
mdsmith implements 49 of 52 active markdownlint rules (47
366+
fully, 2 partial); the other 3 are scheduled in plans 172
367+
and 182.
368368

369369
### Rust Markdown linters (rumdl, mado, panache)
370370

@@ -797,14 +797,15 @@ items most relevant to this comparison are:
797797
lifecycle hooks. This will close part of the gap
798798
with Hugo: deriving artifacts from Markdown sources
799799
without leaving the linter.
800-
- **Closing rule gaps with markdownlint**6 rules remain
800+
- **Closing rule gaps with markdownlint**3 rules remain
801801
unimplemented: [plan 172](../../plan/172_link-style-rule-and-config.md)
802-
covers MD054, and plans 181-182 schedule the remaining 5
803-
(table structure; code-block style). MDS062
804-
(`link-validity`) now covers markdownlint MD011 and MD042;
805-
MDS064 (`atx-heading-whitespace`) covers MD018-MD021 and
806-
MD023; MDS063 (`descriptive-link-text`) covers MD059.
807-
The [coverage matrix][mdcov] tracks each.
802+
covers MD054, and plan 182 schedules the remaining 2
803+
(code-block style). MDS025 (`table-format`) now covers
804+
markdownlint MD055, MD056, and MD058 (MD056 flag-only); MDS062
805+
(`link-validity`) covers MD011 and MD042; MDS064
806+
(`atx-heading-whitespace`) covers MD018-MD021 and MD023;
807+
MDS063 (`descriptive-link-text`) covers MD059. The
808+
[coverage matrix][mdcov] tracks each.
808809
- **User-defined Markdown conventions**
809810
([plan 113][plan113]) — let teams package their own
810811
rule presets the way the built-in conventions

docs/research/markdownlint-coverage/README.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ Status legend:
2020

2121
Deprecated markdownlint numbers (MD002, MD006, MD008,
2222
MD015-MD017) are omitted. As of 2026-05 mdsmith implements
23-
**46 of the 52** active markdownlint rules (**44** fully, **2** partially); the
24-
remaining **6** are scheduled in plans 172 and 181-182.
23+
**49 of the 52** active markdownlint rules (**47** fully, **2** partially); the
24+
remaining **3** are scheduled in plans 172 and 182.
2525

2626
## Headings
2727

@@ -104,11 +104,11 @@ remaining **6** are scheduled in plans 172 and 181-182.
104104

105105
## Tables
106106

107-
| markdownlint | Checks | mdsmith | Status |
108-
|----------------------------|-------------|---------|-------------|
109-
| MD055 table-pipe-style | edge pipes | | 🔲 plan 181 |
110-
| MD056 table-column-count | equal cells | | 🔲 plan 181 |
111-
| MD058 blanks-around-tables | blank lines | | 🔲 plan 181 |
107+
| markdownlint | Checks | mdsmith | Status |
108+
|----------------------------|-------------|---------|---------|
109+
| MD055 table-pipe-style | edge pipes | MDS025 | |
110+
| MD056 table-column-count | equal cells | MDS025 | partial |
111+
| MD058 blanks-around-tables | blank lines | MDS025 | |
112112

113113
## mdsmith-only rules (no markdownlint analog)
114114

internal/integration/alloc_budget_test.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,12 @@ const allocBudgetCeiling = 10
3737
// first run. Mid-fix rules (MDS025, MDS026) carry the post-partial
3838
// number; full-fix rules are absent.
3939
var allocBudgetGrandfathered = map[string]int{
40-
"MDS025": 50, // table-format
40+
// MDS025 absorbed the GFM structure checks (MD055/056/058) when
41+
// plan 181 folded MDS060 into it; the structure pass parses every
42+
// row a second time alongside tablefmt's alignment scan. Reducing
43+
// this to the ≤ 10 ceiling needs the single-table-walk refactor
44+
// scheduled as a follow-up to plan 181.
45+
"MDS025": 110, // table-format
4146
"MDS026": 18, // table-readability
4247
"MDS027": 25, // cross-file-reference-integrity
4348
"MDS029": 398, // conciseness-scoring

internal/rules/MDS025-table-format/README.md

Lines changed: 156 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,56 @@
22
id: MDS025
33
name: table-format
44
status: ready
5-
description: Tables must have consistent column widths and padding.
5+
description: Tables must have consistent edge pipes, equal column counts, surrounding blank lines, and prettier-style alignment.
66
category: table
77
nature: style
88
maintainability: null
9-
markdownlint: null
9+
markdownlint:
10+
- id: MD055
11+
name: table-pipe-style
12+
- id: MD056
13+
name: table-column-count
14+
partial: true
15+
- id: MD058
16+
name: blanks-around-tables
1017
---
1118
# MDS025: table-format
1219

13-
Tables must have consistent column widths and padding.
20+
Tables must have consistent edge pipes, equal column counts,
21+
surrounding blank lines, and prettier-style alignment.
22+
23+
A GFM table must satisfy four conditions:
24+
25+
1. Every row's leading/trailing pipe presence matches the configured
26+
`style` (the markdownlint MD055 check).
27+
2. Every non-header row, including the delimiter row, has the same
28+
logical cell count as the header (MD056).
29+
3. The table has a blank line before and after (MD058).
30+
4. Each bordered table has aligned column widths and consistent
31+
padding (the prettier-style alignment pass that gave the rule its
32+
name), with the configured `separator-style`.
33+
34+
Conditions 1, 3, and 4 are auto-fixed by `mdsmith fix`. Condition 2
35+
(MD056) is flagged but never auto-rewritten on its own: a missing
36+
cell's intended content is unknown. The alignment pass does pad
37+
short rows with empty cells while it normalises widths, so a fixed
38+
*bordered* table is structurally clean even when the original
39+
missed a cell. A borderless table is not formatted by the
40+
alignment pass — tablefmt requires edge pipes on every row. MD056
41+
therefore keeps firing on a borderless short row after fix; add
42+
the edge pipes or fill the cell to resolve it.
1443

1544
## Settings
1645

17-
| Setting | Type | Default | Description |
18-
|-------------------|--------|------------|--------------------------------------------------------------|
19-
| `pad` | int | `1` | spaces on each side of cell content |
20-
| `separator-style` | string | `"spaced"` | separator row layout (see examples below): spaced or compact |
46+
| Setting | Type | Default | Description |
47+
|-------------------|--------|----------------|------------------------------------------------------------------------------------|
48+
| `pad` | int | `1` | spaces on each side of cell content |
49+
| `separator-style` | string | `"spaced"` | separator row layout (see examples below): `spaced` or `compact` |
50+
| `style` | string | `"consistent"` | edge-pipe style: `consistent`, `leading_and_trailing`, or `no_leading_or_trailing` |
51+
52+
`consistent` infers the required edge-pipe shape from each table's
53+
header row and holds every other row to it. The other two values
54+
require or forbid leading and trailing pipes on every row.
2155

2256
Separator row examples:
2357

@@ -40,6 +74,7 @@ rules:
4074
table-format:
4175
pad: 1
4276
separator-style: spaced
77+
style: consistent
4378
```
4479
4580
Opt into the dense compact form:
@@ -135,7 +170,49 @@ wrap: markdown
135170

136171
<?/include?>
137172

138-
### Bad
173+
### Good -- borderless
174+
175+
<?include
176+
file: good/borderless.md
177+
wrap: markdown
178+
?>
179+
180+
```markdown
181+
# Borderless table
182+
183+
No leading or trailing pipe on any row. The style is
184+
consistent, so the table passes.
185+
186+
Key | Value
187+
--- | -----
188+
a | one
189+
b | two
190+
```
191+
192+
<?/include?>
193+
194+
### Good -- blockquoted
195+
196+
<?include
197+
file: good/blockquote.md
198+
wrap: markdown
199+
?>
200+
201+
```markdown
202+
# Blockquote table
203+
204+
> Quoted intro.
205+
>
206+
> | Key | Value |
207+
> | --- | ----- |
208+
> | a | one |
209+
>
210+
> Quoted outro.
211+
```
212+
213+
<?/include?>
214+
215+
### Bad -- misaligned
139216

140217
<?include
141218
file: bad/default.md
@@ -153,7 +230,7 @@ wrap: markdown
153230

154231
<?/include?>
155232

156-
### Bad -- alignment
233+
### Bad -- alignment indicators
157234

158235
<?include
159236
file: bad/alignment.md
@@ -170,24 +247,84 @@ wrap: markdown
170247

171248
<?/include?>
172249

250+
### Bad -- mixed edge pipes (MD055)
251+
252+
<?include
253+
file: bad/mixed-pipes.md
254+
wrap: markdown
255+
?>
256+
257+
```markdown
258+
# Mixed pipes
259+
260+
Key | Value
261+
--- | -----
262+
| a | one |
263+
b | two
264+
```
265+
266+
<?/include?>
267+
268+
### Bad -- missing cell (MD056)
269+
270+
<?include
271+
file: bad/missing-cell.md
272+
wrap: markdown
273+
?>
274+
275+
```markdown
276+
# Missing cell
277+
278+
| Key | Value |
279+
| --- | ----- |
280+
| a | one |
281+
| b |
282+
```
283+
284+
<?/include?>
285+
286+
### Bad -- no surrounding blanks (MD058)
287+
288+
<?include
289+
file: bad/no-blank-lines.md
290+
wrap: markdown
291+
?>
292+
293+
```markdown
294+
# No blanks
295+
296+
Paragraph before.
297+
| Key | Value |
298+
| --- | ----- |
299+
| a | one |
300+
Paragraph after.
301+
```
302+
303+
<?/include?>
304+
173305
## Edge Cases
174306

175-
| Scenario | Behavior |
176-
|--------------------------------|----------------------------------------------------|
177-
| table inside blockquote | `> ` prefix preserved on each line |
178-
| table inside list | indentation prefix preserved |
179-
| table inside fenced code block | skipped, not checked or modified |
180-
| escaped pipe in cell | `\|` treated as literal, not column boundary |
181-
| single-column table | formatted normally with minimum width of 3 |
182-
| inline code, links, emphasis | width measured in display columns, syntax included |
307+
| Scenario | Behavior |
308+
|-------------------------------------|---------------------------------------------------------------------------------------|
309+
| table inside blockquote | `> ` prefix preserved on each line; MD058 blanks use the bare `>` marker |
310+
| table inside list | indentation prefix preserved |
311+
| table inside fenced code block | skipped, not checked or modified |
312+
| table inside a generated section | skipped (both passes); the directive owns the bytes |
313+
| escaped pipe in cell | `\|` treated as literal, not a column boundary |
314+
| single-column table | formatted normally with minimum width of 3 |
315+
| inline code, links, emphasis | width measured in display columns, syntax included |
316+
| short row (MD056) | flagged; the alignment pass pads it with empty cells while reformatting widths |
317+
| `no_leading_or_trailing` + bordered | edges stripped; alignment pass then leaves the now-borderless table alone (converges) |
183318

184319
## Meta-Information
185320

186321
- **ID**: MDS025
187322
- **Name**: `table-format`
188323
- **Status**: ready
189-
- **Default**: enabled, pad: 1
190-
- **Fixable**: yes
324+
- **Default**: enabled, pad: 1, separator-style: spaced, style: consistent
325+
- **Fixable**: yes (MD055 edges, MD058 blanks, alignment; MD056 column count is flagged only)
191326
- **Implementation**:
192327
[source](./)
193328
- **Category**: table
329+
- **markdownlint coverage**: MD055 (table-pipe-style), MD056
330+
(table-column-count, flag only), MD058 (blanks-around-tables)
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
---
2+
diagnostics:
3+
- line: 4
4+
column: 1
5+
message: "missing blank line before table"
6+
- line: 6
7+
column: 1
8+
message: "missing blank line after table"
9+
---
10+
# Blockquote no blanks
11+
12+
> Quoted intro.
13+
> | Key | Value |
14+
> | --- | ----- |
15+
> | a | one |
16+
> Quoted outro.
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
---
2+
diagnostics:
3+
- line: 3
4+
column: 1
5+
message: "table is not formatted; row 4: expected \"| b | |\""
6+
- line: 6
7+
column: 1
8+
message: "table column count; expected 2, got 1"
9+
---
10+
# Missing cell
11+
12+
| Key | Value |
13+
| --- | ----- |
14+
| a | one |
15+
| b |
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
---
2+
diagnostics:
3+
- line: 5
4+
column: 1
5+
message: "table pipe style; expected no leading or trailing pipes"
6+
---
7+
# Mixed pipes
8+
9+
Key | Value
10+
--- | -----
11+
| a | one |
12+
b | two
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
---
2+
diagnostics:
3+
- line: 4
4+
column: 1
5+
message: "missing blank line before table"
6+
- line: 6
7+
column: 1
8+
message: "missing blank line after table"
9+
---
10+
# No blanks
11+
12+
Paragraph before.
13+
| Key | Value |
14+
| --- | ----- |
15+
| a | one |
16+
Paragraph after.
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# Blockquote no blanks
2+
3+
> Quoted intro.
4+
>
5+
> | Key | Value |
6+
> | --- | ----- |
7+
> | a | one |
8+
>
9+
> Quoted outro.

0 commit comments

Comments
 (0)