Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Variable section depth #182

Open
TiemenSch opened this issue Sep 5, 2024 · 1 comment
Open

Variable section depth #182

TiemenSch opened this issue Sep 5, 2024 · 1 comment

Comments

@TiemenSch
Copy link

As proposed in #160, I created this issue to discuss the handling of variable depth sections.

The main challenge resides in the bookkeeping. In it's simplest form this would just be an array of entries.

For the Ratio theme I currently use the array approach, with the additions that section ends are also calculated (rather forcefully).
https://gitlab.com/ratio-case-os/typst/polylux-ratio/-/blob/main/src/sections.typ

/// Sections state variable that tracks the first reveal of any section.
#let ratio-sections = state("ratio-sections", ())

/// Register a new section.
#let register-section(level: 1, body) = locate(loc => {
  ratio-sections.update(s => {
    let new = ()
    for sec in s {
      if sec.end == none and level <= sec.level {
        sec.end = loc
      }
      new.push(sec)
    }
    new.push((body: body, level: level, start: loc, end: none))
    new
  })
})

/// Get the current section, regardless of level.
#let current-section = locate(loc => {
  let sections = ratio-sections.at(loc)
  sections.last()
})

/// Get the current section of a given level. Returns the last seen section of that kind,
/// or any higher up section if that was more recently seen.
#let current-section-of(level: 1) = locate(loc => {
  let sections = ratio-sections.at(loc)
  for sec in sections.rev() {
    if sec.level <= level {
      return sec
    }
  }
  none
})

To register headings on the fly I then use

// Heading setup.
#show heading: it => (
  context {
    let settings = ratio-settings.get()

    // Register sections and subsections.
    let register = settings.heading-registration-level
    let first-subslide = logic.subslide.get().first() == 1
    if settings.heading-registration-level != none and first-subslide and it.level <= register {
      register-section(it.body, level: it.level)
    }
    it
  }
)

Although I would love to only register them on their first "uncover" instead of the first subslide where they might still be hidden, but that is another matter.

@TiemenSch
Copy link
Author

I would love for all/most themes to use the same machinery for this, such that it behaves more predictable for users.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant