• Stars
    star
    305
  • Rank 133,843 (Top 3 %)
  • Language
    JavaScript
  • License
    ISC License
  • Created almost 8 years ago
  • Updated 9 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Better TOML parsing and stringifying all in that familiar JSON interface.

@iarna/toml

Better TOML parsing and stringifying all in that familiar JSON interface.

Coverage Status

** TOML 1.0.0-rc.1 **

TOML Spec Support

The most recent version as of 2019-04-21: 1.0.0-rc.1

Other Versions

1.0.0-rc.1 parsers can load almost any TOML 0.4 and TOML 0.5 document, but TOML 1.0.0-rc.1 docs are not always compatible with TOML 0.4 and TOML 0.5 parsers. If you're using this to generate TOML documents and you want an older parser to be able to read them you may want to use the latest TOML 0.5 version of this module.

Example

const TOML = require('@iarna/toml')
const obj = TOML.parse(`[abc]
foo = 123
bar = [1,2,3]`)
/* obj =
{abc: {foo: 123, bar: [1,2,3]}}
*/
const str = TOML.stringify(obj)
/* str =
[abc]
foo = 123
bar = [ 1, 2, 3 ]
*/

Visit the project github for more examples!

Why @iarna/toml

  • Support for TOML 1.0.0-rc.1!
  • Highly correct! Careful adherence to spec.
  • See TOML-SPEC-SUPPORT for a comparison of which TOML features are supported by the various Node.js TOML parsers.
  • Speedy! See benchmarks at end.
  • BigInt support on Node 10!
  • 100% test coverage.
  • Small parser bundle (if you use @iarna/toml/parse-string).
  • No deps.
  • Detailed and easy to read error messages‼
> TOML.parse(src)
Error: Unexpected character, expecting string, number, datetime, boolean, inline array or inline table at row 6, col 5, pos 87:
5: "abc\"" = { abc=123,def="abc" }
6> foo=sdkfj
       ^
7:

TOML.parse(str) → Object (example)

Also available with: require('@iarna/toml/parse-string')

Synchronously parse a TOML string and return an object.

TOML.stringify(obj) → String (example)

Also available with: require('@iarna/toml/stringify')

Serialize an object as TOML.

[your-object].toJSON

If an object TOML.stringify is serializing has a toJSON method then it will call it to transform the object before serializing it. This matches the behavior of JSON.stringify.

The one exception to this is that toJSON is not called for Date objects because JSON represents dates as strings and TOML can represent them natively.

moment objects are treated the same as native Date objects, in this respect.

TOML.stringify.value(obj) -> String

Also available with: require('@iarna/toml/stringify').value

Serialize a value as TOML would. This is a fragment and not a complete valid TOML document.

Promises and Streaming

The parser provides alternative async and streaming interfaces, for times that you're working with really absurdly big TOML files and don't want to tie-up the event loop while it parses.

TOML.parse.async(str[, opts]) → Promise(Object) (example)

Also available with: require('@iarna/toml/parse-async')

opts.blocksize is the amount text to parser per pass through the event loop. Defaults to 40kb.

Asynchronously parse a TOML string and return a promise of the resulting object.

TOML.parse.stream(readable) → Promise(Object) (example)

Also available with: require('@iarna/toml/parse-stream')

Given a readable stream, parse it as it feeds us data. Return a promise of the resulting object.

readable.pipe(TOML.parse.stream()) → Transform (example)

Also available with: require('@iarna/toml/parse-stream')

Returns a transform stream in object mode. When it completes, emit the resulting object. Only one object will ever be emitted.

Lowlevel Interface (example) (example w/ parser debugging)

You construct a parser object, per TOML file you want to process:

const TOMLParser = require('@iarna/toml/lib/toml-parser.js')
const parser = new TOMLParser()

Then you call the parse method for each chunk as you read them, or in a single call:

parser.parse(`hello = 'world'`)

And finally, you call the finish method to complete parsing and retrieve the resulting object.

const data = parser.finish()

Both the parse method and finish method will throw if they find a problem with the string they were given. Error objects thrown from the parser have pos, line and col attributes. TOML.parse adds a visual summary of where in the source string there were issues using parse-pretty-error and you can too:

const prettyError = require('./parse-pretty-error.js')
const newErr = prettyError(err, sourceString)

What's Different

Version 3 of this module supports TOML 1.0.0-rc.1. Please see the CHANGELOG for details on exactly whats changed.

TOML we can't do

  • -nan is a valid TOML value and is converted into NaN. There is no way to produce -nan when stringifying. Stringification will produce positive nan.
  • Detecting and erroring on invalid utf8 documents: This is because Node's UTF8 processing converts invalid sequences into the placeholder character and does not have facilities for reporting these as errors instead. We can detect the placeholder character, but it's valid to intentionally include them in documents, so erroring on them is not great.
  • On versions of Node < 10, very large Integer values will lose precision. On Node >=10, bigints are used.
  • Floating/local dates and times are still represented by JavaScript Date objects, which don't actually support these concepts. The objects returned have been modified so that you can determine what kind of thing they are (with isFloating, isDate, isTime properties) and that their ISO representation (via toISOString) are representative of their TOML value. They will correctly round trip if you pass them to TOML.stringify.
  • Binary, hexadecimal and octal values are converted to ordinary integers and will be decimal if you stringify them.

Changes

I write a by hand, honest-to-god, CHANGELOG for this project. It's a description of what went into a release that you the consumer of the module could care about, not a list of git commits, so please check it out!

Benchmarks

You can run them yourself with:

$ npm run benchmark

The results below are from my desktop using Node 13.13.0. The library versions tested were @iarna/[email protected], [email protected], [email protected], @sgarciac/[email protected], @ltd/[email protected], and [email protected]. The speed value is megabytes-per-second that the parser can process of that document type. Bigger is better. The percentage after average results is the margin of error.

New here is fast-toml. fast-toml is very fast, for some datatypes, but it also is missing most error checking demanded by the spec. For 0.4, it is complete except for detail of multiline strings caught by the compliance tests. Its support for 0.5 is incomplete. Check out the spec compliance doc for details.

As this table is getting a little wide, with how npm and github display it, you can also view it seperately in the BENCHMARK document.

@iarna/toml toml-j0.4 toml @sgarciac/bombadil @ltd/j-toml fast-toml
Overall 28MB/sec
0.55%
- - - - -
01-small-doc-mixed-type-inline-array 5.3MB/sec
0.48%
- - - - 12MB/sec
0.13%
Spec Example: v0.4.0 25MB/sec
0.40%
9.9MB/sec
0.15%
0.9MB/sec
0.37%
1.3MB/sec
1.02%
28MB/sec
0.33%
-
Spec Example: Hard Unicode 63MB/sec
0.47%
17MB/sec
0.21%
2MB/sec
0.25%
0.6MB/sec
0.47%
65MB/sec
0.27%
79MB/sec
0.09%
Types: Array, Inline 7.2MB/sec
0.53%
4.1MB/sec
0.09%
0.1MB/sec
0.69%
1.4MB/sec
0.86%
10MB/sec
0.33%
9MB/sec
0.16%
Types: Array 6.8MB/sec
0.09%
6.8MB/sec
0.20%
0.2MB/sec
0.81%
1.3MB/sec
0.82%
8.9MB/sec
0.36%
29MB/sec
0.16%
Types: Boolean, 20MB/sec
0.22%
9.3MB/sec
0.29%
0.2MB/sec
0.91%
1.9MB/sec
0.85%
16MB/sec
0.29%
8.6MB/sec
0.22%
Types: Datetime 17MB/sec
0.09%
11MB/sec
0.17%
0.3MB/sec
0.75%
1.6MB/sec
0.42%
9.8MB/sec
0.40%
6.5MB/sec
0.11%
Types: Float 8.5MB/sec
0.29%
5.8MB/sec
0.33%
0.2MB/sec
0.91%
2.2MB/sec
0.91%
14MB/sec
0.25%
7.9MB/sec
0.33%
Types: Int 5.8MB/sec
0.13%
4.5MB/sec
0.14%
0.1MB/sec
0.63%
1.5MB/sec
0.73%
9.8MB/sec
0.14%
8.1MB/sec
0.16%
Types: Literal String, 7 char 25MB/sec
0.15%
8.3MB/sec
0.38%
0.2MB/sec
0.71%
2.3MB/sec
1.04%
23MB/sec
0.28%
14MB/sec
0.21%
Types: Literal String, 92 char 44MB/sec
0.23%
12MB/sec
0.14%
0.3MB/sec
0.63%
13MB/sec
1.12%
100MB/sec
0.14%
77MB/sec
0.15%
Types: Literal String, Multiline, 1079 char 23MB/sec
0.35%
7.2MB/sec
0.34%
0.9MB/sec
0.86%
47MB/sec
1.07%
380MB/sec
0.13%
641MB/sec
0.14%
Types: Basic String, 7 char 25MB/sec
0.09%
7MB/sec
0.08%
0.2MB/sec
0.82%
2.3MB/sec
1.02%
15MB/sec
0.12%
13MB/sec
0.14%
Types: Basic String, 92 char 44MB/sec
0.15%
8MB/sec
0.39%
0.1MB/sec
1.52%
12MB/sec
1.53%
70MB/sec
0.17%
71MB/sec
0.16%
Types: Basic String, 1079 char 24MB/sec
0.36%
5.7MB/sec
0.12%
0.1MB/sec
3.65%
42MB/sec
1.67%
93MB/sec
0.13%
617MB/sec
0.14%
Types: Table, Inline 9.4MB/sec
0.21%
5.2MB/sec
0.23%
0.1MB/sec
1.18%
1.4MB/sec
1.20%
8.5MB/sec
0.68%
8.7MB/sec
0.30%
Types: Table 6.8MB/sec
0.13%
5.5MB/sec
0.22%
0.1MB/sec
1.10%
1.5MB/sec
1.05%
7.3MB/sec
0.54%
19MB/sec
0.21%
Scaling: Array, Inline, 1000 elements 40MB/sec
0.27%
2.4MB/sec
0.20%
0.1MB/sec
1.90%
1.6MB/sec
1.14%
18MB/sec
0.16%
32MB/sec
0.12%
Scaling: Array, Nested, 1000 deep 2MB/sec
0.17%
1.6MB/sec
0.09%
0.3MB/sec
0.62%
- 1.8MB/sec
0.80%
13MB/sec
0.19%
Scaling: Literal String, 40kb 59MB/sec
0.26%
10MB/sec
0.14%
3MB/sec
0.91%
13MB/sec
0.40%
479MB/sec
0.25%
19kMB/sec
0.20%
Scaling: Literal String, Multiline, 40kb 61MB/sec
0.23%
5.3MB/sec
0.30%
0.2MB/sec
1.78%
12MB/sec
0.55%
276MB/sec
0.16%
21kMB/sec
0.10%
Scaling: Basic String, Multiline, 40kb 61MB/sec
0.21%
6MB/sec
0.40%
2.8MB/sec
0.75%
12MB/sec
0.60%
1kMB/sec
0.13%
27kMB/sec
0.14%
Scaling: Basic String, 40kb 60MB/sec
0.13%
6.6MB/sec
0.13%
0.2MB/sec
1.67%
13MB/sec
0.30%
504MB/sec
0.26%
19kMB/sec
0.22%
Scaling: Table, Inline, 1000 elements 26MB/sec
0.17%
7.3MB/sec
0.83%
0.3MB/sec
0.95%
2.5MB/sec
1.24%
5.4MB/sec
0.22%
13MB/sec
0.22%
Scaling: Table, Inline, Nested, 1000 deep 8MB/sec
0.10%
5.2MB/sec
0.25%
0.1MB/sec
0.45%
- 3.1MB/sec
0.58%
10MB/sec
0.19%

Tests

The test suite is maintained at 100% coverage: Coverage Status

The spec was carefully hand converted into a series of test framework independent (and mostly language independent) assertions, as pairs of TOML and YAML files. You can find those files here: spec-tests.

Further tests were written to increase coverage to 100%, these may be more implementation specific, but they can be found in coverage and coverage-error.

I've also written some quality assurance style tests, which don't contribute to coverage but do cover scenarios that could easily be problematic for some implementations can be found in: test/qa.js and test/qa-error.js.

All of the official example files from the TOML spec are run through this parser and compared to the official YAML files when available. These files are from the TOML spec as of: 357a4ba6 and specifically are:

The stringifier is tested by round-tripping these same files, asserting that TOML.parse(sourcefile) deepEqual TOML.parse(TOML.stringify(TOML.parse(sourcefile)). This is done in test/roundtrip-examples.js There are also some tests written to complete coverage from stringification in: test/stringify.js

Tests for the async and streaming interfaces are in test/async.js and test/stream.js respectively.

Tests for the parser's debugging mode live in test/devel.js.

And finally, many more stringification tests were borrowed from @othiym23's toml-stream module. They were fetched as of b6f1e26b572d49742d49fa6a6d11524d003441fa and live in test/toml-stream.

Improvements to make

  • In stringify:
    • Any way to produce comments. As a JSON stand-in I'm not too worried about this. That said, a document orientated fork is something I'd like to look at eventually…
    • Stringification could use some work on its error reporting. It reports what's wrong, but not where in your data structure it was.
  • Further optimize the parser:
    • There are some debugging assertions left in the main parser, these should be moved to a subclass.
    • Make the whole debugging parser thing work as a mixin instead of as a superclass.

More Repositories

1

aproba

A ridiculously light-weight function argument validator
JavaScript
131
star
2

in-publish

Detect if we were run as a result of `npm publish`.
JavaScript
128
star
3

run-queue

A promise based, dynamic priority queue runner, with concurrency limiting.
JavaScript
58
star
4

rtf-to-html

Convert RTF to HTML in pure JavaScript.
JavaScript
58
star
5

abraxas

A streaming gearman client / worker / server (as you choose)
JavaScript
53
star
6

funstream

Funstream gives you iteratorish methods on your streams.
JavaScript
51
star
7

rtf-parser

This is a general RTF parser. It takes an text stream and produces a document object representing the parsed document. In and of itself, this isn't super useful but it's the building block for other tools to convert RTF into other formats.
JavaScript
45
star
8

require-inject

A simple mock injector compatible needing no instrumentation in the libraries being tested
JavaScript
33
star
9

App-Every

Easily create and queue cronjobs from the command line
Perl
32
star
10

console-control-strings

A library of cross-platform tested terminal/console command strings for doing things like color and cursor positioning. This is a subset of both ansi and vt100. All control codes included work on both Windows & Unix-like OSes, except where noted.
JavaScript
30
star
11

streampub

A streaming EPUB3 writer.
JavaScript
26
star
12

call-limit

Limit the number of simultaneous executions of a async function.
JavaScript
24
star
13

word-count

Count words, with Unicode! Uses Unicode 9.0.0 character classes for improved clarity of implementation.
JavaScript
20
star
14

wide-align

JavaScript
20
star
15

sql-lexer

An SQL lexer for Node.js
JavaScript
18
star
16

require-timer

Track and report module load times
JavaScript
18
star
17

has-unicode

Try to guess if your terminal supports unicode
JavaScript
17
star
18

assetize

proof-of-concept
JavaScript
16
star
19

promise-inflight

One promise for multiple requests in flight to avoid async duplication
JavaScript
16
star
20

tacks

Generate fixture modules from folders
JavaScript
16
star
21

fetch-fic

Package up delicious, delicious fanfic from various sources into epub ebooks ready for reading in your ereader of choice. It can ALSO take your freshly written fanfic and prepare it for sharing easy peasy
JavaScript
14
star
22

node-perlisms

The best of Perl, implemented in node
JavaScript
14
star
23

git-rss

A simple git command for generating RSS from a 'git log' type commandline
13
star
24

toml-spec-tests

These are the spec tests for TOML used by @iarna/toml
10
star
25

iarna-lib

Mad science: Declare intra-package library paths and load modules from them.
JavaScript
9
star
26

iarna-math

Math in easy to use english!
JavaScript
9
star
27

babel-autonode

Automatically and transparently use as little babel as possible with whatever version of node is in use.
JavaScript
8
star
28

node-qw

Quoted word literals! For Node.js!
JavaScript
7
star
29

replace-deep-dep

Change a transitive dependency version without updating the things requiring it.
JavaScript
6
star
30

joe-editor

a fork/mirror of joe
C
6
star
31

dont-stop

DON'T STOP
JavaScript
5
star
32

package-manager-complexity

My talk on package manager (+ npm) complexity, given for Nodevember.
5
star
33

dotfiles

Emacs Lisp
5
star
34

timer-ease

Sugar for JavaScript's ugly, ugly timer functions
JavaScript
5
star
35

iarna-parser

A traceable, unlimited-depth recursive-descent parsing engine
JavaScript
5
star
36

atom-joe

Wordstar/Joe Style Editing for the Atom Editor
CoffeeScript
5
star
37

win-symlink-test

Test what (sym)link-like-things work on Windows and in what combination
JavaScript
5
star
38

tar

A simple tar CLI based on node-tar -- highly compatible, very fast, can produce idempotent tar outputs when using "portable" mode. Intended for use in environments without a tar binary (ie, Windows), particularly for portable package.json run scripts.
JavaScript
5
star
39

private-bot

A bot for managing access to private slack channels
JavaScript
4
star
40

promises-distilled

Super simple A+ style promises for the purposes of code reading
JavaScript
4
star
41

opml-js

OPML Parsing for Node.js
JavaScript
4
star
42

On-Event

Perl
4
star
43

lua-to-json

Converts a series of lua variable declarations (with tables) into their JSON equivalent.
JavaScript
4
star
44

llmod

List all of the javascript in your project, both plain `.js` files and node modules.
JavaScript
4
star
45

babelrc-v8

A collection of babelrcs for the v8 versions that ship with node.
JavaScript
4
star
46

worm-whats-new

JavaScript
4
star
47

poodle-safe

Make your Chrome poodle safe, the easy way
Shell
3
star
48

cli

Some simple CLI scaffolding for promise returning applications.
JavaScript
3
star
49

emojitime

A command line toollet to print the time as an emoji
JavaScript
3
star
50

gearman-packet

A streaming packet parser and emitter for the Gearman protocol and Node.js
JavaScript
3
star
51

babel-autonode-init

Setup a new project with babel-autonode.
JavaScript
3
star
52

isa-stream

Ducktype if something is a Node.js compatible stream
JavaScript
2
star
53

manage-npm-scripts

Manage package.json `npm run` scripts
JavaScript
2
star
54

iarna-sh

A bash subset command line parser
JavaScript
2
star
55

jtoml

Use the json cli to read and query your TOML
JavaScript
2
star
56

Coro-Localize

Localize variables to a coroutine
Perl
2
star
57

rtf-to-bbcode

Converts RTF to bbcode, for posting to your favorite forum
JavaScript
2
star
58

mysql-federated-gearman

Provide an interface to gearman for MySQL using federated tables
JavaScript
2
star
59

MooseX-Event

A Node.js style event Role for Moose
Perl
2
star
60

promisable

Yet Another Node.js Promises Module
JavaScript
2
star
61

HPMoR

Mirror of http://hpmor.com/ as fetched from Fanfiction.net via Perl's WWW::FetchStory
HTML
2
star
62

collect-callbacks

Aggregate many event emissions into one
JavaScript
2
star
63

talks

Talks I've given
2
star
64

Event-Wrappable

Sugar to let you instrument event listeners at a distance
Perl
2
star
65

Tie--ExecHash

Perl
1
star
66

arquivo

JavaScript
1
star
67

iarna-create-npm

undefined
JavaScript
1
star
68

talking-up-talked-down-tech

Conference talk: Talking up talked down technology
1
star
69

plbenchmark

Benchmarks for Node that measure CPU time, work like Perl's Benchmark module
JavaScript
1
star
70

filesystem-errorcodes

Which error conditions result in which codes across node supported OSes?
JavaScript
1
star
71

ONE

On-Event-- Wrapping MooseX::Event around AnyEvent
Perl
1
star
72

handbrake-cli

Provides the handbrake cli in a crossplatform compatible manor
JavaScript
1
star
73

qtoml

Use TOML to construct object literals directly in JavaScript
JavaScript
1
star
74

PEAR_PackageFileManager_GitRepoOnly

PEAR packaging support for pulling in only the files checked into a git repo
PHP
1
star
75

tags

undefined
1
star
76

git-remerge

Semi-automated rebuilding of integration branches-- rebase for branches containing only merges
Perl
1
star
77

AnyEvent-Collect

Block till one or more events fire
Perl
1
star
78

AnyEvent-Gearman

Release history of AnyEvent-Gearman
Perl
1
star
79

AnyEvent-Sleep

Sleep for n seconds while events still fire
Perl
1
star
80

read-module-list

JavaScript
1
star
81

AnyEvent-Capture

Call asynchronous APIs synchronously
Perl
1
star
82

abraxas-server

Gearman Server, in Node.js
JavaScript
1
star
83

accountbooks

1
star
84

parse-jsf

WIP Parse Joe Syntax Files and generate parsers from them
JavaScript
1
star
85

DBIx-Abstract

Perl
1
star
86

npm-show-versions

Show important package availability information
JavaScript
1
star
87

SecondLife-DataTypes

Support for parsing, working with and printing Second Life's data types
Perl
1
star
88

link-duplicates

Detect duplicate files and hard link them
JavaScript
1
star