Fix dropped and duplicated lines for nested collapse ranges - #470
Open
MaxFreedomPollard wants to merge 1 commit into
Open
MaxFreedomPollard wants to merge 1 commit into
MaxFreedomPollard wants to merge 1 commit into
Conversation
`parseSections` in packages/@expressive-code/plugin-collapsible-sections/src/utils.ts skips any `collapse` range that overlaps a section it already collected, because the `<details>`-based rendering cannot handle overlapping sections. The check only tested whether the new range's `from` or `to` falls inside an existing section, so a range that fully contains an existing one, e.g. `collapse={3-5, 1-8}`, was not recognized as overlapping and got added anyway.
Both sections then reached `sectionizeAst` in src/ast.ts, which splices sections into the line array from last to first while reading their content from the unmodified `lines` array. With `collapse={3-5, 1-8}` on a 10-line block, splicing the 1-8 section shrinks the array, so the following splice for 3-5 removes line 10 and appends copies of lines 3 to 5: rendered code that no longer matches the source.
Replaces the two partial checks with the standard interval overlap test `from <= existingTo && existingFrom <= to`, which covers containment in both directions and keeps the previous results for every range combination that was already handled.
✅ Deploy Preview for expressive-code ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
collapse={3-5, 1-8}renders code that no longer matches the source. On a 10-line block, line 10 disappears and lines 3 to 5 show up a second time at the bottom. Writing the same two ranges the other way round,collapse={1-8, 3-5}, renders correctly, so whether you lose a line depends on the order you list the ranges in.Cause
parseSectionsinpackages/@expressive-code/plugin-collapsible-sections/src/utils.tsskips any range that overlaps a section it already collected, because the<details>-based rendering cannot handle overlapping sections. The check (lines 23 to 26 before this change) only tested whether the new range'sfromortofalls inside an existing section:A range that fully contains an existing section satisfies neither test, so
{ from: 1, to: 8 }was collected alongside{ from: 3, to: 5 }instead of being skipped.sectionizeAstinsrc/ast.tsthen splices both sections into the output array from last to first (line 57), while reading their contents from the unmodifiedlinesarray. Splicing the 1-8 section replaces eight entries with one, so the nextoutp.splice(from - 1, to - from + 1, outerElement)for 3-5 lands on entries that have shifted: it removes line 10 and appends a second copy of lines 3 to 5.Fix
The two partial checks become the standard interval overlap test, which covers containment in both directions:
Every range combination that already worked keeps its previous result.
collapse={2-5, 3-6},collapse={2-5, 5-6}andcollapse={2-5, 1-2}still drop the second range, andcollapse={2-5, 6-10}still keeps both.Tests
test/preprocess-meta.test.tsgets the two orderings of a containing range, andtest/rendering.test.tsgets a rendering test that asserts the section boundaries and that the rendered code lines are exactly the source lines, so a dropped or duplicated line fails the test. Both fail onmainand pass with the fix.Verification
pnpm --filter @expressive-code/plugin-collapsible-sections test-shortpasses, 14 tests in 2 files. Withsrc/utils.tsreverted tomainand the new tests in place, the same command fails 2 of 14, reporting sections at lines 1-9 and 10-12 for a 9-line block.pnpm --filter @expressive-code/core --filter @expressive-code/plugin-collapsible-sections --filter @expressive-code/plugin-frames --filter @expressive-code/plugin-line-numbers --filter @expressive-code/plugin-text-markers test-shortpasses, 459 tests across the five packages.pnpm exec eslint packages/@expressive-code/plugin-collapsible-sectionsandpnpm exec prettier --checkon the changed files are both clean, andpnpm --filter @expressive-code/plugin-collapsible-sections buildsucceeds.Added a patch changeset for
@expressive-code/plugin-collapsible-sections.