package cmarkit
Install
dune-project
Dependency
Authors
Maintainers
Sources
sha512=42fa920e84f2b7d45f5cf1251d3308daa7becff2590f7ce84186cb22335415b02cc9bc44179095bf0d37624fb5a0e66d1c96fcc1b12f1106f567247a71c79039
doc/cmarkit/Cmarkit_renderer/index.html
Module Cmarkit_rendererSource
Renderer abstraction.
Stateful renderer abstraction to render documents in Stdlib.Buffer.t values.
Note. This is a low-level interface. For quick and standard renderings see Cmarkit_html.of_doc, Cmarkit_latex.of_doc and Cmarkit_commonmark.of_doc. If you want to extend them, see this example.
Rendering
The type for renderers.
doc_to_string r d renders document d to a string using renderer r.
buffer_add_doc r b d renders document d on buffer b using renderer r.
Renderers
The type for rendering contexts, holds a renderer, a Stdlib.Buffer.t value to act on and rendering state.
The type for inline renderers.
Return false if you are not interested in rendering the given inline. Use Context.inline and Context.block on the given context if you need to invoke the renderer recursively.
The type for block renderers.
Return false if you are not interested in rendering the given block. Use Context.inline and Context.block with the given context if you need to invoke the renderer recursively.
The type for document renderers.
Return false if you are not interested in rendering the given document. Use Context.inline, Context.block and Context.doc with the given context if you need to invoke the renderer recursively.
val make :
?init_context:(context -> Cmarkit.Doc.t -> unit) ->
?inline:inline ->
?block:block ->
?doc:doc ->
unit ->
tmake ?init_context ?inline ?block ?doc () is a renderer using inline, block, doc to render documents. They all default to (fun _ _ -> false), which means that by default they defer to next renderer (see compose).
init_context is used to initialize the context for the renderer before a document render. It defaults to fun _ _ -> ().
compose g f renders first with f and if a renderer returns false, falls back on its counterpart in g.
The init_context of the result calls g's initialization context function first, followed by the one of f. This means f's initialization function can assume the context is already setup for g.
Accessors
Normally you should not need these but you may want to peek into other renderers.
init_context r is the context initalization function for r.
Rendering contexts
Extending renderers
This example extends the Cmarkit_html.renderer but it applies mutatis mutandis to the other backend document renderers.
Let's assume you want to:
- Extend the abstract syntax tree with a
Docblock which allows to splice documents in another one (note that splicing is already built-in via theCmarkit.Block.Blocksblock case). - Change the rendering of
Cmarkit.Inline.Imageinlines to render HTMLvideooraudioelements depending on the link's destination suffix. - For the rest use the built-in
Cmarkit_html.rendererrenderer as it exists.
This boils down to:
- Add a new case to the abstract syntax tree.
- Define a
custom_htmlrenderer which treatsCmarkit.Inline.Imageand the newDoccase the way we see it fit and returnfalseotherwise to use the built-in renderer. composecustom_htmlwithCmarkit_html.renderer
type Cmarkit.Block.t += Doc of Cmarkit.Doc.t (* 1 *)
let media_link c l =
let has_ext s ext = String.ends_with ~suffix:ext s in
let is_video s = List.exists (has_ext s) [".mp4"; ".webm"] in
let is_audio s = List.exists (has_ext s) [".mp3"; ".flac"] in
let defs = Cmarkit_renderer.Context.get_defs c in
match Cmarkit.Inline.Link.reference_definition defs l with
| Some Cmarkit.Link_definition.Def (ld, _) ->
let start_tag = match Cmarkit.Link_definition.dest ld with
| Some (src, _) when is_video src -> Some ("<video", src)
| Some (src, _) when is_audio src -> Some ("<audio", src)
| None | Some _ -> None
in
begin match start_tag with
| None -> false (* let the default HTML renderer handle that *)
| Some (start_tag, src) ->
(* More could be done with the reference title and link text *)
Cmarkit_renderer.Context.string c start_tag;
Cmarkit_renderer.Context.string c {| src="|};
Cmarkit_html.pct_encoded_string c src;
Cmarkit_renderer.Context.string c {|" />|};
true
end
| None | Some _ -> false (* let the default HTML renderer that *)
let custom_html =
let inline c = function
| Cmarkit.Inline.Image (l, _) -> media_link c l
| _ -> false (* let the default HTML renderer handle that *)
in
let block c = function
| Doc d ->
(* It's important to recurse via Cmarkit_renderer.Context.block *)
Cmarkit_renderer.Context.block c (Cmarkit.Doc.block d); true
| _ -> false (* let the default HTML renderer handle that *)
in
Cmarkit_renderer.make ~inline ~block () (* 2 *)
let custom_html_of_doc ~safe doc =
let default = Cmarkit_html.renderer ~safe () in
let r = Cmarkit_renderer.compose default custom_html in (* 3 *)
Cmarkit_renderer.doc_to_string r docThe custom_html_of_doc function performs your extended renderings.