Reading the grid

render-checklist(checklist:, title: auto) is the function that draws the grid you already saw in Your first checklist: every official item, grouped by section (and, when the checklist has one, by a mid-level group inside a section), each item’s resolved page number(s), and a Diagnostics block listing anything that doesn’t add up. In an ordinary project you never call it directly — the checklist(...) satellite (Wiring a real project) calls it for you — but it’s exported on its own too, in case a project ever needs the grid outside the usual two-document setup.

A checklist is plain data, as already seen: name, full-name, items, plus optional headers, style, and citation fields covered later in this manual. checklist: never defaults to anything, even though CONSORT ships built in — an explicit choice costs nothing and avoids a silent, surprising default once a project is juggling more than one grid.

Diagnostics

Five situations are flagged, always in the same way, so strict: mode (below) catches every one of them consistently:

The first three (not covered / blank / unknown id) show up right in the Page column, as a warning marker; every diagnostic’s full sentence, including the two that have no single cell of their own (unknown id, duplicate na()), is listed underneath the table, in a dedicated Diagnostics block.

#import "../../lib.typ": *
#import "../../../typst-contexture/lib.typ" as contexture

// Isolates every diagnostic case grid.typ can raise, one per line, against
// a tiny made-up checklist so each is trivially visible in checklist.pdf.

#let tiny = (
  name: "TINY-TEST",
  full-name: [Tiny test checklist (not a real reporting guideline)],
  items: (
    (section: "Section A", topic: "Topic 1", group: none, id: "t1",
      description: [Covered normally --- the ordinary, non-diagnostic case.]),
    (section: "Section A", topic: "Topic 1", group: none, id: "t2",
      description: [Never check()'d or na()'d --- demonstrates "not covered".]),
    (section: "Section A", topic: "Topic 2", group: none, id: "t3",
      description: [check()'d with blank content --- demonstrates "blank content".]),
    (section: "Section B", topic: "Topic 3", group: none, id: "t4",
      description: [Both check()'d and na()'d --- demonstrates the conflict diagnostic.]),
    (section: "Section B", topic: "Topic 3", group: none, id: "t5",
      description: [na()'d twice --- demonstrates "declared N times".]),
    (section: "Section B", topic: "Topic 4", group: "Sub-group demo", id: "t6",
      description: [Under a group header, first of a 2-row Topic rowspan.]),
    (section: "Section B", topic: "Topic 4", group: "Sub-group demo", id: "t7",
      description: [Under the same group header, second row of the same Topic rowspan.]),
  ),
)

#show: contexture.bundle.with(
  template: body => {
    set page(width: 16.6cm, height: auto, margin: 12pt)
    set text(size: 9.5pt)
    body
  },
  documents: (checklist(checklist: tiny),),
)

t1 --- the normal case, no diagnostic expected:

#check("t1")[Normal content, correctly covered.]

t2 --- never covered.

t3 --- blank content:

#check("t3")[]

t4 --- both check() and na() on the same id:

#check("t4")[Covered anyway.]
#na("t4", reason: [Declared not applicable here only to test the conflict
  with check().])

t5 --- na() declared twice for the same id:

#na("t5", reason: [First declaration.])
#na("t5", reason: [Second declaration --- deliberate duplicate.])

t6/t7 --- sharing the "Sub-group demo" group and the same Topic:

#check("t6")[First item of the group demonstration.]
#check("t7")[Second item of the same group, same topic.]

An id entirely unknown to the "tiny" checklist, referenced once via
`check()` and once via `na()`:

#check("zzz")[This id doesn't exist in any grid --- unknown id via check().]
#na("yyy", reason: [Neither does this one --- unknown id via na().])

This same example also shows what happens when consecutive items share one topic (t6/t7, both “Topic 4”, under the “Sub-group demo” group): the Topic cell spans both rows instead of repeating.

Strict mode

By default, every diagnostic above is a soft, visible marker — easy to spot while drafting, but it won’t fail a build on its own. strict: true, passed to contexture.bundle(...) (not to checklist(...) — strictness is a property of the whole compile, so it covers any other contexture-based package sharing it too), turns every one of them into a hard compile error instead:

#show: contexture.bundle.with(
  strict: true,
  documents: (checklist(checklist: my-checklist),),
)

= Manuscript

// No check("s1") anywhere below --- this manuscript now
// FAILS TO COMPILE under strict: true, with a real compile
// error naming the uncovered item, instead of a soft marker
// sitting quietly in checklist.pdf.

The positive case — everything covered, strict: true compiles cleanly, with no diagnostic anywhere:

#show: contexture.bundle.with(
  strict: true,
  documents: (checklist(checklist: my-checklist),),
)

= Manuscript

#check("s1")[This item is covered here.]
#na("s2", reason: [Not applicable to this manuscript, with a
  proper justification.])

A real project typically reserves strict: true for a CI compile or a final pre-submission check — a hard gate — while drafting locally without it, so an incomplete manuscript still produces a readable checklist.pdf with markers instead of refusing to build at all.

← Marking items: check and naQuoting the real wording →