Compact Web Language (COWEL)

github.com/eisenwave/cowel

Contents

1

Introduction

2

Motivation

3

Getting started

4

Syntax in a nutshell

4.1

Whitespace

4.2

Paragraph splitting

5

Directives

5.1

Directive names

5.2

Directive arguments

5.2.1

Named arguments

5.2.2

Positional arguments

5.3

Directive content

5.4

Directive processing

6

Contexts and output

7

Themes

8

List of directives

8.1

Comments

8.1.1

\comment — Comments

8.2

Text formatting

8.3

Code and syntax highlighting

8.3.1

\code — Inline code

8.3.1.1
Manual nested highlighting
8.3.1.2
Highlighting prefix and suffix
8.3.1.3
Further advice on highlighting
8.3.2

\codeblock — Code blocks

8.3.3

\hl — Syntax highlight override

8.3.4

\pre — Preformatted blocks

8.3.5

\literally — Treat input literally as text

8.3.6

\unprocessed — Suppress directive processing

8.4

Math

8.4.1

\math — Inline math

8.4.2

\mathblock — Math blocks

8.5

Separators and word breaking

8.5.1

\br — Break line

8.5.2

\hr — Horizontal rule

8.5.3

\wbr — Word break opportunity

8.5.4

\nobr — Unbroken words

8.5.5

\word — Deprecated alias for \nobr

8.6

Special characters

8.6.1

\U — Code point literal

8.6.2

\N — Code point by name

8.6.3

\Udigits — Digits of code point

8.6.4

\c — Character references

8.7

Special blocks

8.7.1

\Babstract — Abstract blocks

8.7.2

\Bquote — Quote blocks

8.7.3

\blockquote — Alias for \Bquote

8.7.4

\Bug — Bug blocks

8.7.5

\Bdecision — Decision blocks

8.7.6

\Bdel — Deletion blocks

8.7.7

\Bdetails — Details blocks aka spoilers

8.7.8

\details — Alias for \Bdetails

8.7.9

\Bdiff — Difference blocks

8.7.10

\Bex — Example blocks

8.7.11

\Bins — Insertion blocks

8.7.12

\Bimp — Important blocks

8.7.13

\Bnote — Note blocks

8.7.14

\Btip — Tip blocks

8.7.15

\Btodo — TODO blocks

8.7.16

\Bwarn — Warning blocks

8.7.17

Deprecated aliases

8.7.17.1
\bug — Deprecated alias for \Bug
8.7.17.2
\decision — Deprecated alias for \Bdecision
8.7.17.3
\delblock — Deprecated alias for \Bdel
8.7.17.4
\diff — Deprecated alias for \Bdiff
8.7.17.5
\example — Deprecated alias for \Bex
8.7.17.6
\insblock — Deprecated alias for \Bins
8.7.17.7
\important — Deprecated alias for \Bimp
8.7.17.8
\note — Deprecated alias for \Bnote
8.7.17.9
\tip — Deprecated alias for \Btip
8.7.17.10
\todo — Deprecated alias for \Btodo
8.7.17.11
\warning — Deprecated alias for \Bwarn
8.8

Lists

8.8.1

\ul — Unordered lists

8.8.2

\ol — Ordered lists

8.8.3

\li — List items

8.8.4

\item — List item pseudo-directive

8.8.5

\dl — Definition lists

8.9

Tables

8.10

Headings

8.10.1

\make-contents — Make table of contents

8.11

Bibliography

8.11.1

\bib — Add bibliography entry

8.11.2

\make-bib — Generate bibliography

8.12

References

8.12.1

\ref — References

8.12.2

\mail — E-Mail addresses

8.12.3

\tel — Telephone numbers

8.13

Foreign languages

8.13.1

\html — Inline HTML

8.13.2

\htmlblock — HTML blocks

8.13.3

\html-* — HTML element literals

8.13.4

\script — JavaScript blocks

8.13.5

\noscript — No-JavaScript content

8.13.6

\style — CSS blocks

8.14

Paragraph control

8.14.1

\p — Paragraphs

8.14.2

\paragraphs — Enable paragraph splitting

8.14.3

\block — Display as block content

8.14.4

\inline — Display as inline content

8.15

Sections

8.15.1

\there — Append content to section

8.15.2

\here — Copy section content

8.15.3

\hereblock — Copy section content in block

8.16

File management

8.16.1

\include — Include text from a file

8.16.2

\import — Import a sub-document

8.17

Macros

8.17.1

\macro — Define a macro

8.17.2

\put{} — Replaced with provided content

8.17.3

\put{0}, \put{1}, … — Replaced with argument

8.17.4

\put{...} — Forwarding provided arguments

8.17.5

Avoiding name collisions

8.18

Miscellaneous

8.18.1

\div — Content division

8.18.2

\trim — Trim input

8.18.3

\text — Plaintext context

8.19

Variables and calculations

8.19.1

\Vset — Set a variable

8.19.2

\Vget — Get a variable

8.19.3

\Cadd — Perform addition

8.19.4

\Csub — Perform subtraction

8.19.5

\Cmul — Perform multiplication

8.19.6

\Cdiv — Perform division

1. Introduction

COWEL is a markup language with TeX-like syntax, intended to generate HTML documents, mainly for proposals and technical text. Many of its features are purpose-built for use in WG21, such as for writing C++ proposals.

The following COWEL code ...

Hello, \strong{strong} world!

... generates the HTML ...

Hello, <strong>strong</strong> world!

... which renders as:

Hello, strong world!

2. Motivation

Many similar tools (mpark/wg21, bikeshed, etc.) are based on Markdown. This makes them beginner-friendly, but advanced formatting requires heavy use of Markdown extensions or mixed use of Markdown and HTML tags. Metadata such as bibliographies, document information, etc. also rely on yet another format (e.g. JSON, YAML).

This makes these tools difficult to master and makes the design incoherent. Why do we need three languages glued together just to format our documents?

COWEL is the missing middle, the missing link. It makes producing HTML a natural part of the language, lets you specify metadata, and more, all in one, simple syntax.

3. Getting started

COWEL is still early in development, and not available in any package manager yet. To install it and run COWEL:

git clone https://github.com/Eisenwave/cowel.git --recursive cd cowel cmake -B build cmake --build build ./build/cowel-cli INPUT.cow OUTPUT.html

It is recommended to use a .cow or .cowel file extension for COWEL documents.

Many text editors support associating such file extensions with TeX or LaTeX syntax highlighting, whose syntax is similar enough to get some basic highlighting.

A VSCode plugin for proper highlighting is planned, among other features.

4. Syntax in a nutshell

COWEL has a minimalistic but powerful syntax, built on top of only three syntactical constructs:

There is no special syntax besides that, meaning that as long as some bit of code doesn't contain a \, it's all interpreted as plaintext. This makes COWEL exceptionally suited to nest other languages inside of it in code blocks etc.

4.1. Whitespace

COWEL translates very directly into HTML. Any whitespace in text is preserved exactly as is. The way that whitespace is processed then depends on the produced HTML and how it is CSS-styled.

At a top level, whitespace is merged and line breaks are rendered like spaces:

This displays on one line because line breaks render like spaces.

Generated HTML:

<p>This displays on one line because line breaks render like spaces.</p>

Rendered output:

This displays on one line because line breaks render like spaces.

4.2. Paragraph splitting

At the top-level in the document and within the content of certain directives, paragraph splitting takes place. All content in COWEL is either inline content, block content, or meta content. Text and escape sequences are inline content, and directives are sometimes inline and sometimes block content. Certain directives (e.g. \comment) that don't generate anything rendered are meta content.

The process of paragraph splitting works as follows:

COWEL markup:

First paragraph. Second paragraph. \blockquote{This is a block directive.}

Generated HTML:

<p>First paragraph.</p> <p>Second paragraph.</p> <blockquote>This is a block directive.</blockquote>

5. Directives

A directive is a way of generating plaintext, HTML, both, or neither. You can think of it as a "command" or "function call".

Every directive has three parts:

5.1. Directive names

A directive name selects a specific directive to be processed. The name begins with a \ character, followed by any character that is valid in an HTML (custom) tag name. This includes any alphanumeric ASCII characters, U+002D (-), U+002E (.), U+005F (_), and various Unicode characters.

You can use an empty block of content to "cut a name short":

Thisisavery\wbr{}longword.

Doing so is equivalent to writing \wbr and longword immediately following one another.

The use of '.' (period) characters in directive names is deprecated. Currently, \a.b would get parsed as a directive name, but this behavior will be removed in the future. This will result in \a being parsed as a directive name, followed by plaintext .b.

5.2. Directive arguments

Directive arguments can be positional arguments or named arguments. Arguments are separated by commas. Unlike anywhere else, whitespace surrounding directive arguments is ignored.

Arguments provide additional information to a directive.

Often, arguments are converted to HTML attributes.

\b[id = abc]{Bold text.}

Generated HTML:

<b id=abc>Bold text.</b>

5.2.1. Named arguments

Named arguments are of the form name = value, where spaces anywhere around name and value are ignored. Named arguments are matched to directive parameters before any positional arguments, meaning that positional arguments fill the remaining unmatched arguments.

Argument names can consist of any character, except ASCII control characters, U+0020 SPACE, U+0022 ("), U+0027 ('), U+002C (,), U+002F (/), U+003D (=), U+003E (>), U+005B ([), U+005C (\), U+005D (]), U+007B ({), U+007D (}), and noncharacters.

If you want to provide a positional argument that is name = value instead, you can do so by writing:

\comment{"name = value" as a positional argument} \xyz[name \= value] \comment{named argument with name "name" and value "value"} \xyz[name = value]

Only the literal = character can be used for named arguments, not its escaped variant \=.

5.2.2. Positional arguments

Positional arguments are content just like any other content, except that an unbalanced closing U+005D (]) or a U+002C (,) ends the content.

You can use escape sequences to continue otherwise ended content.

\xyz[hello, world] \comment{Two positional arguments} \xyz[hello\, world] \comment{One positional argument containing a comma.} \xyz[hello[]world] \comment{OK, [] is balanced and included in single argument} \xyz[hello\]world] \comment{OK} \xyz[hello\[world] \comment{OK} \xyz[hello[world] \comment{error: unterminated arguments}

5.3. Directive content

The directive content is the primary input to a directive. It is delimited by a '{' and ends with a matching closing '}'. This means that you can have opening and closing braces inside text, but they need to be balanced.

COWEL markup:

\b{Bold text { with braces }.}

Generated HTML:

<b>Bold text { with braces }.</b>

Escape sequences don't participate in this "brace matching", so they can be used to literally produce a brace character.

COWEL markup:

\b{Bold text \{ with brace.}

Generated HTML:

<b>Bold text { with brace.</b>

Unlike in the directive arguments, whitespace is not trimmed.

COWEL markup:

\b{bold} \i{ italic }

Generated HTML:

<b>bold</b> <i> italic </i>

Only one such block of content can be provided, unlike in TeX, which has a similar syntax, but permits multiple blocks. Each block is separated by a pair of braces.

5.4. Directive processing

Unlike in typical programming languages, where the input to a function is processed at the call site and the resulting values are passed into the function, COWEL directives have absolute control over their inputs and how they are processed.

Say you have a JavaScript function:

function f(x) { console.log(x); } f(2 + 2);

f has no idea that its input was originally 2 + 2. It only sees the value 4 and prints it, "oblivious to the outside".

COWEL follows a different model:

\comment{\b{x}}

No <b> tag is ever generated because \b{x} is never processed. \comment is not magical feature; it simply has control over all of its contents and arguments, and it can choose not to process them.

You can even make a \comment2 directive that works just like \comment yourself:

\macro[\comment2]{}

6. Contexts and output

There are two types of contexts: plaintext contexts and HTML contexts. These control what directives (and other content) will generate.

The COWEL text & will be converted to & literally in a plaintext context, and to &amp; in an HTML context.

Any directive is capable of generating either plaintext or HTML, and the output may be substantially different depending on the context.

The \c directive is used to generate HTML character references, aka "HTML entities". It converts its input to plaintext to determine the chosen character. Within such a plaintext context, directives like \b will simply output their content as plaintext:

\c{\b{Omega}} \c{Omega}

Generated HTML:

&Omega; &Omega;

Also, \c will only emit an HTML entity in an HTML context. In a plaintext context (such as in the input to \c), it outputs the character directly. For example, if we write:

\c{\c{Omega}}

The generated (malformed) HTML is:

&Ω;

7. Themes

COWEL outputs documents that can be viewed in light mode and dark mode.

When the document is opened with support for JavaScript, there is an button in the top-right that can be used to switch between three modes:

Forced light/dark mode works by adding a light or dark class to the <html> element in the DOM.

If you want to customize colors with CSS, remember to make them respond to theme and OS preference changes.

For reference, you can look at the CSS in the COWEL source code to see how it's done properly.

8. List of directives

8.1. Comments

Unlike many other markup languages, COWEL has no dedicated syntax for comments. However, there exists a \comment directive which you can use to put comments into code.

8.1.1. \comment — Comments

The \comment directive does not process its arguments or content. It outputs no plaintext or HTML.

While comments don't output anything, §4.2. Paragraph splitting is based on blank lines in the source, so comments don't split paragraphs:

Text \comment{This is \directive{comment} content.} Text

Generated HTML:

<p>Text Text</p>

8.2. Text formatting

COWEL allows for basic text formatting using various directives. Many of the formatting directives are some direct equivalent of an HTML element. For these, there is a fixed HTML element that will always be used. You can rely on this when adding custom CSS.

Directive HTML Renders as
\b{...} <b>...</b> Bold text
\cite{...} <cite>...</cite> Name of cited work
\del{...} <del>...</del> Deleted text
\dfn{...} <dfn>...</dfn> Definition
\em{...} <em>...</em> Emphasized text
\gterm{...} unspecified grammar-term
\i{...} <i>...</i> Italic text
\ins{...} <ins>...</ins> Inserted text
\kbd{...} <kbd>...</kbd> Ctrl + Keyboard key
\mark{...} <mark>...</mark> Marked/highlighted
\o{...} unspecified Oblique text
\q{...} <q>...</q> Quoted text
\s{...} <s>...</s> Struck text
\samp{...} <samp>...</samp> Sample output
\sans{...} unspecified Sans-serif font
\serif{...} unspecified Serif font
\small{...} <small>...</small> Small text
\span{...} <span>...</span> (No change in formatting)
\sub{...} <sub>...</sub> Subscript
\sup{...} <sup>...</sup> Superscript
\strong{...} <strong>...</strong> Strong text
\tt{...} unspecified Teletype/monospace font
\var{...} <var>...</var> Variable name
\u{...} <u>...</u> Underlined text

All such formatting directives convert all named arguments directly into HTML attributes.

By default, a substantial amount of directives are styled the same way. For example, \cite, \var, \i and \em are all italic. Both \strong and \b are bold. Both \tt and \samp use teletype font.

However, you can customize the style; see §8.13.6. \style — CSS blocks.

The difference between oblique (\o) and italic (\i) text is that oblique text is merely slanted, while italic text is fundamentally a different font with different characters.

8.3. Code and syntax highlighting

COWEL uses µlight for syntax highlighting. While the set of supported language is relatively small, the highlighter is ultra-light, extremely fast, and deals with modern C++ features correctly.

8.3.1. \code — Inline code

The \code directive produced syntax-highlighted text in code font.

Arguments
  • lang (plaintext) — the syntax highlighting language.
  • nested (yes/no) — whether whether to omit <code> tags.
  • prefix (plaintext) — code before the input from the view of the highlighter.
  • suffix (plaintext) — code after input from the view of the highlighter.
Input content
The input to a \code directive is a plaintext context. However, there are special rules for formatting directives and pure plaintext directives (see below).
HTML output
In an HTML context, the \code takes the input source code, applies syntax highlighting, and outputs the result surrounded by <code>...</code>.
Plaintext output
In a plaintext context, \code simply outputs the input source code.
Display style
Inline

COWEL markup:

\code[cpp]{123}

This applies C++ syntax highlighting, and generates HTML. The <h-> tags are an implementation detail and may be subject to change.

<code><h- data-h=num>123</h-></code>
8.3.1.1. Manual nested highlighting

The nested parameter is a plaintext context, which accepts either yes or no, where no is the default. When enabled, the surrounding <code> tags are omitted, which makes it suitable for nesting languages within other \code or \codeblock directives.

You can nest JSON inside of a C++ string literal as follows:

Call: \code[cpp]{out.write_json("\code[json,nested=yes]{{"x":123,"y":true,"z":null}}")}

This renders as follows:

Call: out.write_json("{"x":123,"y":true,"z":null}")

Note that by default, you may often not even notice a visual difference between using the nested parameter and not using it. However, the difference would be obvious once you want to style <code> elements to have borders, background color, padding, and other such styling features. nested=yes directly emits the highlighting HTML elements, which is more composable.

8.3.1.2. Highlighting prefix and suffix

The prefix and suffix parameters are plaintext contexts which can be used to further control highlighting. Especially with inline code, the highlighting depends on the surrounding code.

prefix and suffix can be used to provide that surrounding code, without becoming part of the highlighted output.

Using prefix, we can control whether a JSON string is interpreted as a markup key, or as a string value:

In JSON, there are \code[json,prefix=\{]{"keys"} and \code[json]{"values"}.

This renders as:

In JSON, there are "keys" and "values".

Notice that the color of "keys" is different because it is interpreted as if it was positioned like:

{"keys"
8.3.1.3. Further advice on highlighting

Writing \code directives directly is often too tedious, so you'll likely want to define a macro to make this easier:

\comment{Defines a \js directive that can be used in place of \code[js] from now on:} \macro[\js]{\code[js]{\put}} Let's highlight \js{var} in JavaScript.

8.3.2. \codeblock — Code blocks

The \codeblock directive works exactly like \code, but it is a block directive, not an inline directive.

Additionally, code blocks render using borders and a dark background by default. This can be controlled using the borders.

\codeblock[js]{ // Borders enabled let x = 0; } \codeblock[js,borders=no]{ // Borders disabled let x = 0; }

This renders as:

// Borders enabled let x = 0; // Borders disabled let x = 0;

8.3.3. \hl — Syntax highlight override

The \hl directive forces certain syntax highlighting to be applied to some text; it is a manual override for when automatic syntax highlighting is insufficient or broken. It displays as inline content and wraps its content (which is an HTML context) in the appropriate syntax highlighting tags.

It has a single name argument, which is the µlight long name for a highlight type. You can obtain a list of possible long names at ulight.h from the definition of enum ulight_highlight_type. The long name is the enumerator name without the ULIGHT_HL prefix, all lowercase, and with hyphens instead of underscores.

It is possible to mix automatic syntax highlighting with manual overrides:

\comment{_Int128 is manually highlighted as a type keyword, and x is automatically highlighted as an identifier} \code[c]{\hl[keyword-type]{_Int128} x}

This generates the HTML (subject to change):

<code><h- data=h=kw_type>_Int128</h-> <h- data-h=id>x</h-></code>

It renders as _Int128 x.

While it is also possible to produce the highlighting tags using \html-h-[data-h=kw_type]{_Int128}, the "short names" (kw_type) are not stable, i.e. they are more likely to change. Only µlight long names should be used directly.

8.3.4. \pre — Preformatted blocks

The \pre directive contains pre-formatted content. It can be used to contain code, however, there is no syntax highlighting in a \pre block.

COWEL markup:

\pre{ Hello, world! ============= a b c }

This renders as:

Hello, world!
=============
    a b c

Unlike \codeblock, \pre currently does not support the borders=no option. This will be added in the future.

8.3.5. \literally — Treat input literally as text

The \literally directive treats its input source code as plain text, even if it contains directives or escape sequences. It outputs the given input source code as text.

Its content is an unprocessed context, and it takes no arguments.

COWEL markup:

\pre{\literally{ This \comment{comment} \{ is taken literally \}! }}

This renders as:

This \comment{comment} \{ is taken literally \}!

\put pseudo-directives in macros are still processed, even inside \literally blocks because \macro replaces any appearances of \put with the given content, disregarding the semantics of any directives nested within.

8.3.6. \unprocessed — Suppress directive processing

The \unprocessed directive works just like \literally, except that escape sequences are processed into their escaped characters.

COWEL markup:

\pre{\unprocessed{ This \comment{comment} \{ is unprocessed \}! }}

This renders as:

This \comment{comment} { is unprocessed }!

\unprocessed and (to a lesser extent) \literally are very useful for nesting code inside COWEL that already contains underscores. For example, \n is an escape sequence for newline characters in many languages, and it may be annoying if it gets interpreted as an \n directive:

\codeblock[cpp]{\unprocessed{ std::string_view s = "Several\nLines\nof\nCode."; }}

This renders as:

std::string_view s = "Several\nLines\nof\nCode.";

Notice that COWEL technically parses a \nLines directive instead of just \n, which is the part that turns into a newline escape sequence in the C++ code block. However, that is ultimately irrelevant for syntax highlighting because the source characters of \nLines are taken as text, and then split up according to C++ syntax.

\put pseudo-directives in macros are still processed, even inside \unprocessed blocks because \macro replaces any appearances of \put with the given content, disregarding the semantics of any directives nested within.

8.4. Math

In recent years, browser support for MathML within HTML has become widespread. COWEL relies entirely on the browser for properly rendering math as MathML, which is very simple and lightweight, but not as portable as "baking" the math into an SVG.

If you have existing MathML, you can embed their content using \html or \htmlblock:

Math \html{ <math display=inline> <mfrac> <mi>x</mi> <mn>2</mn> </mfrac> </math> } in a sentence.

This renders as:

Math x 2 in a sentence.

You can also keep the MathML separate within an XML document and \include it:

Math \html{\include{math.mml}} in a sentence.

However, hand-writing MathML would be extremely tedious and verbose, so COWEL offers some convenience directives, listed below.

8.4.1. \math — Inline math

A \math directive surrounds its content with <math display=inline>...</math> tags, and displays as inline content.

Its content is an HTML context, and within it, additional pseudo-directives like \mi or \mn corresponding to MathML elements can be used. Essentially, this allows you to build MathML using COWEL syntax.

See Mozilla's MathML elements reference for a list of supported elements/directives.

The previous example in §8.4. Math could also be written like:

Math \math{ \mfrac{\mi{x}\mn{2}} } in a sentence.

If you frequently use math inside plain sentences, you can define a convenience macro:

\macro[\mathsqr{...}]{\math{\msup{\mi{\put}\mn{2}}}} The sum of \mathsqr{x} and \mathsqr{y}

This renders as:

The sum of x2 and y2

8.4.2. \mathblock — Math blocks

The \mathblock directive functions almost exactly as the \math directive, but it displays as block content instead of inline content, and it produces an opening <math display=block> tag.

8.5. Separators and word breaking

8.5.1. \br — Break line

The \br directive produces a line break, and corresponds to the HTML element <br/>. It displays as inline content, and its input content is ignored.

\br is particularly useful when line breaks are treated same as spaces, which is the case in most HTML content.

8.5.2. \hr — Horizontal rule

The \hr directive produces a horizontal rule, and corresponds to the HTML element <hr/>. It displays as block content, and its input content is ignored.

Here is an example:


8.5.3. \wbr — Word break opportunity

The \wbr directive produces a word break opportunity, and corresponds to the HTML element <wbr>. It displays as inline content, and its input content is ignored.

<wbr> elements can be inserted into the middle of long words, which, if they don't fit on one line, will be broken at the point of the <wbr> element (without a hyphen at the end of the line).

Since µlight only supports UTF-8 output, \wbr is equivalent to \U{200B}, which outputs a U+200B ZERO-WIDTH SPACE code point.

If you want to provide a word break hint but have a hyphen at the end of the line, use \U{AD} or \c{shy} to output a U+00AD SOFT HYPHEN.

8.5.4. \nobr — Unbroken words

The \nobr directive is a formatting directive which prevents word breaks within its content. Its content is an HTML context. This is done by applying a white-space: nowrap; style its content.

Another way to prevent word-breaking is to use non-breaking spaces. You can insert these using

8.5.5. \word — Deprecated alias for \nobr

This directive is deprecated and will be removed in the future.

The \word directive has the same effect as \nobr.

8.6. Special characters

It is quite common that a text document should include special characters. While COWEL is built on UTF-8, and in theory one could just write the character directly into the source code, not every text editor handles special characters well.

To increase portability, COWEL has the \U and \c directives.

8.6.1. \U — Code point literal

The input to a \U directive is a plaintext context, which should be a sequence of hexadecimal numbers specifying a Unicode scalar value; that is, a code point which UTF-8 permits to be encoded.

\U{30} generates '0' U+0030 DIGIT ZERO.

Like anywhere else, directives inside of \U are allowed.

8.6.2. \N — Code point by name

The \N directive behaves almost identically to \U, except that its input has to be a Unicode name rather than a hex digits. That is, the name of a code point, or one of its "control", "alternate", or "correction" aliases.

\N{DIGIT ZERO} generates '0' U+0030 DIGIT ZERO.

\N can lead to much more descriptive, human-friendly code, compared to \U.

The main issue with \U is that it is very non-descriptive in source code. It simply contains a handful of digits, and unless the reader is a Unicode expert who happens to know that sequence, they cannot easily tell what the purpose of the character is.

8.6.3. \Udigits — Digits of code point

The \Udigits directive is essentially the inverse of the \U directive. Its input is also a plaintext context; rather than producing a code point from a digit sequence, it produces a digit sequence from its input code point.

This can be fine-tuned with the following parameters:

zfill
The minimum amount of digits that should be produced. This is an integer argument in range [0, 1024], and defaults to zero. If the amount of digits is less than zfill, it will be left-padded with additional '0' characters.
base
The base of the output digit sequence, in range [2, 16]. This defaults to 16, meaning that the digits are printed in hexadecimal.
lower
A yes/no plaintext argument, defaulting to no. If yes is specified, digits beyond '9' (i.e. 'A' to 'F') will be output in lower case instead.

COWEL markup:

U+\Udigits[4]{x}

This renders as:

U+0078

Note that U+0078 is the usual way in which Unicode code points are represented. That is, U+, followed by at least four hexadecimal digits. It is also possible to define a macro if we need this frequently:

\macro[\code-point]{U+\Udigits{\put}} \code-point{x}

\Udigits can also be combined with \N to produce human-readable descriptions of code points, while also keeping our source code readable:

\macro[\named-char{...}]{U+\Udigits[4]{\N{\put}} \put} \named-char{SECTION SIGN}

This renders as:

U+00A7 SECTION SIGN

\Udigits uses only the first code point within the input text, even though the entire input text is processed into plaintext.

If we provide more than a single code point, some input is discarded:

\Udigits{abc}

This renders as

61

... which corresponds to a, whereas b and c are discarded.

8.6.4. \c — Character references

The input to a \c directive is a plaintext context, where the same content is permitted as for HTML character references, aka. HTML entities, between '&' and ';'.

Using \U and \c, the '&' character can be produced in a number of ways:

In an HTML context, \c{xyz} is literally translated into &xyz;. In a plaintext context, the character reference is mapped onto its corresponding code point(s), and those code points are output directly.

Like anywhere else, directives inside of \c are allowed.

8.7. Special blocks

Often, the content we write falls into some special category like "example", "note", etc. COWEL supports a large number of special block directives, which wrap their content in a block, with background color, borders, etc.

The input to all special block directives is an HTML context, they all convert their arguments to HTML attributes, and they all display as block content.

8.7.1. \Babstract — Abstract blocks

Abstracts provide a summary of the document.

8.7.2. \Bquote — Quote blocks

The \blockquote directive directly corresponds to the <blockquote> element.

Quotes blocks or "block quotes" display quoted text.

8.7.3. \blockquote — Alias for \Bquote

The \blockquote directive is equivalent to the \Bquote directive.

8.7.4. \Bug — Bug blocks

A bug block contains the description of a bug. This often includes a code block which demonstrates how to reproduce the bug.

8.7.5. \Bdecision — Decision blocks

A decision block indicates that a decision needs to be made.

8.7.6. \Bdel — Deletion blocks

A deletion block acts as a wrapper for a large amount of deleted content. It is typically used when individual \del directives would be too tedious to use.

8.7.7. \Bdetails — Details blocks aka spoilers

The \Bdetails directive directly corresponds to the <details> element. Within \Bdetails, the \summary directive can be used to specify summary text.

This is a summary. Click to open! A details block contains details which need to be revealed by the user. This is also referred to as "spoiler".

8.7.8. \details — Alias for \Bdetails

The \details directive is equivalent to the \Bdetails directive.

8.7.9. \Bdiff — Difference blocks

A difference block contains changes, where some content within is typically deleted or inserted.

8.7.10. \Bex — Example blocks

An example block contains examples.

8.7.11. \Bins — Insertion blocks

A deletion block acts as a wrapper for a large amount of inserted content. It is typically used when individual \ins directives would be too tedious to use.

8.7.12. \Bimp — Important blocks

Important blocks contain especially important information.

8.7.13. \Bnote — Note blocks

Note blocks contain less important information, which can often be skipped over by readers.

8.7.14. \Btip — Tip blocks

Tip blocks contain useful advice.

8.7.15. \Btodo — TODO blocks

TODO blocks contain actions that remain to be done. They may indicate that a part of a project is incomplete.

8.7.16. \Bwarn — Warning blocks

Warning blocks warn the reader of some hazard or potential mistake.

8.7.17. Deprecated aliases

Some of the special blocks also have alternative spellings which only exist for compatibility with past versions. The new naming scheme is for all special blocks to have a \B* name.

These directives are deprecated and will be removed in a future version.

8.7.17.1. \bug — Deprecated alias for \Bug
8.7.17.2. \decision — Deprecated alias for \Bdecision
8.7.17.3. \delblock — Deprecated alias for \Bdel
8.7.17.4. \diff — Deprecated alias for \Bdiff
8.7.17.5. \example — Deprecated alias for \Bex
8.7.17.6. \insblock — Deprecated alias for \Bins
8.7.17.7. \important — Deprecated alias for \Bimp
8.7.17.8. \note — Deprecated alias for \Bnote
8.7.17.9. \tip — Deprecated alias for \Btip
8.7.17.10. \todo — Deprecated alias for \Btodo
8.7.17.11. \warning — Deprecated alias for \Bwarn

8.8. Lists

8.8.1. \ul — Unordered lists

The \ul directive corresponds to the <ul> element, and produces an unordered list.

8.8.2. \ol — Ordered lists

The \ol directive corresponds to the <ol> element, and produces an ordered list.

8.8.3. \li — List items

The \li directive corresponds to the <li> element, and produces a list item with <ul> or <ol>.

COWEL markup:

\ul{ \li{first bullet} \li{second bullet} } \hr \ol{ \li{first bullet} \li{second bullet} }

This renders as:


  1. first bullet
  2. second bullet

8.8.4. \item — List item pseudo-directive

This directive is deprecated and will be removed in a future version.

Within \ul and \ol, the \item pseudo-directive can also be used instead of \li.

8.8.5. \dl — Definition lists

The \dl directive corresponds to the <dl> element, and produces a definition list. Within that list, you can use

8.9. Tables

Tables are simply produced by using the \table, \thead, \tbody, \tfoot, \tr, \th, \td, \colgroup, \col, and \caption directives to produce the corresponding HTML tags with the same name.

To perform advanced styling, like controlling alignment within columns, use a \style directive.

8.10. Headings

Headings can be produced using the \h1, \h2, \h3, \h4, \h5, and \h6 directives to produce the corresponding HTML tags with the same name.

Headings take a listed argument, which is a yes/no plaintext argument. Unless its value is no, headings are numbered and added to the table of contents (§8.10.1. \make-contents — Make table of contents) automatically.

Headings also take a show-number argument, which is a yes/no plaintext argument. Unless this is no, the heading number will be included in the title, in the format 1.2.3. Title. However, even if show-number is no, the number heading is internally numbered as usual, and its number can be seen in the table of contents.

Other arguments to these headings are converted into attributes of the corresponding HTML element. An id argument can be provided explicitly.

If none is provided, an id is synthesized from the content within the heading.

Headings can be referenced using the \ref directive:

\h2{Heading with synthesized id} \h2[id=xyz]{Heading with manual id} \comment{These can be referenced as follows} \ref[#heading-with-synthesized-id] \ref[#xzy]

8.10.1. \make-contents — Make table of contents

The \make-contents directive generates the table of contents, which is comprised of all the headings within the document. It takes no arguments and its content is ignored. It displays as a block.

The table of contents is is populated by headings (§8.10. Headings) as the document is processed.

Since the table of contents should usually not be listed within itself, an unlisted heading may be used:

\h2[listed=no]{Contents} \make-contents

A similar effect can be achieved using \html-h2 (§8.13.3. \html-* — HTML element literals). However, using \html-h2 will also not emit a link icon in the gutter, and it will not synthesize an id for that heading.

The underlying contents can be obtained with \here[std.contents]. \make-contents additionally wraps those contents in HTML elements to chang their visual appearance.

8.11. Bibliography

In technical writing it is common for documents to reference other papers, and it is expected that references are properly cited. To support this,

COWEL provides directives for adding bibliography entries, and for generating a bibliography automatically.

8.11.1. \bib — Add bibliography entry

The \bib directive adds a single entry to the bibliography. Its content is ignored, and it displays as a meta directive.

It has a number of parameters, each of which is a plaintext context:

id
The identifier of the bibliography entry. This can later be referenced using \ref[id].
author
The name of the author(s). This is in no particular format, and if you want to provide multiple authors, you can do so via a comma-separated list here.
title
The title of the cited work.
date
The date of publication. No particular format is enforced; this is simply a string, so you can choose some local format.
publisher
The name of the publisher.
link
The primary link to the document. This should typically be a short link because it is copied into each \ref to the bibliography entry.
long-link
A "long link" to the document. If present, this will be rendered within the bibliography, and it is typically meant to be a semantic or more stable link than the link. You can also think of it as a "link for pretty printing".
issue-link
A link to issue tracking for the document. For example, in WG21 circles, this may be a link to the GitHub issue where a paper is tracked.

Every argument except the id is optional, although you will hardly get meaningful bibliography output if only the id is specified.

8.11.2. \make-bib — Generate bibliography

The \make-bib directive generates a bibliography. This is typically done towards the bottom of the document, but can be done anywhere.

It takes no arguments, its content is ignored, and it displays as a block.

The \make-bib directive is populated by uses of \bib directives in order of use. That is, the bibliography is not automatically sorted for you; the order in which \bib directives are used is also the order in which the bibliography entries are generated.

Similar to \make-contents, it is a wrapper for the underlying std.bib section.

8.12. References

8.12.1. \ref — References

The \ref directive takes a single to argument, which can be a URL, anchor, or something else. It produces an <a> tag with some content inside.

The content is an HTML context, and is what actually gets displayed. If no content is provided, it can be synthesized from the following types of references:

COWEL markup:

\ref[mail:john@us.gov]

HTML output (<a> tag may have additional attributes):

<a href=mail:john@us.gov>john@us.gov</a>

C++ standard draft links can be synthesized into human-readable descriptions.

\ref[https://eel.is/c++draft/expr#1]

This renders as:

8.12.2. \mail — E-Mail addresses

A \mail directive behaves the same \ref directive that is given a mailto URL. However, the input is provided as content instead of an argument, and the displayed text cannot be customized.

The following two lines produce the same output:

Please contact \mail{john@us.gov}. Please contact \ref[mailto:john@us.gov].

8.12.3. \tel — Telephone numbers

A \tel directive behaves the same \ref directive that is given a tel URL. However, the input is provided as content instead of an argument, and the displayed text cannot be customized.

The following two lines produce the same output:

Please contact \tel{+1234}. Please contact \ref[tel:+1234].

8.13. Foreign languages

8.13.1. \html — Inline HTML

The \html directive can be used to output HTML literally. Its content is a plaintext context, and it displays as inline content.

COWEL markup:

This is \html{<b>bold text</b>}.

Generated HTML:

This is <b>bold text</b>.

The \html directive can produce malformed HTML content if you're not careful. See, §8.13.3. \html-* — HTML element literals for a safer option.

8.13.2. \htmlblock — HTML blocks

The \htmlblock directive works exactly like the \html directive, but displays as block content instead of inline content.

The \htmlblock directive can produce malformed HTML content if you're not careful. See, §8.13.3. \html-* — HTML element literals for a safer option.

8.13.3. \html-* — HTML element literals

Any directive beginning with \html- can be used to produce an HTML element directly. Its content is a plaintext context, and it displays as inline content. Arguments are converted to HTML attributes of the produced tag.

COWEL markup:

This is \html-span[id=abc]{a span}.

Generated HTML:

This is <span id=abc>a span</span>.

8.13.4. \script — JavaScript blocks

The content of a \script directive is a plaintext context, where the input is treated as JavaScript code and surrounded in <script>/*...*/</script> tags.

\script displays as meta content (like \comment).

COWEL markup:

\script{ console.log("hello"); }

Generated HTML:

<script> console.log("hello"); </script>

8.13.5. \noscript — No-JavaScript content

The \noscript directive corresponds to the <noscript> element. Its content is an HTML context, and will only be shown by the browser when JavaScript is disabled.

8.13.6. \style — CSS blocks

The content of a \style directive is a plaintext context, where the input is treated as JavaScript code and surrounded in <style>/*...*/</style> tags.

\style displays as meta content (like \comment).

COWEL markup:

\style{ body { color: red; } }

Generated HTML:

<style> body { color: red; } </style>

8.14. Paragraph control

In some cases, the automatic §4.2. Paragraph splitting process is not enough. To get more fine-tuned control, we have a number of directives.

8.14.1. \p — Paragraphs

The \p directive surrounds its content in <p>...</p> tags.

8.14.2. \paragraphs — Enable paragraph splitting

The \paragraphs directive activates paragraph splitting. This may be useful in places where it is not active by default.

COWEL markup:

\ul{ \item{\paragraphs{ First paragraph in bullet. Second paragraph. }} }

Generated HTML:

<ul> <li> <p>First paragraph in bullet.</p> <p>Second paragraph in bullet.</p> </li> </ul>

8.14.3. \block — Display as block content

The \block directive doesn't add any HTML itself, but causes its contents to be considered block content.

\block can be used to suppress automatic paragraph splitting:

\comment{No <p> tags will be added here} \block{ First paragraph. Second paragraph. }

8.14.4. \inline — Display as inline content

The \inline directive works like the \block directive, but causes its contents to display as inline content, not as block content.

8.15. Sections

Often, you want to produce content in one place, but have it display in another place within the document. A classic example is collecting headings automatically in a table of contents, or copying the content of a heading into a preview when referenced by \ref[#id].

8.15.1. \there — Append content to section

The \there directive displays as meta content. Basically, it stashes away its input content (which is an HTML context) somewhere else.

It takes a single section argument which specifies the name of the section. The section argument is a plaintext context.

By default, all document content is placed within a <main> element, inside <body>, inside html. \there allows you to write outside of the <main> element:

You can change the title of the document as follows:

\there[std.head]{ \html-title{This is the document title!} }

8.15.2. \here — Copy section content

The \here directive inserts the content from another section at its location. It displays as inline content.

It takes a single section argument which specifies the name of the section. The section argument is a plaintext context.

All references produced by \here are resolved in a post-processing step, which allows forward-references.

COWEL markup:

\there[sec]{before/} (\here[sec]) \there[sec]{/after}

Generated HTML:

(before//after)

8.15.3. \hereblock — Copy section content in block

The \hereblock directive functions exactly like the \here directive, but displays as block content instead of inline content.

8.16. File management

Once projects get larger, it often becomes difficult to manage everything in a single file. Also, tooling may benefit from having separate files. For example, keeping separate SVG files or CSS files may have better IDE support than writing these out directly inside of COWEL.

COWEL provides directives to load content from other files.

8.16.1. \include — Include text from a file

The \include directive produces plaintext by loading the text contents of another file, relative to the directory of the document.

It has no arguments, and its content is a plaintext context in which the path is specified.

Say we have a JavaScript file example.js which we want to keep separate from the document. We can then include it into a \script block to use it as a script, or we can include it into a \codeblock to display its contents.

\codeblock[js]{ // code included from example.js: \include{example.js} }

Assuming that example.js is located in the same directory as the document and that loading the file succeeds, this renders as:

// code included from example.js: function sqr(x) { return x * x; }

Directives and any other COWEL content within the file are not processed. \include simply takes the text content of the file and generates plaintext from it.

However, when the directive is used in an HTML context (like if we simply use \include in the middle of the document), it is subject to escaping (&&amp;, etc.) just like any other text. In other words, you are also safe from HTML tags inside of included text breaking the document, barring a few directives, like \html or \script; no such escaping takes place inside of \script.

8.16.2. \import — Import a sub-document

The \import directive loads the content from another COWEL document, substitutes the \import directive for those contents, and processes them.

It has no arguments, and its content is a plaintext context in which the path is specified.

While \import and \include are similar, there are some stark differences:

Say we have another test.cow files containing:

Hello, \strong{imports}! Next paragraph.

When using \import, the contents of the other file are substituted where we have written \import, which means that imported content also plays nicely with paragraph splitting:

First paragraph. \import{test.cow}

Generated HTML:

<p>First paragraph. Hello, <strong>imports</strong>!</p> <p>Next paragraph.</p>

It is common practice to collect macros and other reusable components in separate documents, and to \import them when needed. This can help you avoid copying boilerplate between multiple documents.

It is also common to split documents into multiple files that are combined using a sequence of \imports.

8.17. Macros

8.17.1. \macro — Define a macro

The \macro directive defines a macro, which is basically a user-defined directive. It has a single pattern argument, which shall be a single pattern directive which describes the defined directive.

The arguments and content of the pattern directive are not processed, but can be used to document how the directive is meant to be used.

\comment{The following two definitions are equivalent:} \macro[\m{...}]{xyz} \macro[\m]{xyz}

Within macros, uses of the \put pseudo-directive are replaced with the inputs to the macro. There are multiple forms of the \put which expand different parts of the macro input.

The content of a \put directive is a plaintext context, and specifies which part of the provided content or arguments should be used.

8.17.2. \put{} — Replaced with provided content

A \put directive with no given content (or empty/blank content) is replaced with the content provided to the macro upon use.

\macro[\bi]{\b{\i{\put}}} \comment{Now, the following are equivalent:} \b{\i{bold and italic}} \bi{bold and italic}

8.17.3. \put{0}, \put{1}, … — Replaced with argument

When the content provided to \put is an integer, the corresponding argument is selected, where 0 represents the first argument.

Additionally, such a \put directive has an else parameter, which replaces the \put directive if not enough positional arguments were provided to the macro. If there is no else argument, this would result in an error instead.

\macro[\arg0]{\put[else = otherwise]{0}} \arg0[abc]{xyz} \arg0{xyz}

After macro substitution, this markup is equivalent to:

abc otherwise

Notice that xyz is ignored in either case because there is no \put{} that would make use of it.

The second macro invocation \arg0{xyz} would result in an error if no else argument was provided.

8.17.4. \put{...} — Forwarding provided arguments

\put{...} (where the given content is three periods) expands to all provided macro arguments. It shall only appear as a positional argument to a directive, with no surrounding content. That is:

\put{...} is especially useful when creating "wrapper macros" for other directives:

\macro[\js_block]{\codeblock[lang=js,\put{...}]{\put}} \comment{ \js_block now acts as a shorthand for JavaScript blocks, and thanks to forward with \put{...}, we can provide further arguments to the underlying \codeblock directive. } \js_block[borders=no]{ function sqr(x) { return x * x; } }

After macro substitution, this markup is equivalent to:

\codeblock[lang=js,borders=no]{ function sqr(x) { return x * x; } }

8.17.5. Avoiding name collisions

Since COWEL continuously adds more directives in the future, you should try to avoid names that may collide with those when defining your own macros. COWEL builtin directive names only use alphanumeric characters and '-'.

The '_' character can be used as part of directive names, and COWEL will never use this in its own names. Therefore, you should try to "namespace" your own macros like:

\macro[\abc_i]{macro definition here ...} \abc_i

8.18. Miscellaneous

8.18.1. \div — Content division

The \div directive surrounds its contents in <div>...</div> tags. It displays as a block, and its content is an HTML context. \div's named arguments are turned into HTML attributes.

8.18.2. \trim — Trim input

The content of a \text directive is an HTML context (§6. Contexts and output). Its arguments are ignored. \text is a formatting directive.

The process of trimming eliminates leading and trailing whitespace in the input, at the COWEL source level.

Every\trim{ day}

This renders as:

Everyday

\trim is primarily useful inside of macros. We might not want to space-separate content if some of it is empty. For example, we could define a \Note macro where the user can optionally provide a number for that note:

\macro[\Note]{\trim{Note \put}:} \Note Something something. \Note{1} Something else.

This renders as:

Note: Something something.

Note 1: Something else.

Notice that because \put expands to no content, the trailing space after Note is eliminated. If it wasn't eliminated, we would end up with {Note :}, but there should never be a space before the colon.

8.18.3. \text — Plaintext context

The content of a \text directive is a plaintext context (§6. Contexts and output). Its arguments are ignored.

It simply outputs the input that it was given as text. Therefore, it acts as a sort of wrapper for plaintext. Notably, this forces the generation of plaintext even when \text is within an HTML context.

8.19. Variables and calculations

While COWEL is not intended to be general purpose programming language, and more advanced interactive features are better suited for JavaScript, it does provide a few ways to perform calculations.

8.19.1. \Vset — Set a variable

\Vset sets the value of a variable to some provided plaintext. It displays as a meta directive.

It takes a single var argument, which is a plaintext context for the name of the variable. The directive content is also a plaintext context, and provides the value of the variable.

COWEL markup:

\comment{Sets x = 123} \Vset[x]{123} \comment{Accesses the value of x, which is 123} \Vget[x]

This renders as:

123

8.19.2. \Vget — Get a variable

\Vget obtains the value of a variable, and displays as inline. Its content is ignored.

It takes a single var argument, which is a plaintext context for the name of the variable. See above for an example.

If the variable denoted by the var argument does not exist, \Vget expands to nothing.

8.19.3. \Cadd — Perform addition

The \Cadd directive performs an integer addition between its (nameless) arguments. Its content is ignored, and it displays as inline.

Each of its arguments is a plaintext context, where the argument is interpreted as an integer, and then summed.

COWEL markup:

\Cadd[1, 2, 3, -1] \comment{1 + 2 + 3 + (-1)}

This renders as:

5

You can also combine \Cadd with \Vget and \Vset to store the results of your calculations:

\comment{Reset paragraph number} \Vset[index]{0} \comment{Define a macro for automatically incrementing paragraph numbers.} \macro[\p.num]{ \Vset[index]{\Cadd[\Vget[index],1]} \Vget[index] } Paragraph \p.num Paragraph \p.num

This renders as:

Paragraph 1

Paragraph 2

\Cadd and other calculation directives are mainly intended for incrementing paragraph numbers and other basic tasks.

8.19.4. \Csub — Perform subtraction

The \Csub directive behaves like the \Cadd directive, except that it performs subtraction instead of addition.

8.19.5. \Cmul — Perform multiplication

The \Cmul directive behaves like the \Cadd directive, except that it performs multiplication instead of addition.

8.19.6. \Cdiv — Perform division

The \Cdiv directive behaves like the \Cdiv directive, except that it performs division instead of addition.

Division by zero results in an error.