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 🙏

© 2026 – Pkg Stats / Ryan Hefner

dms-js-parser

v0.5.2

Published

Pure-JavaScript parser for DMS, a data syntax with strong typing, ordered maps, and heredocs.

Readme

dms-js

JavaScript parser for DMS, a data syntax with strong typing, ordered maps, multi-line heredocs, and front-matter metadata.

Two packages live in this repo, both with the same Node API and value shape:

| package | implementation | when to use | | -------- | ------------------------------------ | ---------------------------------------------- | | dms-js-parser | pure JS, zero runtime deps | browsers, default Node usage | | dms-c | N-API addon wrapping the dms-c parser | hot paths where you want a C-backed parser |

See Performance below for the honest answer to "is the C addon faster?" (short version: not always, on Node).

What DMS looks like

A medium-size tier-0 document, exercising every feature you'd touch in a real config — front matter, comments (line + trailing), nested tables, list-of-tables with the + marker, flow forms, distinct types, and a heredoc with a trim modifier:

+++
title:    "DMS feature tour"
version:  "1.0.0"
updated:  2026-04-24T09:30:00-04:00
+++

# Hash and // line comments both work.
// Bare keys allow full Unicode; quoted keys take any string.

database:
  host:    "db.internal"
  port:    5432            # bumped after the LB change
  pool:    { size: 10, idle_timeout_s: 30 }   # flow table

servers:
  + name: "web1"
    disks:
      + mount: "/"
        size_gb: 100
      + mount: "/var"
        size_gb: 500
  + name: "web2"

regions: ["us-east-1", "eu-west-1", "ap-south-1"]

sql: """SQL _trim("\n", ">")
    SELECT id, email
      FROM users
     WHERE active = true
    SQL

Tier 1 layers structured decorators on top of the value tree. Sigils bind to families published by a dialect; here is dms+html carrying an HTML fragment as a DMS document:

+++
_dms_tier: 1
_dms_imports:
  + dialect: "html"
    version: "1.0.0"
+++

+ |html(lang: "en")
  + |head
    + |title "DMS feature tour"
    + |meta(charset: "UTF-8")
  + |body(class: "main")
    + |h1 "Welcome to DMS"
    + |p(class: "lede")
      + "Click "
      + |a(href: "/spec.html") "here"
      + " to read the spec."

Full feature tour, format comparison, and dialect index on the DMS website.

Install

npm install dms-js-parser      # pure JS (works in Node and browsers)
npm install dms-c           # native (C) addon — Node only

Usage

// pure JS port:
const dms = require('dms-js-parser');

// native (C) port — same API, same value shape:
const dms_c = require('dms-c');

const src   = require('fs').readFileSync('config.dms', 'utf8');
const value = dms.decode(src);            // or dms_c.decode(src)
const doc   = dms.decodeDocument(src);    // → { body, comments, meta, originalForms }

SPEC v0.14 renamed the entry points: parsedecode, parseDocumentdecodeDocument, toDMSencode, toDMSLiteencodeLite. The old names still work as deprecated aliases in this release; they will be removed in the release after 0.14.x.

Tables are plain objects (insertion-ordered for string keys per ES2015), lists are arrays. Datetimes are wrapped types: the pure module returns LocalDate / LocalTime / LocalDateTime / OffsetDateTime class instances; the C addon returns plain { __dmsType, value } objects with the same shape. Encoders that detect via __dmsType + value work unchanged across both ports. See dms.js for the full type surface.

Working with comments and heredocs

DMS preserves comments through parse → mutate → re-emit (SPEC §Comments). The Document carries them on a side-channel keyed by breadcrumb path; the same shape lets you attach a comment to a value after parsing and have it round-trip through encode:

const dms = require('dms-js-parser');

const doc = dms.decodeDocument('db:\n  port: 8080\n');

// Mutate a value in place.
doc.body.db.port = 5432;

// Attach a leading line comment to db.port.
doc.comments.push({
  comment:  { content: '# bumped after LB change', kind: 'line' },
  position: 'leading',
  path:     ['db', 'port'],
});

console.log(dms.encode(doc));

Forcing a heredoc on emit

Strings parse and re-emit in their source form. To switch a basic-quoted string to a heredoc (or to construct one from scratch), push an originalForms entry whose lit.form.kind === 'heredoc':

doc.body.db.greeting = 'Hello, friend.\nWelcome aboard.\n';

doc.originalForms.push({
  path: ['db', 'greeting'],
  lit: {
    kind: 'string',
    form: {
      kind:      'heredoc',
      flavor:    'basic-triple',   // or 'literal-triple' for '''
      label:     null,             // null = unlabeled (terminator is """ / ''')
      modifiers: [],               // { name, args } records — _trim(...), _fold_paragraphs(), …
    },
  },
});

Round-trip rules (SPEC §Round-trip semantics): comments stick to still-present nodes; deleting a node drops its comments; newly inserted nodes start with no comments. The first originalForms entry per path wins, so override a parser-recorded form by replacing rather than appending if the key is already present.

Browser

dms.js uses no Node-specific APIs and works in modern browsers as-is. Drop it in with a <script> tag and the API attaches to window.DMS:

<script src="dms.js"></script>
<script>
  const doc = DMS.decodeDocument(sourceText);
</script>

The same file still works as a CommonJS module (require('dms-js-parser')).

Performance

50,000-key flat document (~700 KB), best-of-5, startup-subtracted, Node 23 on Windows 11:

| tier | DMS port | time | peer | time | DMS / peer | |-------------|-----------|----------|-------------|---------|------------| | pure JS | dms-js-parser | 60.7 ms | js-yaml | 94.0 ms | 0.65× — DMS faster | | native (C) | dms-c | 59.5 ms | JSON.parse (V8 native) | 21.3 ms | 2.79× |

Node is the surprising case. V8's JIT optimizes the pure-JS parser hard, and the N-API marshalling cost of building 50k JS strings + setting properties on a single object eats the C port's parse-time advantage. On this fixture the two tiers tie. The C port wins on documents with heavy datetime / number content and short keys; the pure port wins on dict-heavy maps. Pick whichever ergonomics you prefer — the perf difference is small.

The pure-vs-pure column is the honest one for Node. There's no widely-used pure-JS JSON parser to bench against (V8's JSON.parse is C++), so JSON only appears in the FFI tier; correspondingly there's no widely-used libyaml binding for Node, so YAML only appears in the pure tier.

Reproduce with:

npm install                                      # pure deps
(cd dms-c && npm install)                        # builds the addon
(cd bench-formats && npm install)                # js-yaml + @iarna/toml
python bench-formats/bench_decoders.py --tier both

Test

npm test

Runs test_roundtrip.js (encode emitter) and test_comments.js (comment-AST attachment).

Conformance

The fixture corpus lives in dms-tests (4500+ pairs). Clone it once as a sibling:

git clone https://gitlab.com/flo-labs/pub/dms-tests.git ../dms-tests

Then run the sweep:

python3 ../dms-tests/run_conformance.py "node encoder.js"

dms-tests can also drive every implementation in one shot — see its README for the cross-language workflow.

Publish

npm publish

You'll need to run npm login once.

License

MIT OR Apache-2.0