Basics

Let's start with the basics, so that you can be productive right away! Also, just so you know, each example is a live editor.

Emphasis

A prefix underscore will emphasize a word. Use two for strong emphasis.

One underscore is italics
Two underscores is bold

Brackets can be used to emphasize multiple words or parts of a word.

The apple pie was amazing!

Alternatively you can use the tilde, which is a non-breaking space:

amazing!

The @@ operator is used to create links. On the left goes the link's label (optional) and on the right, the URL.

Again, you can group with brackets:

Finally, you can put the URL in a variable if you find it more convenient:

Check out my blog!

Also note the use of the tilde above. It is required otherwise the ! is understood to be part of the URL.

Images

The link syntax also serves to display images. Prefix the path with image:

You can give images a title as well:

quaint

If you want to control the image's size or other properties you should use the % operator:

QUAINT

Headers

Begin a line with one equal sign for a h1 tag, two for a h2 tag, and so on:

h1

h2

h3

h4

h5
h6

Lists

An asterisk at the beginning of a line creates a bullet point.

  • Bread
  • Tomatoes
  • Goat cheese

A hash sign, on the other hand, starts an ordered list.

  1. One!
  2. Two!
  3. Three!

Tables

A leading + creates a header row and a leading | creates a normal row.

NameSurnameJob
AliceLovelacePhysicist
HaroldWorthingtonBanker

Of course, you may think aligning table elements is a little annoying, or perhaps your table is stored in a JSON file and you would like to make a table automatically for it.

Definitions

The `:=` operator creates definitions.

quaint
A cool markup language.
xml
Not cool at all.

Blockquotes

A prefix > will create a blockquote. Consecutive lines will be merged.

Hello, I am a great man

Although, you can use indent, too.

Hello, I am a great man

Multiple blockquote levels can be done, but they require a space between the [>]s.

Hello!
Bonjour!

Code blocks

The ampersand operator creates a code block:

This is a code block

If you wish to highlight the code in a particular language, you need to use the quaint-highlight plugin and then write out the language before the &:

function square(x) {
    return x * x;
}

This will not work if you don't use the plugin.

Inline code

A prefix backtick makes a word into inline code.

Here is code

Normally you will want to use brackets:

Simple as 1 + 1 = 2

Note that only the outer bracket pair will be stripped off:

Simple as [1 + 1 = 2]

For the rare case where you want to show an unmatched opening or closing bracket as code, escape it with a backslash:

The opening bracket is [

Comments

Any block that comes after ;; will be ignored by Quaint:

I have nothing to hide

Escaping

If you want to print a character without triggering any special meaning it may have, simply prefix it with a backslash.

__Not _emphasized
[Bracketed!]
You~have~to~escape~tildes

Also, Quaint thinks every sequence of operator characters is a distinct operator. So while x@@#y looks like a link to #y it is actually an application of the @@# operator, which does not exist. Escaping an operator character makes it a word character, so in that case you can escape # to get the desired behavior:

No@@#escaping

Whitespace/grouping

Spacing

The spacing between an operator and its operand determine the priority of the operator. More spacing means a larger operand. To put it simply:

One word is bolded
All the words are bolded
One word is linked

Play a bit with the spacing above to get a feel of the results

Indent

An indented block after an operator belongs to that operator:

  • This is all inside the bullet point
all inside the strong emphasis
  • You can also put the operator on its own line.

Grouping

You can group together any chunk of text by enclosing it in square brackets ([]). They effectively behave like a single word.

Brackets do not show up
Emphasis on one word
Emphasis on many words
Here is a link
Here is another link

HTML Generation

The % operator is used to generate arbitrary HTML nodes, if you need to. The full syntax looks like this:

tag#id.class %
  attribute = value
  child1
  child2
  ...

You can specify multiple classes. If there is no tag, the default is div.

x2

An error occurred! (Not really)

You can also write the nodes more compactly by putting every property and element inside square brackets.

A link to google!

Gotchas

Now here's what will not work. % cannot be used as a suffix operator without adding a space (this is so that you can say that 100% of crows are black or the glass is 50% full without creating tags, which would be confusing). With a space before %, it will create a tag, but with the space comes the need for grouping brackets. So a line break, for example, is [br %]:

First br% line
Second line

Notice how the first br% is just shown normally and does not create a <br> tag, whereas [br %] does!

Also, because of Quaint's fixed priorities (all operators are right-associative), this will not work as intended (it creates a <klass> tag):

div.nope

To make it work, put spaces around %, or brackets around span.klass.

yes
yes

html macro

Alternatively, you can embed HTML directly using one of these two methods:

x2 x2

Inject CSS

Injecting CSS!

Oranges are orange!
HELLO

Inject JavaScript

Note that this is different from embedding JavaScript: what I mean by inject is to write code inside the generated HTML, with script tags. This is done as follows:

js :: javascript code

For example,

js :: console.log("hello")

will print “hello” to the console when you load the page in the browser. It will do nothing at generation time.

HTML Sandbox

Let's generate HTML!

  1. 22 is 4
  2. 222 is 16
  3. And so forth...

Variables

If there is a piece of markup you don't want to put in the middle of a paragraph, for example a long URL for a link, or want to use multiple times, then variables are for you. It's very simple:

variable => contents
...
{variable}

For example:

Theropods are a family of dinosaurs which, according to the study by Smith, had very large wings that allowed them to fly to the moon.

Better yet… you can define the variable after it is used, and it will work anyway!

Quaint is a language similar to Markdown with a dash of Haml

A variable can be used multiple times.

KNOCK! KNOCK! KNOCK!

Rules

Simply put, a rule is a reusable template that you assign a name or an operator to. Rules help with terseness and code reusability, although abusing them could make your code difficult to read. The syntax for a rule is:

[pattern] => template

A pattern is a normal Quaint expression, but any word which is prefixed with a backslash becomes a variable. The variable can be inserted in the template using curly brackets ({variable}). Here is an example of a rule someone may write to make superscripts easier:

23

Both arguments must be present in order for the rule to work. If either is absent, for instance ^2 lacks the text argument, the rule will not be run. You can change this by declaring the argument as \maybe\text instead:

23 and 3 match, but 2^ does not

Conversely, if you declare the pattern [^ \superscript], Quaint requires the operator to be prefix:

3 matches, but 2^3 and 2^ do not

Behavior

Rules do not modify Quaint's parser: the ^ operator has always existed, it is just that by default it just prints itself out. This is an advantage, because rules in Quaint are predictable: the operator we just defined is right-associative, because all operators in Quaint are right-associative. They are sensitive to spacing like all operators, they can be bracketed like all operators, and so on.

  • Superscript one word
  • Superscript multiple words
  • Right associative: 23456
  • Emphasizedsuperscript
  • Superscripting a whole block!

Rule Sandbox

I am a big fan of oranges and other orange food like carrots.

The orange is a fruit, who would have thought?

Scripting

Curly brackets switch to “eval mode”. They could contain JavaScript, or Earl Grey, or something else. By default the “eval” used is just a key-based load/store mechanism. Other scripting languages require importing a plugin.

Supposing the quaint-javascript plugin is used, as it is on this site, then you can embed JS expressions:

2 + 2 = 4

You can also use JS inside rules. The variables declared by the rule are also available in JavaScript! They are not strings, but you can convert them into strings by calling the raw method on them.

HELLO! I DON'T MEAN TO SHOUT, BUT WHERE'S THE BEEF?

It is also possible to build HTML programmatically. quaint-javascript comes with the h function. If you use h, though, make sure to call engine.gen on the arguments to apply Quaint markup to them! Unless you are converting them to strings, that is. The markup will be lost if you do that.

This is bold!

With the quaint command line and API, you can provide environment variables for use inside curly brackets. See the -d option for the quaint command.

Conditionals

Generate something different depending on the value of a variable or of metadata with conditionals:

First there is the condition ?? iftrue construct:

yes

You can add a branch to generate when the condition expression is false with the !! operator.

yes
no

cond !! iffalse is shorthand for cond ?? cond !! iffalse.

true
no

{true} and {false} trivially evaluate to true or false respectively, but they are not super useful.

On metadata

Meta variables, when they are not defined, will trigger the false branch:

no
yes

They also trigger the false branch if they are set to “false":

  • no

On variables

As conditionals, you can use variables imported with include @@ #include, with the -d flag of the command line, or set by setenv

  • yes
  • no

Loops

The each macro can be used to generate loops over various data. The syntax is:

each data variable ::
  body

each data var1 var2 ... ::
  body

There are many kinds of data you can iterate on:

On lists

  1. I need bread
  2. I need milk
  3. I need bananas

On tables

Depending on whether it has a row of headers, a table is interpreted either as a list of objects or as a list of lists:

With a header, it is a list of objects:

  • Alice is 21 years old and is a baker
  • Bob is 42 years old and is a banker
  • Carmen is 33 years old and is a fraud

Without, you have to declare a variable for each column, just like this:

  • Alice is 21 years old and they are a baker
  • Bob is 42 years old and they are a banker
  • Carmen is 33 years old and they are a fraud

On documents

  • Hello, Alice
  • Hello, Bob

On metadata

  • Tagged: Cool!
  • Tagged: Wow!

On JSON

  • Hello, Alice!
  • Hello, Bob!
  • Alice is a baker
  • Bob is a banker

This works just as well if you include external data, of course. Also, check out the quaint-yaml plugin if you wish to include and iterate over YAML.

Macros

Macros are typically written with the :: operator, either as macro :: body or macro argument :: body.

css

See here

doctype

Generate a doctype tag for a document:

doctype :: html
==> <!DOCTYPE html>

data

data reads a data file and returns it (usually so you can put it in a variable)

For example:

movies => data :: movies.json

= List of movies!
each {movies} movie :: * {movie.title}

Also consider the quaint-yaml plugin if you wish to fetch YAML data:

plugins :: yaml
movies => data :: movies.yaml
...

dump

See store

each

See Loops

html

See here

include

include reads a file and then does something special with it:

include :: template
include :: template.q
include :: data.json, other-data.json

Also consider the quaint-yaml plugin if you wish to include over YAML:

plugins :: yaml
include :: data.yaml

meta

meta lets you declare metadata: title, author, and so on. It also lets you print out the data elsewhere in the file.

You are reading My Life by Me!.

plugin

This imports a plugin directly from Quaint. It won't work here in the browser, but it will offline.

The syntax works like this:

plugin name ::
  option = value
  ...

For example:

plugin highlight ::
  defaultLanguage = python

You will need to install the corresponding packages locally. For instance, for the highlight plugin to work, you need to execute this command beforehand:

npm install quaint-highlight

plugins

This is shorthand to import plugins with their default options:

plugins :: highlight javascript

This will import quaint-highlight and quaint-javascript with their default options.

resources

The resources macro lets you include files in your output. By default, the resources will be inserted in the head tag.

resources ::
  style.css
  my-script.js

Depending on command-line options, the resources may be copied over to a resource directory and linked to, or inlined directly in the output (at the appropriate location). The default is to copy and link.

scope

scope creates a new scope, so that all variables declared in the body are only visible inside that body.

insidex-iny-out
outsidex-outy-out

store

store is mostly useful in conjunction with the API and/or templates. With this macro you can push data to an internal “document" (a list of references, or a list of script tags to put in <head> for instance), and then dump that document somewhere convenient. You don't have to dump after everything has been stored.

  1. Bob
  2. Clara
  3. Damian

One use case of store is in Quaint's very documentation. The code for this page declares:

store sidebar ::
  toc::

That is to say, “put the table of contents in the sidebar”. Then, the template it is using dumps the contents of the sidebar document in the sidebar.

You can also use store and dump along with each.

  1. Bob Clara
  2. Damian

Notice, however, that Bob and Clara are part of the same element as far as each is concerned.

template

Define the template to use for this file. For example, if you specify

template :: mytemplate

The Quaint compiler will go through the following steps:

  1. Generate the HTML for the whole file
  2. Put the HTML in the variable body
  3. Fetch mytemplate.q
  4. Go to 1 (with the original in the variable body)

So if mytemplate.q contains:

#header % header
{body}
#footer % footer

Then any file that uses it as a template will generate a header div above and a footer div below.

The CLI lets you specify a template directory with the -t options. You can also customize how files are read.

Two templates are defined by default and can be used directly:

Plugins can define more templates that use the @ syntax. Check their documentation.

toc

toc prints out a table of contents based on the headers declared in the markup. It can be used anywhere in the file.

One

Two

Two point one

Two point two

Three

when

Alternative notation for the ?? operator. They both work identically.

hello

See conditionals

Error reporting

If an error occurs in a Quaint document, the error will be inlined inside a span with class error (which you can style yourself, for example I suggest using bold red, so you don't accidentally skim over your outrageous blunders).

There is an ReferenceError: error is not defined here.

If you want more information about an error, a stack trace for example, you can dump the errors sub-document. Each error will contain a link to its corresponding stack trace.

An error ReferenceError: blah is not defined [#1] and another SyntaxError: Unexpected end of input [#2], woe is me!

E.match: 'Error? e' could not find a match for value 'ReferenceError: blah is not defined' [#3]