(*---------------------------------------------------------------------------
   Copyright (c) 2021 The cmarkit programmers. All rights reserved.
   SPDX-License-Identifier: ISC
  ---------------------------------------------------------------------------*)

(** Rendering CommonMark to L{^A}T{_E}X.

    Generates L{^A}T{_E}X fragments, consult the {{!integration}
    integration notes} for requirements on the document.

    See {{!page-index.quick}a quick example} and {{!doc_frame}another one}.

    {b Warning.} Rendering outputs are unstable, they may be tweaked even
    between minor versions of the library. *)

(** {1:rendering Rendering} *)

type heading_level =
| Part
| Chapter
| Section
| Subsection (** *)
(** The type for main L{^A}T{_E}X headings levels. *)

val of_doc :
  ?backend_blocks:bool -> ?first_heading_level:heading_level ->
  Cmarkit.Doc.t -> string
(** [of_doc d] is a L{^A}T{_E}X fragment for [d]. See {!val-renderer}
    for more details and documentation about rendering options. *)

(** {1:renderer Renderer} *)

val renderer :
  ?backend_blocks:bool -> ?first_heading_level:heading_level -> unit ->
  Cmarkit_renderer.t
(** [renderer] is a default L{^A}T{_E}X renderer. This renders
    the strict CommonMark abstract syntax tree and the supported
    Cmarkit {{!Cmarkit.extensions}extensions}.

    The inline, block and document renderers always return
    [true]. Unknown block and inline values are rendered by a
    L{^A}T{_E}X comment.

    The following options are available:

    {ul
    {- [backend_blocks], if [true], code blocks with language [=latex]
       are written verbatim in the output and any other code block whose
       langage starts with [=] is dropped. Defaults to [false].}
    {- [first_heading_level], the L{^A}T{_E}X heading level to use
       for the first CommonMark heading level. Defaults to [Section].}}

    See {{!Cmarkit_renderer.example}this example} to extend or
    selectively override the renderer. *)

(** {1:render Render functions}

    Only useful if you extend the renderer. *)

val newline : Cmarkit_renderer.context -> unit
(** [newline c] starts a new line. Except on the first call on [c] which is
    a nop. *)

val latex_escaped_uchar : Cmarkit_renderer.context -> Uchar.t -> unit
(** [latex_escaped_uchar c u] renders the UTF-8 encoding of [u] on [c]
    propertly escaped for L{^A}T{_E}X. That is the characters
    [&] [%] [$] [#] [_] [{] [}] [~] [^] [\ ]
    are escaped. This also renders U+0000 to {!Uchar.rep}. *)

val buffer_add_latex_escaped_uchar : Buffer.t -> Uchar.t -> unit
(** [buffer_add_latex_escaped_uchar] is {!latex_escaped_uchar} but appends
    to a buffer value. *)

val latex_escaped_string : Cmarkit_renderer.context -> string -> unit
(** [latex_escaped_string c s] renders string [s] on [c] with
    characters [&] [%] [$] [#] [_] [{] [}] [~] [^] [\ ] escaped. This
    also escapes U+0000 to {!Uchar.rep}. *)

val buffer_add_latex_escaped_string : Buffer.t -> string -> unit
(** [buffer_add_latex_escaped_string] is {!latex_escaped_string}
    but acts on a buffer value. *)

(** {1:integration L{^A}T{_E}X integration notes}

    Along with the built-in [graphicx] package, the following
    L{^A}T{_E}X packages are needed to use the outputs of the default
    renderer:
{v
tlmgr install enumitem listings hyperref  # Required
tlmgr install ulem                        # Strikethrough extension
tlmgr install bera fontspec               # Optional
v}
    This means you should have at least the following in your
    document preamble:
{v
% Required
\usepackage{graphicx}
\usepackage{enumitem}
\usepackage{listings}
\usepackage{hyperref}
\usepackage[normalem]{ulem} % Strikethrough extension

% Optional
\usepackage[scaled=0.8]{beramono} % A font for code blocks
\usepackage{fontspec}             % Supports more Unicode characters
v}

    See the sections below for more details.

    {2:char_encoding Character encoding}

    The output is UTF-8 encoded.
    {{:https://tug.org/TUGboat/tb39-1/tb121ltnews28.pdf}It became} the
    the default encoding for L{^A}T{_E}X in 2018. But if you are using
    an older version a [\usepackage[utf8]{inputenc}] may be needed.

    Using [xelatex] rather than [pdflatex] will not get stuck on missing
    glyphs.

    {2:links Autolinks and links}

    The {{:https://www.ctan.org/pkg/hyperref}[hyperref]} package is
    used to render links ([\href]) and autolink ([\url]). Link
    destination starting with a [#] are assumed to refer to
    {{!labels}section labels} and are rendered using the [\hyperref]
    macro, with the [#] chopped.

    {2:images Images}

    Images are inserted using the
    {{:https://ctan.org/pkg/graphicx}graphicx}'s package. Only
    images with relative URLs are supported, those that point
    to external ressources on the www are turned into links.

    {2:labels Section labels}

    Section labels are added to the output whenever
    {!Cmarkit.Block.Heading.val-id} holds a value. If the identifier
    already exists it is made unique by appending ["-"] and the first
    number starting from 1 that makes it unique. Also the character
    [_] seems problematic in labels even when escaped, we map it to [-]
    (if you know any better get in touch).

    {2:lists Lists}

    To support the starting point of ordereded lists without having to
    fiddle with [enumi] counters, the
    {{:https://www.ctan.org/pkg/enumitem}[enumitem]} package is used.

    {2:code_blocks Code blocks}

    If a language [lang] can be
    {{!Cmarkit.Block.Code_block.language_of_info_string}extracted}
    from a code block info string, the
    {{:https://www.ctan.org/pkg/listings}[listings]} package is used
    with the corresponding language in a [lstlisting] environment.
    Otherwise the built-in [verbatim] environment is used.

    Note that the [listings] package has no definition for the [ocaml]
    language, the default renderings are a bit subpar and
    break on character literals with double quotes. This improves things:
{v
\lstset{
  columns=[c]fixed,
  basicstyle=\small\ttfamily,
  keywordstyle=\bfseries,
  upquote=true,
  commentstyle=\slshape,
  breaklines=true,
  showstringspaces=false}

\lstdefinelanguage{ocaml}{language=[objective]caml,
   % Fixes double quotes in char literals
   literate={'"'}{\textquotesingle "\textquotesingle}3
            {'\\"'}{\textquotesingle \textbackslash"\textquotesingle}4,
}
v}

   {2:doc_frame Document frame}

   The default renderer only generates L{^A}T{_E}X fragments. You
   may want to add a document frame. For example:
{[
let latex_doc_of_md ?(title = "") md =
  let doc = Cmarkit.Doc.of_string md in
  let r = Cmarkit_latex.renderer () in
  let buffer_add_doc = Cmarkit_renderer.buffer_add_doc r in
  let buffer_add_title = Cmarkit_latex.buffer_add_latex_escaped_string in
  let maketitle = if title = "" then "" else {|\maketitle|} in
  Printf.kbprintf Buffer.contents (Buffer.create 1024)
{|\documentclass{article}

\usepackage{graphicx}
\usepackage{enumitem}
\usepackage{listings}
\usepackage{hyperref}
\usepackage[normalem]{ulem}
\usepackage[scaled=0.8]{beramono}
\usepackage{fontspec}

\lstset{
  columns=[c]fixed,
  basicstyle=\small\ttfamily,
  keywordstyle=\bfseries,
  upquote=true,
  commentstyle=\slshape,
  breaklines=true,
  showstringspaces=false}

\lstdefinelanguage{ocaml}{language=[objective]caml,
  literate={'"'}{\textquotesingle "\textquotesingle}3
            {'\\"'}{\textquotesingle \textbackslash"\textquotesingle}4,
}

\title{%a}
\begin{document}
%s
%a
\end{document}|} buffer_add_title title maketitle buffer_add_doc doc
]}

Ignore this: ".
*)
