Overview
Add a `--fix` flag that automatically repairs auto-fixable violations in Markdown files in-place.
Problem
gomarklint currently only detects and reports violations — users must fix them manually. Many violations follow deterministic patterns that can be repaired automatically (e.g., missing blank lines around fences, bare URLs, trailing punctuation in headings).
Design
Fix representation
Each `LintError` optionally carries a `Fix` describing how to repair the violation:
```go
type Fix struct {
StartLine int // first affected line (1-indexed)
EndLine int // last affected line (inclusive); == StartLine for single-line
Lines []string // replacement lines (nil = delete the range)
}
```
Rules that can produce a fix attach it to the `LintError` they return. Rules that cannot fix a violation leave `Fix` nil.
Application order
Fixes are applied from the bottom of the file upward (descending line order) so that insertions and deletions on earlier lines do not shift the line numbers of later fixes.
CLI
```
gomarklint --fix [files...]
```
Exits 0 when all violations were fixed (or there were none). Exits non-zero if any unfixable violations remain after applying fixes.
Idempotency
Running `--fix` twice must produce identical output.
Fixable rules
| Rule |
Fix |
| `final-blank-line` |
Append a newline at end of file |
| `no-hard-tabs` |
Replace `\t` with spaces |
| `no-bare-urls` |
Wrap in angle brackets: `` |
| `no-setext-headings` |
Convert setext heading to ATX (`#` / `##`) |
| `no-multiple-blank-lines` |
Collapse consecutive blank lines to one |
| `blanks-around-fences` |
Insert / delete blank lines around code fences |
| `blanks-around-headings` |
Insert / delete blank lines around headings |
| `blanks-around-lists` |
Insert / delete blank lines around lists |
| `no-trailing-punctuation` |
Strip trailing punctuation from heading text |
| `consistent-code-fence` |
Normalize all fences to the file's first style |
| `consistent-emphasis-style` |
Normalize `*` / `_` to the file's first style |
| `consistent-list-marker` |
Normalize `-` / `*` / `+` to the file's first style |
| `max-line-length` |
Hard-wrap prose lines at word boundaries (skip code blocks and bare URLs) |
Not auto-fixable
| Rule |
Reason |
| `single-h1` |
Cannot decide which H1 to keep |
| `duplicate-heading` |
Cannot decide which to rename |
| `empty-alt-text` |
Cannot generate meaningful alt text |
| `no-empty-links` |
Cannot supply a URL |
| `fenced-code-language` |
Cannot guess the language |
| `external-link` |
Cannot repair broken URLs |
| `link-fragments` |
Cannot repair broken anchors |
| `heading-level` |
Structural change — too risky to automate |
| `no-emphasis-as-heading` |
Conversion is ambiguous (heading level unknown) |
| `unclosed-code-block` |
Cannot determine where to close |
Open questions
- Should `--fix` also print remaining (unfixable) violations, or stay silent on success?
- For `no-hard-tabs`: hard-code 4 spaces per tab, or add a config option?
- Add `--fix-dry-run` to preview changes without writing?
Overview
Add a `--fix` flag that automatically repairs auto-fixable violations in Markdown files in-place.
Problem
gomarklint currently only detects and reports violations — users must fix them manually. Many violations follow deterministic patterns that can be repaired automatically (e.g., missing blank lines around fences, bare URLs, trailing punctuation in headings).
Design
Fix representation
Each `LintError` optionally carries a `Fix` describing how to repair the violation:
```go
type Fix struct {
StartLine int // first affected line (1-indexed)
EndLine int // last affected line (inclusive); == StartLine for single-line
Lines []string // replacement lines (nil = delete the range)
}
```
Rules that can produce a fix attach it to the `LintError` they return. Rules that cannot fix a violation leave `Fix` nil.
Application order
Fixes are applied from the bottom of the file upward (descending line order) so that insertions and deletions on earlier lines do not shift the line numbers of later fixes.
CLI
```
gomarklint --fix [files...]
```
Exits 0 when all violations were fixed (or there were none). Exits non-zero if any unfixable violations remain after applying fixes.
Idempotency
Running `--fix` twice must produce identical output.
Fixable rules
Not auto-fixable
Open questions