Compact Web Language (COWEL)
Contents
Introduction
Getting started
Motivation
Syntax in a nutshell
Whitespace
Paragraph splitting
Directives
Directive names
Directive arguments
Directive content
Contexts and output
Themes
List of directives
Comments
\comment
— Comments
Text formatting
Code and syntax highlighting
\code
— Inline code
\codeblock
— Code blocks
\hl
— Syntax highlight override
\pre
— Preformatted blocks
Math
\math
— Inline math
\mathblock
— Math blocks
Separators and word breaking
\br
— Break line
\hr
— Horizontal rule
\wbr
— Word break opportunity
\word
— Unbroken words
Special characters
\U
— Code point literal
\c
— Character references
Special blocks
\abstract
— Abstract blocks
\blockquote
— Quote blocks
\bug
— Bug blocks
\decision
— Decision blocks
\delblock
— Deletion blocks
\details
— Details blocks aka spoilers
\diff
— Difference blocks
\example
— Example blocks
\insblock
— Insertion blocks
\important
— Important blocks
\note
— Note blocks
\tip
— Tip blocks
\todo
— TODO blocks
\warning
— Warning blocks
Lists
\ul
— Unordered lists
\ol
— Ordered lists
\dl
— Definition lists
Tables
Headings
References
\ref
— References
\mail
— E-Mail addresses
\tel
— Telephone numbers
Foreign languages
\html
— Inline HTML
\htmlblock
— HTML blocks
\html-*
— HTML element literals
\script
— JavaScript blocks
\noscript
— No-JavaScript content
\style
— CSS blocks
Paragraph control
\p
— Paragraphs
\paragraphs
— Enable paragraph splitting
\block
— Display as block content
\inline
— Display as inline content
Sections
\there
— Append content to section
\here
— Copy section content
\hereblock
— Copy section content in block
Macros
\def
— Define a macro
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.
... generates the HTML ...
... which renders as:
2. Getting started
COWEL is still early in development, and not available in any package manager yet. To install it and run COWEL:
3. 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.
4. Syntax in a nutshell
COWEL has a minimalistic but powerful syntax, built on top of only three syntactical constructs:
\ various-directives [ positional args, named-args = 0] { and content} Text.
- Escape sequences, such as
,\ {
,\ }
, etc.\ \
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.
Generated HTML:
Rendered output:
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.
) that don't generate anything rendered are meta content.
The process of paragraph splitting works as follows:
-
Blank-line-separated blocks of inline content is wrapped in in
tags. Meta content is not counted as a blank line, so it "continues" inline content, but no effort is made to wrap it in< p > ...</ p >
.< p > ...</ p > -
Block content stays untouched, i.e. it is not wrapped in
. However, it also terminates prior inline content, like a blank line.< p > ...</ p >
Generated HTML:
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:
- The
selects a specific directive to be processed.\ directive-name -
An optional
[comma-separated, positional arguments, named-arguments = ...]
provides additional inputs to the directive. -
An optional
{block of content}
provides a "main input" to a directive.
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,
'
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.
Generated HTML:
5.3. Directive content
The directive content is the primary input to a directive.
It is delimited by a '
Generated HTML:
Escape sequences don't participate in this "brace matching", so they can be used to literally produce a brace character.
Generated HTML:
Unlike in the directive arguments, whitespace is not trimmed.
Generated HTML:
6. Contexts and output
There are two types of contexts: plaintext contexts and HTML contexts. These control what directives (and other content) will generate.
&
will be converted to
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.
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
will simply output their content as plaintext:
Generated HTML:
Also,
will only emit an HTML entity in an HTML context.
In a plaintext context (such as in the input to
), it outputs the character directly.
For example, if we write:
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:
- Sync the theme with the OS (default)
- Light mode (ignoring system preference)
- Dark mode (ignoring system preference)
Forced light/dark mode works by adding a
element in the DOM.
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
directive which you can use to put comments into code.
8.1.1. \comment
— Comments
The
directive does not process its arguments or content.
It outputs no plaintext or HTML.
Generated HTML:
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 |
---|---|---|
|
|
Bold text |
|
|
Name of cited work |
|
|
|
|
|
Definition |
|
|
Emphasized text |
|
unspecified | |
|
|
Italic text |
|
|
Inserted text |
|
|
Ctrl + Keyboard key |
|
|
Marked/highlighted |
|
unspecified | Oblique text |
|
|
Quoted text |
|
|
|
|
|
Sample output |
|
unspecified | |
|
unspecified | |
|
|
Small text |
|
|
Subscript |
|
|
Superscript |
|
|
Strong text |
|
unspecified | |
|
|
Variable name |
|
|
Underlined text |
All such formatting directives convert all named arguments directly into HTML attributes.
,
,
and
are all italic.
Both
and
are bold.
Both
and
use teletype font.
However, you can customize the style; see §8.12.6.
— CSS blocks.
) and italic (
) 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
directive produced syntax-highlighted text in code font.
- Arguments
-
accepts a single\code lang argument which specifies the language used for syntax highlighting. - Input content
-
The input to a
directive is a plaintext context. However, there are special rules for formatting directives and pure plaintext directives (see below).\code - HTML output
-
In an HTML context, the
takes the input source code, applies syntax highlighting, and outputs the result surrounded by\code
.< code > ...</ code > - Plaintext output
-
In a plaintext context,
simply outputs the input source code.\code - Display style
- Inline
This applies C++ syntax highlighting, and generates HTML.
The
tags are an implementation detail and may be subject to change.
directives directly is often too tedious,
so you'll likely want to define a macro to make this easier:
8.3.2. \codeblock
— Code blocks
The
directive works exactly like
,
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
This renders as:
8.3.3. \hl
— Syntax highlight override
The
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
.
The long name is the enumerator name without the
This generates the HTML (subject to change):
It renders as
.
,
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
directive contains pre-formatted content.
It can be used to contain code, however, there is no syntax highlighting in a
block.
This renders as:
Hello, world! ============= a b c
,
currently does not support the
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.
or
:
This renders as:
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
directive surrounds its content with
tags,
and displays as inline content.
Its content is an HTML context,
and within it, additional pseudo-directives like
or
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.
8.4.2. \mathblock
— Math blocks
The
directive functions almost exactly as the
directive,
but it displays as block content instead of inline content,
and it produces an opening
tag.
8.5. Separators and word breaking
8.5.1. \br
— Break line
The
directive produces a line break,
and corresponds to the HTML element
.
It displays as inline content, and its input content is ignored.
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
directive produces a horizontal rule,
and corresponds to the HTML element
.
It displays as block content, and its input content is ignored.
Here is an example:
8.5.3. \wbr
— Word break opportunity
The
directive produces a word break opportunity,
and corresponds to the HTML element
.
It displays as inline content, and its input content is ignored.
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
element (without a hyphen at the end of the line).
Since µlight only supports UTF-8 output,
is equivalent to
,
which outputs a U+200B ZERO-WIDTH SPACE code point.
or
to output a U+00AD SOFT HYPHEN.
8.5.4. \word
— Unbroken words
The
directive is a formatting directive which prevents word breaks within its content.
Its content is an HTML context.
This is done by applying a
Combined
.
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
and
directives.
8.6.1. \U
— Code point literal
The input to a
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.
generates '
are allowed.
8.6.2. \c
— Character references
The input to a
directive is a plaintext context,
where the same content is permitted as for HTML character references, aka. HTML entities,
between '
and
, the '
- Literally '
& ' in text
(code point literal for U+0026)\ U { 26}
(like\ c { amp}
, named character reference)&
(like\ c { #38}
, decimal character reference)&38;
(like\ c { #x26}
, hexadecimal character reference)&x26;
In an HTML context,
is literally translated into
.
In a plaintext context, the character reference is mapped onto its corresponding code point(s),
and those code points are output directly.
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. \abstract
— Abstract blocks
8.7.2. \blockquote
— Quote blocks
The
directive directly corresponds to the
element.
Quotes blocks or "block quotes" display quoted text.
8.7.3. \bug
— Bug blocks
8.7.4. \decision
— Decision blocks
8.7.5. \delblock
— Deletion blocks
A deletion block acts as a wrapper for a large amount of deleted content.
It is typically used when individual
directives would be too tedious to use.
8.7.6. \details
— Details blocks aka spoilers
The
directive directly corresponds to the
element.
Within
,
the
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.7. \diff
— Difference blocks
A difference block contains changes,
where some content within is typically deleted or inserted.
8.7.8. \example
— Example blocks
8.7.9. \insblock
— Insertion blocks
A deletion block acts as a wrapper for a large amount of inserted content.
It is typically used when individual
directives would be too tedious to use.
8.7.10. \important
— Important blocks
8.7.11. \note
— Note blocks
8.7.12. \tip
— Tip blocks
8.7.13. \todo
— TODO blocks
8.7.14. \warning
— Warning blocks
8.8. Lists
8.8.1. \ul
— Unordered lists
The
directive corresponds to the
element, and produces an unordered list.
Within that list,
you can use the pseudo-directive
to produce list items.
8.8.2. \ol
— Ordered lists
The
directive corresponds to the
element, and produces an ordered list.
Within that list,
you can use the pseudo-directive
to produce list items.
8.8.3. \dl
— Definition lists
The
directive corresponds to the
element, and produces a definition list.
Within that list, you can use
for definition terms, and\dt
for definition descriptions.\dd
8.9. Tables
Tables are simply produced by using the
,
,
,
,
,
,
,
,
,
and
directives to
produce the corresponding HTML tags with the same name.
directive.
8.10. Headings
Headings can be produced using the
,
,
,
,
, and
directives to
produce the corresponding HTML tags with the same name.
Arguments to these headings are converted into attributes of the corresponding HTML element.
An
If none is provided, an
directive:
8.11. References
8.11.1. \ref
— References
The
directive takes a single
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:
mailto URLs (e-mail addresses)tel URLs (telephone numbers)http andhttps URLs- Anchors (
#id ) for some heading in the document - Anything defined in the bibliography using
\bib
HTML output (
tag may have additional attributes):
This renders as:
8.11.2. \mail
— E-Mail addresses
A
directive behaves the same
directive that is given a
8.11.3. \tel
— Telephone numbers
A
directive behaves the same
directive that is given a
8.12. Foreign languages
8.12.1. \html
— Inline HTML
The
directive can be used to output HTML literally.
Its content is a plaintext context,
and it displays as inline content.
Generated HTML:
directive can produce malformed HTML content if you're not careful.
See, §8.12.3.
— HTML element literals for a safer option.
8.12.2. \htmlblock
— HTML blocks
The
directive works exactly like the
directive,
but displays as block content instead of inline content.
directive can produce malformed HTML content if you're not careful.
See, §8.12.3.
— HTML element literals for a safer option.
8.12.3. \html-*
— HTML element literals
Any directive beginning with
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.
Generated HTML:
8.12.4. \script
— JavaScript blocks
The content of a
directive is a plaintext context,
where the input is treated as JavaScript code and surrounded in
tags.
displays as meta content (like
).
Generated HTML:
8.12.5. \noscript
— No-JavaScript content
The
directive corresponds to the
element.
Its content is an HTML context,
and will only be shown by the browser when JavaScript is disabled.
8.12.6. \style
— CSS blocks
The content of a
directive is a plaintext context,
where the input is treated as JavaScript code and surrounded in
tags.
displays as meta content (like
).
Generated HTML:
8.13. 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.13.1. \p
— Paragraphs
The
directive surrounds its content in
tags.
8.13.2. \paragraphs
— Enable paragraph splitting
The
directive activates paragraph splitting.
This may be useful in places where it is not active by default.
Generated HTML:
8.13.3. \block
— Display as block content
The
directive doesn't add any HTML itself,
but causes its contents to be considered block content.
can be used to suppress automatic paragraph splitting:
8.13.4. \inline
— Display as inline content
The
directive works like the
directive,
but causes its contents to display as inline content, not as block content.
8.14. 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
.
8.14.1. \there
— Append content to section
The
directive displays as meta content.
Basically, it stashes away its input content (which is an HTML context) somewhere else.
It takes a single
8.14.2. \here
— Copy section content
The
directive inserts the content from another section at its location.
It displays as inline content.
It takes a single
All references produced by
are resolved in a post-processing step,
which allows forward-references.
Generated HTML:
8.14.3. \hereblock
— Copy section content in block
The
directive functions exactly like the
directive,
but displays as block content instead of inline content.
8.15. Macros
8.15.1. \def
— Define a macro
The
directive defines a macro,
which is basically a user-defined directive.
It has a single
When a macro is used, the content within the
directive is copied.
Any uses of the
pseud-directive inside the macro are replaced with copies
of the input content.