Skip to content

Concise markup language + templating system inspired by haml, SLiP, sexp2xml, and tenjin.

License

Notifications You must be signed in to change notification settings

josephwecker/zml

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Current work and issues can be found at
PivotalTracker

Feel free to ping us if you want to be added to the pivotaltracker account.

The Little ZMLer

ZML is a small markup language that uses indentation to represent
hierarchy of tags.

tags

By default, ZML document translates into XML:


:document
  :title My first ZML example
    has a pretty long title
  :table
    :tr
      :td cell 11
      :td cell 12
    :tr
      :td cell 21
      :td cell 22

<?xml version="1.0"?>
<document>
  <title>My first ZML example has a pretty long title</title>
  <table>
    <tr>
      <td>cell 11</td>
      <td>cell 12</td>
    </tr>
    <tr>
      <td>cell 21</td>
      <td>cell 22</td>
    </tr>
  </table>
</document>

indentation matters

Note how it treats indentation to mix text and tags:


:document
  :head First line of the HEAD tag.
    Second line of the HEAD - note the indentation.
  :body Obviously, that line belongs to BODY.
    This one is also part of the BODY.
  OOPS, this line is part of the DOCUMENT tag!

<?xml version="1.0"?>
<document>
  <head>
    First line of the HEAD tag.
    Second line of the HEAD - note the indentation.
  </head>
  <body>
    Obviously, that line belongs to BODY.
    This one is also part of the BODY.
  </body>
  OOPS, this line is part of the DOCUMENT tag!
</document>

inline tags

Inline tags must have a closing semicolon in the same line:


:document
  :title Here's a :strong big fat; title

<?xml version="1.0"?>
<document>
  <title>Here's a <strong>big fat</strong> title</title>
</document>

comments

ZML supports single-line comments and special *comment tags:


:document || Comment to the end of line
  *comment first line of the comment
    second line of the comment
  :body || Note this tag has an empty body!

<?xml version="1.0"?>
<document><body/></document>

attributes

Syntax for attributes is:


:document(author: Sergei Matusevich
          encoding: UTF-8 language: en-us)
  :title(class: header)

<?xml version="1.0"?>
<document author="Sergei Matusevich" encoding="UTF-8" language="en-us">
  <title class="header"/>
</document>

Note that because we use parenthesis, attributes can span multiple
lines. Multiline attributes must be indented, just like the body of
the tag.

escaping special characters

To escape special characters, we can use backslash or any of the |""|,
|’’|, or |``| quotes:


:document(onload: |"onload();"|)
  :title \:tag escaping

<?xml version="1.0"?>
<document onload="onload();">
  <title>:tag escaping</title>
</document>

multiline quotes

Note that |""| quotes can span multiple lines, but it still must be
indented relatively to the enclosing tag:


:document
  :script(type: text/javascript) |"
    function onload() {
      alert("Hello there");
    } "|

<?xml version="1.0"?>
<document>
  <script type="text/javascript">
    function onload() {
      alert("Hello there");
    } </script>
</document>

id and class attributes

ZML has special syntax for id and class attributes, common in (X)HTML:


:document#sample-001
  :table#sample-table-id.bigtable-class
    :tr.bigtable-class.odd-row
      :td cell 11
      :td cell 12
    :tr.bigtable-class.even-row
      :td cell 21
      :td cell 22

<?xml version="1.0"?>
<document id="sample-001">
  <table id="sample-table-id" class="bigtable-class">
    <tr class="odd-row bigtable-class">
      <td>cell 11</td>
      <td>cell 12</td>
    </tr>
    <tr class="even-row bigtable-class">
      <td>cell 21</td>
      <td>cell 22</td>
    </tr>
  </table>
</document>

Note that each :tr tag has two classes that got pasted into a single
attribute value. Order of id and class attributes does not matter.

div tags

If class or id (or both) are used, we can omit :tag name
alltogether. ZML uses div tag in such case:


:document
  #header(onclick: |"alert('hello');"|) a header DIV
  #body.grid-3
    .title isn't that neat?
    More text for the body
  :div#footer a footer DIV

<?xml version="1.0"?>
<document>
  <div id="header" onclick="alert('hello');">a header DIV</div>
  <div id="body" class="grid-3">
    <div class="title">isn't that neat?</div>
    More text for the body
  </div>
  <div id="footer">a footer DIV</div>
</document>

We can freely mix shortcuts for div, class, and id with the regular
ZML syntax.

special tag – *html

ZML can be extended with special tags that hook up to the user-defined
code for custom syntax. Such tags start with the ‘*’ character instead
of ‘:’. Most useful tag is *html. Compare this:


:html or is it?

<?xml version="1.0"?>
<html>or is it?</html>

With this:


*html or is it?

<?xml version="1.0"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
  <head>
    <meta http-equiv="content-type" content="text/html; charset=utf-8" />
    <meta http-equiv="content-language" content="en-us" />
    <meta name="MSSmartTagsPreventParsing" content="true" />
  </head>
  <body>or is it?</body>
</html>

That is, *html creates a lot of boilerplate HTML for us!

*html special attributes

It also gives special treatment to many attributes, e.g.


*html(title: That's a document title
      favicon: /img/favicon.ico
      encoding: koi8-r language: ru)
  Here goes the body

<?xml version="1.0"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ru" lang="ru">
  <head>
    <meta http-equiv="content-type" content="text/html; charset=koi8-r" />
    <meta http-equiv="content-language" content="ru" />
    <meta name="MSSmartTagsPreventParsing" content="true" />
    <title>That's a document title</title>
    <link href="/img/favicon.ico" rel="icon" />
    <link href="/img/favicon.ico" rel="shortcut icon" />
  </head>
  <body>Here goes the body</body>
</html>

Note the link and title tags, as well as the change in meta http-equiv
parameters.

*html special attributes – complete list

Here’s the full list of special attributes that *html currently
supports:

document type

  • type: HTML type. Can be one of:
html2
html3
strict
frameset
xhtml_strict
xhtml_frameset
transitional
xhtml_transitional

This attribute selects what HTML template to use, e.g.


*html(type:html2) test

<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta http-equiv="Content-Language" content="en-us">
    <meta name="MSSmartTagsPreventParsing" content="TRUE">
  </head>
  <body>test</body>
</html>

*html(type:xhtml_frameset) test

<?xml version="1.0"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
  <head>
    <meta http-equiv="content-type" content="text/html; charset=utf-8" />
    <meta http-equiv="content-language" content="en-us" />
    <meta name="MSSmartTagsPreventParsing" content="true" />
  </head>
  <body>test</body>
</html>

encoding and language

  • encoding: document encoding. UTF-8 by default.
  • language: content-language part of the http-equiv. Also sets the
    lang and xml:lang attributes of the html tag, if html type requires
    so. Default is en-us.

other special attributes for *html

  • nosmarttag: true or false. Controls MSSmartTagsPreventParsing.
  • stylelibs: Names of ZSS libraries to include
  • remove_unused_css: false (default) or true. Turns on CSS optimization.
  • description
  • keywords
  • copyright
  • title
  • favicon

Various shortcuts. The following example uses them all:


*html(description: document description
      keywords: zml zss markup erlang
      copyright: Joseph Wecker
      title: page title
      favicon: /img/favicon.ico)
  test

<?xml version="1.0"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
  <head>
    <meta http-equiv="content-type" content="text/html; charset=utf-8" />
    <meta http-equiv="content-language" content="en-us" />
    <meta name="description" content="document description" />
    <meta name="keywords" content="zml zss markup erlang" />
    <meta name="copyright" content="Copyright (c) Joseph Wecker" />
    <meta name="MSSmartTagsPreventParsing" content="true" />
    <title>page title</title>
    <link href="/img/favicon.ico" rel="icon" />
    <link href="/img/favicon.ico" rel="shortcut icon" />
  </head>
  <body>test</body>
</html>

*table markup

Special tag *table implements a simple markup language for tables. It
looks like this:


*table
  | a | b |
  | c | d |

This code translates into:


<?xml version="1.0"?>
<table>
  <tr>
    <td>a</td>
    <td>b</td>
  </tr>
  <tr>
    <td>c</td>
    <td>d</td>
  </tr>
</table>

Each row of the table must begin and end with the ‘|’
character. Spaces are treated as-is; note that “||” (with no spaces)
is treated as a comment:


*table | a|b |  || comment!

results in


<?xml version="1.0"?>
<table><tr><td> a</td><td>b </td></tr></table>

Note that it is OK to start table immediately after the *table tag, on
the same line. Comments and quoted strings are also supported.

inline tags inside *table

It is perfectly fine to have other tags inside the *table markup. ‘|’
characters inside such tags are just regular characters, and are not
interpreted as column separators, e.g.


*table | :strong some | text; |

translates into:


<?xml version="1.0"?>
<table>
  <tr>
    <td>
      <strong>some | text</strong>
    </td>
  </tr>
</table>

tr and td attributes

To specify attributes for tr and td tags, prefix them with “tr_” and
“td_”, respectively, and define them in the *table tag:


*table#bigtable(tr_class: row td_class: cell border: 0) | a | b |

translates into:


<?xml version="1.0"?>
<table id="bigtable" border="0">
  <tr class="row">
    <td class="cell">a</td>
    <td class="cell">b</td>
  </tr>
</table>

Templating

Variables

Syntax for variables is:


${variable}

To refer nested data sets, separate identifiers with dots:


${data_set.nestedDataSet.var}

Variables can be used inside the :tag body or in attribute values.
Behavior of the *special tags depends on the tag implementation,
e.g. *comment and *verbatim treat variables as any other text.

Repeated blocks

To iterate over a data set, use the *with special tag, e.g.


:table
  *with(id: data_set)
    :tr :td ${user_name}; :td ${user_address};

Here :tr block will be replicated as many times as there are records
in the given data_set.

Data set ID is specified in the *with id attribute. We can also write
*with#data_set to same effect.

ZML Gotchas

Special characters that begin a tag

Remember that ‘.’ period, ‘:’ colon, and ‘#’ hash are special characters that
can start inline tags, when immediately followed by one or more alpha
characters, e.g.


:a(href: http://github.com) github.com

translates into


<a href="http://github.com"> github<div class="com"></div></a>

i.e. a string “.com” is treated as inline div block here. Oops.

To avoid this, escape the dot with the backslash or quote the whole string, and
write github\.com or |“github.com”|.

Note that tag name must begin with the alpha character, so the the strings
like “$9.99” or “#1” will remain untouched.

Semicolons

Remember that ‘;’ semicolon closes the inline tag, but only if there is an
inline tag to close. Otherwise, semicolon will remain as is. E.g.


.example Check if :i x &lt; y; for every value of x

results in


<div class="example">Check if <i>x &lt</i> y; for every value of x</div>

Note that the first semicolon that belongs to < string has been translated
as the end of the :i tag, but the second semicolon remained as is.

The issue occurs only when the extra semicolon is inside the inline tag.
Since tags that start the line does not have to be closed, there’s no need to
escape semicolons in such case.

Spaces around inline tags

Spaces around inline tags are preserved, just like any other spaces between
words. The only spaces that ZML truncates are those immediately following the
tag name (but not the list of attributes), e.g.


.example   Hello :a (href: #)  world;!

produces


<div class="example">Hello <a href="#">  world</a>!</div>

i.e. ZML had removed spaces between “.example” and “Hello”, and between “a” and
“href”. All other spacing remained intact.

About

Concise markup language + templating system inspired by haml, SLiP, sexp2xml, and tenjin.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published