Cmarkit.Mapper
Abstract syntax tree mappers.
Mappers help with pushing abstract syntax tree transformations in every node with a minimal amount of code by defaulting the cases you don't handle. The default map maps leaves to themselves and otherwise propagates the map to all childrens.
This map has the form of List.filter_map
, however it is akin to List.concat_map
as it allows:
None
Some _
Some (Inlines _)
or Some (Blocks _)
See an example.
The type for mapper results.
val default : 'a result
default
is `Default
.
val delete : 'a result
delete
is `Map None
.
val ret : 'a -> 'a result
ret v
is `Map (Some v)
.
type 'a map = t -> 'a -> 'a filter_map
The type for maps on values of type 'a
.
The type for mappers on values of type 'a
.
This is what you specify. Return `Default
if you are not interested in handling the given case. Use map_inline
or map_block
with the given mapper if you need to call the mapper recursively.
val make :
?inline_ext_default:Inline.t map ->
?block_ext_default:Block.t map ->
?inline:Inline.t mapper ->
?block:Block.t mapper ->
unit ->
t
make ?inline ?block ()
is a mapper using inline
and block
to map the abstract syntax tree. Both default to fun _ _ -> `Default
.
The mapper knows how to default the built-in abstract syntax tree and the built-in extensions. It maps them in document and depth-first order.
If you extend the abstract syntax tree you need to indicate how to default these new cases by providing inline_ext_default
or block_ext_default
functions. By default these functions raise Invalid_argument
.
map_doc m d
maps Doc.block d
with m
. If the document block maps to None
is replaced by Block.empty
.
Warning unstable. The following may change in the future. This function also maps the blocks present Block.Footnote.Def
label definitions but will not map inline or block data in Label.def
cases unknown to Cmarkit
. If the block maps to None
for the footnote it is replaced by Block.empty
.
Also note that if these label definitions were defined in d
's abstract syntax tree, they will also already be mapped in Block.Link_reference_definition
and Block.Ext_footnote_definition
cases. It is possible to collect these mapped definitions via Block.defs
on the resulting document's block.
inline_ext_default m
is the inline extensions defaulter of m
This example sets all code blocks of document doc
without info string to lang
.
let set_unknown_code_block_lang ~lang doc =
let open Cmarkit in
let default = lang, Meta.none in
let block m = function
| Block.Code_block (cb, meta)
when Option.is_none (Block.Code_block.info_string cb) ->
let layout = Block.Code_block.layout cb in
let code = Block.Code_block.code cb in
let cb = Block.Code_block.make ~layout ~info_string:default code in
Mapper.ret (Block.Code_block (cb, meta))
| _ ->
Mapper.default (* let the mapper thread the map *)
in
let mapper = Mapper.make ~block () in
Mapper.map_doc mapper doc