Module Cmarkit.LabelSource
Labels.
Labels are used by reference links to refer to the definitions of link reference definitions, footnote definitions and your own interpretations.
Labels
The type for label keys. These are link labels normalized for matching.
The type for link labels.
make key text is a label with key id and unormalized text text.
key_id l is the label's key. If l comes out of a parse this l's normalized text.
text l is the text of l.
text_to_string l is the lines of text separated by spaces. In contrast to key this has not gone throught normalization.
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. See for example Link_definition.Def or Block.Footnote.Def.
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.
See an example.
type context = [ | `Def of t option * t(*Label definitions
*)| `Ref of [ `Link | `Image ] * t * t option(*Label references
*)
]The type for resolver contexts. See resolver.
The type for resolvers. context is:
`Def (prev, current)when we just hit a link reference definition or footnote definition that defines the labelcurrent. If there is already a definition forcurrent'skeyit is provided inprev(whosemetahas the location of the definition if you parse with locations). IfNoneis returned thecurrentdefinition is ignored, and definitionprev(if any) is kept for the document. IfSome lis returnedl's key will be bound to the parsed definition forcurrentinDoc.defsat the end of parsing. The result of the resolver is stored in the abstract syntax tree and available viaLink_definition.defined_labelandBlock.Footnote.defined_label.`Ref (kind, ref, def)when we just hit a link or image referencing labelref.defis the label definingref'skeyin the document (if any). The result of the resolver is the label stored for resolving the reference to its definition in the resultingInline.Linknode;Nonemeans thatlabelis undefined and the inline becomesInline.Textlike in CommonMark.
See an example and the default_resolver.
default_resolver is the default resolver.
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) -> defResolver 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)