Foremark Reference Manual
Foremark Reference Manual

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>&lt;i&gt;</code> element does not
have the <code>&gt;</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: &amp; &lt; &gt; &quot;

  • 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 This is a subset of XML NCName. It's quite restricted but still covers all standard HTML and Foremark XML elements.

    11.

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: &lt; br / &gt; (displayed as "&lt; br / &gt;")
Self-closing: &lt;br&gt; (displayed as "&lt;br&gt;" unless there's <code>&lt;/br&gt;</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. -->
    &lt;b&gt;Bold text&lt;/b&gt;

    <!-- 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
![alt text (optional)](https://derpicdn.net/img/2018/11/8/1877696/medium.png) 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")

![^][](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.
    ![](https://derpicdn.net/img/2013/8/4/391426/large.png)

[!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.
    ![](https://derpicdn.net/img/2018/8/18/1809969/large.png)

[!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 to size="large". The content is not moved to the side margin and always occupies a row.

    • !! — Translated to size="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 as le pixra pe li + mupli-pixra

      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.

      33.

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.

Differences from Markdeep
  • 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.

Yet to be written about...
  • 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

2 Does not have an effect. Treated as "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 and id.

Unreferenced labels are omitted from the output.

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.

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--> |"^][>&lt;\t"| ---> |"^][>&lt;\t"| -*-+            +-> |"^][>&lt;\t :"| ---- |"^][>&lt;\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>
Yet to be added...
  • Referencing equations

Tables

Yet to be written about...

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~~ 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:

4 Chinese and Japanese are written without word dividers (わかち書き), often causing a headache to writers with certain text formats that require formatting to be applied on per-word basis.

Source Result
B is for **B**ooze B is for Booze
お前は**もう**死んでいる お前はもう死んでいる 44

4 Chinese and Japanese are written without word dividers (わかち書き), often causing a headache to writers with certain text formats that require formatting to be applied on per-word basis.

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">&gt;&gt;&gt; x = [1, 2, 3, 4]
&gt;&gt;&gt; [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.

Yet to be written about...

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(/(.+):[^ :]+/), then counter is $1 and label is $1{}.

  • If id.match(/(.+) [^ :]+/), then counter is $1 and label 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 when label 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, and html > pre which represent the content root. If mf-text is the content root, it will be wrapped by <mf-document> and all attributes are moved to the <mf-document>. pre is converted to mf-text first.

  • html > script instructs the web browser to load the viewer application. The viewer application locates this tag

    5 The viewer uses the document.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.

    55 and uses its src attribute as a base path for loading other assets.

5 The viewer uses the document.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.

Overriding the asset path

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.

Rationale

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-.

![](https://vimeo.com/channels/staffpicks/151493973 oembed-maxwidth="1280")
Mixed active content issue

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):

setWorkingDom

If you are using the library in a Node.js environment, you must specify a DOM global object using this function.

expandMfText

Scans for <mf-text> elements in a given DOM node, and lowers them into Foremark XML.

Foremark will not work with HTML

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.

Stylesheets are not included

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 on mf-code and mf-diagram

  • Rename <mf-media> elements to img.

  • 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