Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Annotation Data

Use the optional data: (...) dictionary to describe an annotation for custom views. Fields can be titles, tags, review status, or values specific to your document. Deixis does not prescribe their names or types:

Source

#deixis-endnote(id: <method>, data: (
  title: [Explain the method], tags: ("method", "review"), status: "open",
))[Why this method suits the problem.]

#deixis-mark(of: <method>)[Another use]

Complete source and preview setup

Output · Click to zoom

deixis-query-notes() returns the dictionary unchanged as note.data. The small review example uses it for titles, a filtered table, and usage counts. An annotation without custom data has (:).

Ownership And Forward Declarations

DeclarationWhere data belongs
Original deixis-mark(id: ...) or specialized markOn that original declaration
A creating footnote/endnote/margin/inset/sidenote wrapperOn the wrapper, even without a public ID
A standalone -body callOn that body, with or without an ID
An attached -body(of: ...) or wrapperInherited from the original; omit data
A reused mark with of:Shared annotation data is available on the parent query record; omit data

All six original/body/reuse orders retain the same dictionary. Neither an early attachment nor an early reuse reserves or overrides data. Nonempty data with of: is diagnosed rather than merged; the default empty dictionary means omission. Each annotation has one owner, independently of its body rendering scope and counter series. To attach an explanation with data, declare it on the original:

Source

#deixis-endnote-body(of: <method>)[Why the method works.]
#deixis-mark(id: <method>, data: (title: "Method",))[The method]

Complete source and preview setup

Output · Click to zoom

Anonymous inline/region decoration can also carry data, visible with include-unpaired: "mark". An anonymous phantom call has no record; supplying nonempty data to it requires an original id. There is no per-occurrence data option or mutable metadata setter. Custom body renderers receive the same dictionary under their existing record’s data field; physical page-body records also retain it.

Titles, Grouping, And Filtering

Data has no automatic rendering or selection semantics. The default outline continues to show safe static body excerpts. Choose a title explicitly:

Source

#deixis-note-outline(
  summary: note => note.data.at("title", default: note.summary),
)

Complete source and preview setup

Output · Click to zoom

For status headings, use group-by: note => note.data.at("status", default: "Unsorted"). A group callback must return a string. Filter tags/status or sort custom fields with ordinary array operations:

Source

#context {
  let pending = deixis-query-notes().filter(note =>
    note.data.at("status", default: none) == "open")
  for note in pending {
    [#link(note.dest, note.data.at("title", default: note.summary)) #linebreak()]
  }
}

Complete source and preview setup

Output · Click to zoom

IDs, counts, locations, marks, body descriptors, and styles remain runtime fields. Custom names stay nested: data: (id: "my value",) changes note.data.id and cannot change note.id. Deixis never merges custom fields into its records or style cascade, so there is no list of reserved custom keys.

Data is opaque. Queries, default outlines, registration discovery, and static summary extraction never traverse it or invoke its callbacks. A title containing context, state updates, or other executable content runs only when a caller explicitly renders that value. Rendering a custom title in several views can therefore execute it several times; use static titles for reusable presentation. Safe body/passage summaries remain separate from this explicit user payload.