wastl

Nimble

An elegant markup language for a more civilized age.

Nimble is a markup language that tries to make it easy to author semantically-useful documents with special consideration given to HTML5 output. Things like blog posts, wiki articles, and documentation are meant to be easy to write using Nimble. Some parts of Nimble syntax rely on aligning things using indentation, and so Nimble likes to be written in a monospaced font. If you've ever used a wiki markup language, you should feel right at home using Nimble.

Nimble markup is used to express the semantics of a document, not the style; you use Nimble to express things like "this text is a quotation", but not things like "this text should be in its own box with a large quotation mark on one side" (for that, use CSS). Documents written in Nimble represent a hierarchy of elements, much like documents written in HTML. In fact, internally, a Nimble renderer first converts your text to a parse tree, and then a separate process renders that tree. A parsed Nimble document includes the tree itself (which represents the semantics of the document) as well as extra metadata such as document attributes or macro definitions.

For a more thorough example, you can also see the Nimble source of this page. You might want to wait until you've read it the normal way, though.

If you'd like to use Nimble in your own project, it is available as a Perl module on CPAN complete with an HTML renderer. The source code is also available on GitHub.

On the other hand, you might just want to test out Nimble before you install it. Feel free to play along with the examples in this document.

When to choose Nimble

There are many different markup languages available these days. To help you know when to choose Nimble, here are some things that make Nimble special:

To prevent you from making the wrong choice, here are some things Nimble is not:

Syntax basics

Nimble syntax is divided into two categories: block, which includes containers for text (such as lists or figures) and some kinds of special declarations (such as macro definitions or document attributes), and inline, which includes designations done within text (such as indicating emphasis, strong wording, links, or code). The system displaying the rendered output chooses how to style these blocks and inline designations (for HTML, CSS is used).

You can place a backslash (\) before any single character to escape it, removing any special meaning it might have and rendering it literally — except within code blocks, where everything is always literal.

Inline-level elements

To indicate that text has strong importance, wrap it in asterisks (*). To indicate that text has emphasis, wrap it in slashes (/).

CodeResult
This section is /very/ important.  *Don't miss it!*
This section is very important. Don't miss it!

To reduce the need for escaping in other uses of these characters, an asterisk or slash followed by whitespace does not count as starting an inline element, and an asterisk or slash preceeded by whitespace does not count as ending an inline element.

CodeResult
What is 2 * 3 / 4?

My favorite color is /orange / blue/,
but people find that strange.

What do you get if you multiply *6 * 9*? 42!

What is 2 * 3 / 4?

My favorite color is orange / blue, but people find that strange.

What do you get if you multiply 6 * 9? 42!

To express some inline text as code, wrap it in at least one backtick (`). If the code itself contains sequences of backticks, more backticks can be used to wrap the code (but use the same number for the start and end). Spaces at the start or end of the wrapped code are ignored (unless there isn't anything but spaces).

CodeResult
Always start your Perl scripts
with `use strict;` and `use warnings;`.

In Nimble, wrap `code` in
at least one backtick (`` ` ``).

Always start your Perl scripts with use strict; and use warnings;.

In Nimble, wrap code in at least one backtick (`).

Make a link by writing [http://example.com/url link text], which becomes link text. This is actually shorthand for [link http://example.com/url link text]. If the link text is omitted, the URL is used: [http://example.com/] becomes http://example.com/.

Include an image by writing [img path/to/image.jpg alt text]. If the alt text is omitted, an empty string will be used.

You can use HTML entities directly: typing &yen; produces ¥, and typing &#xA3; produces £. There are also some shorthands for useful entities: -- creates an endash (–), --- creates an emdash (—). You can create arrows using --> ==> <== <--, which gives → ⇒ ⇐ ←. Of course, if you want those actual symbols, you could put them in code blocks (`-->` becomes -->) or escape them (\--> becomes -->).

Most of the inline syntaxes can be nested; for example, the text of a link can be an image, or strong text can have emphasis. This isn't true in cases where it doesn't make sense, like in the alt text of an image.

Macros can be used as inline elements; this will be covered later.

Block-level elements

Blocks are typically written with a blank line between them. This increases document legibility, but it isn't required except where adjacent blocks would be ambiguous (primarily, where a plain paragraph would consider syntax on the next line to be inline markup instead of block markup). Many blocks can contain other blocks; this is done by keeping the indent level from the content of the first line of the block (for an example of this, see the section on lists). A blank line (empty or only containing whitespace) has no effect on indentation level.

Paragraphs

Text on its own is converted to a paragraph element:

CodeResult
This is one paragraph.

This is another paragraph;
you can use single newlines
to hard-wrap your text if
you prefer.

This is one paragraph.

This is another paragraph; you can use single newlines to hard-wrap your text if you prefer.

Code blocks

To create a code block, place at least three backticks (```) on a line before your code, and the same number on a line after it. The code will be taken verbatim, and no Nimble syntax will be parsed within the block.

CodeResult
Here is a simple Perl script:

```
#!/usr/bin/perl -w
use strict;

print "Hello, world!\n";
```

When run, it prints `Hello, world!`.

Here is a simple Perl script:

#!/usr/bin/perl -w
use strict;

print "Hello, world!\n";

When run, it prints Hello, world!.

Document attributes

Nimble documents can define any number of key-value pairs which are returned by the parser in addition to the other parts of the document. (Check your parser's documentation for how to access them.) They are useful for specifying values that need to be used outside the Nimble document, such as the page title, related tags, or the name of the author. The code using your document can use these values however it likes. Attribute values are a single line of raw text — they do not get parsed as Nimble markup. To define an attribute, write @name value:

@title How to slay a dragon in twelve easy steps
@author King Arthur
@tags dragonslaying, self-help guides

To kill a dragon...

Again, these attributes aren't used by Nimble. They're merely returned by the parser for use elsewhere. For example, with the above document, the application might choose to put the @title within part of the page's <title> tags, use the @author to link the article from the author's page, and split the @tags by commas to index them in a database.

Lists

Several kinds of lists are supported by Nimble syntax.

An unordered list is simply a series of items for which the order is irrelevant. It is often drawn as a bulletted list, and so Nimble uses lines prefixed by asterisks (*) to indicate elements of an unordered list:

CodeResult
Today's menu:

* Roast flank of dragon
* Dragon ribs with a honey glaze
* Dragonscale stew with fresh bread

Today's menu:

  • Roast flank of dragon
  • Dragon ribs with a honey glaze
  • Dragonscale stew with fresh bread

Lists allow nesting; you can put several elements within a list, such as paragraphs and other lists:

CodeResult
Places I'd like to visit:

* The dragon's cave
  
  Why?
  * It's full of tasty dragon meat
  * Also probably treasure
* The castle kitchen
  * It's /also/ full of tasty dragon meat
    * (we just killed a dragon)

Places I'd like to visit:

  • The dragon's cave

    Why?

    • It's full of tasty dragon meat
    • Also probably treasure
  • The castle kitchen

    • It's also full of tasty dragon meat

      • (we just killed a dragon)

An ordered list is a series of items for which the order does matter. It is often drawn as a numbered list, and so Nimble uses lines prefixed by numbers and a dot (1., 2., ...) or just a number sign and a dot (#.) if you'd like the item to be numbered automatically:

CodeResult
Top three reasons to kill a dragon:

3. They're scary.
2. Their treasure.
1. There is tasty meat.

Top three reasons to kill a dragon:

  1. They're scary.
  2. Their treasure.
  3. There is tasty meat.
CodeResult
How to kill a dragon:

#. Hire a fighter with a proven track
   record for killing dragons.
#. Hire a bunch of clerics to constantly
   heal the fighter.
#. Hire at least twelve high-level wizards.
   
   Seriously, more like a hundred would be better.
#. Tell them to go kill the dragon.
#. At this point, there are only two outcomes:
   * They kill the dragon; pay them
     with part of its vast treasure.
   * The dragon kills them; don't
     pay them.  That would be silly.

How to kill a dragon:

  1. Hire a fighter with a proven track record for killing dragons.
  2. Hire a bunch of clerics to constantly heal the fighter.
  3. Hire at least twelve high-level wizards.

    Seriously, more like a hundred would be better.

  4. Tell them to go kill the dragon.
  5. At this point, there are only two outcomes:

    • They kill the dragon; pay them with part of its vast treasure.
    • The dragon kills them; don't pay them. That would be silly.

As shown above, by continuing the indent level of the first line of a list item, sub-elements are placed within that item.

A definition list is a list of topics and their definitions. Topics are given on lines starting with a question mark (?), and definitions are given on lines starting with an equals sign (=). A definition list must begin with a topic, after which topics and definitions can be freely intermixed in any amounts.

CodeResult
Parts of a dragon:

? Mouth
= Contains teeth
= Can breathe fire
? Claws
= Very pointy, probably avoid
? Tasty meats
= ? Flank
  = Good for cooking on its own
  ? Ribs
  = Let's try this one with a honey glaze
  ? Other bits
  = Maybe turn them into a stew?
? Scales
= Good for fashioning into armor!

Parts of a dragon:

Mouth
Contains teeth
Can breathe fire
Claws
Very pointy, probably avoid
Tasty meats
Flank
Good for cooking on its own
Ribs
Let's try this one with a honey glaze
Other bits
Maybe turn them into a stew?
Scales
Good for fashioning into armor!

Figures

A figure is a self-contained piece of content that often has a caption and is referred to from the main document. A figure's contents and optional caption are all contained by a block starting with a percent symbol (%); a caption is denoted by a sub-element block starting with an equals sign (=). When rendering to HTML, if a caption is used, there should only be one at either the start or the end of the figure.

CodeResult
% ```
  #!/usr/bin/perl -w
  use strict;
  
  use Dragon::Meat;
  
  my $bits = Dragon::Meat::bits->new("tasty");
  my $stew = $bits->dice->cook;
  ```
  = Mom's recipe for Dragon stew.
#!/usr/bin/perl -w
use strict;

use Dragon::Meat;

my $bits = Dragon::Meat::bits->new("tasty");
my $stew = $bits->dice->cook;
Mom's recipe for Dragon stew.

Blockquotes

A blockquote is a block-level quotation; it is similar to merely writing something like He said, "how are you?", but is more semantically meaningful and often uses styling meant for larger sections of text. A blockquote is indicated by a line starting with a quotation mark ("). To include a citation, add a sibling block-level element starting with a dash (-); in the HTML renderer, this will place the quotation's resulting <blockquote> in a <figure> with CSS class quote and the citation in a corresponding <figcaption>.

CodeResult
Just a blockquote:

" I once killed a dragon the size of a castle!

A blockquote with a citation:

" Wow, these dragons sure are delicious!
- Anybody who has tasted one.

Just a blockquote:

I once killed a dragon the size of a castle!

A blockquote with a citation:

Wow, these dragons sure are delicious!
Anybody who has tasted one.

Headers and sections

Much like in HTML, there are two ways to semantically define the outline of your document. The first way, taken from old-style HTML and often seen in other markup languages, is to use headers with explicitly specified depth. In Nimble, you can create an explicit header element (HTML's <h1><h6> tags) by starting a line with an exclamation mark (!) immediately followed by a number (1 – 6) to indicate the depth (or no number, which defaults to depth 1).

CodeResult
! All About Dragons

This document covers all aspects of dragons.

!2 Weapons

Stuff to avoid while hunting dragons.

!3 Claws

Pointy. Avoid.

!3 Teeth

Pointier. Definitely avoid.

!2 Meat

Delicious. Bring back to castle.

The second mechanism for defining the outline of your document is by implicitly expressing depth through nested sections. HTML support for this sort of document structure is new as of HTML5. Using sections alleviates many issues with headers with explicit depths; for example, reorganizing a document no longer requires renumbering headers.

Nimble syntax uses a block starting with an open curly brace ({), optionally followed by the section header, to begin a section, and a closed curly brace (}) to end one. In addition, you can simultaneously close any number of sections and optionally start a new one by stacking all of the braces together; for example to close one section and start a new sibling section, you might write }{ Section Title. Any sections left open at the end of the document will be automatically closed.

In HTML rendering, the block started by an open curly brace actually corresponds to a <header> at the start of a section; if the header contains a single paragraph, that paragraph is converted to an <h1> tag.

CodeResult
{ All About Dragons

This document covers all aspects of dragons.

{ Weapons

Stuff to avoid while hunting dragons.

{ Claws

Pointy. Avoid.

}{ Teeth

Pointier. Definitely avoid.

}

}{ Meat

Delicious. Bring back to castle.

}}

Sometimes, like above, it can be clearer to close a section separately from its parent (see Meat, above) rather than all at once (like }}{ Meat).

The contents of a section aren't indented any more than the section itself. Extra elements you'd like to appear within the header of the section are indented, however. For example, a section header with a paragraph subtitle might look like this:

{ ! Nimble markup language -- syntax documentation
  
  An elegant markup language for a more civilized age.

...

}

Because the contents of the above example section's header isn't a lone paragraph, an explicit ! is used to create the <h1> in the section's header element.

Advanced features

These features require understanding of the output format (like HTML) and can be a little complicated to use.

Raw data

Sometimes, you need to include some particular raw data in the middle of your output. Maybe you need to create an HTML tag that isn't supported by Nimble. To do this, Nimble provides a mechanism to produce raw data for a specific output format. When using a raw data declaration, it is up to you to ensure that the output is valid for your output format. Nimble makes no attempt to protect you from invalid output.

Every use of a raw data declaration requires the target output format to be specified. If the current output format does not match the format specified in the raw data declaration, no output is produced.

Block-level syntax for raw data has two ways to use it. For raw data that fits on a single line, use #raw <format> <data>, replacing <format> with the output format for which this raw declaration is enabled, and replacing <data> with the raw text you would like produced at the location of the declaration.

#raw html <aside>

When in HTML output mode, this paragraph
will end up in an `<aside>` block.

#raw html <input type="button" value="Click me!"/>

Another paragraph that will end up
inside the `<aside>` block.

#raw html </aside>

The second way to use block-level syntax allows for multiple lines of raw data. To do this, omit the <data> part of the declaration, and instead merely write #raw <format>. After this, all subsequent lines indented further than the #raw declaration will be treated as raw output.

CodeResult
#raw html
  <table style="width:100%;">
    <tr><td>1</td><td>2</td></tr>
    <tr><td>3</td><td>4</td></tr>
  </table>
12
34

There also exists an inline syntax for raw data: anywhere within inline text, write [raw <format> <data>], again replacing <format> with the target output format and <data> with the raw text you would like produced at the location of the declaration. This syntax comes with a caveat: the square brackets must be balanced, but backslashes can be used to escape square brackets or other backslashes if necessary. Thus, [raw html [a]] is legal, but to produce [\[ as raw data using inline syntax, one would write [raw html \[\\\[].

Macros

Nimble includes a simple system for defining and reusing custom output structures via macros. A macro is a named set of raw data declarations which support variable substitution. Macros must be declared before they can be used.

Each macro can define a raw data output (called a #result) for each output format you'd like to target; if a macro has no #result for the current output format, no output is produced by the macro. Each macro can also have zero or more arguments (each called an #arg); each argument has a name, whether it should be parsed as nimble markup or raw data, and optionally a default value to use when it is not given.

When a macro is used, arguments of type nimble will be parsed as Nimble text and rendered to the current output format before variable substitution. Arguments of type raw will be passed through verbatim. Examples of this are below.

Declaration

A macro declaration consists of three parts: a starting line with its name, argument (input) definitions, and result (output) definitions.

To declare a macro, use the block-level declaration #macro <name>, replacing <name> with the desired name of the macro. This name can only contain letters, numbers, and underscores. A macro declaration produces no output.

#macro example

After the #macro line and indented further, define zero or more arguments using #arg <name> <type> <default>, replacing <name> with the argument name (only letters, numbers, and underscores), <type> with either nimble (to parse that argument as nimble code) or raw (to do no processing of the argument), and <default> with the desired single-line default value for the argument. Much like the syntax for #raw, a multi-line default may instead be given by omitting the default on the #arg line and instead including it on lines below indented further than the #arg line itself.

  #arg apple nimble This is /Nimble/-style markup.
  #arg banana raw This text will be taken <em>literally</em>.
  #arg pear nimble
    * This text is the default value for argument `pear`.
    * It will only be used if no `pear` argument is given to the macro.

Finally, define one or more results using #result <format> <data>, replacing <format> with the output format for which this result is targeted and <data> with the raw data to be output for that format. The rules for indicating where in the <data> section variables should be substituted depend on the output format being targeted. Much like the syntax for #raw, a multi-line value may instead be given by omitting the data on the #result line and instead including it on lines below indented further than the #result line itself.

HTML

In a #result html ... declaration, variable substitution is indicated by {{name}}, where name is the name of the argument to substitute.

  #result html <div>{{content}}</div>

You can also specify filters to be applied to argument values before they are substituted. These are given after the argument name as |filter in the order in which they should be applied. Available filters are:

xmlenc
XML-encodes any &"<> characters within the value
urlenc
URL-encodes any non-alphanumeric characters within the value

Here's an example which uses both of these mechanisms to properly encode the arguments:

#macro phpdoc
  #arg topic raw
  #result html
    <a class="phplink" href="http://php.net/{{topic|urlenc|xmlenc}}">{{topic|xmlenc}}</a>

Use

Macros can be used in both block and inline contexts.

The block-level syntax for macro use begins with a line consisting of a dollar sign ($) immediately followed by the name of the macro: $example. After this, zero or more of the arguments defined for the macro can be passed; this is done by a further-indented line consisting of the argument name immediately followed by a colon (:) and either a single-line value on the same line or a multi-line value on futher-indented subsequent lines.

$example
  apple: The *actual* value for this argument.
  banana:
    This raw text input
    spans several lines.

The inline syntax for macro use consists of a square-bracketed block starting with a dollar sign ($) immediately followed by the name of the macro: [$example ...]. Within the block, arguments are given as key=value pairs separated by whitespace; if a value contains spaces, it should instead be written in double or single quotation marks like arg1="value with spaces" arg2='value with spaces'. Within a quoted argument value, quotation marks (of the type enclosing the value) and backslashes must be escaped to be used: arg1="' \\ \"" arg2='\' \\ "'. Because Nimble locates the end of the macro before it's parsed, any square brackets within argument values need to either be balanced or escaped.

Examples

Let's say you want to easily make links to PHP documentation.

#macro phpdoc
  #arg topic raw
  #result html
    <a class="phplink" href="http://php.net/{{topic|urlenc|xmlenc}}">{{topic|xmlenc}}</a>

This macro takes a single argument, topic, as raw text. It produces a link with a special class (for later CSS targetting), an appropriate URL (by taking the topic, URL-encoding it, and then XML-encoding it), and then using the same topic again as the link text (by simply XML-encoding it). While it would be possible to replicate parts of this (no class attribute, no URL encoding) by writing [http://php.net/topic topic] repeatedly, using a macro allows easy maintenance of your document if the URL for PHP documentation changes or you want to update the class. It also means that you can merely type [$phpdoc topic=something] to make such a link, saving typing and reducing errors (what if you accidentally update a URL but not the label?).

CodeResult
#raw html
  <style>
  /* Add some extra styles to make
     phpdoc links stand out. */
  .phplink {
    background-color: #eeeeee;
    border: 1px solid #777bb4;
    color: #3b3d5a;
    padding-right: 4px;
  }
  .phplink:hover {
    color: #999999;
  }
  .phplink:before {
    content: "php";
    background-color: #777bb4;
    color: #000000;
    padding: 0 4px;
    margin-right: 4px;
  }
  </style>

In PHP, [$phpdoc topic=array_map] takes its callback first,
but [$phpdoc topic=array_filter] takes it last.

In PHP, array_map takes its callback first, but array_filter takes it last.

Suppose you want to make a macro to help demonstrate Nimble code easliy — say, have the Nimble code on the left and the result on the right, like this:

CodeResult
/Example/ Nimble *syntax*.
Example Nimble syntax.

In fact, there are many uses of this macro all over this very documentation! Here's what it looks like:

#macro example
  #arg code raw
  #arg result nimble
  #result html
    <table class="example">
      <tr><th>Code</th><th>Result</th></tr>
      <tr><td><pre>{{code|xmlenc}}</pre></td><td>{{result}}</td></tr>
    </table>

The first argument, code, takes raw text to be rendered. Upon output, it is XML-encoded: {{code|xmlenc}}. This causes the Nimble syntax given for that argument to appear as literal text in the output. The second argument, result, is of type nimble, causing it to be parsed as Nimble code. Its resulting syntax is not XML-encoded, and so it appears as regular rendered HTML in the output: {{result}}. Thus, the above example is created like this:

CodeResult
$example
  code:
    /Example/ Nimble *syntax*.
  result:
    /Example/ Nimble *syntax*.
CodeResult
/Example/ Nimble *syntax*.
Example Nimble syntax.

(Yes, the above example used an $example macro within an $example macro.)

You could achieve a similar result for demonstrating raw HTML by making the result argument of type raw, instead:

#macro example_html
  #arg code raw
  #arg result raw
  #result html
    <table class="example">
      <tr><th>Code</th><th>Result</th></tr>
      <tr><td><pre>{{code|xmlenc}}</pre></td><td>{{result}}</td></tr>
    </table>

$example_html
  code:
    <s>Strikethrough!</s>
  result:
    <s>Strikethrough!</s>

...produces...

CodeResult
<s>Strikethrough!</s>
Strikethrough!

Suppose you embed a lot of YouTube videos using the <object> tag interface.

#macro youtube
  #arg id raw
  #result html
    <object width="640" height="390">
      <param name="movie" value="https://www.youtube.com/v/{{id|xmlenc}}?version=3"></param>
      <param name="allowScriptAccess" value="always"></param>
      <embed src="https://www.youtube.com/v/{{id|xmlenc}}?version=3"
             type="application/x-shockwave-flash"
             allowscriptaccess="always"
             width="640" height="390"></embed>
    </object>

Then, anywhere in your document, simply write...

CodeResult
$youtube
  id: w-nBuRToaNQ

Want to be able to tag things with [citation needed] like you can on Wikipedia?

CodeResult
#macro citation_needed
  #result html <sup>[citation needed]</sup>

That dragon was delicious. [$citation_needed]
That dragon was delicious. [citation needed]

Or, to actually cite thigs, maybe something like....

CodeResult
#macro ref
  #arg id raw
  #result html
    <sup
      ><a href="#cite-{{id|urlenc|xmlenc}}">[{{id|xmlenc}}]</a
    ></sup>

#macro cite
  #arg id raw
  #arg text nimble
  #result html
    <div>
      <a name="cite-{{id|xmlenc}}" id="cite-{{id|xmlenc}}"></a>
      {{id|xmlenc}}. {{text}}
    </div>

That dragon was delicious.[$ref id=1]  We could catch another
in that cave.[$ref id=2]

[$cite id=1 text="I should know; I just ate it."]
[$cite id=2 text="I just saw a dragon in that cave."]

That dragon was delicious.[1] We could catch another in that cave.[2]

1. I should know; I just ate it.
2. I just saw a dragon in that cave.

The weird newlines in the ref macro are to prevent extra whitespace from appearing within the <sup> tag.

Output formats

Many output formats are possible; Nimble syntax is first converted to a syntax tree, and then the syntax tree is rendered. Future possibilities include LaTeX, Perl POD, Markdown, or Wikipedia (MediaWiki) markup.

HTML

The HTML output format tries to produce semantically-useful HTML5 — sections ({ ... }) are <section>s, blockquotes with citations are contained within <figure>s, and so forth.

In general, the HTML renderer tries to keep stray whitespace within tags rather than outside them. This prevents extra text nodes from being generated. For example, paragraphs might look like this:

<p>paragraph 1</p
><p>paragraph 2</p
><p>paragraph 3</p
>

This is valid HTML; when an application reads it, it will generate only a series of paragraph nodes with no intervening text nodes containing merely unnecessary newlines. This means that newline-separated inline or inline-block elements won't have extra spaces between them, and any JavaScript using the Node.childNodes DOM interface will only see the nodes you intended.

You can see an example of HTML output from Nimble by viewing the source of this page, specifically the section within the <article> tags.

Try it!

You can test out Nimble if you like. The test page has some limits on CPU time and input size to prevent anyone from doing something too ridiculous.