npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

mark-js

v1.0.0

Published

Mark, an unified notation for all

Downloads

673

Readme

Mark Notation

npm version CI codecov

Mark Notation is a modern, unified data format that combines the best aspects of JSON, XML, HTML, and other popular formats while eliminating their limitations. It provides a clean syntax with full type support, making it ideal for configuration files, data exchange, and document markup.

Table of Contents

| | Mark | JSON | HTML | JSX | XML | S-expr | YAML | | ------------ | ---- | ---- | ---- | ---------------------------------- | ------------ | ------ | ------------------------------------- | | Clean syntax | yes | yes | no | no | verbose | yes | yes (only for basic usage) | | Fully-typed | yes | yes | no | partially(in {...}) | need schema | yes | yes | | Generic | yes | yes | no | no | yes | yes | yes | | Mixed content support | yes | hard | yes | yes | yes | hard (poor map support) | hard | | High-order composition | yes | possible | no | yes | verbose | yes | possible | | Wide adoption | not (at the moment) | yes | yes | yes | yes | limited | limited |

Mark Syntax

The major syntax extension Mark makes to JSON is the introduction of a Mark element. 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                                 // element with name 'form'
  <'!--'comment>                      // HTML comment as special element
  <div class:'form-group'             // nested child element
    <label for:email                  // 'for' and its value, both unquoted
      "Email address:"                // text needs to be double quoted
    >
    <input type:email, id:email>      // element without child
  >
  <div class:'form-group'             // 'form-group' is a quoted symbol
    <label for:pwd; "Password">       // pwd is an unquoted symbol
    <input type:password, id:pwd>     // attrs separated by comma, like JSON
  >
  <button class:[btn, 'btn-info']     // attribute with complex values
    "Submit"                          // text quoted with double 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 element has 3 facets of data:

  • Element name, which is mapped to object.constructor.name under JavaScript.
  • Attributes, which is a collection of key-value pairs, stored as normal JavaScript named properties.
  • Contents, which is a list of child objects, stored as indexed properties inside the same JavaScript object.

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 element is mapped to just one plain JavaScript object, which is more compact and efficient compared to other JSON-based DOM models (e.g. JsonML, virtual-dom, MicroXML), and is more intuitive to use 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.

You can refer to the data model spec for details.

Mark vs. JSON

Mark is a superset of JSON. It extends JSON notation with additional scalar and container types.

Compared to JSON, Mark has the following advantages:

  • Additional scalar types supported under Mark, compared to JSON, include: symbol, decimal number, datetime, binary (supporting essentially all the major built-in data types under JS).
  • For container types, other than array and map, Mark supports a new type element. Mark element has a type-name, which is important in identifying what the data represents; whereas JSON map is actually an anonymous object, missing the type name.
  • Mark element has built-in mixed-content support, which is common in all markup formats, and thus allows Mark to conveniently represent document-oriented data, which is awkward for JSON.
  • Mark incorporates some syntax enhancements to JSON ~(e.g. allowing comments, name without quotes)~, thus making the format more friendly for humans.

Some disadvantages of Mark, compared to JSON would be:

  • It is no longer a subset of JavaScript literal syntax, although a Mark object is still a simple POJO in JS data model.
  • It does not yet have wide support, like JSON, at the moment.

Mark vs. HTML/JSX

Compared to HTML/JSX, Mark has the following advantages:

  • Mark is a generic data format, whereas HTML is a specialized format for web content.
  • It does not have whitespace ambiguity, as the text objects are quoted explicitly. Thus Mark can be minified or prettified without worrying about changing the underlying content.
  • Mark attributes can have complex values, like JSON, not just quoted string values as in HTML.
  • It has a very clean syntax, whereas HTML5 parsing can be challenging even with HTML5 spec.
  • It is always properly closed; whereas HTML self-closing tag syntax is non-extensible and error-prone.
  • The DOM produced under Mark model, is just a hierarchy of POJO objects, which can be easily processed using the built-in JS functions or 3rd party libraries, making Mark an ideal candidate for virtual DOM and other application usages.

Mark vs. XML

Compared to XML, Mark has the following advantages:

  • Mark attributes can have complex objects as values; whereas XML attribute values always need to be quoted and cannot have complex objects as values, which is not flexible in syntax and data model.
  • Mark syntax is much cleaner than XML. It does not have whitespace ambiguity. It does not have all the legacy things like DTD. It does not have the verbose closing tag.
  • The data model produced by Mark is fully typed, like JSON; whereas XML is only semi-typed, when there's no schema.

Mark vs. S-expressions

Lisp and S-expression gave rise to novel ideas like high-order composition, self-hosting program, data as code, code as data, etc.. It's the source of inspiration of Mark and Lambda Script.

The advantage of Mark over S-expressions is that it takes a more modern, web-first approach in its design, making it more readily usable 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:

  • The core module mark.js, which provides parse() and stringify() functions, like JSON, and a direct Mark object construction function Mark(), and some functional APIs to work with the object content.
  • Sub-module mark.mutate.js, which provides mutative APIs to change the Mark object data model.
  • Sub-module mark.convert.js, which provides conversion between Mark format and other formats like HTML and XML.
  • Sub-module mark.selector.js, which provides CSS selector based query interface on the Mark object model, like jQuery.

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.

And Mark Notation support for VS Code:

Documentation

Credits

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