harrellbm / Bookletic

Create beautiful booklets using Typst
Apache License 2.0
6 stars 2 forks source link

Requires manual page breaks #4

Open dei-layborer opened 3 weeks ago

dei-layborer commented 3 weeks ago

I'm creating this issue for discussion purposes, as I think it's going to be impossible to fix/implement without changes to typst itself.

As it stands, there's no way to figure out where a page break will occur in the rendered PDF, meaning there's no way to re-order the pages. I did some experimenting with some of the introspection methods, but got stuck.

I was able to get an array of content blocks from within a piece of text:

let paragraphChildren(body) = {
  let contents = body.fields().at("children")
}

On a content block, the fields() method returns a dictionary, but with only one key (children). This in turn contains an array of various content blocks; sometimes it's a full paragraph, sometimes not.

My original idea was to use this plus layout() to get a running tally of the height of each content block, and then compare that to the page height. But there doesn't seem to be a way to do this. Variable scope rules (a for loop can't write to a variable not stored within the loop itself, for example) mean just storing the total in a variable is out. I played with state as a possible solution, but because of the way this works, it broke typst's built-in loop protections. Here's the full code I tried so far:

let contentMeasure(body) = {
    let blockHeight = state("b", 0)   // height of a given block
    let contentHeight = state("c", 0) // cumulative total

    let everything = body.fields()
    let contents = body.fields().at("children")
    for c in contents {
        layout(size => [
            #let (height, ) = measure(block(width: 100%, c))
            #blockHeight.update(height)
        ])
        context {
            let oldHeight = contentHeight.get()
            contentHeight.update(
                oldHeight + blockHeight.get()
            )
        }
    }
}

I'm not sure where to go from here, unfortunately. But who knows, maybe this will give someone else an idea?

harrellbm commented 2 weeks ago

@dei-layborer definitely a feature I would like to see as well. This is also an issue on typst itself discussing it. https://github.com/typst/typst/issues/5092