This document describes the features supported by Foremark.
Foremark Text
Code blocks in this section including both of Foremark Text and converted
Foremark XML are automatically compared against the actual conversion
results by the test harness (test/mftext.js
).
Header
The first paragraph starting with a boldface text is treated as a header.
**Document title** A subtitle or whatever deemed appropriate to be displayed near the title
<mf-title>
Document title
</mf-title>
<mf-lead>
A subtitle or whatever deemed appropriate to be displayed near the title
</mf-lead>
Block quotations
Email-style indenting creates a block quotation:
> Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
> tempor incididunt ut labore et dolore magna aliqua.
Only an empty line closes a block quotation. This requirement prevents a text editor's hard wrapping functionality from messing up blockquotes:
Here comes a famous passage:
> Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua.
Still in a block quotation...
No longer in a block quotation.
<p>Here comes a famous passage:</p>
<blockquote><p>
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua.
Still in a block quotation...
</p></blockquote>
<p>No longer in a block quotation.</p>
Block quotes are processed before most kinds of Foremark constructs (even HTML tags!). However, code blocks are processed earlier so that quotation marks inside a code fence are handled as intended:
> <i>This `<i>` element does not
> have the `>` sign in it.</i>
>
> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Markdown
>
> >
> >
>
> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
<blockquote>
<p><i>This <code><i></code> element does not
have the <code>></code> sign in it.</i></p>
<mf-codeblock><mf-code type="Markdown">
>
>
</mf-code></mf-codeblock>
</blockquote>
Fenced code blocks
A line starting with three or more tildes (~
) or backticks (`
) starts a fenced code block. The fence can be followed by one or more keywords and the first one specifies the language:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Shell $ yes hello world ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ None output hello world hello world ... ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
<mf-codeblock>
<mf-code type="Shell">
$ yes hello world
</mf-code>
<mf-code type="None output">
hello world
hello world
...
</mf-code>
</mf-codeblock>
```````````````````````````````
You sometimes want backticks
but that's okay too!
```````````````````````````````
<mf-codeblock>
<mf-code type="">
You sometimes want backticks
but that's okay too!
</mf-code>
</mf-codeblock>
HTML tags
Foremark Text interprets well-formed HTML tags embedded in a text node as HTML tags. The criterions are chosen to be very strict in order to minimize the chance of misdetections. A HTML tag will not be interpreted as a HTML tag unless all of the following criterias are met:
It's not inside a code block or an inline code markup. (HTML tags are processed after code blocks and inline code markups.)
It must use a strictly valid XML syntax, which means:
No self-closing tags.
<br/>
(empty-element tag) should be used in place of<br>
.<
,>
, and"
inside an attribute must be escaped.Every attribute must have a value.
Only the following XML entities are permitted inside:
&
<
>
"
It must not include a XML namespace in the tag name.
It must not contain any redundant whitespaces in the following places:
Between
<
or</
and the tag name.Between the tag name and
>
of a closing tag.Between
<
,>
, and/
.
If it doesn't use an empty-element tag, then there must exist a matching closing tag.
The tag name and all attribute names match
/^[a-z][-a-z0-9]*$/
1 .1 This is a subset of XML NCName. It's quite restricted but still covers all standard HTML and Foremark XML elements.
Valid tag: <br />
Extra whitespaces: < br / > (displayed as "< br / >")
Self-closing: <br> (displayed as "<br>" unless there's `</br>`)
<p>
Valid tag: <br />
Extra whitespaces: < br / > (displayed as "< br / >")
Self-closing: <br> (displayed as "<br>" unless there's <code></br></code>)
</p>
The conversion described in this section only applies to HTML tags embedded as a textual content (like most of the Foremark Text constructs).
If HTML tags are not wrapped by <![CDATA[...]]>
, they will be parsed by the XHTML parser and converted to XHTML elements before the Foremark text processing takes place.
<mf-text>
<!-- The web browser interprets this as a bold element -->
<b>Bold text</b>
<!-- Converted to a bold element as a part of the Foremark
text processing. -->
<b>Bold text</b>
<!-- Equivalent to the previous example. -->
<![CDATA[ <b>Bold text</b> ]]>
</mf-text>
Hyperlinks
Normal hyperlinks
[This](https://www.example.com) is a normal Markdown hyperlink.
[This](https://www.example.com "lo mupli" attr="value") has some attributes.
https://www.example.com/ほげ test@example.com
ipfs://QmXoypizjW3WknFiJnKLwHCnL72vedxjQkDDP1mXWo6uco/wiki/
<myproto://www.example.com/lorem ipsum> <weird address@example.com>
<p>
<a href="https://www.example.com">This</a> is a normal Markdown hyperlink.
</p>
<p>
<a href="https://www.example.com" title="lo mupli" attr="value">This</a> has some attributes.
</p>
<p>
<a href="https://www.example.com/ほげ"><code>https://www.example.com/ほげ</code></a>
<a href="mailto:test@example.com"><code>test@example.com</code></a>
</p>
<p>
<a href="ipfs://QmXoypizjW3WknFiJnKLwHCnL72vedxjQkDDP1mXWo6uco/wiki/"><code>ipfs://QmXoypizjW3WknFiJnKLwHCnL72vedxjQkDDP1mXWo6uco/wiki/</code></a>
</p>
<p>
<a href="myproto://www.example.com/lorem ipsum"><code>myproto://www.example.com/lorem ipsum</code></a>
<a href="mailto:weird address@example.com"><code>weird address@example.com</code></a>
</p>
Symbolic hyperlinks
Link targets can be placed out-of-text:
[**This**] [] is a symbolic hyperlink with an implied symbol name.
[This] [example] is a symbolic hyperlink with an explicit symbol name.
Also, notice that the link target can span across multiple lines.
All link breaks within a link target are removed.
[**This**]: https://www.example.com
[example]: https://
www.example.com "title text here" attr="value"
<p>
<a href="https://www.example.com"><b>This</b></a> is a symbolic hyperlink with an implied symbol name.
</p>
<p>
<a href="https://www.example.com" title="title text here" attr="value">This</a> is a symbolic hyperlink with an explicit symbol name.
Also, notice that the link target can span across multiple lines.
All link breaks within a link target are removed.
</p>
Symbol names are case-sensitive.
A link target definition is only associated with the closest preceding symbolic hyperlink. A symbolic hyperlink is associated with a link target definition only if:
The hyperlink precedes the link target definition.
There is no hyperlink or link target definiton with an identical symbol name between the hyperlink and the link target definition.
A symbolic hyperlink is not formed if no link target could be associated.
[This][example] is not a hyperlink and is displayed as `[This][example]`.
[This][example] is a hyperlink.
[example]: https://www.example.com
[example]: https://www.example.com/this-link-target-definition-is-ignored
<p>
[This][example] is not a hyperlink and is displayed as <code>[This][example]</code>.
</p>
<p>
<a href="https://www.example.com">This</a> is a hyperlink.
</p>
The association cannot be formed across the boundaries of <mf-text>
.
<mf-text>
[This][example] is not a hyperlink and is displayed as `[This][example]`.
</mf-text>
<mf-text>
[example]: https://www.example.com
</mf-text>
Media
The pudding face looks like
 or
![alt text (optional)][pudding].
[pudding]: https://derpicdn.net/img/2018/11/8/1877696/medium.png
<p>
The pudding face looks like
<mf-media src="https://derpicdn.net/img/2018/11/8/1877696/medium.png" alt="alt text (optional)" /> or
<mf-media src="https://derpicdn.net/img/2018/11/8/1877696/medium.png" alt="alt text (optional)" />.
</p>
Inline media are directly rendered as <mf-media>
elements.
Read Symbolic hyperlinks for more about symbolic hyperlinks ([pudding]
in the above example).
Use the block syntax to insert a media block using <mf-figure>
. The block syntax is distinguished by the colon at the end and the addition of an optional media label:
The pudding faces are shown below:
![^][alttext](https://derpicdn.net/img/2018/11/8/1877696/medium.png):
Media block (manually positioned)
![!!][alttext](https://derpicdn.net/img/2018/11/8/1877696/medium.png):
Media block (manually positioned) but takes entire a row
![!Figure fig1][alttext](https://derpicdn.net/img/2018/11/8/1877696/medium.png):
Figure (possibly automatically positioned)
<p>The pudding faces are shown below:</p>
<mf-figure>
<p><mf-media src="https://derpicdn.net/img/2018/11/8/1877696/medium.png" alt="alttext" /></p>
<mf-figure-caption><p>
Media block (manually positioned)
</p></mf-figure-caption>
</mf-figure>
<mf-figure size="full">
<p><mf-media src="https://derpicdn.net/img/2018/11/8/1877696/medium.png" alt="alttext" /></p>
<mf-figure-caption><p>
Media block (manually positioned) but takes entire a row
</p></mf-figure-caption>
</mf-figure>
<mf-figure id="Figure fig1" size="large">
<p><mf-media src="https://derpicdn.net/img/2018/11/8/1877696/medium.png" alt="alttext" /></p>
<mf-figure-caption><p>
Figure (possibly automatically positioned)
</p></mf-figure-caption>
</mf-figure>
The first part ([^]
, [!Figure fig1]
) is based on the floating contents block syntax. Sidenote labels (e.g., [!basenameonly]
) may not be used.
![^][][symbol]:
(A media block with a symbolic name) is not supported.
A media tag optionally include XML attributes:

![^][](https://derpicdn.net/img/2018/11/8/1877696/medium.png style="animation: 2000ms _2qw9KkueUdLlzZdwjgAKzl both infinite linear"):
Media caption
<p>
<mf-media src="https://derpicdn.net/img/2018/11/8/1877696/medium.png" alt=""
style="animation: 2000ms _2qw9KkueUdLlzZdwjgAKzl both infinite linear" />
</p>
<mf-figure>
<p>
<mf-media src="https://derpicdn.net/img/2018/11/8/1877696/medium.png" alt=""
style="animation: 2000ms _2qw9KkueUdLlzZdwjgAKzl both infinite linear" />
</p>
<mf-figure-caption>
<p>Media caption</p>
</mf-figure-caption>
</mf-figure>
Floating contents
Figures and sidenotes use a (somewhat) unified syntax:
Let there be some paragraph text[^sidenote].
See [!!Figure fig1] as well as [!Table table]. [!図:fig2]も併せてご覧下さい。
.i ko zgana [!le pixra pe li mupli-pixra]
[^]:
This is displayed as a sidenote without numbering.
[^sidenote]: Here comes the sidenote.
Sidenotes are different from figures in the point that
the first line is not treated specially as a caption.
[!!Figure fig1]: Twily for dummies.

[!Table table]:
Since the caption line was left empty, this table has no caption.
| Elements of Harmony | Pillars of Old Equestria |
|---------------------|--------------------------|
| Honesty | Strength |
| Kindness | Healing |
| Laughter | Hope |
| Generosity | Beauty |
| Loyalty | Bravery |
| Magic | Sorcery |
[!図:fig2]: Yay.

[!le pixra pe li mupli-pixra]: Empty figure.
The part surrounded by brackets is called a label. A label consists of the following components:
A preceding
^
(caret),!
(exclamation mark), or!!
(two exclamation marks) specify how the content should be layouted.^
— The default mode. On a large screen, the content is moved to the side margin.!
— Translated tosize="large"
. The content is not moved to the side margin and always occupies a row.!!
— Translated tosize="full"
. The content occupies the maximum available width (including the side margin).
An optional label identifier, which consists of:
An optional number prefix. This serves the purpose of identifying an independent counter for each figure type (e.g., figure/table), and as a text to be displayed before a number. There are two forms:
The space-delimited form like
[^Figure fig]
inserts a whitespace between the prefix and a number.The non-space-delimited form like
[^図:fig]
does not insert a whitespace.
This component is included in the floating element ID along with the base name.
A non-empty base name.
A base name may not include
:
or a whitespace character. Therefore, a label[^le pixra pe li mupli-pixra]
is interpreted asle pixra pe li
+mupli-pixra
3 .3 «le pixra pe li □»
roughly means "the picture pertaining to number □" in Lojban. It could be written more concisely as«le li □ pixra»
, which isn't supported by Foremark at this point.
The number prefix and the base name together forms a label identifier.
Although the figure syntax described here can be used for any kinds of contents, it's better to use the media block syntax if you just intend to display a media file as a figure.
Figures and sidenotes use the unified system. Still, there is a dedicated syntax for figures.
Like Markdeep, sidenotes may contain multiple lines, but they must be indented to be included.
Sidenotes can contain multiple paragraphs.
Find a way to place table captions above tables but not figure captions.
And there is a syntax for citations, which is similar to that of sidenotes:
Here's a citation [#A2018].
[#A2018]:
From a casual conversation with Person A in 2018.
<p>
Here's a citation <mf-ref to="A2018" />.
</p>
<mf-cite id="A2018">
<p>From a casual conversation with Person A in 2018.</p>
</mf-cite>
The preceding ^
, !
, and #
symbols do not constitute the label identifier. so it's technically possible to refer to a figure with a different symbol. However, it's considered a bad practice because it makes it harder to find a tag using a text editor's search functionality.
The following table summarizes all forms of labels:
Label | Reference | Definition | size | id |
---|---|---|---|---|
[!!] | N/A | <mf-note> | "full" 2 | note |
[!] | N/A | <mf-note> | "large" | note |
[^] | N/A | <mf-note> | note | |
[!!endnote] | ¹ | <mf-note> | "full" 2 | endnote |
[!endnote] | ² | <mf-note> | "large" | endnote |
[^sidenote] | ³ | <mf-note> | sidenote | |
[#cite] | [cite] | <mf-cite> | cite | |
[!!Figure fig1] | Figure 1 | <mf-figure> | "full" | Figure fig1 |
[!Figure fig2] | Figure 2 | <mf-figure> | "large" | Figure fig2 |
[^Figure fig3] | Figure 3 | <mf-figure> | Figure fig3 | |
[!!図:fig2] | 図1 | <mf-figure> | "full" | 図:fig2 |
[!図:fig2] | 図2 | <mf-figure> | "large" | 図:fig2 |
[^図:fig3] | 図3 | <mf-figure> | 図:fig3 |
"large"
.
The Label column shows the raw source code.
All reference tags are translated into
<mf-ref>
elements. The Reference column shows how a<mf-ref>
is displayed.The contents of a floating element is wrapped by an element shown in the Definition column. This element has the attributes shown in the last two columns,
size
andid
.
Unreferenced labels are omitted from the output.
Diagrams
Colon symbols create a diagram (<mf-diagram>
):
The railroad diagram of Foremark figure label: ::: .---. ::: .->| |-. ::: .---------. .---------. / '---' \ .-----------. .------------. ::: o--> |"^][><\t"| ---> |"^][><\t"| -*-+ +-> |"^][><\t :"| ---- |"^][><\t :" | -+->o ::: '---------' ^ '---------' / \ .---. / '-----------' ^ '------------' / ::: \ / '->| : |-' \ / ::: '----------' '---' '-------------'
<p>The railroad diagram of Foremark figure label:</p>
<mf-diagram>
.---.
.->| |-.
.---------. .---------. / '---' \ .-----------. .------------.
o--> |"^][><\t"| ---> |"^][><\t"| -*-+ +-> |"^][><\t :"| ---- |"^][><\t :" | -+->o
'---------' ^ '---------' / \ .---. / '-----------' ^ '------------' /
\ / '->| : |-' \ /
'----------' '---' '-------------'
</mf-diagram>
Alternative style:
::::::::::::::::::::::::::::: :: ,-----, :: :: | | "le si'o kurfa" :: :: '-----' :: :::::::::::::::::::::::::::::
<mf-diagram>
,-----,
| | "le si'o kurfa"
'-----'
</mf-diagram>
Markdeep-style diagrams are not supported. Diagram lines must not include other texts.
Headings
First level
===========
Second level
------------
# First level
## Second level
### Third level
#### Fourth level
##### Fifth level
...
<h1>First level</h1>
<h2>Second level</h2>
<h1>First level</h1>
<h2>Second level</h2>
<h3>Third level</h3>
<h4>Fourth level</h4>
<h5>Fifth level</h5>
<p>...</p>
Horizontal rules
----- - - - _____ _ _ _ ***** * * *
<hr /><hr /><hr /><hr /><hr /><hr />
Lists
The following types of lists are supported:
Marker | Type | CSS class |
---|---|---|
- | Unordered list (<ul> ) | minus |
+ | Unordered list (<ul> ) | plus |
* | Unordered list (<ul> ) | asterisk |
[*] / - [*] | Unordered list (<ul> ) | checked |
[ ] / - [ ] | Unordered list (<ul> ) | unchecked |
42. | Ordered list (<ol> ) | |
: | Definition list (<dl> ) |
A line starting with one of the markers starts a list (such lines are called marker lines). The list goes on until a line with the original indentation is encountered:
- Marker line
Non-marker lines
And goes on...
We're out!
<ul>
<li class="minus"><p>Marker line
Non-marker lines
And goes on...</p></li>
</ul>
<p>We're out!</p>
To handle hard wrapping, outdentation is ignored unless the current line contains a marker or is separated by a blank line:
- Marker line
- Marker line
And goes on...
We're out!
<ul>
<li class="minus"><p>Marker line</p></li>
<li class="minus"><p>Marker line
And goes on...</p></li>
</ul>
<p>We're out!</p>
Term1 : Defintion1 And goes on... Term2 : Definition 2
<dl>
<dt><p>Term1</p></dt>
<dd><p>Defintion1
And goes on...</p></dd>
<dt><p>Term2</p></dt>
<dd><p>Definition 2</p></dd>
</dl>
Consecutive items with the same list type are merged into one list:
- Item1
- Item2
1. Item3
<ul>
<li class="minus"><p>Item1</p></li>
<li class="minus"><p>Item2</p></li>
</ul>
<ol>
<li><p>Item3</p></li>
</ol>
A number in ordered lists does matter. A non-sequential number restarts a list to make numbers consistent:
1. Item1
3. Item2
4. Item3
<ol>
<li><p>Item1</p></li>
</ol>
<ol start="3">
<li><p>Item2</p></li>
<li><p>Item3</p></li>
</ol>
Definition lists takes the last line as the caption:
Asymmetric cryptography : An encryption system that uses pairs of keys: public keys and private keys.
<dl>
<dt><p>Asymmetric cryptography</p></dt>
<dd><p>An encryption system that uses pairs of keys: public keys
and private keys.</p></dd>
</dl>
Admonitions
!!! Danger: Can I have your attention please?! The message follows...
<mf-admonition type="danger">
<mf-admonition-title>
Can I have your attention please?!
</mf-admonition-title>
<p>
The message follows...
</p>
</mf-admonition>
A caption line is in one of the following formats:
Source | Admonition type | Caption |
---|---|---|
!!! | (empty) | (none) |
!!! Type | Type | (none) |
!!! Type: Caption | Type | Caption |
Equations
$$ \Lo(X, \wo) = \Le(X, \wo) + \int_\Omega \Li(X, \wi) ~ f_X(\wi, \wo) ~ | \n \cdot \wi | ~ d\wi $$ Look at an inline equation: $e^{i \pi} + 1 = 0$
<mf-eq-display>\Lo(X, \wo) = \Le(X, \wo) + \int_\Omega \Li(X, \wi) ~ f_X(\wi, \wo) ~ | \n \cdot \wi | ~ d\wi</mf-eq-display>
<p>
Look at an inline equation: <mf-eq>e^{i \pi} + 1 = 0</mf-eq>
</p>
Referencing equations
Tables
Tables
Paragraphs
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
consequat. </p>
<p>Duis aute irure dolor in reprehenderit in voluptate velit esse
cillum dolore eu fugiat nulla pariatur.</p>
Text styles
Source | Result |
---|---|
**bold** | bold |
__bold__ | bold |
*italic* | italic |
_italic_ | italic |
~~strikethrough~~ | |
`inline code` | inline code |
Formatted text may cross lines, but not paragraphs.
Lorem ipsum dolor **sit amet, consectetur** adipisicing _elit Duis_ aute irure dolor in ...
<p>
Lorem ipsum dolor <b>sit amet,
consectetur</b> adipisicing _elit
</p>
<p>
Duis_ aute irure dolor in ...
</p>
Formatting can be applied to a part of words:
Source | Result |
---|---|
B is for **B**ooze | B is for Booze |
お前は**もう**死んでいる | お前はもう死んでいる 4 |
Differences from common Markdown dialects
Indented code blocks were removed.
The criteria for embedded HTML tags is stricter.
Foremark XML
HTML elements
The following HTML elements are supported and styled appropriately.
<h1>
...<h9>
<p>
<i>
,<b>
,<a>
<code>
<ul>
,<ol>
,<ll>
<dl>
,<dt>
,<dd>
<br>
Document — <mf-document>
<mf-document>
<mf-title>Document title</mf-title>
</mf-document>
Header — <mf-title>
<mf-title>I Have No Mouth and I Must Scream</mf-title>
<mf-lead>Harlan Ellison</mf-lead>
<mf-title>
inserts a document title. <mf-lead>
inserts a subtitle and if it exists it must follow <mf-title>
.
Relevant Foremark Text tags: **title**
Lists
<ul>
<li><p>unordered list</p></li>
</ul>
<ol>
<li><p>ordered list</p></li>
</ol>
<dl>
<dt><p>caption</p></dt>
<dd><p>decsription</p></dd>
</dl>
HTML lists <ul>
(unordered list), <ol>
(ordered list), and <dl>
(definition list) are supported.
ul > li
may have one of the following CSS classes:
checked
indicates that a checked checkbox should be displayed next the item.unchecked
indicates that an unchecked checkbox should be displayed next the item.
Relevant Foremark Text tags: -
+
*
[ ]
[x]
and more
Code blocks — <mf-code>
<mf-codeblock>
<mf-code type="Python input">>>> x = [1, 2, 3, 4]
>>> [y * 2 for y in x]</mf-code>
<mf-code type="none output">[2, 4, 6, 8]</mf-code>
</mf-codeblock>
<mf-code>
displays a code block with syntax highlighting.
type
attribute is a space-separated string and the first element indicates the syntax name used for syntax highlighting.
One or more <mf-code>
elements can be wrapped by <mf-codeblock>
.
<mf-code>
is a block element that should not be confused with <code>
, which is an inline element used to insert a inline code fragment.
The semantics of the rest of type
attribute value.
Relevant Foremark Text tags: ~~~~
–~~~~
LaTeX equations — <mf-eq>
<mf-eq-display>
\Lo(X, \wo) = \Le(X, \wo) + \int_\Omega \Li(X, \wi) ~ f_X(\wi, \wo) ~ | \n \cdot \wi | ~ d\wi
</mf-eq-display>
<p>
The LLVM target <i>triplet</i> is comprised of <i>five</i> elements.
Therefore, <mf-eq>3 = 5</mf-eq>.
</p>
<mf-eq>
inserts an inline LaTeX equation. Similarly, <mf-eq-display>
inserts a display LaTeX equation.
Relevant Foremark Text tags: $inline$
$$display$$
Media — <mf-media>
<p>
<!-- Simply translated to <img> -->
<mf-media src="https://derpicdn.net/img/2013/8/4/391426/large.png" />
<!-- DeviantArt oEmbed -->
<mf-media src="http://fav.me/d89ginp" />
</p>
<mf-media>
works almost identically as <img>
except that it supports a variety of media types through media handlers.
Floating elements
Figures and sidenotes have the following common attributes:
The optional
id
attribute is used to reference the element from<mf-ref>
.size="large"
prevents the element to be layouted in a confined space like the sidenote margin.size="full"
causes the element to occupy the maximum available width. Not supported by sidenotes (because it doesn't make sense!).
size="full"
enables a special styling, which also enables the sidenote margin (even if there aren't actual sidenotes).
The id
attribute of citations has the same semantics as that of figures and sidenotes. They don't support size
though.
Figures — <mf-figure>
<mf-figure id="figureId" counter="table" label="Table {}" size="large">
<mf-figure-caption>
Caption
</mf-figure-caption>
<p>
Contents
</p>
</mf-figure>
counter
identifies a counter used to generate a figure number.label
specifies the format of the displayed figure label.{}
is substituted with a number.
If both of counter
and label
are omitted but id
is specified, counter
and label
are implied from id
provided that id
is in a particular form.
If
id.match(/(.+):[^ :]+/)
, thencounter
is$1
andlabel
is$1{}
.If
id.match(/(.+) [^ :]+/)
, thencounter
is$1
andlabel
is$1 {}
.
Relevant Foremark Text tags:
[^counter basename]: caption
[!counter basename]: caption
![^counter basename][alt](url): caption
![!counter basename][alt](url): caption
(generates<img>
wrapped with<mf-figure>
)
Sidenotes/Endnotes — <mf-note>
<mf-note id="noteId" size="large">
<p>
Contents
</p>
</mf-note>
Relevant Foremark Text tags: [^noteId]: contents
[!noteId]: contents
Citations — <mf-cite>
<mf-cite id="citeId" label="Abadi2005">
<p>
Contents
</p>
</mf-cite>
label
specifies the displayed citation label.id
is used whenlabel
is omitted.
Unlike sidenotes, citations are always rendered where they are defined (so that document authors can make a section dedicated for references). However, copies of them may be displayed as sidenotes around their references.
Relevant Foremark Text tags: [#citeId]: contents
Figure/note references — <mf-ref>
<mf-note id="noteId"> ... </mf-note>
<p>
<mf-ref to="noteId" />
</p>
Relevant Foremark Text tags: [^noteId]
[!noteId]
Admonitions — <mf-admonition>
<mf-admonition type="danger">
<mf-admonition-title>
Can I have your attention please?!
</mf-admonition-title>
<p>
The message follows...
</p>
</mf-admonition>
Relevant Foremark Text tag: !!!
Diagrams — <mf-diagram>
<mf-diagram><![CDATA[
.---------.
| Server |<------.
'----+----' |
| |
| DATA CYCLE |
v |
.---------. .----+----.
| Security| | File |
| Policy +->| Manager |
'---------' '---------'
]]></mf-diagram>
Relevant Foremark Text tags: :::
Miscellaneous elements
<mf-error>
indicates an error encountered while processing<mf-text>
.
Viewer application
Document
A Foremark document is an XHTML file that consolidates Foremark Text/XML markups and a script tag for loading the viewer application.
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"><pre><![CDATA[
**Document title**
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
consequat.
]]></pre> <!-- Foremark footer -->
<script src="../browser/foremark.js" async="async" /></html>
A document includes one of
html > mf
,html > mf-text
, andhtml > pre
which represent the content root. Ifmf-text
is the content root, it will be wrapped by<mf-document>
and all attributes are moved to the<mf-document>
.pre
is converted tomf-text
first.html > script
instructs the web browser to load the viewer application. The viewer application locates this tag 5 and uses its5 The viewer uses thedocument.currentScript
API which is widely supported by modern web browsers. If it's unavailable, the viewer falls back to a heuristics based on the script file name.src
attribute as a base path for loading other assets.
The viewer determines the base path of assets using the script tag from which the viewer was loaded. This behavior can be overridden by adding another script tag with a data-rel="foremark"
attribute. The script tag doesn't have to load an actually-executed script. For example, type="text/plain"
attribute could be used to make a script tag that doesn't load anything at all.
Using pre
makes it possible for text browsers (such as Lynx) to display Foremark documents to some extent.
The viewer application does not support HTML files for various reasons:
The web browser's DOM API behaves differently when displaying a HTML file. For example, XHTML preserves the original case for
HTMLElement#tagName
while HTML doesn't.The behavior of
CDATA
in HTML is inconsistent between browsers.
Configuration
The viewer receives configuration objects through window.foremarkConfig
. Each script tag with data-rel="foremark-config"
must supply exactly one configuration object:
<script data-rel="foremark-config">
(window.foremarkConfig = window.foremarkConfig || []).push({
/* ... */
});
</script>
<script src="global.js" data-rel="foremark-config" async="async" />
The signature of a configuration object is defined using the ViewerConfig
interface. The viewer has the default configuration object and the user-specified configuration is merged into that. See the auto-generated API reference for more details.
Styling
Built atop of HTML, the viewer allows customization via custom stylesheets.
The following CSS class of the content root element (mf, mf-text, pre
) modifies the behavior of the viewer:
class="no-sidenotes"
disables sidenotes. This means all[^note]
are treated like[!note]
.
The type
attribute of a mf-code
element is preserved. Because only the first word in type
is considered for determining the syntax for syntax highlighting, the rest of the value can be used to pass extra information:
<mf-text>
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Shell
$ yes hello world
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ None output
hello world
hello world
...
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
</mf-text>
<style>
mf-code[type*="output"] {
font-style: italic;
}
</style>
Items in an unordered list are given CSS class names according to the marker symbols used to define them (e.g., minus
for -
). Read Lists for details.
The following example disables word-wrapping in fenced code blocks:
<style>
@media screen { mf-code {
white-space: pre;
overflow-wrap: normal;
} }
</style>
Media handlers
<mf-media>
elements are processed using media handlers.
Media handlers are defined using the viewer configuration interface's mediaHandlers
property. Each media handler is described using the MediaHandler
interface. See the auto-generated API reference for more details.
The viewer provides several built-in media handlers (BUILTIN_MEDIA_HANDLERS
). The .merge
operator can be used to make modifications to the default set.
(window.foremarkConfig = window.foremarkConfig || []).push({
'mediaHandlers.merge': {
'image': null, // Disable the built-in image handler
'image.merge': {
// Or, just change the image handler's URL pattern.
// The image handler is not a catch-all handler any more.
patterns: [/\.jpg$/i],
},
'myhandler': { // Define a new handler
/* ... */
},
},
});
HTML5 media handlers
BUILTIN_MEDIA_HANDLERS = {
'image': {
patterns: null,
handler: handleImageMedia,
priority: 0,
},
'video': {
patterns: [/\.(mp4|m4v|avi|pg|mov|wmv)$/i],
handler: handleVideoMedia,
priority: 20,
},
'audio': {
patterns: [/\.(mp3|ogg|wav|au|opus|m4a|wma)$/i],
handler: handleAudioMedia,
priority: 10,
},
/* ... */
};
These media handlers converts <mf-media>
to <img>
, <video>
, or <audio>
depending on file extensions and simply copies all XML attributes. patterns
is null
for the image handler, thus it serves as a catch-all handler.
Inline frame media handler
BUILTIN_MEDIA_HANDLERS = {
'youtube': {
patterns: [/* ... */],
handler: /* ... */,
priority: 150,
options: {
pattern: /* (regex) */,
frameUrl: 'https://www.youtube.com/embed/$1',
},
},
'sketchfab': {
patterns: [/* ... */],
handler: /* ... */,
priority: 150,
options: {
pattern: /* (regex) */,
frameUrl: 'https://sketchfab.com/models/$1/embed',
},
},
/* ... */
};
This media handler applies a RegExp
-based replacement rule to generate an <iframe>
url from a media URL. All attributes (except for src
) are copied to a generated <iframe>
element.
oEmbed media handler
BUILTIN_MEDIA_HANDLERS = {
'oembed': {
patterns: [/* ... */],
handler: /* ... */,
priority: 100,
options: {
endpoints: {
'vimeo': /* ... */,
'deviantart': /* ... */,
'soundcloud': /* ... */,
/* ... */
},
timeout: 30000,
},
},
/* ... */
};
This media handler embeds an embedded representation of a URL using the oEmbed protocol.
options.endpoints
defines a set of oEmbed endpoints. Each endpoint defines a support URL scheme and the endpoint URL to which the media handler sends a request to generate the embedded representation of a media URL. Each endpoint is defined using the OEmbedEndpoint
interface. The default set is defined by BUILTIN_OEMBED_ENDPOINTS
.
The media handler is activated if a media URL matches any of the defined endpoint URL scheme. The media URL is supplied as a url
query parameter. An additional query parameter can be specified using a XML attribute with prefix oembed-
.

A media will fail to load if a page is served over HTTPS and the endpoint URL use HTTP. Specify an HTTPS URL whenever possible to avoid this problem.
Table of contents
The viewer displays a table of contents that allows quick navigation to various parts of a page.
A table of contents is constructed by looking for heading elements (h1
, h2
, ...) in a document.
If a sitemap is associated with a current page, it will be displayed in the table of contents and the headings of the current page will be embedded inside the current page's sitemap entry.
Sitemap
A sitemap defines a tree of documents, which usually represents the entire structure of a writing piece. A sitemap is displayed in a table of contents and by using it users can quickly navigate to other associated documents.
A sitemap can be associated with a document using the configuration system. See the auto-generated API reference for more details. A simple example is shown below:
(window.foremarkConfig = window.foremarkConfig || []).push({
'sitemap.merge': {
'main': [
['The Foremark Book', ['/examples/book.mf.xhtml']],
['Media element test', ['/examples/media.mf.xhtml']],
],
},
});
When you use a sitemap, it's recommended to define a sitemap in an external script and load it from all documents.
Using Foremark as a library
As a NPM library, Foremark provides the following exports (accompanied with their synopses; navigate the hyperlinks for details):
If you are using the library in a Node.js environment, you must specify a DOM global object using this function.
Scans for
<mf-text>
elements in a given DOM node, and lowers them into Foremark XML.
DOM behaves quite differently betweeen XHTML and HTML. Because of this, Foremark does not work with a HTML document.
setWorkingDom
throws an exception if the specified DOM global object is for a HTML document.On a web browser, Foremark fails to initialize on a HTML document.
Markups generated by expandMfText
aren't pure XHTML and make use of custom elements defined by Foremark XML. They won't render as intended without a proper post-processing and stylesheet. It's up to an application to do that. Here's the possible minimum list of things an application has to do:
Provide stylesheet rules for all custom elements.
white-space: pre
onmf-code
andmf-diagram
Rename
<mf-media>
elements toimg
.Handle
<mf-error>
. For example, an application could abort processing when a<mf-error>
element is encountered.
The following code is a modified excerpt from Foremark's test fixture. It makes use of the jsdom
library:
const {expandMfText, setWorkingDom} = require('foremark');
// Create an XHTML document
const dom = new JSDOM(
'<html xmlns="http://www.w3.org/1999/xhtml" />',
{contentType: 'application/xhtml+xml'}, // XHTML mime type
);
const document = dom.window.document;
const body = document.createElement('body');
// Create a Foremark Text element
const mfText = document.createElement('mf-text');
mfText.textContent = text;
body.appendChild(mfText);
// Expand it
setWorkingDom(dom.window);
expandMfText(mfText);
// Now `body` contains the expanded document