How to repeat content on exactly one page?

I’m programmatically generating documents with typst, and I have a special requirement for one that I don’t know how to handle.

I have a certain content (a table) which should be repeated as often as possible on one page, but only one page (ok, finally that might become 2 pages, not sure yet :)). I don’t know how big that content is beforehand, the only assumption I can really make is that it fits on the page at least once.

Do I need to look into fiddling with sizes manually somehow? Or is there a convenient way? Thanks for any pointers!

Hi there @KillTheMule, you may want to have a look at the Repeat Function – Typst Documentation, perhaps mixed with a Measure Function – Typst Documentation.

EDIT: some packages like etykett – Typst Universe may also give you some hints.

As often as possible? What is considered often? You can repeat it so often that your whole page is just a black rectangle across the whole height. One under another, or randomly all over the page? Why do you need to repeat the same thing multiple times? Is this some title page or something?

I take it @KillTheMule wants something like this:

#set page(paper: "a6")

#let tab = table(
  columns: 3,
  [A], [B], [C],
 ..range(1,16).map(str),
)

#let gap = 1em
// Need to measure table height to decide how many times to repeat
// This is a hardcoded version to generate example
#repeat(tab, gap:gap)
#repeat(tab, gap:gap)

Example: the table repeats as much as possible to fill one page only (or perhaps the # of pages could be passed as a parameter):

A6 Paper A4 Paper
image

EDIT: What would be great is a function that does the same as the repeat function but vertically.

1 Like

Thanks for your answers!

Sorry if I was unclear. One item should be under the other (they pretty much fill the page horizontally), and then as many as may fit on that page. They’re grade sheets for teachers to use, and they need one for each pupil, but the more I can get on one page, the less printing is needed.

@vmartel08 Thanks for suggesting repeat, I was under the impression that I could use that only to fill space horizontally, not vertically. Hardcoding is a no-go, so thanks for suggesting the measure function, that might just help me over that hill :slight_smile:

(e) Just seeing your EDIT, I’d indeed like a vertical repeat function for that exact use case.

So zero space between them? For printing, I think most printers won’t print more than a few millimeters near the paper sides.

#let fill-first-page(body) = {
  set page(margin: 5mm)
  set par(spacing: 0pt)
  layout(size => {
    let table-size = measure(body, ..size)
    let count = int(size.height / table-size.height)
    for _ in range(count) {
      body
    }
  })
  pagebreak(weak: true)
}

#let the-table = {
  set text(9pt)
  show table.cell.where(y: 0): strong
  let rows = 10
  let header = (
    [Date],
    [Assignment Name],
    [Points Earned],
    [Points Possible],
    [Total Earned],
    [Total Possible],
    [Current overall %],
    [Current Letter Grade],
  )
  table(
    columns: (15mm, 1fr) + (15mm,) * (header.len() - 2),
    align: center + horizon,
    table.header(..header),
    ..range(header.len() * rows).map(_ => [~]),
  )
}

#fill-first-page(the-table)

Second page

I haven’t seen a single example where repeat is used vertically. Maybe when CJK vertical layout will come. RFC: Vertical Writing Mode · Issue #5908 · typst/typst · GitHub

3 Likes

This is a great solution for when the table takes the whole width of the page.

A slight variation, merging both solutions (repeat both horizontally and vertically) would be:

#let fill-first-page(body) = {
  set page(margin: 5mm)
  set par(spacing: 0.5em)
  layout(size => {
    let table-size = measure(body, ..size)
    let count = int(size.height / table-size.height)
    for _ in range(count) {
      repeat(body, gap: 0.5em)
    }
  })
  pagebreak(weak: true)
}

#let the-table = table(
  columns: 3,
  [A], [B], [C],
  ..range(1, 16).map(str),
)

#fill-first-page(the-table)

Second page

I did include a gap between the tables, which should be adjusted as needed.

2 Likes

Thanks both of you, that works nicely!

1 Like

If you mean that it’s an oversight, then it’s not:

I didn’t think or implied it was an oversight (I had read the reply as well).

1 Like