Skip to content

Fix merge behavior with newlines using character-precise offsets#128

Merged
jmthomas merged 5 commits intomasterfrom
newlines
Jan 8, 2026
Merged

Fix merge behavior with newlines using character-precise offsets#128
jmthomas merged 5 commits intomasterfrom
newlines

Conversation

@jmthomas
Copy link
Collaborator

@jmthomas jmthomas commented Jan 8, 2026

Summary

  • Fix merge behavior with newlines by using character-precise offsets instead of line-based ranges
  • Convert project from npm to pnpm for faster, more reliable dependency management
  • Add comprehensive test coverage for merge scenarios and blank line handling (+62% more tests)

Problem

The merge/copy function was using line-based ranges (always column 0), which caused incorrect behavior when merging diffs involving blank lines and newlines. Content was being inserted rather than properly replacing the target range.

Fixes #93

Solution

Store character offsets from diff-match-patch throughout the pipeline and use Ace's built-in indexToPosition() for precise character-to-position conversion during merge operations.

Key Changes

Before After
Custom line length calculations Ace's built-in indexToPosition()
Line-based ranges (column 0) Character-precise ranges
Lost character position info Preserves exact offsets

Test Plan

New Tests Added

Test Suite Tests Coverage
blank-lines.cy.js 8 Blank line merging at start/middle/end
issue-93.cy.js 4 Issue #93 scenario, bracket integrity
diff-granularity.cy.js 4 Broad vs specific diff grouping

🤖 Generated with Claude Code

jmthomas and others added 4 commits January 8, 2026 10:12
The copy/merge function was using line-based ranges (always column 0),
which caused incorrect behavior when merging diffs involving blank lines
and newlines. Content was being inserted rather than properly replacing
the target range.

This fix preserves character offsets from diff-match-patch throughout
the pipeline and uses Ace's built-in indexToPosition() for precise
character-to-position conversion during merge operations.

Fixes #93

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Replace package-lock.json with pnpm-lock.yaml
- Update GitHub Actions workflow to use pnpm
- Update README installation instructions to show pnpm first

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
New test suites:
- blank-lines.cy.js: Tests for blank line merging at start, middle, end
- issue-93.cy.js: Reproduces GitHub issue #93, tests bracket integrity
- diff-granularity.cy.js: Tests broad vs specific diff grouping

New fixtures:
- blank-line-start/middle/end.html: Blank line position tests
- multiple-blank-lines.html: Multiple consecutive blank lines
- issue-93-scenario.html: Exact scenario from the reported issue
- diff-granularity.html: Adjacent diffs for granularity testing

Fixed existing tests:
- Uncommented assertions in ltr-bottom and rtl-bottom tests
  (now pass with the character offset fix)

Test count increased from 26 to 42 (+62%)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
pnpm doesn't automatically install Cypress binary like npm does.
Added explicit `pnpm exec cypress install` step and a wait for
the server to be ready before running tests.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
README.md Outdated
Comment on lines 26 to 35
pnpm add @openc3/ace-diff
pnpm add ace-builds

# or with npm
npm i @openc3/ace-diff -S
npm i ace-builds -S


# or with yarn
yarn add @openc3/ace-diff
yarn add ace-builds
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't the @openc3/ be removed here?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah I'm going to push back to the base ace-diff name

Comment on lines +368 to +375
// Get the content to insert using character offsets from the source
const sourceValue = sourceEditor.ace.getValue()
const contentToInsert = sourceValue.substring(sourceStartOffset, sourceEndOffset)

// Use Ace's built-in indexToPosition for precise character-to-position conversion
const targetDoc = targetEditor.ace.getSession().doc
const startPos = targetDoc.indexToPosition(targetStartOffset)
const endPos = targetDoc.indexToPosition(targetEndOffset)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice, this is much cleaner

Copy link
Collaborator

@ryan-pratt ryan-pratt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the @openc3/ needs to be removed from readme. Otherwise looks good

@jmthomas jmthomas merged commit 3614d0c into master Jan 8, 2026
2 checks passed
@jmthomas jmthomas deleted the newlines branch January 8, 2026 23:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Strange merging behavior with insert into newline

2 participants