Skip to main content

Document

Struct Document 

Source
pub struct Document { /* private fields */ }
Expand description

A fully-parsed, typed in-memory Quillmark document.

Document is the canonical representation of a Quillmark Markdown file. Markdown is both the import and export format; the structured data here is primary.

§Structure

  • main — the entry Card (sentinel is Sentinel::Main(reference)).
  • cards — ordered composable cards (each with Sentinel::Card(tag)).

Backend plates consume the flat JSON wire shape produced by Document::to_plate_json. That method is the only place in core that reconstructs {"QUILL": ..., "CARDS": [...], "BODY": "..."}.

Implementations§

Source§

impl Document

Source

pub fn set_quill_ref(&mut self, reference: QuillReference)

Replace the QUILL reference on the main card’s sentinel.

§Invariants enforced

The QuillReference type guarantees structural validity; no further checks are needed here.

§Warnings

This method never modifies warnings.

Source

pub fn card_mut(&mut self, index: usize) -> Option<&mut Card>

Return a mutable reference to the composable card at index, or None if out of range.

§Warnings

This method never modifies warnings.

Source

pub fn push_card(&mut self, card: Card)

Append a composable card to the end of the card list.

§Invariants

card.sentinel() must be Sentinel::Card; a main card cannot be appended as a composable card. Debug assert.

§Warnings

This method never modifies warnings.

Source

pub fn insert_card(&mut self, index: usize, card: Card) -> Result<(), EditError>

Insert a composable card at index.

§Invariants enforced

index must be in 0..=len. An index > len returns EditError::IndexOutOfRange.

§Warnings

This method never modifies warnings.

Source

pub fn remove_card(&mut self, index: usize) -> Option<Card>

Remove and return the composable card at index, or None if out of range.

§Warnings

This method never modifies warnings.

Source

pub fn set_card_tag( &mut self, index: usize, new_tag: impl Into<String>, ) -> Result<(), EditError>

Replace the tag (sentinel) of the composable card at index.

Field-bag semantics. This mutates only the sentinel; the card’s frontmatter and body are untouched. After the call:

  • Fields valid under both old and new schemas round-trip unchanged.
  • Fields only in the old schema linger in the bag (silently ignored by Quill::form and validate_document, but still emitted by to_markdown()).
  • Fields only in the new schema are absent — surfaced as Default or Missing by Quill::form, and MissingRequired by validate_document.

Schema-aware migration (clearing orphans, applying defaults, etc.) is the caller’s responsibility — set_card_tag is a structural primitive.

§Invariants enforced
§Warnings

This method never modifies warnings.

Source

pub fn move_card(&mut self, from: usize, to: usize) -> Result<(), EditError>

Move the composable card at from to position to.

If from == to, this is a no-op and returns Ok(()).

§Invariants enforced

Both from and to must be in 0..len. Either being out of range returns EditError::IndexOutOfRange with the offending index.

§Warnings

This method never modifies warnings.

Source§

impl Document

Source

pub fn to_markdown(&self) -> String

Emit canonical Quillmark Markdown from this document.

§Contract
  1. Type-fidelity round-trip. Document::from_markdown(&doc.to_markdown()) returns a Document equal to doc by value and by type variant. QuillValue::String("on") round-trips as a string, never as a bool. QuillValue::String("01234") round-trips as a string, never as an integer. This guarantee is the whole point of owning emission.

  2. Emit-idempotent. to_markdown is a pure function of doc; two calls on the same doc return byte-equal strings.

Byte-equality with the original source is not guaranteed.

§Emission rules (§5.2)
  • Line endings: \n only. CRLF normalization happens on import.
  • Frontmatter: ---\n, QUILL: <ref> first, remaining fields in IndexMap insertion order, ---\n, blank line.
  • Cards: one blank line before each, fence ---\nCARD: <tag>\n<fields>\n---\n<body>.
  • Body: emitted verbatim after frontmatter (and cards).
  • Mappings and sequences: block style at every nesting level.
  • Booleans: true / false.
  • Null: null.
  • Numbers: bare literals (integer or float as stored in serde_json::Value).
  • Strings: always double-quoted, JSON-style escaping (\", \\, \n, \t, \uXXXX for control chars). This is the load-bearing rule that guarantees type fidelity.
  • Multi-line strings: double-quoted with \n escape sequences. No block scalars (|, >) in v1.
§Open decisions (resolved)
  • Nested-map order. QuillValue is backed by serde_json::Value whose object type (serde_json::Map) preserves insertion order when the serde_json/preserve_order feature is enabled (it is in this workspace). Insertion order is therefore preserved for nested maps at emit time.

  • Empty containers.

    • Empty object ({}) → the key is omitted from emit entirely.
    • Empty array ([]) → emitted as key: []\n.
§What is preserved
  • YAML comments: own-line and inline trailing comments round-trip at their source position. Inline comments on sentinel lines (QUILL: r # … / CARD: t # …) round-trip too. Comments whose host disappears at emit time (empty-mapping omission, programmatic field removal) degrade to own-line comments at the same indent so the comment text is preserved even when its position shifts.
  • !fill tags: round-trip via the fill flag on FrontmatterItem::Field.
§What is lost
  • Other custom tags (!include, !env, …): the tag is dropped; the scalar value is preserved.
  • Original quoting style: all strings are re-emitted double-quoted regardless of how they were written in the source.
Source§

impl Document

Source

pub fn from_main_and_cards( main: Card, cards: Vec<Card>, warnings: Vec<Diagnostic>, ) -> Self

Create a Document from a pre-built main Card and composable cards.

The caller must guarantee that main.sentinel is Sentinel::Main(_) and every card in cards has sentinel = Sentinel::Card(_).

Source

pub fn from_markdown(markdown: &str) -> Result<Self, ParseError>

Parse a Quillmark Markdown document, discarding any non-fatal warnings.

Source

pub fn from_markdown_with_warnings( markdown: &str, ) -> Result<ParseOutput, ParseError>

Parse a Quillmark Markdown document, returning warnings alongside the document.

Source

pub fn main(&self) -> &Card

The document’s main (entry) card.

Source

pub fn main_mut(&mut self) -> &mut Card

Mutable access to the main card.

Source

pub fn quill_reference(&self) -> &QuillReference

The quill reference (name@version-selector) carried by the main card’s sentinel. Convenience reader over doc.main().sentinel().

Source

pub fn cards(&self) -> &[Card]

Ordered list of composable card blocks.

Source

pub fn cards_mut(&mut self) -> &mut [Card]

Mutable access to the composable cards slice.

Source

pub fn warnings(&self) -> &[Diagnostic]

Non-fatal warnings collected during parsing.

Source

pub fn to_plate_json(&self) -> Value

Serialize this document to the JSON shape expected by backend plates.

The output has the following top-level keys, which match what lib.typ.template reads at Typst runtime:

{
  "QUILL": "<ref>",
  "<field>": <value>,
  ...
  "BODY": "<global-body>",
  "CARDS": [
    { "CARD": "<tag>", "<field>": <value>, ..., "BODY": "<card-body>" },
    ...
  ]
}

This is the only place in quillmark-core that knows about the plate wire format. All internal consumers (Quill, backends) call this instead of constructing the shape by hand.

Trait Implementations§

Source§

impl Clone for Document

Source§

fn clone(&self) -> Document

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for Document

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl PartialEq for Document

Source§

fn eq(&self, other: &Self) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.