Module Djot.Doc

A parsed document: its blocks, and the footnotes and references they define.

A document does not keep the text it was parsed from. To edit a document's text and parse only what the edit affects, use Source.

type t
val of_string : ?profile:Profile.t -> ?locs:bool -> ?frontmatter:bool -> string -> t

Parses a djot text.

Each heading gets an identifier and is wrapped, with the blocks under it, in a Block.t.Section. Footnote and reference definitions stay in the blocks, and are also collected by label in footnotes and references.

  • parameter profile

    the syntax to accept; default Profile.djot

  • parameter locs

    whether to record source positions, see textloc; default false

  • parameter frontmatter

    whether to read Frontmatter; default false

val frontmatter : t -> Frontmatter.t option

The frontmatter the text started with. None for a document made from blocks.

val make : ?profile:Profile.t -> ?frontmatter:Frontmatter.t -> Block.t node list -> t

The document these blocks make: headings get identifiers and sections, and footnotes and references are collected, as of_string does for a text.

A Block.t.Section among the blocks is replaced by its blocks, its attributes going to the heading it opens with, so the blocks of a document can be given back. An identifier already on a heading or section is kept as a written one, also when it is in auto_identifiers of the document the blocks came from; give it source_blocks to have those derived again.

The document has no positions: textloc gives Textloc.none.

  • parameter frontmatter

    default none

val with_frontmatter : Frontmatter.t option -> t -> t

The document with this frontmatter, or none. Its blocks keep their positions, which are in the text the document was parsed from.

val to_string : ?style:style -> t -> string

The document as djot source, in the syntax of the profile it was parsed with. An identifier in auto_identifiers is not written.

With `Safe or `Checked, parsing the result with that profile gives the same tree, up to source positions, except that:

  • whitespace runs in attribute values collapse to one space;
  • a span with no attributes, an empty block quote, an empty table and an empty definition item read back as something else;
  • two adjacent bullet lists with the same marker read back as one;
  • a | in a table cell's text splits the cell.

The round trip is proved in Rocq for a fragment of documents written with `Safe; beyond it this is tested, not proved.

With `Naive the result need not parse back to the same tree; see style.

frontmatter is written first, its text as it was.

  • parameter style

    default `Checked

val blocks : t -> Block.t node list
val source_blocks : t -> Block.t node list

blocks without the identifiers in auto_identifiers, as they were written. Each block is the one at the same place in blocks, with only those identifiers removed. make given these blocks, the profile and the frontmatter gives a document with the same to_string and auto_identifiers.

val footnotes : t -> (string * Block.t node list) list

The footnotes: one entry per label, with the blocks of its definition as they are in blocks. A definition written inside another is in that one's blocks and has an entry of its own.

Two labels are the same when they are equal once each run of whitespace is replaced by one space, so [^a b] and [^a b] are one footnote and [^a] and [^A] are two. When a label is defined more than once, the entry holds the last definition; every definition is in blocks.

val footnote : t -> string -> Block.t node list option

The blocks of the footnote with this label, compared as in footnotes.

val references : t -> (string * (string * Attr.t)) list

Explicit reference definitions: label, destination, attributes.

val auto_references : t -> (string * (string * Attr.t)) list

One reference per heading: the heading's text as label, and its identifier after a # as destination.

val auto_identifiers : t -> string list

The identifiers derived from a heading's text, in document order; an identifier a heading was written with is not listed. Going through the headings and sections in document order, the first one with the next listed identifier is the one it was derived for.

val reference : t -> string -> (string * Attr.t) option

A label's destination, from an explicit definition or else from a heading.

val textloc : t -> 'a node -> Textloc.t

Textloc.none unless the document was parsed with ~locs:true and the node came from that parse. A list item spans from its marker to its last content, a table row its line, a cell from its leading |, a caption from its ^, a footnote definition from its [^].

type syntax = Kernel.Ast.syntax_role =
  1. | RAttrSpec
    (*

    Attributes in braces, {...}.

    *)
  2. | ROpenFence
    (*

    A code block's or div's opening fence line.

    *)
  3. | RCloseFence
    (*

    Its closing fence line, absent when unclosed.

    *)
val syntax_locs : t -> 'a node -> (syntax * Textloc.t) list

The node's delimiting syntax, in source order. Empty under the same conditions as textloc.