diff options
| author | Lukasz Kasprzak <lukas@labunix.xyz> | 2026-08-19 07:47:30 +0200 |
|---|---|---|
| committer | Lukasz Kasprzak <lukas@labunix.xyz> | 2026-08-19 07:47:30 +0200 |
| commit | eff4b89cff4e1b8fcceb23c54cb62ec636ce62fe (patch) | |
| tree | 9ec7b1f1dac45249cf8434097623b7db9f0e47c8 /lib/render/escape.mli | |
| parent | 897c274fd28402159ca6d45eedc1257b1ce98696 (diff) | |
| download | colitur-eff4b89cff4e1b8fcceb23c54cb62ec636ce62fe.tar.gz colitur-eff4b89cff4e1b8fcceb23c54cb62ec636ce62fe.zip | |
feat(render): per-flavour escaping and RFC 5545 line folding
Six flavours: latex, groff, html, xml, ics, none. Markdown, AsciiDoc and
plain text map to none deliberately -- their metacharacters are
context-dependent and escaping them aggressively produces worse output
than not escaping.
An unrecognised extension returns None rather than falling back to none:
guessing the flavour wrong produces malformed output that looks fine
until it does not.
Folding backs off to a non-continuation byte, so a fold never splits a
UTF-8 sequence -- the failure mode that would corrupt Polish and Latin
names in a published feed.
Diffstat (limited to 'lib/render/escape.mli')
| -rw-r--r-- | lib/render/escape.mli | 28 |
1 files changed, 28 insertions, 0 deletions
diff --git a/lib/render/escape.mli b/lib/render/escape.mli new file mode 100644 index 0000000..97cf050 --- /dev/null +++ b/lib/render/escape.mli @@ -0,0 +1,28 @@ +(** Per-flavour escaping for the template engine, plus RFC 5545 line folding. + + 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_ + +val all : flavour list +val to_string : flavour -> string +val of_string : string -> flavour option + +(** [of_extension ".tex"] is [Some Latex]. Returns [None] for an unrecognised + extension: the caller must treat that as an error, never as a fallback to + [None_] (spec section 5 -- guessing wrong here produces malformed output + that looks fine until it does not). *) +val of_extension : string -> flavour option + +(** Escape one interpolated value for [flavour]. *) +val apply : flavour -> string -> string + +(** Fold one unfolded content line per RFC 5545 section 3.1: at most 75 octets + per line, continuation lines prefixed with one space, CRLF terminators, + never splitting a UTF-8 sequence. The returned string ends with CRLF. *) +val fold_ics : string -> string |
