# cortav specification
[*cortav] is a markup language designed to be a simpler, but more capable alternative to markdown. its name derives from the [>dict Ranuir words] [!cor] "writing" and [!tav] "document", translating to something like "(plain) text document".
dict: http://ʞ.cc/fic/spirals/glossary
the cortav [!format] can be called [!cortavgil], or [!gil cortavi], to differentiate it from the reference implementation [!cortavsir] or [!sir cortavi].
%toc
## cortav vs. markdown
the most important difference between cortav and markdown is that cortav is strictly line-oriented. this choice was made to ensure that cortav was relatively easy to parse. so while a simple [$.ct] file may look a bit like a [$.md] file, in reality it's a lot closer to gemtext than any flavor of markdown.
## encoding
a cortav document is made up of a sequence of codepoints. UTF-8 must be supported, but other encodings (such as UTF-32 or C6B) may be supported as well. lines will be derived by splitting the codepoints at the linefeed character or equivalent. note that unearthly encodings like C6B or EBCDIC will need to select their own control sequences.
## file type
a cortav source file is identified using a file extension, file type, and/or magic byte sequence.
three file extensions are defined as identifying a cortav source file. where relevant, all must be recognized as indicating a cortav source file.
* [$ct] is the shorthand extension
* [$cortav] is the canonical disambiguation extension, for use in circumstances where [$*.ct] is already defined to mean a different file format.
* [$] is the canonical Corran extension, a byte sequence comprising the unicode codepoints [$U+E3CE U+E3BD]. where the filesystem in question does not specify a filename encoding, the bytes should be expressed in UTF-8.
three more extensions are reserved for identifying a cortav intent file.
* [$ctc] is the shorthand extension
* [$cortavcun] is the canonical disambiguation extension
* [$] is the canonical Corran extension, a byte sequence comprising the unicode codepoints [$U+E3CE U+E3BD U+E3CE]. where the filesystem in question does not specify a filename encoding, the bytes should be expressed in UTF-8.
on systems which use metadata to encode filetype, two values are defined to identify cortav source files
* [$text/x-cortav] should be used when strings or arbitrary byte sequences are supported
* [$CTAV] (that is, the byte sequence [$0x43 0x54 0x41 0x56]) should be used on systems that support only 32-bit file types/4-character type codes like Classic Mac OS.
two more values are defined to identify cortav intent files.
* [$text/x-cortav-intent]
* [$CTVC] (the byte sequence [$0x43 0x54 0x56 0x43])
on systems which do not define a canonical way of encoding the filetype but support extended attributes of some kind, such as linux, an attribute named [$mime] may be created and given the value [$text/x-cortav] or [$text/x-cortav-intent]; alternatively, extensions may be used.
it is also possible to indicate the nature of a cortav file without using filesystem metadata. this is done by prefixing the file with a magic byte sequence. the sequence used depends on the encoding.
* for UTF-8 and ASCII, [$%ct[!\\n]] (that is, the byte sequence [$0x25 0x63 0x74 0x0A]) should be used
* for C6B, the file should begin with the word [$] (that is, the byte sequence [$0x03 0x07 0x3E 0x2D]).
consequently, this sequence should be ignored by a cortav parser at the start of a file (except as an indication of file format).
for FreeDesktop-based systems, the [$velartrill-cortav.xml] file included in the repository supplies mappings for the extensions and magic byte sequences. a script is also included which can be registered with xdg-open so that double-clicking on a cortav file will render it out and open it in your default web browser.
## structure
cortav is based on an HTML-like block model, where a document consists of sections, which are made up of blocks, which may contain a sequence of spans. flows of text are automatically conjoined into spans, and blocks are separated by one or more newlines. this means that, unlike in markdown, a single logical paragraph [*cannot] span multiple ASCII lines. the primary purpose of this was to ensure ease of parsing, but also, both markdown and cortav are supposed to be readable from within a plain text editor. this is the 21st century. every reasonable text editor supports soft word wrap, and if yours doesn't, that's entirely your own damn fault.
the first character(s) of every line (the "control sequence") indicates the role of that line. if no control sequence is recognized, the sequence [$.] is implied instead. the standard line classes and their associated control sequences are listed below. some control sequences have alternate forms, in order to support modern, readable unicode characters as well as plain ascii text.
* paragraphs (. ¶ ❡): a paragraph is a simple block of text. the period control sequence is only necessary if the paragraph text begins with something that would otherwise be interpreted as a control sequence.
* newlines (\\): inserts a line break into previous paragraph and attaches the following text. mostly useful for poetry or lyrics.
* section starts (# §): starts a new section. all sections have an associated depth, determined by the number of sequence repetitions (e.g. "###" indicates depth-three"). sections may have headers and IDs; both are optional. IDs, if present, are a sequence of raw-text immediately following the hash marks. if the line has one or more space character followed by styled-text, a header will be attached. the character immediately following the hashes can specify a particular type of section. e.g.:
** [$#] is a simple section break.
** [$#anchor] opens a new section with the ID [$anchor].
** [$# header] opens a new section with the title "header".
** [$#anchor header] opens a new section with both the ID [$anchor] and the title "header".
** [$#>conversation] opens a blockquote section named [$conversation] without a header.
** [$#^id] opens a footnote section for the multiline footnote [$id]. the ID must be specified.
** [$#$id] opens the multiline macro [$id]. the ID must be specified.
** [$#&id mime] opens a new inline object [$id] of type [$mime]. useful for embedding SVGs. the ID and mime type must be specified.
* lists (* :): these are like paragraph nodes, but list nodes that occur next to each other will be arranged so as to show they compose a sequence. depth is determined by the number of stars/colons. like headers, a list entry may have an ID that can be used to refer back to it; it is indicated in the same way. if colons are used, this indicates that the order of the items is signifiant. :-lists and *-lists may be intermixed; however, note than only the last character in the sequence actually controls the depth type.
* directives (%): a directive issues a hint to the renderer in the form of an arbitrary string. directives are normally ignored if they are not supported, but you may cause a warning to be emitted where the directive is not supported with [$%!] or mark a directive critical with [$%!!] so that rendering will entirely fail if it cannot be parsed.
* comments (%%): a comment is a line of text that is simply ignored by the renderer.
* asides (!): indicates text that diverges from the narrative, and can be skipped without interrupting it. think of it like block-level parentheses. asides which follow one another are merged as paragraphs of the same aside, usually represented as a sort of box. if the first line of an aside contains a colon, the stretch of styled-text from the beginning to the aside to the colon will be treated as a "type heading," e.g. "Warning:"
* code (~~~): a line beginning with ~~~ begins or terminates a block of code. the opening line should look like one of the below
** [$~~~]
** [$~~~ language] (markdown-style shorthand syntax)
** [$~~~ \[language\] ~~~] (cortav syntax)
** [$~~~ \[language\] #id ~~~]
** [$~~~ title ~~~]
** [$~~~ title \[language\] ~~~]
** [$~~~ \[language\] title ~~~]
** [$~~~ title \[language\] #id ~~~]
* reference (tab): a line beginning with a tab is treated as a "reference." references hold out-of-line metadata for preceding text like links and footnotes. a reference consists of an identifier followed by a colon and an arbitrary number of spaces or tabs, followed by text. whether this text is interpreted as raw-text or styled-text depends on the context in which the reference is used.
* quotation (<): a line of the form [$<[!name]> [!quote]] denotes an utterance by [$name].
* blockquote (>): alternate blockquote syntax. can be nested by repeating the
* subtitle (--): attaches a subtitle to the previous header
* embed (&): embeds a referenced object. can be used to show images or repeat previously defined objects like lists or tables, optionally with a caption.
** &myimg All that remained of the unfortunate blood magic pageant contestants and audience (police photo)
** &$mymacro arg 1|arg 2|arg 3
* break (---): inserts a horizontal rule or other context break; does not end the section. must be followed by newline.
* table cells (+ |): see [>ex.tab table examples].
## styled text
most blocks contain a sequence of spans. these spans are produced by interpreting a stream of [*styled-text] following the control sequence. styled-text is a sequence of codepoints potentially interspersed with escapes. an escape is formed by an open square bracket [$\[] followed by a [*span control sequence], and arguments for that sequence like more styled-text. escapes can be nested.
* strong \[*[!styled-text]\]: causes its text to stand out from the narrative, generally rendered as bold or a brighter color.
* emphatic \[![!styled-text]\]: indicates that its text should be spoken with emphasis, generally rendered as italics
* literal \[$[!styled-text]\]: indicates that its text is a reference to a literal sequence of characters, variable name, or other discrete token. generally rendered in monospace
* strikeout \[$[~styled-text]\]: indicates that its text should be struck through or otherwise indicated for deletion
* insertion \[$[+styled-text]\]: indicates that its text should be indicated as a new addition to the text body.
** consider using a macro definition [$\edit: [~[#1]][+[#2]]] to save typing if you are doing editing work
* link \[>[!ref] [!styled-text]\]: produces a hyperlink or cross-reference denoted by [$ref], which may be either a URL specified with a reference or the name of an object like an image or section elsewhere in the document. the unicode characters [$→] and [$🔗] can also be used instead of [$>] to denote a link.
* footnote \[^[!ref] [!styled-text]\]: annotates the text with a defined footnote
* raw \[\\[!raw-text]\]: causes all characters within to be interpreted literally, without expansion. the only special characters are square brackets, which must have a matching closing bracket
* raw literal \[$\\[!raw-text]\]: shorthand for [\[$[\…]]]
* macro \{[!name] [!arguments]\}: invokes a [>ex.mac macro], specified with a reference
* argument \[#[!var]\]: in macros only, inserts the [$var]-th argument. otherwise, inserts a context variable provided by the renderer.
* raw argument \[##[!var]\]: like above, but does not evaluate [$var].
* term \[&[!name] ([!label])\]: quotes a defined term with a link to its definition
* inline image \[&@[!name]\]: shows a small image or other object inline. the unicode character [$🖼] can also be used instead of [$&@].
## identifiers
any identifier (including a reference) that is defined within a named section must be referred to from outside that section as [$[!sec].[!obj]], where [$sec] is the ID of the containing section and [$obj] is the ID of the object one wishes to reference.
## context variables
context variables are provided so that cortav renderers can process templates. certain context variables are provided for by the standard. you can test for the presence of a context variable with the directive [$%[*when] ctx [!var]].
* {def cortav.file} the name of the file currently being rendered
* {def cortav.path} the absolute path of the file currently being rendered
* {def cortav.time} the current system time in the form [$[#cortav.time]]
* {def cortav.date} the current system date in the form [$[#cortav.date]]
* {def cortav.datetime} the current system date and time represented in the locale or system-standard manner (e.g. [$[#cortav.datetime]])
* {def cortav.page} the number of the page currently being rendered
* {def cortav.id} the identifier of the renderer
* {def cortav.hash} the SHA3 hash of the source file being rendered
def: [*[#1]]:
on systems with environment variables, these may be accessed as context variables by prefixing their name with [$env.].
different renderers may provide context in different ways, such as from command line options or a context file. any predefined variables should carry an appropriate prefix to prevent conflation.
## directives
d: [$%[*[##1]]]
* {d author} encodes document authorship
* {d cols} specifies the number of columns the next object should be rendered with
* {d include} transcludes another file
* {d quote} transcludes another file, without expanding the text except for paragraphs
* {d embed}, where possible, embeds another file as an object within the current one. in HTML this could be accomplished with e.g. an iframe.
* {d expand} causes the next object (usually a code block) to be fully expanded when it would otherwise not be
* {d pragma} supplies semantic data about author intent, the kind of information document contains and hints about how it should be displayed to the user. think of them like offhand remarks to the renderer -- there's no guarantee that it'll pay any attention, but if it does, your document will look better. pragmas have no scope; they affect the entire document. the pragma function exists primarily as a means to allow parameters that would normally need to be specified on e.g. the command line to be encoded in the document instead in a way that multiple implementations can understand. a few standard pragmas are defined.
** {d pragma layout} gives a hint on how the document should be layed out. the first hint that is understood will be applied; all others will be discarded. standard hints include:
*** essay
*** narrative
*** screenplay: uses asides to denote actions, quotes for dialogue
*** stageplay: uses asides to denote actions, quotes for dialogue
*** manual
*** glossary
*** news
** {d pragma accent} specifies an accent hue (in degrees around the color wheel) for renderers which support colorized output
** {d pragma accent-spread} is a factor that controls the "spread" of hues used in the document. if 0, only the accent color will be used; if larger, other hues will be used in addition to the primary accent color.
** {d pragma dark-on-light on|off} controls whether the color scheme used should be light-on-dark or dark-on-light
** {d pragma page-width} indicates how wide the pages should be
! note on pragmas: particularly when working with collections of documents, you should not keep formatting metadata in the documents themselves! the best thing to do is to have a makefile for compiling the documents using whatever tools you want to support, and encoding the rendering options in this file (for the reference implementation this currently means as command line arguments, but eventually it will support intent files as well) so they can all be changed in one place; pragmas should instead be used for per-document [*overrides] of default settings.
! a workaround for the lack of intent files in the reference implementation is to have a single pseudo-stylesheet that contains only {d pragma} statements, and then import this file from each individual source file using the {d include} directive. this is suboptimal and recommended only when you need to ensure compatibility between different implementations.
! when creating HTML files, an even better alternative may be to turn off style generation entirely and link in an external, hand-written CSS stylesheet. this is generally the way you should compile sources for existing websites if you aren't going to write your own extension.
##ex examples
~~~ blockquotes #bq [cortav] ~~~
the following excerpts of text were recovered from a partially erased hard drive found in the Hawthorne manor in the weeks after the Incident. context is unknown.
#>
—spoke to the man under the bridge again, the one who likes to bite the heads off the fish, and he suggested i take a brief sabbatical and journey to the Wandering Oak (where all paths meet) in search of inspiration and the forsaken sword of Pirate Queen Granuaile. a capital idea! i shall depart upon the morrow, having honored the Lord Odin and poisoned my accursed minstrels as is tradition—
—can't smell my soul anymore, but that's beside the point entirely—
—that second moon (always have wondered why nobody else seems to notice the damn fool thing except on Michaelmas day). alas, my luck did not endure, and i was soon to find myself knee-deep in—
—just have to see about that, won't we!—
#
the nearest surviving relative of Lord Hawthorne is believed to be a wandering beggar with a small pet meerkat who sells cursed wooden trinkets to unwary children. she will not be contacted, as the officers of the Yard fear her.
~~~
~~~links & notes #lnr [cortav] ~~~
this sentence contains a [>zombo link] to zombo com. you can do anything[^any] at zombo com.
zombo: https://zombo.com
any: anything you want
~~~
~~~ macros #mac [cortav] ~~~
the ranuir word {gloss cor|writing}…
gloss: [*[#1]] “[#2]”
~~~
~~~ tables #tab [cortav] ~~~
here is a glossary table.
+ english :+ ranuir + zia ţai + thaliste +
| honor :| tef | pang | mbecheve |
| rakewym :| hirvag | hi phang | nache umwelinde |
| eat :| fese | dzia | rotechqa |
and now the other way around!
+:english :| honor |
+:ranuir :| tef |
+:zia ţai :| pang |
+:thalishte:| mbecheve |
~~~
## extensions
the cortav specification also specifies a number of extensions that do not have to be supported for a renderer to be compliant. the extension mechanism supports the following directives.
* inhibits: prevents an extension from being used even where available
* uses: turns on an extension that is not specified by the user operating the renderer (e.g. on the command line)
* needs: causes rendering to fail with an error if the extensions are not available
where possible, instead of [$needs x y z], the directive [$when has-ext x y z] should be used instead. this causes the next section to be rendered only if the named extensions are available. [$unless has-ext x y z] can be used to provide an alternative format.
extensions are mainly interacted with through directives. all extension directives must be prefixed with the name of the extension.
### toc
sections that have a title will be included in the table of contents. the table of contents is by default inserted at the break between the first level-1 section and the section immediately following it. you may instead place the directive [$toc] where you wish the TOC to be inserted, or suppress it entirely with [$inhibits toc]. note that some renderers may not display the TOC as part of the document itself.
### smart-quotes
a cortav renderer may automatically translate punctuation marks to other punctuation marks depending on their context.
### hilite
code can be highlighted according to the formal language it is written in.
### lua
renderers with a lua interpreter available can evaluate lua code:
* [$%lua use [!file]]: evaluates [$file] and makes its definitions available
* [$\[%lua raw [!script]\]]: evaluates [$script] and emits the string it returns (if any) in raw span context.
* [$\[%lua exp [!script]\]]: evaluates [$script] and emits the string it returns (if any) in expanded span context.
* [$%lua raw [!script]]: evaluates [$script] and emits the string array it returns (if any) in raw block context.
* [$%lua exp [!script]]: evaluates [$script] and emits the string array it returns (if any) in expanded block context.
the interpreter should provide a [$cortav] table with the objects:
* ctx: contains context variables
used files should return a table with the following members
* macros: an array of functions that return strings or arrays of strings when invoked. these will be injected into the global macro namespace.
### ts
the [*ts] extension allows documents to be marked up for basic classification constraints and automatically redacted. if you are seriously relying on ts for confidentiality, make damn sure you start the file with [$%[*requires] ts], so that rendering will fail with an error if the extension isn't supported.
ts enables the directives:
* [$ts class [!scope] [!level] (styled-text)]: indicates a classification level for either the while document (scope [!doc]) or the next section (scope [!sec]). if the ts level is below [$level], the section will be redacted or rendering will fail with an error, as appropriate. if styled-text is included, this will be treated as the name of the classification level.
* [$ts word [!scope] [!word] (styled-text)]: indicates a codeword clearance that must be present for the text to render. if styled-text is present, this will be used to render the name of the codeword instead of [$word].
* [$when ts level [!level]]
* [$when ts word [!word]]
ts enables the spans:
* [$\[🔒#[!level] [!styled-text]\]]: redacts the span if the security level is below that specified.
* [$\[🔒.[!word] [!styled-text]\]]: redacts the span if the specified codeword clearance is not enabled.
(the padlock emoji is shorthand for [$%ts].)
ts redacts spans securely; that is, they are simply replaced with an indicator that they have been redacted, without visually leaking the length of the redacted text.
~~~#ts-example example [cortav] ~~~
%ts word doc sorrowful-pines SORROWFUL PINES
# intercept R1440 TCT S3
this communication between the ambassador of [*POLITY DOORMAT CRIMSON] "Socialist League world Glory" and an unknown noble of [*POLITY ROSE] "the Empire of a Thousand Suns" was intercepted by [*SYSTEM SUPINE WARBLE].
## involved individuals
* (A) [*DOORMAT CRIMSON] Ambassador [🔒.morose-frenzy Hyacinth Autumn-Lotus] (confidence 1.0)
* (B) [*ROSE] Duchess [!UNKNOWN] (confidence 0.4)
## provenance
this communication was retrieved by [🔒#3 automated buoy downlink] from [*SYSTEM SUPINE WARBLE].
%ts level sec 9 ULTRAVIOLET
##> transcript
<A> we may have a problem
<B> Hyacinth, I told you not to contact me without—
<A, shouting> god DAMMIT woman I am trying to SAVE your worthless skin
<B> Hyacinth! your Godforsaken scrambler!
<A> …oh, [!fuck].
(signal lost)
~~~
# reference implementation
the cortav standard is implemented in [$cortav.lua], found in this repository. only the way [$cortav.lua] interprets the cortav language is defined as a reference implementation; other behaviors are simply how [$cortav.lua] implements the specification and may be copied, ignored, tweaked, violently assaulted, or used as inspiration by a compliant parser.
the reference implementation can be used both as a lua library and from the command line. [$cortav.lua] contains the parser and renderers, [$ext/*] contain various extensions, [$sirsem.lua] contains utility functions, and [$cli.lua] contains the CLI driver.
## lua library
there are various ways to use cortav from a lua script; the simplest however is probably to precompile your script with luac and link in the necessary components of the implementation. for instance, say we have the following program
~~~ stdin2html.lua [lua] ~~~
local ct = require 'cortav'
local mode = {}
local doc = ct.parse(io.stdin, {file = '(stdin)'}, mode)
doc.stage = {
kind = 'render';
format = 'html';
mode = mode;
}
output:write(ct.render.html(doc, {accent = '320'}))
~~~
and the only extension we need is the table-of-contents extension. our script can be translated into a self-contained lua bytecode blob with the following command
~~~
$ luac -s -o stdin2html.lc $cortav_repo/{sirsem,cortav,ext/toc}.lua stdin2html.lua
~~~
and can then be operated with the command [$lua stdin2html.lc], with no further need for the cortav repository files. note that the order of the [$luac] command is important! [$sirsem.lua] must come first, followed by [$cortav.lua], followed by any extensions. your driver script (i.e. the script with the entry point into the application) should always come last.
### building custom tools
generally, most existing file-format conversion tools (cmark, pandoc, and so on) have a crucial limitation: they hardcode specific assumptions like document structure. this means that the files they output are generally not suitable as-is for the users' purposes, and require further munging, usually by hateful shell or perl scripts. some tools do provide libraries end users to use as a basis for designing their own tools, but these are often limited, and in any case the user ends up having to write their own (non-standard) driver. it's no surprise that very few people end up doing this.
[$cortav.lua]'s design lends itself to a more elegant solution. one can of course write their own driver using [$cortav] as a library, but most of the time when you're compiling document sources, you just want a binary you can run from the command line or a makefile. with [$cortav.lua], you can extend its capabilities easily while keeping the same driver.
in the [$cortav] spec, extensions are mostly intended to give different implementations the ability to offer extra capabilities, but the reference implementation uses an extension architecture that makes it easy to write and add your own. for each type of new behavior you want to implement, just create a new extension and list it on the make command line:
~~~
$ nvim ~/dev/my-cortav-exts/imperial-edict.lua
$ make cortav extens+=$HOME/dev/my-cortav-exts/*.lua
~~~
the cortav binary this produces will have all the extra capabilities you personally need, without any need to fork [$cortav.lua] itself or even touch the repository.
there's no reason [$cortav.lua] shouldn't be able to load extensions at runtime as well; i just haven't implemented this behavior yet. it probably would only take a few extra lines of code tho.
i will eventually document the extension API, but for now, look at [$ext/toc.lua] for a simple example of how to register an extension.
## command line driver
the [$cortav.lua] command line driver can be run from the repository directory with the command [$lua ./cli.lua], or by first compiling it into a bytecode form that links in all its dependencies. this is the preferred method for installation, as it produces a self-contained executable which loads more quickly, but running the driver in script form may be desirable for development or debugging.
the repository contains a GNU makefile to automate compilation of the reference implementation on unix-like OSes. simply run [$$ make cortav] or [$$ gmake cortav] from the repository root to produce a self-contained bytecode executable that can be installed anywhere on your filesystem, with no dependencies other than the lua interpreter.
! note that the makefile strips debugging symbols to save space, so running [$cli.lua] directly as a script may be helpful if you encounter errors and need stacktraces or other debugging information.
henceforth it will be assumed that you have produced the [$cortav] executable and placed it somewhere in your [$$PATH]; if you are instead running [$cortav.lua] directly as an interpreted script, you'll need to replace [$$ cortav] with [$$ lua ./cli.lua] in incantations.
when run without commands, [$cortav.lua] will read input from standard input and write to standard output. alternately, a source file can be given as an argument. to write to a specific file instead of the standard output stream, use the [$-o [!file]] flag.
~~~
$ cortav readme.ct -o readme.html
# reads from readme.ct, writes to readme.html
$ cortav -o readme.html
# reads from standard input, writes to readme.html
$ cortav readme.ct
# reads from readme.ct, writes to standard output
~~~
### switches
[$cortav.lua] offers various switches to control its behavior.
+ long + short + function +
| [$--out [!file]] :|:[$-o]:| sets the output file (default stdout) |
| [$--log [!file]] :|:[$-l]:| sets the log file (default stderr) |
| [$--define [!var] [!val]] :|:[$-d]:| sets the context variable [$var] to [$val] |
| [$--mode-set [!mode]] :|:[$-y]:| activates the [>refimpl-mode mode] with ID [!mode]
| [$--mode-clear [!mode]] :|:[$-n]:| disables the mode with ID [!mode] |
| [$--mode [!id] [!val]] :|:[$-m]:| configures mode [!id] with the value [!val] |
| [$--mode-set-weak [!mode]] :|:[$-Y]:| activates the [>refimpl-mode mode] with ID [!mode] if the source file does not specify otherwise
| [$--mode-clear-weak [!mode]] :|:[$-N]:| disables the mode with ID [!mode] if the source file does not specify otherwise
| [$--mode-weak [!id] [!val]] :|:[$-M]:| configures mode [!id] with the value [!val] if the source file does not specify otherwise
| [$--help] :|:[$-h]:| display online help |
| [$--version] :|:[$-V]:| display the interpreter version |
###refimpl-mode modes
most of [$cortav.lua]'s implementation-specific behavior is controlled by use of [!modes]. these are namespaced options which may have a boolean, string, or numeric value. boolean modes are set with the [$-y] [$-n] flags; other modes use the [$-m] flags.
most modes are defined by the renderer backend. the following modes affect the behavior of the frontend:
+ ID + type + effect
| [$render:format]:| string | selects the [>refimpl-rend renderer] (default [$html])
| [$parse:show-tree]:| flag | dumps the parse tree to the log after parsing completes
##refimpl-rend renderers
[$cortav.lua] implements a frontend-backend architecture, separating the parsing stage from the rendering stage. this means new renderers can be added to [$cortav.lua] relatively easily. currently, only an [>refimpl-rend-html HTML renderer] is included; however, a [$groff] backend is planned at some point in the future, so that PDFs and manpages can be generated from cortav files.
###refimpl-rend-html html
the HTML renderer is activated with the incantation [$-m render:format html]. it is currently the default backend. it produces a single HTML file, optionally with CSS styling data, from a [$.ct] input file.
it supports the following modes:
* string (css length) [$html:width] sets a maximum width for the body content in order to make the page more readable on large displays
* number [$html:accent] applies an accent hue to the generated webpage. the hue is specified in degrees, e.g. [$-m html:accent 0] applies a red accent.
* flag [$html:dark-on-light] uses dark-on-light styling, instead of the default light-on-dark
* flag [$html:fossil-uv] outputs an HTML snippet suitable for use with the Fossil VCS webserver. this is intended to be used with the unversioned content mechanism to host rendered versions of documentation written in cortav that's stored in a Fossil repository.
* number [$html:hue-spread] generates a color palette based on the supplied accent hue. the larger the value, the more the other colors diverge from the accent hue.
* string [$html:link-css] generates a document linking to the named stylesheet
* flag [$html:gen-styles] embeds appropriate CSS styles in the document (default on)
* flag [$html:snippet] produces a snippet of html instead of an entire web page. note that proper CSS scoping is not yet implemented (and can't be implemented hygienically since [$scoped] was removed 😢)
* string [$html:title] specifies the webpage titlebar contents (normally autodetected from the document based on headings or directives)
~~~
$ cortav readme.ct --out readme.html \
-m render:format html \
-m html:width 40em \
-m html:accent 80 \
-m html:hue-spread 35 \
-y html:dark-on-light # could also be written as:
$ cortav readme.ct -ommmmy readme.html render:format html html:width 40em html:accent 80 html:hue-spread 35 html:dark-on-light
~~~
## further directions
### LCH support
right now, the use of color in the HTML renderer is very unsatisfactory. the accent mechanism operates on the basis of the CSS HSL function, which is not perceptually uniform; different hues will present different mixes of brightness and some (yellows?) may be ugly or unreadable.
the ideal solution would be to simply switch to using LCH based colors. unfortunately, only Safari actually supports the LCH color function right now, and it's unlikely (unless Lea Verou and her husband manage to work a miracle) that Colors Level 4 is going to be implemented very widely any time soon.
this leaves us in an awkward position. we can of course do the math ourselves, working in LCH to implement the internal [$@tone] macro, and then "converting" these colors to HSL. unfortunately, you can't actually convert from LCH to HSL; it's like converting from pounds to kilograms. LCH can represent any color the human visual system can perceive; sRGB can't, and CSS HSL is implemented in sRGB. however, we could at least approximate something that would allow for perceptually uniform brightness, which would be an improvement, and this is probably the direction to go in, unless a miracle occurs and [$lch()] or [$color()] pop up in Blink.
it may be possible to do a more reasonable job of handling colors in the postscript and TeX outputs. unsure about SVG but i assume it suffers the same problems HTML/CSS do. does groff even support color??
### intent files
there's currently no standard way to describe the intent and desired formatting of a document besides placing pragmas in the source file itself. this is extremely suboptimal, as when generating collections of documents, it's ideal to be able to keep all formatting information in one place. users should also be able to specify their own styling overrides that describe the way they prefer to read [$cortav] files, especially for uses like gemini or gopher integration.
at some point soon [$cortav] needs to address this by adding intent files that can be activated from outside the source file, such as with a command line flag or a configuration file setting. these will probably consist of lines that are interpreted as pragmata. in addition to the standard intent format however, individual implementations should feel free to provide their own ways to provide intent metadata; e.g. the reference implementation, which has a lua interpreter available, should be able to take a lua script that runs after the parse stage and generates . this will be particularly useful for the end-user who wishes to specify a particular format she likes reading her files in without forcing that format on everyone she sends the compiled document to, as it will be able to interrogate the document and make intelligent decisions about what pragmata to apply.