fix(lsp): section-range termination is level-aware (caption audit follow-up)
CI / cargo fmt --check (push) Successful in 20s
CI / cargo clippy (push) Successful in 37s
CI / cargo test (push) Successful in 27s
CI / editor keymaps (push) Successful in 1m38s

The post-captions audit found find_section_range terminated a generated
section only at the next *level-1* heading. With a custom non-1
*_header_level (e.g. a level-2 Generated Tags index) a following same-level
section could be absorbed into the replaced span. Terminate at the next
heading of level <= the matched section's level instead, which keeps the
deeper `level+1` sub-groups inside while stopping at a sibling/parent.

Test: find_section_range_stops_at_same_level_sibling. 0 failures, clippy clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-31 18:49:00 +00:00
parent 545367c3f6
commit 3fd04b0efa
2 changed files with 27 additions and 7 deletions
+10 -7
View File
@@ -1886,16 +1886,19 @@ pub mod ops {
// the existing content to remain, resulting in duplicated links
// on subsequent runs.
//
// New logic walks forward until it finds the next *level1*
// heading (the start of the next toplevel section) or reaches the
// end of the document. The span end is set to the start of that
// next heading (exclusive) or to the end of the last block.
// New logic walks forward until it finds the next heading at the
// same level as (or shallower than) the matched section heading —
// i.e. the next sibling/parent section — or reaches the end of the
// document. Using `<= section_level` (rather than a hard-coded 1)
// keeps deeper sub-headings (e.g. the `level+1` per-tag groups of a
// `Generated Tags` index) inside the replaced span at any configured
// `*_header_level`. The span end is the start of that next heading
// (exclusive) or the end of the last block.
let section_level = h.level;
let mut end = h.span.end;
for next_block in ast.children.iter().skip(i + 1) {
// If we encounter another level1 heading, the current section
// ends just before it.
if let BlockNode::Heading(next_h) = next_block {
if next_h.level == 1 {
if next_h.level <= section_level {
end = next_h.span.start;
break;
}