compare l0 l1 is String.compare (key l0) (key l1).
Definitions
A label definition is the content referenced by its key.
Labels are defined in documents via footnotes and link reference definitions. Additional label definitions can be added before parsing starts by using the defs argument of Doc.of_string. They can also be manipulated and created on the fly during parsing by using a resolver.
The type for label definitions. Maps label keys to their definition.
Resolvers
To have more control over the label definitions used in a document, the defs argument of Doc.of_string can be specified to pre-populate the label definitions used during parsing; for example with those of a previously parsed document.
In addition the resolver argument can be specified to:
Alter or suppress label definitions made by link reference definitions and footnote definitions. It can also be used to warn, by side effect, on multiple label definitions.
Alter, or suppress label references on reference links and images – which happen after all label definitions have been made. You can define the actual label that will be used for resolving the reference to its definition.
In particular 2. can be used to create synthetic label definitions on undefined label references. This provides the ability to treat the very liberal link label syntax as a domain specific language of yours (e.g. for data binding).
Note that parsing is not finished when resolvers are invoked this is the reason why you don't get access to the definition's data during resolution.
`Def (prev, current) when we just hit a link reference definition or footnote definition that defines the label current. If there is already a definition for current's key it is provided in prev (whose meta has the location of the definition if you parse with locations). If None is returned the current definition is ignored, and definition prev (if any) is kept for the document. If Some l is returned l's key will be bound to the parsed definition for current in Doc.defs at the end of parsing. The result of the resolver is stored in the abstract syntax tree and available via Link_definition.defined_label and Block.Footnote.defined_label.
`Ref (kind, ref, def) when we just hit a link or image referencing label ref. def is the label defining ref's key in the document (if any). The result of the resolver is the label stored for resolving the reference to its definition in the resulting Inline.Link node; None means that label is undefined and the inline becomes Inline.Text like in CommonMark.
This resolves according to the CommonMark specification. The first label definition always takes over subsequent ones and resolution is left untouched (i.e. a label has to be defined in the document to be used):
let default_resolver = function
| `Def (None, l) -> Some l
| `Def (Some _, _) -> None (* Previous takes over *)
| `Ref (_, _, def) -> def
Resolver example
In this example we assume references to undefined labels denote links to pages or media in our wiki and want to process them them later via a tree transformation or in a renderer extension.
We devise a resolver to create synthetic labels on any undefined label so that the CommonMark parser does not turn them into text.
let wikilink = Cmarkit.Meta.key () (* A meta key to recognize them *)
let make_wikilink label = (* Just a placeholder label definition *)
let meta = Cmarkit.Meta.tag wikilink (Cmarkit.Label.meta label) in
Cmarkit.Label.with_meta meta label
let with_wikilinks = function
| `Def _ as ctx -> Cmarkit.Label.default_resolver ctx
| `Ref (_, _, (Some _ as def)) -> def (* As per doc definition *)
| `Ref (_, ref, None) -> Some (make_wikilink ref)