Update section behavior

This commit is contained in:
2026-08-23 14:25:12 +02:00
parent c612cdd28d
commit 5ad715426d
6 changed files with 66 additions and 29 deletions
+34
View File
@@ -3,6 +3,7 @@ package main
import (
"bytes"
"regexp"
"strings"
"github.com/yuin/goldmark/ast"
"github.com/yuin/goldmark/text"
@@ -10,6 +11,11 @@ import (
var sectionHeadingRe = regexp.MustCompile(`(?m)^#{1,6} `)
// headingTextRe matches an ATX heading at the start of a section. The
// heading text is everything after the `#`s and the required space, on the
// first line.
var headingTextRe = regexp.MustCompile(`^(#{1,6})\s+([^\n]*)`)
// splitSections splits raw markdown into sections.
// Section 0 is any content before the first heading.
// Each subsequent section begins at a heading line and runs to the next.
@@ -64,3 +70,31 @@ func joinSections(sections [][]byte) []byte {
}
return buf.Bytes()
}
// sectionHeading returns the heading level (1..6) and trimmed text of a
// section produced by splitSections. Returns level=0 for the pre-heading
// section (index 0).
func sectionHeading(section []byte) (level int, text string) {
m := headingTextRe.FindSubmatch(section)
if m == nil {
return 0, ""
}
return len(m[1]), strings.TrimSpace(string(m[2]))
}
// sectionSpanEnd returns the exclusive end index of the section span starting
// at start: the first following section whose heading level is <= start's.
// Sections nested deeper than start (its subsections) belong to the span, so
// editing a `##` covers every `###`+ under it up to the next `##` or `#`.
func secionSpanEnd(sections [][]byte, start int) int {
level, _ := sectionHeading(sections[start])
if level == 0 {
return start + 1
}
for i := start + 1; i <= len(sections); i++ {
if l, _ := sectionHeading(sections[i]); l > 0 && l <= level {
return i
}
}
return len(sections)
}