diff options
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/render/escape.ml | 33 | ||||
| -rw-r--r-- | lib/render/escape.mli | 10 |
2 files changed, 34 insertions, 9 deletions
diff --git a/lib/render/escape.ml b/lib/render/escape.ml index f506c44..ee9ce6c 100644 --- a/lib/render/escape.ml +++ b/lib/render/escape.ml @@ -1,18 +1,19 @@ -type flavour = Latex | Groff | Html | Xml | Ics | None_ +type flavour = Latex | Typst | Groff | Html | Xml | Ics | None_ -let all = [ Latex; Groff; Html; Xml; Ics; None_ ] +let all = [ Latex; Typst; Groff; Html; Xml; Ics; None_ ] let to_string = function - | Latex -> "latex" | Groff -> "groff" | Html -> "html" + | Latex -> "latex" | Typst -> "typst" | Groff -> "groff" | Html -> "html" | Xml -> "xml" | Ics -> "ics" | None_ -> "none" let of_string = function - | "latex" -> Some Latex | "groff" -> Some Groff | "html" -> Some Html + | "latex" -> Some Latex | "typst" -> Some Typst | "groff" -> Some Groff | "html" -> Some Html | "xml" -> Some Xml | "ics" -> Some Ics | "none" -> Some None_ | _ -> None let of_extension = function | ".tex" -> Some Latex + | ".typ" -> Some Typst | ".ms" | ".mom" | ".me" -> Some Groff | ".html" | ".htm" -> Some Html | ".xml" -> Some Xml @@ -37,6 +38,29 @@ let latex = function | '~' -> "\\textasciitilde{}" | c -> String.make 1 c +(* Typst markup metacharacters, verified live against the installed `typst` + 0.14.2 binary rather than assumed (probe: each character escaped, + compiled, pdftotext'd back, confirmed literal; each also confirmed to + do something ELSE when left bare -- '#' opens code mode, '*'/'_' toggle + strong/emph, '$' opens math, '@' opens a reference (a bare "@word" is a + hard COMPILE ERROR, not merely mangled output, if "word" resolves to no + label), '<'/'>' can close around a bare word into label syntax that + swallows it whole, '`' opens raw, '~' is a non-breaking space, and a run + of two or three '-' becomes an en/em dash). Backslash-escapable in every + case -- no character on this list needed a non-backslash workaround. + '-' is escaped UNCONDITIONALLY, not only inside a detected run: this + function has no lookahead (see [expand]'s own comment above), so it + cannot tell "is this hyphen part of a run" one character at a time: a + probe confirmed escaping every hyphen independently ("\-\-\-") still + typesets as three literal hyphens, never collapsing to an em dash, so + the single per-character rule is sufficient for runs of any length. *) +let typst = function + | '\\' -> "\\\\" + | '#' -> "\\#" | '*' -> "\\*" | '_' -> "\\_" | '$' -> "\\$" + | '@' -> "\\@" | '<' -> "\\<" | '>' -> "\\>" | '`' -> "\\`" + | '~' -> "\\~" | '-' -> "\\-" + | c -> String.make 1 c + let html = function | '&' -> "&" | '<' -> "<" | '>' -> ">" | '"' -> """ | '\'' -> "'" @@ -57,6 +81,7 @@ let groff s = let apply flavour s = match flavour with | Latex -> expand latex s + | Typst -> expand typst s | Groff -> groff s | Html | Xml -> expand html s | Ics -> expand ics s diff --git a/lib/render/escape.mli b/lib/render/escape.mli index 97cf050..ee1e20b 100644 --- a/lib/render/escape.mli +++ b/lib/render/escape.mli @@ -3,11 +3,11 @@ Knows nothing about calendars. Pure and total: every function is defined on every string, and none reads the clock, the environment or the filesystem. *) -(** The six escaping modes. Markdown, AsciiDoc and plain text all use [None_]: - their metacharacter sets are context-dependent, and escaping them - aggressively produces worse output than not escaping at all (spec section 5). - This is a documented limitation of those flavours. *) -type flavour = Latex | Groff | Html | Xml | Ics | None_ +(** The seven escaping modes. Markdown, AsciiDoc and plain text all use + [None_]: their metacharacter sets are context-dependent, and escaping + them aggressively produces worse output than not escaping at all (spec + section 5). This is a documented limitation of those flavours. *) +type flavour = Latex | Typst | Groff | Html | Xml | Ics | None_ val all : flavour list val to_string : flavour -> string |
