Skip to content

Commit 1ec60c7

Browse files
kmelveclaude
andauthored
feat: add nofix language tag to skip code blocks (#5)
Add support for `nofix` and `*-nofix` language tags to prevent boxfix from processing code blocks. This is useful for documentation that needs to show intentionally broken diagrams as examples. - Skip code blocks with `nofix` or `*-nofix` (e.g., `text-nofix`) - Add "before" example files showing broken LLM output - Update README with vibecoded section and nofix documentation - Add tests for the new behavior Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 01d9896 commit 1ec60c7

File tree

9 files changed

+162
-24
lines changed

9 files changed

+162
-24
lines changed

README.md

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
LLMs generate ASCII diagrams with broken borders. This fixes them.
44

5-
```
5+
```nofix
66
Before After
77
┌─────────────────────┐ ┌─────────────────────┐
88
│ Component A │ → │ Component A │
@@ -14,7 +14,7 @@ Before After
1414

1515
LLMs generate ASCII diagrams with misaligned right borders. The top and bottom boundary lines (`┌───┐`, `└───┘`) are usually correct because they're repetitive patterns. But content lines with variable text end up short:
1616

17-
```
17+
```nofix
1818
┌─────────────────────────┐
1919
│ This line is too short│ ← Right border doesn't align
2020
│ API Gateway │ ← Same problem here
@@ -102,7 +102,7 @@ boxfix doc1.md doc2.md --in-place
102102

103103
The key insight: **boundary lines are reliable, content lines aren't**.
104104

105-
```
105+
```nofix
106106
┌─────────────────────┐ ← Boundary: LLMs get this right (repetitive)
107107
│ Content here │ ← Content: LLMs mess this up (variable)
108108
│ More content │ ← Content: Same problem
@@ -138,7 +138,7 @@ The key insight: **boundary lines are reliable, content lines aren't**.
138138
```
139139
┌─────────────────┐
140140
│ ┌─────────────┐ │
141-
│ │ Inner
141+
│ │ Inner
142142
│ └─────────────┘ │
143143
└─────────────────┘
144144
```
@@ -149,6 +149,7 @@ The key insight: **boundary lines are reliable, content lines aren't**.
149149
- Lines without border characters
150150
- Already-aligned diagrams
151151
- Non-diagram code blocks
152+
- Code blocks with `nofix` or `*-nofix` language tag (e.g., ` ```nofix ` or ` ```text-nofix `)
152153

153154
## Programmatic API
154155

@@ -339,6 +340,10 @@ If your diagram has content that overflows the boundaries, you'll need to either
339340

340341
Boundary expansion is planned for a future release.
341342

343+
## Vibecoded
344+
345+
This entire library was built with [Claude Code](https://claude.ai/code) and Claude Opus 4.5. Every line of code, test, and documentation was generated through AI-assisted development.
346+
342347
## License
343348

344349
MIT

examples/README.md

Lines changed: 16 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,12 @@
22

33
This directory contains examples of properly aligned diagrams that demonstrate boxfix output.
44

5-
> **Note:** This repository has a Claude Code hook that automatically runs boxfix on markdown files. This means any intentionally misaligned "Before" examples get auto-fixed. The examples below show what boxfix produces, and inline comparisons show what it fixes.
6-
75
## What Gets Fixed
86

97
boxfix pads short content lines to match boundary widths. Here's what broken input looks like vs fixed output:
108

119
**Broken (what LLMs often generate):**
12-
```
10+
```nofix
1311
┌──────────────┐ ← boundary is 16 chars wide
1412
│ Short│ ← content line is only 8 chars (missing padding)
1513
│ Also short│ ← another short line
@@ -28,13 +26,15 @@ The boundary lines (`┌───┐`, `└───┘`) are the reference widt
2826

2927
## Examples
3028

31-
| File | Description |
32-
|------|-------------|
33-
| [`simple-box.md`](./simple-box.md) | Single box with content lines |
34-
| [`nested-boxes.md`](./nested-boxes.md) | Boxes within boxes |
35-
| [`multiple-boxes.md`](./multiple-boxes.md) | Several boxes in one diagram |
36-
| [`ascii-style.md`](./ascii-style.md) | ASCII `+---+` style boxes |
37-
| [`architecture.md`](./architecture.md) | Complex architecture diagram |
29+
Each example has a `.before.md` version showing typical broken LLM output and a fixed version:
30+
31+
| Before (broken) | After (fixed) | Description |
32+
|-----------------|---------------|-------------|
33+
| [`simple-box.before.md`](./simple-box.before.md) | [`simple-box.md`](./simple-box.md) | Single box with content lines |
34+
| [`nested-boxes.before.md`](./nested-boxes.before.md) | [`nested-boxes.md`](./nested-boxes.md) | Boxes within boxes |
35+
| [`multiple-boxes.before.md`](./multiple-boxes.before.md) | [`multiple-boxes.md`](./multiple-boxes.md) | Several boxes in one diagram |
36+
| [`ascii-style.before.md`](./ascii-style.before.md) | [`ascii-style.md`](./ascii-style.md) | ASCII `+---+` style boxes |
37+
| [`architecture.before.md`](./architecture.before.md) | [`architecture.md`](./architecture.md) | Complex architecture diagram |
3838

3939
## Running boxfix
4040

@@ -58,18 +58,14 @@ npx boxfix --check examples/*.md
5858

5959
## Testing with Broken Input
6060

61-
To test boxfix with actual broken diagrams, create a test file outside this repo or disable the hook temporarily:
61+
The `.before.md` files use the `nofix` language tag to preserve broken diagrams:
6262

63-
```bash
64-
# Create a test file with broken diagram
65-
cat > /tmp/test.md << 'EOF'
66-
```
63+
````markdown
64+
```nofix
6765
┌──────────────┐
68-
│ Short│
66+
│ Short
6967
└──────────────┘
7068
```
71-
EOF
69+
````
7270

73-
# Run boxfix
74-
npx boxfix /tmp/test.md
75-
```
71+
Code blocks with `nofix` or `*-nofix` language tags are skipped by boxfix.

examples/architecture.before.md

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# Architecture Diagram (Before)
2+
3+
A complex architecture diagram with misaligned content throughout.
4+
5+
```nofix
6+
┌─────────────────────────────────────────────────────────────────┐
7+
│ Landing Page A Landing Page B │
8+
│ ┌──────────────────────┐ ┌──────────────────────────┐ │
9+
│ │ content[] │ │ content[] │ │
10+
│ │ ├─ heroPageBlock │ │ ├─ featureSpotlight │ │
11+
│ │ ├─ reference ───────┼────┬────┼──┤ reference ────────────┤ │
12+
│ │ └─ articlePageBlock│ │ │ └─ quotePageBlock │ │
13+
│ └──────────────────────┘ │ └──────────────────────────┘ │
14+
└──────────────────────────────┼──────────────────────────────────┘
15+
16+
17+
┌────────────────────────┐
18+
│ reusablePageBlock │
19+
│ (document) │
20+
│ │
21+
│ title: "Shared CTA" │
22+
│ invertColor: false │
23+
│ content[0]: │
24+
│ callToActionBlock │
25+
└────────────────────────┘
26+
```
27+
28+
Multiple nested boxes with varying content line widths. `boxfix` handles the complexity.

examples/ascii-style.before.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# ASCII Style Boxes (Before)
2+
3+
Classic ASCII art with misaligned content lines.
4+
5+
```nofix
6+
+------------------------+
7+
| Database Connection |
8+
| Host: localhost |
9+
| Port: 5432|
10+
+------------------------+
11+
|
12+
v
13+
+------------------------+
14+
| Connection Pool|
15+
| Max: 10 |
16+
| Timeout: 30s |
17+
+------------------------+
18+
```
19+
20+
Content lines vary in length. Run `boxfix` to align them to the 26-character boundary.

examples/multiple-boxes.before.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# Multiple Boxes (Before)
2+
3+
Multiple boxes in the same diagram with misaligned content.
4+
5+
```nofix
6+
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
7+
│ Service A │ │ Service B │ │ Service C │
8+
│ Port 3000│ │ Port 3001│ │ Port 3002│
9+
└──────────────┘ └──────────────┘ └──────────────┘
10+
│ │ │
11+
└──────────────────┼───────────────────┘
12+
13+
14+
┌────────────────┐
15+
│ Load Balancer│
16+
│ nginx:latest│
17+
└────────────────┘
18+
```
19+
20+
Each box has content lines that don't match their boundary widths. Run `boxfix` to align.

examples/nested-boxes.before.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# Nested Boxes (Before)
2+
3+
Boxes within boxes - each with misaligned content.
4+
5+
```nofix
6+
┌───────────────────────────────┐
7+
│ Outer Container │
8+
│ │
9+
│ ┌─────────────────────┐ │
10+
│ │ Inner Box │ │
11+
│ │ with content│ │
12+
│ └─────────────────────┘ │
13+
│ │
14+
│ ┌─────────────────────┐ │
15+
│ │ Another Inner│ │
16+
│ │ More content │ │
17+
│ └─────────────────────┘ │
18+
│ │
19+
└───────────────────────────────┘
20+
```
21+
22+
Both outer and inner box content lines need padding. `boxfix` handles nested boxes correctly.

examples/simple-box.before.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# Simple Box (Before)
2+
3+
A single box with misaligned content lines - typical LLM output.
4+
5+
```nofix
6+
┌────────────────────────┐
7+
│ User Authentication │
8+
│ Service│
9+
│ │
10+
│ Handles login/logout│
11+
└────────────────────────┘
12+
```
13+
14+
Content lines are shorter than the 26-character boundary width. Run `boxfix` to fix.

src/markdown.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,16 @@ export function boxfixMarkdown(markdown: string): BoxfixResult {
4747
let totalStats = emptyStats();
4848

4949
for (const block of blocks) {
50+
// Skip blocks marked with nofix language tag
51+
if (block.language === "nofix" || block.language?.endsWith("-nofix")) {
52+
totalStats = mergeStats(totalStats, {
53+
linesFixed: 0,
54+
blocksProcessed: 1,
55+
diagramsFound: 0,
56+
});
57+
continue;
58+
}
59+
5060
// Check if this code block contains a diagram
5161
if (!isDiagram(block.content)) {
5262
totalStats = mergeStats(totalStats, {

test/boxfix.test.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,29 @@ const x = 1;
351351
expect(result.stats.blocksProcessed).toBe(1);
352352
});
353353

354+
it("skips code blocks with nofix language tag", () => {
355+
const input = `\`\`\`nofix
356+
┌───┐
357+
│ x│
358+
└───┘
359+
\`\`\``;
360+
const result = boxfixMarkdown(input);
361+
expect(result.fixed).toBe(input);
362+
expect(result.stats.linesFixed).toBe(0);
363+
expect(result.stats.diagramsFound).toBe(0);
364+
});
365+
366+
it("skips code blocks with -nofix suffix", () => {
367+
const input = `\`\`\`text-nofix
368+
┌───┐
369+
│ x│
370+
└───┘
371+
\`\`\``;
372+
const result = boxfixMarkdown(input);
373+
expect(result.fixed).toBe(input);
374+
expect(result.stats.linesFixed).toBe(0);
375+
});
376+
354377
it("handles multiple code blocks", () => {
355378
const input = `\`\`\`
356379
┌───┐

0 commit comments

Comments
 (0)