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

@Y.D.X First of all, thanks a lot, and secondly sorry to not have responded earlier.

You did nudge me in the right direction. Here is the solution to my original question:

#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(
///   wrapper: it => rect(it),
///   include-heading-in-wrapper: false, // optional
///   depth: 1, // optional
/// )
/// ```
///
/// Note: `#set` rules (like `#set text(lang: "fr")`) must be declared before calling `#show: wrapp-section`
#let wrapp-section(
  body,
  wrapper: none,
  depth: 1,
  include-heading-in-wrapper: false,
) = {
  // The wrapper function
  let fn = none
  // The fenced elements to be wrapped
  let fenced = ()

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

      // Print the heading itself and start a new fence
      if include-heading-in-wrapper {
        fn = wrapper
        fenced.push(it)
      } else {
        it
        fn = wrapper
      }
    } else if fn != none {
      // Continue the fence
      fenced.push(it)
    } else {
      it // if not in any fence
    }
  }

  // Complete the last fence
  if fn != none {
    fn(fenced.join())
  }
}

And a usage example:

#set text(lang: "en")

#show: wrapp-section.with(
  wrapper: it => rect(it),
  include-heading-in-wrapper: true,
  depth: 2,
)

= heading 1 - a

== heading 2 - a

some
text _and_ 
more

=== heading 3 - a

stuff

== heading 2 - b
test

Which generates:


The only thing I would like to improve would be to factorize the repeated block:

if fn != none {
  // Complete the last fence
  fn(fenced.join())
  fn = none
  fenced = ()
}
2 Likes