How to access the text of the current section (before the next heading)?

A slightly better version, that pass both the heading and the content to a single function:

#let is-heading(it) = {
  it.func() == heading
}

/// A show rule that wrap everything between two headings of the same level
///
/// Usage: ```
/// #show: wrapp-section.with(
///   depth: 1, // optional
///   wrapper: (heading: none, section: none) => {
///    rect[
///      heading: #box[#rect[#heading]]
///      
///      section: #box[#rect[#section]]
///    ]
///  }
/// )
/// ```
///
/// Note: `#set` rules (like `#set text(lang: "fr")`) must be declared before calling `#show: wrapp-section`
#let wrapp-section(
  body,
  depth: 1,
  wrapper: none,
) = {
  // The heading of the current section
  let heading = none
  // The content of the current section
  let section = ()

  for it in body.children {
    let x = it.func();
    
    if (is-heading(it) and it.fields().at("depth") < depth) {
      if heading != none {
        // Complete the last section
        wrapper(heading: heading, section: section.join())
        heading = none
        section = ()
      }
      it
    } else if is-heading(it) and it.fields().at("depth") == depth {
      if heading != none {
        // Complete the last section
        wrapper(heading: heading, section: section.join())
        heading = none
        section = ()
      }

      heading = it
    } else if heading != none {
      // Continue the current section
      section.push(it)
    } else {
      it // if not in any section (before the first heading of the appropriate depth)
    }
  }

  // Complete the last section
  if heading != none {
    wrapper(heading: heading, section: section.join())
  }
}

The same example as above:

#set text(lang: "en")

#show: wrapp-section.with(
  depth: 2,
  wrapper: (heading: none, section: none) => {
    heading
    rect(section)
  }
)


= heading 1 - a

== heading 2 - a

some
text _and_ 
more

=== heading 3 - a

stuff

== heading 2 - b
test

And a more interesting example that demonstrate how manipulate both the heading and the content of the section level you want to format:

#set text(lang: "en")

#show: wrapp-section.with(
  depth: 2,
  wrapper: (heading: none, section: none) => {
    rect[
      heading: #box[#rect[#heading]]
      
      section: #box[#rect[#section]]
    ]
  }
)


= heading 1 - a

== heading 2 - a

some
text _and_ 
more

=== heading 3 - a

stuff

== heading 2 - b
test


= heading 1 - c

== heading 2 - c

some
text _and_ 
more

=== heading 3 - c

stuff

== heading 2 - d
test

2 Likes