Insert trailing pages

I want to print a booklet. A booklet has 4 pages per sheet of paper, so if the total pages are not divisible by 4, there are blank pages left.

I’d like to insert the last “blank” pages explicitly and mark them with “NOTES” text.

How do I figure out the number of pages so far? I tried here().page():

#page()[]
#page()[]
#page()[]
#page()[]

#context {
    let p = here().page()
    let empty = (3 - calc.rem(here().page()-2,4))

    for num in array.range(0, empty) {
        //page(header: none, footer: none)[#p #empty]
    }
}

but the value it returns is the page where the next text is going to be placed. So when there are 4 pages already, it never converges. (Also, it’s going to give different results when the document doesn’t end with a page break, am I right?)

Is there a way to solve this?

To get the raw value of a counter you can use the get function.

context{

c=counter(page).get()

}

If you want the value of the counter at a specific location you can use the at() function:

context{

c=counter(page).at(location)

}

And if you want the total number of page, you can use the final function

context{

c= counter(page).final()

}

These functions always give an array of integer. So if you want to get an integer, you need to add first()

context{

c=counter(page).get().first()

}

You can read more information on this page

I tried to use .final(), but that never converged in any case at all.

I also tried to use counter(page).get(), but the result is the same:

#page()[]
#page()[]
#page()[]
#page()[]

#context {
    let over = calc.rem(counter(page).get().first()-2, 4)
    for num in array.range(0, 3-over) {
        page(header: none, footer: none)[da #over]
    }
}

and it never converges.

I think it’s because it counts page breaks. I don’t want to count the page break if it doesn’t lay out another page (if it’s at the end of the documet).

How is counter(page).get() different to here().page()?

No the counter works more subtly than that. It really counts the nulber of physical pages on the document. So if you put a pagebreak at the documents end, it doesn’t increment the number of pages.

I’m not quite sure why it doesn’t converge. I would need to test the code when I’m home.

Okay, I had an eureka moment and I used counter(page).final(). It still doesn’t converge, but I understand why now. It starts with 1, then 3 pages are added = 7, then 1 page is added = 5, then 3 pages…
I need to know how many pages were added in the last iteration so that I can recover from overshooting. Reading the docs right now.

I think I found the solution. The page counter for the current location is unstable, after all. Sometimes it returns the number of pages before it, sometimes it counts the current page, for whatever reason.
I worked around this by counting pages I inserted and subtracting that from total pages:


#page()[]
#page()[]
#page()[]
//#page()[]

#context {
    let added = counter("added")
    let prev_total = counter(page).final().first()
    let prev_added_count = counter("added").final().first()

    let over = calc.rem(prev_total - prev_added_count - 1, 4)
    let to_add = 3 - over
    for num in array.range(0, to_add) {
        page(header: none, footer: none)[da #prev_total #over #to_add #prev_added_count]
    }
    added.update(to_add)
}

I’m happy for found a solution that works for you. If you care, here is some context about why your initial solution did not work:

Indeed, and the reason for this is quite subtle. Hovering over p in your original solution, we can see that the page number alternates between 4 and 5. Due to some quirks of using the #page function directly, typst has a hard time telling which page we are currently on.
This happens because if the context block doesn’t produce content, then there are only 4 pages and the value of the counter is 4. If the context block does produce content, then this content should be on a new page, and the value of the counter is evaluated at the top of the page and it is 5 (not 4, like before!).

Why does this matter? well, it turns out that the way you calculated empty caused typst to alternate between these 2 values. On the first compiler iteration typst guesses that the context block is non-empty, so p is equal to 5 and empty evaluates to 3 - (5 - 2) = 0 and no page is inserted. Since there is no new page typst sees its initial guess was wrong and it re-evaluates the location of the context block, which is now on page 4 and empty evaluates to 3 - (4 - 2) = 1 so that a new page is inserted after all. We now land pack to our initial situation so that empty is once again re-evaluated, and so on.
And we can test our hypothesis by adding an extra #page at the beginning so that the initial guess is page 6 and empty is evaluated to 3 - (6 - 2 - 4) = 0, so that new pages are inserted and typst initial guess of a non-empty page is correct.