Home

Awesome

Mark Notation

npm version Build Status codecov Analytics

Mark Notation or simply Mark, is a new unified notation for both object and markup data. The notation is a superset of what can be represented by JSON, HTML and XML, but overcomes many limitations of these popular data formats, yet still having a very clean syntax and simple data model.

MarkJSONHTMLXMLS-exprYAML
Clean syntaxyesyesnoverboseyesyes <sub>(only for basic usage)</sub>
Fully-typedyesyesnono <sub>(when no schema)</sub>yesyes
Genericyesyesnoyesyesyes
Mixed content supportyeshardyesyeshard <sub>(poor map support)</sub>hard
High-order compositionyespossiblenoverboseyespossible
Wide adoptionnot <sub>(at the moment)</sub>yesyesyeslimitedlimited

Mark Syntax

The major syntax extension Mark makes to JSON is the introduction of a Mark object. It is a JSON object extended with a type name and a list of content items, similar to element in HTML and XML.

For example, a HTML registration form:

<form>
  <!--comment-->
  <div class="form-group">
    <label for="email">Email address:</label>
    <input type="email" id="email">
  </div>
  <div class="form-group">
    <label for="pwd">Password</label>
    <input type="password" id="pwd">
  </div>
  <button class='btn btn-info'>Submit</button>
</form>

Could be represented in Mark as:

{form                                   // object with type-name 'form'
  (?comment?)                           // Mark pragma, like HTML comment
  {div class:"form-group"               // nested Mark object
    {label for:email                    // property 'for' and its value, both unquoted
      "Email address:"                  // text needs to be quoted
    }
    {input type:email id:email}         // object without any contents
  }
  {div class:form-group
    {label for:pwd "Password"}
    {input type:password id:pwd}        // comma is optional 
  }
  {button class:['btn' btn-info]        // property with complex values
    'Submit'                            // text quoted with single quote
  }
}

You can refer to the syntax spec for details.

Mark Data Model

Mark has a very simple and fully-typed data model.

Each Mark object has 3 facets of data:

Mark utilizes a novel feature in JavaScript that a plain JS object is actually array-like, it can contain both named properties and indexed properties.

So each Mark object is mapped to just one plain JavaScript object, which is more compact and efficient comparing to other JSON-based DOM models (e.g. JsonML, virtual-dom, MicroXML), and is more intuitive to used under JS.

Roughly speaking, data models of JSON, XML, HTML are subsets of Mark data model, and Mark data model is a subset of JS data model.

<div align="center"> <img src='https://mark.js.org/data-model.png' width='300'> </div>

You can refer to the data model spec for details.

Mark vs. JSON

Mark is a superset of JSON. It extends JSON notation with a type-name, and a list of content objects.

Comparing to JSON, Mark has the following advantages:

Some disadvantages of Mark, comparing to JSON would be:

Mark vs. HTML

Comparing to HTML, Mark has the following advantages:

Mark vs. XML

Comparing to XML, Mark has the following advantages:

Mark vs. S-expressions

S-expression from Lisp gave rise to novel ideas like high-order composition, self-hosting program. The clean and flexible syntax of Mark make it ideal for many such applications (e.g. Mark Template, a new JS template engine using Mark for its template syntax), just like s-expression.

The advantage of Mark over S-expressions is that it takes a more modern, JS-first approach in its design, and can be more readily used in web and node.js environments.

mark.js

mark.js is the JS library to work with data in Mark format. It consists of 4 modules:

Usage

Install from NPM:

npm install mark-js --save

Then in your node script, use it as:

const Mark = require('mark-js');
var obj = Mark.parse(`{div {span 'Hello World!'}}`);
console.log("Greeting from Mark: " + Mark.stringify(obj));

To use the library in browser, you can include the mark.js under /dist directory into your html page, like:

<script src='mark.js'></script>
<script>
var obj = Mark(`{div {span 'Hello World!'}}`);  // using a shorthand
console.log("Greeting from Mark: " + Mark.stringify(obj));
</script>

Note: /dist/mark.js has bundled all sub-modules and all dependencies with it, and is meant to run in browser. The entire script is about 14K after gzip. It supports latest browsers, including Chrome, Safari, Firefox, Edge. (Legacy browser IE is not supported.)

If you just want the core functional API, without the sub-modules, you can also use mark.core.js, which is only 7K after gzip. You can also refer to the package.json to create your own custom bundle with the sub-modules you need.

Documentation

Tools, Extensions and Applications of Mark

Credits

Thanks to the following platforms or services that support the open source development of Mark: NPM, GitHub, Travis CI, Codecov, BrowserStack, jsDelivr, Plunker, JS.org.