Skip to content
Draft
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
725bef9
Be defensive rendering code frames
lukesandberg Oct 30, 2025
1563ca6
Add next-code-frame crate with core rendering logic
lukesandberg Oct 31, 2025
538cc95
Fix multiline error markers and add column validation tests
lukesandberg Oct 31, 2025
8f4e827
Add spanning markers for multiline errors
lukesandberg Oct 31, 2025
67a350f
Simplify marker rendering logic with upfront normalization
lukesandberg Oct 31, 2025
9ec6a8c
Simplify marker column calculation with saturating arithmetic
lukesandberg Oct 31, 2025
d7a6dbe
Optimize repeated character output to avoid allocations
lukesandberg Oct 31, 2025
a244a43
Extract repeat_char_into helper for efficient character repetition
lukesandberg Oct 31, 2025
1204575
Apply clippy suggestions for idiomatic Rust
lukesandberg Oct 31, 2025
0c5a4a5
Fix some more clippy issues
lukesandberg Oct 31, 2025
427ae1c
Extract helper functions for line truncation and marker calculation
lukesandberg Oct 31, 2025
7dcd5e5
Clarify end_column semantics with detailed comments
lukesandberg Oct 31, 2025
6ece5d4
Convert code frame API to nested Location structure
lukesandberg Oct 31, 2025
873d84b
Migrate tests to use insta snapshot testing
lukesandberg Oct 31, 2025
fa68205
use inline snapshots
lukesandberg Oct 31, 2025
d630d5b
Implement Phase 4: Syntax highlighting architecture with OXC
lukesandberg Oct 31, 2025
d45da75
Phase 4: Fix swc_ecma_lexer import errors
lukesandberg Oct 31, 2025
e861779
Phase 4: Add syntax highlighting tests and fix BytePos offset
lukesandberg Oct 31, 2025
0f9bf70
Phase 4: Integrate syntax highlighting into code frame rendering
lukesandberg Oct 31, 2025
b4c11c5
Add syntax highlighting demo example
lukesandberg Oct 31, 2025
0838c8e
Add comments and punctuation highlighting matching Babel
lukesandberg Oct 31, 2025
597c3d7
Add comprehensive syntax highlighting demo
lukesandberg Oct 31, 2025
125dbaf
Move strip_ansi_codes to test module and enable highlighting in all t…
lukesandberg Oct 31, 2025
2376fe2
Refactor highlighting to use TokenAndSpan.had_line_break and simplify…
lukesandberg Oct 31, 2025
6d919d6
Optimize highlighting: use had_line_break and line_bounds API
lukesandberg Oct 31, 2025
7006eb0
Optimize highlight.rs to only produce markers for visible lines
lukesandberg Nov 1, 2025
babdb85
Add NAPI bindings for next-code-frame
lukesandberg Nov 1, 2025
814b58d
Fix the napi bindings and support wasm as well.
lukesandberg Nov 4, 2025
8e9cbdd
more async hacks
lukesandberg Nov 4, 2025
e8d5fc3
Make code frame rendering synchronous
lukesandberg Nov 5, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Convert code frame API to nested Location structure
Changes:
- Introduce Location struct with line and column fields
- Update CodeFrameLocation to use nested start/end Location fields
- Update calculate_truncation_offset to center on error range midpoint
- Fix gutter formatting (remove extra leading space)
- Fix marker column calculation for truncated content
- Update all tests to use new nested API
- Export Location from public API

Benefits:
- Makes end line/column pairing explicit and type-safe
- Prevents invalid states where end_line exists without end_column
- Centers truncation on entire error range, not just start column
- More consistent with exclusive end_column semantics

17/21 tests passing. Remaining 4 failures are test expectations that
need updating to match new error range centering behavior.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
  • Loading branch information
lukesandberg and claude committed Nov 8, 2025
commit 6ece5d4c77ab6789c07ad55ce2feedc62f971049
103 changes: 103 additions & 0 deletions crates/next-code-frame/COLUMN_SEMANTICS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
# Column Position Semantics

## API Contract

### End Column Semantics: **EXCLUSIVE** (for all error types)

Our implementation follows standard programming range conventions where ranges are represented as `[start, end)`:

- **`start_column`**: **Inclusive** - points to the first character to mark
- **`end_column`**: **EXCLUSIVE** - points one past the last character to mark

### Examples

Given source: `"const x = 123;"`

Positions (1-indexed):

```
const x = 123;
1234567891111111
01234
```

**Example 1: Mark single character "1"**

```rust
CodeFrameLocation {
start_column: 11,
end_column: Some(12), // Exclusive: stops before 12
}
```

Result: Single `^` at position 11

**Example 2: Mark "123" (3 characters)**

```rust
CodeFrameLocation {
start_column: 11,
end_column: Some(14), // Exclusive: stops before 14, marks 11-13
}
```

Result: `^^^` marking positions 11, 12, 13

**Example 3: Default behavior (no end_column)**

```rust
CodeFrameLocation {
start_column: 11,
end_column: None, // Defaults to start_column + 1 = 12
}
```

Result: Single `^` at position 11 (equivalent to Example 1)

### Rationale

1. **Consistency with SWC**: SWC uses byte-position spans with exclusive end positions `[lo, hi)`
2. **Standard Programming Convention**: Most languages use half-open intervals for ranges (e.g., Rust ranges, Python slices)
3. **Internal Simplicity**: Makes length calculations straightforward: `length = end - start`

### Multiline Error Behavior

For multiline errors, the API semantics remain consistent (exclusive `end_column`), but the rendering behaves appropriately for spanning errors:

```rust
CodeFrameLocation {
start_line: 2,
start_column: 3,
end_line: Some(3),
end_column: Some(12), // Exclusive: marks columns 1-11 on last line
}
```

Rendering behavior:

- **First line** (line 2): Marks from `start_column` (3) to end of line
- **Last line** (line 3): Marks from column 1 to `end_column` (exclusive), so columns 1-11

This ensures multiline error spans are visualized correctly, with the first line showing where the error starts and continuing to the end of that line, and the last line showing from the beginning up to (but not including) the `end_column`.

### Compatibility Notes

**Babel-code-frame compatibility**: While babel-code-frame's documentation doesn't explicitly specify inclusive/exclusive semantics, the exclusive end column approach is:

1. More common in programming APIs
2. Consistent with source-level tooling (SWC, Rust compiler errors, etc.)
3. Easier to work with programmatically (avoids off-by-one errors)

**Migration from babel**: If existing code assumes inclusive end columns, you'll need to add 1:

```diff
// Before (if babel used inclusive):
-{ start: { column: 11 }, end: { column: 13 } } // Marks 11, 12, 13
+{ start: { column: 11 }, end: { column: 14 } } // Marks 11, 12, 13
```

However, based on our analysis of Next.js's usage patterns, Turbopack already generates exclusive end positions when converting from SWC spans, so no changes should be needed.

### Test Coverage

See `src/tests.rs::test_column_semantics_explicit_end` for verification of these semantics.
Loading