├── test
├── assets
│ ├── pass4_result.hjson
│ ├── pass4_result.json
│ ├── failJSON29_test.json
│ ├── failJSON30_test.json
│ ├── failJSON16_test.json
│ ├── failJSON31_test.json
│ ├── pass4_test.json
│ ├── failJSON08_test.json
│ ├── failJSON33_test.json
│ ├── empty_result.hjson
│ ├── failJSON02_test.json
│ ├── failJSON23_test.json
│ ├── failJSON28_test.json
│ ├── empty_result.json
│ ├── empty_test.hjson
│ ├── failJSON05_test.json
│ ├── failJSON06_test.json
│ ├── failJSON07_test.json
│ ├── failJSON19_test.json
│ ├── failJSON20_test.json
│ ├── passSingle_result.hjson
│ ├── passSingle_test.hjson
│ ├── failJSON11_test.json
│ ├── failJSON12_test.json
│ ├── failJSON14_test.json
│ ├── passSingle_result.json
│ ├── failJSON15_test.json
│ ├── failJSON17_test.json
│ ├── failJSON21_test.json
│ ├── failJSON22_test.json
│ ├── failJSON26_test.json
│ ├── failJSON32_test.json
│ ├── failJSON13_test.json
│ ├── failKey4_test.hjson
│ ├── failKey2_test.hjson
│ ├── failKey3_test.hjson
│ ├── failKey5_test.hjson
│ ├── pass2_test.json
│ ├── failKey1_test.hjson
│ ├── failMLStr1_test.hjson
│ ├── failObj2_test.hjson
│ ├── mltabs_result.json
│ ├── extra
│ │ ├── notabs_result.hjson
│ │ ├── notabs_result.json
│ │ ├── notabs_test.json
│ │ ├── root_testmeta.hjson
│ │ ├── separator_testmeta.hjson
│ │ ├── notabs_testmeta.hjson
│ │ ├── root_result.hjson
│ │ ├── root_result.json
│ │ ├── root_test.hjson
│ │ ├── separator_test.json
│ │ ├── separator_result.json
│ │ └── separator_result.hjson
│ ├── failCharset1_test.hjson
│ ├── failJSON10_test.json
│ ├── failStr1a_test.hjson
│ ├── failStr1b_test.hjson
│ ├── failStr2a_test.hjson
│ ├── failStr2b_test.hjson
│ ├── failStr3a_test.hjson
│ ├── failStr3b_test.hjson
│ ├── failStr4a_test.hjson
│ ├── failStr4b_test.hjson
│ ├── failStr5a_test.hjson
│ ├── failStr5b_test.hjson
│ ├── failStr6a_test.hjson
│ ├── failStr6b_test.hjson
│ ├── failStr8a_test.hjson
│ ├── mltabs_test.json
│ ├── stringify
│ │ ├── quotes_strings_ml_test.json
│ │ ├── quotes_strings_ml_result.hjson
│ │ ├── quotes_strings_ml_result.json
│ │ ├── quotes_all_testmeta.hjson
│ │ ├── quotes_always_testmeta.hjson
│ │ ├── quotes_keys_testmeta.hjson
│ │ ├── quotes_strings_testmeta.hjson
│ │ ├── quotes_strings_ml_testmeta.hjson
│ │ ├── quotes_all_test.hjson
│ │ ├── quotes_keys_test.hjson
│ │ ├── quotes_strings_test.hjson
│ │ ├── quotes_all_result.json
│ │ ├── quotes_always_result.json
│ │ ├── quotes_keys_result.json
│ │ ├── quotes_strings_result.json
│ │ ├── quotes_always_result.hjson
│ │ ├── quotes_keys_result.hjson
│ │ ├── quotes_strings_result.hjson
│ │ ├── quotes_all_result.hjson
│ │ └── quotes_always_test.hjson
│ ├── failObj1_test.hjson
│ ├── failObj3_test.hjson
│ ├── failStr1c_test.hjson
│ ├── failStr1d_test.hjson
│ ├── failStr2c_test.hjson
│ ├── failStr2d_test.hjson
│ ├── failStr3c_test.hjson
│ ├── failStr3d_test.hjson
│ ├── failStr4c_test.hjson
│ ├── failStr4d_test.hjson
│ ├── failStr5c_test.hjson
│ ├── failStr5d_test.hjson
│ ├── failJSON34_test.json
│ ├── failStr7a_test.hjson
│ ├── mltabs_result.hjson
│ ├── trail_result.hjson
│ ├── trail_result.json
│ ├── oa_result.hjson
│ ├── oa_test.hjson
│ ├── oa_result.json
│ ├── pass3_result.hjson
│ ├── pass3_result.json
│ ├── pass3_test.json
│ ├── failStr6c_test.hjson
│ ├── failStr6d_test.hjson
│ ├── trail_test.hjson
│ ├── charset2_result.hjson
│ ├── charset2_result.json
│ ├── charset2_test.hjson
│ ├── charset_result.hjson
│ ├── charset_result.json
│ ├── charset_test.hjson
│ ├── kan_result.hjson
│ ├── kan_result.json
│ ├── keys_result.hjson
│ ├── kan_test.hjson
│ ├── strings2_result.hjson
│ ├── comments_result.hjson
│ ├── strings2_result.json
│ ├── keys_result.json
│ ├── strings2_test.hjson
│ ├── comments_result.json
│ ├── keys_test.hjson
│ ├── pass2_result.hjson
│ ├── pass2_result.json
│ ├── stringify1_result.hjson
│ ├── stringify1_test.hjson
│ ├── stringify1_result.json
│ ├── comments_test.hjson
│ ├── strings_result.json
│ ├── strings_result.hjson
│ ├── pass1_result.hjson
│ ├── strings_test.hjson
│ ├── pass1_result.json
│ ├── pass1_test.json
│ └── testlist.txt
└── test.js
├── .gitignore
├── lib
├── hjson-version.js
├── require-config.js
├── hjson-common.js
├── hjson-dsf.js
├── hjson.js
├── hjson-comments.js
├── hjson-parse.js
└── hjson-stringify.js
├── .npmignore
├── bin
├── .eslintrc.json
└── hjson
├── sample
├── package.json
├── sample.js
└── test.hjson
├── .travis.yml
├── .editorconfig
├── .eslintrc.json
├── LICENSE
├── package.json
├── history.md
├── README.md
└── bundle
├── hjson.min.js
└── hjson.js
/test/assets/pass4_result.hjson:
--------------------------------------------------------------------------------
1 | 10
--------------------------------------------------------------------------------
/test/assets/pass4_result.json:
--------------------------------------------------------------------------------
1 | 10
--------------------------------------------------------------------------------
/test/assets/failJSON29_test.json:
--------------------------------------------------------------------------------
1 | [0e]
--------------------------------------------------------------------------------
/test/assets/failJSON30_test.json:
--------------------------------------------------------------------------------
1 | [0e+]
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | coverage/
3 |
--------------------------------------------------------------------------------
/test/assets/failJSON16_test.json:
--------------------------------------------------------------------------------
1 | [\naked]
--------------------------------------------------------------------------------
/test/assets/failJSON31_test.json:
--------------------------------------------------------------------------------
1 | [0e+-1]
--------------------------------------------------------------------------------
/test/assets/pass4_test.json:
--------------------------------------------------------------------------------
1 |
2 | 10
3 |
--------------------------------------------------------------------------------
/lib/hjson-version.js:
--------------------------------------------------------------------------------
1 | module.exports="3.2.1";
2 |
--------------------------------------------------------------------------------
/test/assets/failJSON08_test.json:
--------------------------------------------------------------------------------
1 | ["Extra close"]]
--------------------------------------------------------------------------------
/test/assets/failJSON33_test.json:
--------------------------------------------------------------------------------
1 | ["mismatch"}
--------------------------------------------------------------------------------
/test/assets/empty_result.hjson:
--------------------------------------------------------------------------------
1 | {
2 | "": empty
3 | }
--------------------------------------------------------------------------------
/test/assets/failJSON02_test.json:
--------------------------------------------------------------------------------
1 | ["Unclosed array"
--------------------------------------------------------------------------------
/test/assets/failJSON23_test.json:
--------------------------------------------------------------------------------
1 | ["Bad value", truth]
--------------------------------------------------------------------------------
/test/assets/failJSON28_test.json:
--------------------------------------------------------------------------------
1 | ["line\
2 | break"]
--------------------------------------------------------------------------------
/test/assets/empty_result.json:
--------------------------------------------------------------------------------
1 | {
2 | "": "empty"
3 | }
--------------------------------------------------------------------------------
/test/assets/empty_test.hjson:
--------------------------------------------------------------------------------
1 | {
2 | "": empty
3 | }
4 |
--------------------------------------------------------------------------------
/test/assets/failJSON05_test.json:
--------------------------------------------------------------------------------
1 | ["double extra comma",,]
--------------------------------------------------------------------------------
/test/assets/failJSON06_test.json:
--------------------------------------------------------------------------------
1 | [ , "<-- missing value"]
--------------------------------------------------------------------------------
/test/assets/failJSON07_test.json:
--------------------------------------------------------------------------------
1 | ["Comma after the close"],
--------------------------------------------------------------------------------
/test/assets/failJSON19_test.json:
--------------------------------------------------------------------------------
1 | {"Missing colon" null}
--------------------------------------------------------------------------------
/test/assets/failJSON20_test.json:
--------------------------------------------------------------------------------
1 | {"Double colon":: null}
--------------------------------------------------------------------------------
/test/assets/passSingle_result.hjson:
--------------------------------------------------------------------------------
1 | allow quoteless strings
--------------------------------------------------------------------------------
/test/assets/passSingle_test.hjson:
--------------------------------------------------------------------------------
1 | allow quoteless strings
--------------------------------------------------------------------------------
/test/assets/failJSON11_test.json:
--------------------------------------------------------------------------------
1 | {"Illegal expression": 1 + 2}
--------------------------------------------------------------------------------
/test/assets/failJSON12_test.json:
--------------------------------------------------------------------------------
1 | {"Illegal invocation": alert()}
--------------------------------------------------------------------------------
/test/assets/failJSON14_test.json:
--------------------------------------------------------------------------------
1 | {"Numbers cannot be hex": 0x14}
--------------------------------------------------------------------------------
/test/assets/passSingle_result.json:
--------------------------------------------------------------------------------
1 | "allow quoteless strings"
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | _*
2 | \#*
3 | .*
4 | sample/
5 | coverage/
6 | test/
7 |
--------------------------------------------------------------------------------
/test/assets/failJSON15_test.json:
--------------------------------------------------------------------------------
1 | ["Illegal backslash escape: \x15"]
--------------------------------------------------------------------------------
/test/assets/failJSON17_test.json:
--------------------------------------------------------------------------------
1 | ["Illegal backslash escape: \017"]
--------------------------------------------------------------------------------
/test/assets/failJSON21_test.json:
--------------------------------------------------------------------------------
1 | {"Comma instead of colon", null}
--------------------------------------------------------------------------------
/test/assets/failJSON22_test.json:
--------------------------------------------------------------------------------
1 | ["Colon instead of comma": false]
--------------------------------------------------------------------------------
/test/assets/failJSON26_test.json:
--------------------------------------------------------------------------------
1 | ["tab\ character\ in\ string\ "]
--------------------------------------------------------------------------------
/test/assets/failJSON32_test.json:
--------------------------------------------------------------------------------
1 | {"Comma instead if closing brace": true,
--------------------------------------------------------------------------------
/test/assets/failJSON13_test.json:
--------------------------------------------------------------------------------
1 | {"Numbers cannot have leading zeroes": 013}
--------------------------------------------------------------------------------
/test/assets/failKey4_test.hjson:
--------------------------------------------------------------------------------
1 | {
2 | # invalid name
3 | : 0
4 | }
5 |
--------------------------------------------------------------------------------
/bin/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "rules": {
3 | "no-console": "off"
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/test/assets/failKey2_test.hjson:
--------------------------------------------------------------------------------
1 | {
2 | # invalid name
3 | {name: 0
4 | }
5 |
--------------------------------------------------------------------------------
/test/assets/failKey3_test.hjson:
--------------------------------------------------------------------------------
1 | {
2 | # invalid name
3 | key,name: 0
4 | }
5 |
--------------------------------------------------------------------------------
/test/assets/failKey5_test.hjson:
--------------------------------------------------------------------------------
1 | {
2 | # invalid name
3 | '''foo''': 0
4 | }
5 |
--------------------------------------------------------------------------------
/test/assets/pass2_test.json:
--------------------------------------------------------------------------------
1 | [[[[[[[[[[[[[[[[[[["Not too deep"]]]]]]]]]]]]]]]]]]]
--------------------------------------------------------------------------------
/test/assets/failKey1_test.hjson:
--------------------------------------------------------------------------------
1 | {
2 | # invalid name
3 | wrong name: 0
4 | }
5 |
--------------------------------------------------------------------------------
/test/assets/failMLStr1_test.hjson:
--------------------------------------------------------------------------------
1 | {
2 | # invalid multiline string
3 | ml: '''
4 |
--------------------------------------------------------------------------------
/test/assets/failObj2_test.hjson:
--------------------------------------------------------------------------------
1 | {
2 | # invalid obj
3 | noEnd
4 | {
5 |
6 | }
7 |
--------------------------------------------------------------------------------
/test/assets/mltabs_result.json:
--------------------------------------------------------------------------------
1 | {
2 | "foo": "bar\tjoe\noki\tdoki\n\t\ttwo tabs"
3 | }
--------------------------------------------------------------------------------
/test/assets/extra/notabs_result.hjson:
--------------------------------------------------------------------------------
1 | {
2 | foo: "bar\tjoe\noki\tdoki\n\t\ttwo tabs"
3 | }
--------------------------------------------------------------------------------
/test/assets/extra/notabs_result.json:
--------------------------------------------------------------------------------
1 | {
2 | "foo": "bar\tjoe\noki\tdoki\n\t\ttwo tabs"
3 | }
--------------------------------------------------------------------------------
/test/assets/extra/notabs_test.json:
--------------------------------------------------------------------------------
1 | {
2 | "foo": "bar\tjoe\noki\tdoki\n\t\ttwo tabs"
3 | }
--------------------------------------------------------------------------------
/test/assets/failCharset1_test.hjson:
--------------------------------------------------------------------------------
1 | {
2 | # invalid \u char
3 | char: "\uxxxx"
4 | }
5 |
--------------------------------------------------------------------------------
/test/assets/failJSON10_test.json:
--------------------------------------------------------------------------------
1 | {"Extra value after close": true} "misplaced quoted value"
--------------------------------------------------------------------------------
/test/assets/failStr1a_test.hjson:
--------------------------------------------------------------------------------
1 | {
2 | # invalid quoteless string
3 | ql: ]
4 | }
5 |
--------------------------------------------------------------------------------
/test/assets/failStr1b_test.hjson:
--------------------------------------------------------------------------------
1 | {
2 | # invalid quoteless string
3 | ql: ]x
4 | }
5 |
--------------------------------------------------------------------------------
/test/assets/failStr2a_test.hjson:
--------------------------------------------------------------------------------
1 | {
2 | # invalid quoteless string
3 | ql: }
4 | }
5 |
--------------------------------------------------------------------------------
/test/assets/failStr2b_test.hjson:
--------------------------------------------------------------------------------
1 | {
2 | # invalid quoteless string
3 | ql: }x
4 | }
5 |
--------------------------------------------------------------------------------
/test/assets/failStr3a_test.hjson:
--------------------------------------------------------------------------------
1 | {
2 | # invalid quoteless string
3 | ql: {
4 | }
5 |
--------------------------------------------------------------------------------
/test/assets/failStr3b_test.hjson:
--------------------------------------------------------------------------------
1 | {
2 | # invalid quoteless string
3 | ql: {x
4 | }
5 |
--------------------------------------------------------------------------------
/test/assets/failStr4a_test.hjson:
--------------------------------------------------------------------------------
1 | {
2 | # invalid quoteless string
3 | ql: [
4 | }
5 |
--------------------------------------------------------------------------------
/test/assets/failStr4b_test.hjson:
--------------------------------------------------------------------------------
1 | {
2 | # invalid quoteless string
3 | ql: [x
4 | }
5 |
--------------------------------------------------------------------------------
/test/assets/failStr5a_test.hjson:
--------------------------------------------------------------------------------
1 | {
2 | # invalid quoteless string
3 | ql: :
4 | }
5 |
--------------------------------------------------------------------------------
/test/assets/failStr5b_test.hjson:
--------------------------------------------------------------------------------
1 | {
2 | # invalid quoteless string
3 | ql: :x
4 | }
5 |
--------------------------------------------------------------------------------
/test/assets/failStr6a_test.hjson:
--------------------------------------------------------------------------------
1 | {
2 | # invalid quoteless string
3 | ql: ,
4 | }
5 |
--------------------------------------------------------------------------------
/test/assets/failStr6b_test.hjson:
--------------------------------------------------------------------------------
1 | {
2 | # invalid quoteless string
3 | ql: ,x
4 | }
5 |
--------------------------------------------------------------------------------
/test/assets/failStr8a_test.hjson:
--------------------------------------------------------------------------------
1 | {
2 | # invalid ml-string
3 | foo : ""'text'''
4 | }
5 |
--------------------------------------------------------------------------------
/test/assets/mltabs_test.json:
--------------------------------------------------------------------------------
1 | {
2 | "foo": "bar\tjoe\noki\tdoki\n\t\ttwo tabs"
3 | }
4 |
--------------------------------------------------------------------------------
/test/assets/stringify/quotes_strings_ml_test.json:
--------------------------------------------------------------------------------
1 | {
2 | "unicorn": "foo\nbar\nrainbow"
3 | }
--------------------------------------------------------------------------------
/test/assets/failObj1_test.hjson:
--------------------------------------------------------------------------------
1 | {
2 | # invalid obj
3 | noDelimiter
4 | {
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/test/assets/failObj3_test.hjson:
--------------------------------------------------------------------------------
1 | {
2 | # missing key
3 |
4 | [
5 | test
6 | ]
7 | }
8 |
--------------------------------------------------------------------------------
/test/assets/failStr1c_test.hjson:
--------------------------------------------------------------------------------
1 | [
2 | foo
3 | # invalid quoteless string
4 | ]
5 | ]
6 |
--------------------------------------------------------------------------------
/test/assets/failStr1d_test.hjson:
--------------------------------------------------------------------------------
1 | [
2 | foo
3 | # invalid quoteless string
4 | ]x
5 | ]
6 |
--------------------------------------------------------------------------------
/test/assets/failStr2c_test.hjson:
--------------------------------------------------------------------------------
1 | [
2 | foo
3 | # invalid quoteless string
4 | }
5 | ]
6 |
--------------------------------------------------------------------------------
/test/assets/failStr2d_test.hjson:
--------------------------------------------------------------------------------
1 | [
2 | foo
3 | # invalid quoteless string
4 | }x
5 | ]
6 |
--------------------------------------------------------------------------------
/test/assets/failStr3c_test.hjson:
--------------------------------------------------------------------------------
1 | [
2 | foo
3 | # invalid quoteless string
4 | {
5 | ]
6 |
--------------------------------------------------------------------------------
/test/assets/failStr3d_test.hjson:
--------------------------------------------------------------------------------
1 | [
2 | foo
3 | # invalid quoteless string
4 | {x
5 | ]
6 |
--------------------------------------------------------------------------------
/test/assets/failStr4c_test.hjson:
--------------------------------------------------------------------------------
1 | [
2 | foo
3 | # invalid quoteless string
4 | [
5 | ]
6 |
--------------------------------------------------------------------------------
/test/assets/failStr4d_test.hjson:
--------------------------------------------------------------------------------
1 | [
2 | foo
3 | # invalid quoteless string
4 | [x
5 | ]
6 |
--------------------------------------------------------------------------------
/test/assets/failStr5c_test.hjson:
--------------------------------------------------------------------------------
1 | [
2 | foo
3 | # invalid quoteless string
4 | :
5 | ]
6 |
--------------------------------------------------------------------------------
/test/assets/failStr5d_test.hjson:
--------------------------------------------------------------------------------
1 | [
2 | foo
3 | # invalid quoteless string
4 | :x
5 | ]
6 |
--------------------------------------------------------------------------------
/test/assets/stringify/quotes_strings_ml_result.hjson:
--------------------------------------------------------------------------------
1 | {
2 | unicorn: "foo\nbar\nrainbow"
3 | }
--------------------------------------------------------------------------------
/test/assets/stringify/quotes_strings_ml_result.json:
--------------------------------------------------------------------------------
1 | {
2 | "unicorn": "foo\nbar\nrainbow"
3 | }
--------------------------------------------------------------------------------
/test/assets/extra/root_testmeta.hjson:
--------------------------------------------------------------------------------
1 | {
2 | options: {
3 | legacyRoot: true
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/test/assets/extra/separator_testmeta.hjson:
--------------------------------------------------------------------------------
1 | {
2 | options: {
3 | separator: true
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/test/assets/stringify/quotes_all_testmeta.hjson:
--------------------------------------------------------------------------------
1 | {
2 | options: {
3 | quotes: "all"
4 | }
5 | }
--------------------------------------------------------------------------------
/test/assets/extra/notabs_testmeta.hjson:
--------------------------------------------------------------------------------
1 | {
2 | options: {
3 | multiline: no-tabs
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/test/assets/failJSON34_test.json:
--------------------------------------------------------------------------------
1 | A quoteless string is OK,
2 | but two must be contained in an array.
3 |
--------------------------------------------------------------------------------
/test/assets/stringify/quotes_always_testmeta.hjson:
--------------------------------------------------------------------------------
1 | {
2 | options: {
3 | quotes: "always"
4 | }
5 | }
--------------------------------------------------------------------------------
/test/assets/stringify/quotes_keys_testmeta.hjson:
--------------------------------------------------------------------------------
1 | {
2 | options: {
3 | quotes: "keys"
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/sample/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "private": true,
3 | "dependencies": {
4 | "hjson": "^2.3.0"
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/test/assets/failStr7a_test.hjson:
--------------------------------------------------------------------------------
1 | {
2 | # invalid string containing a newline
3 | foo : "
4 | "
5 | }
6 |
--------------------------------------------------------------------------------
/test/assets/stringify/quotes_strings_testmeta.hjson:
--------------------------------------------------------------------------------
1 | {
2 | options: {
3 | quotes: "strings"
4 | }
5 | }
--------------------------------------------------------------------------------
/test/assets/extra/root_result.hjson:
--------------------------------------------------------------------------------
1 | {
2 | database:
3 | {
4 | host: 127.0.0.1
5 | port: 555
6 | }
7 | }
--------------------------------------------------------------------------------
/test/assets/extra/root_result.json:
--------------------------------------------------------------------------------
1 | {
2 | "database": {
3 | "host": "127.0.0.1",
4 | "port": 555
5 | }
6 | }
--------------------------------------------------------------------------------
/test/assets/stringify/quotes_strings_ml_testmeta.hjson:
--------------------------------------------------------------------------------
1 | {
2 | options: {
3 | quotes: strings
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/test/assets/mltabs_result.hjson:
--------------------------------------------------------------------------------
1 | {
2 | foo:
3 | '''
4 | bar joe
5 | oki doki
6 | two tabs
7 | '''
8 | }
--------------------------------------------------------------------------------
/test/assets/extra/root_test.hjson:
--------------------------------------------------------------------------------
1 | // a object with the root braces omitted
2 | database:
3 | {
4 | host: 127.0.0.1
5 | port: 555
6 | }
7 |
--------------------------------------------------------------------------------
/test/assets/trail_result.hjson:
--------------------------------------------------------------------------------
1 | {
2 | foo: 0 -- this string starts at 0 and ends at 1, preceding and trailing whitespace is ignored -- 1
3 | }
--------------------------------------------------------------------------------
/test/assets/trail_result.json:
--------------------------------------------------------------------------------
1 | {
2 | "foo": "0 -- this string starts at 0 and ends at 1, preceding and trailing whitespace is ignored -- 1"
3 | }
--------------------------------------------------------------------------------
/test/assets/extra/separator_test.json:
--------------------------------------------------------------------------------
1 | {
2 | "foo": "bar",
3 | "unicorn": "rainbow",
4 | "cat": 1,
5 | "hello": [
6 | "world",
7 | "!"
8 | ]
9 | }
--------------------------------------------------------------------------------
/test/assets/oa_result.hjson:
--------------------------------------------------------------------------------
1 | [
2 | a
3 | {}
4 | {}
5 | []
6 | []
7 | {
8 | b: 1
9 | c: []
10 | d: {}
11 | }
12 | []
13 | ]
--------------------------------------------------------------------------------
/test/assets/oa_test.hjson:
--------------------------------------------------------------------------------
1 | [
2 | a
3 | {}
4 | {}
5 | []
6 | []
7 | {
8 | b: 1
9 | c: []
10 | d: {}
11 | }
12 | []
13 | ]
14 |
--------------------------------------------------------------------------------
/test/assets/stringify/quotes_all_test.hjson:
--------------------------------------------------------------------------------
1 | {
2 | "foo": "bar",
3 | "unicorn": "rainbow",
4 | "cat": 1,
5 | "hello": [
6 | "world",
7 | "!"
8 | ]
9 | }
--------------------------------------------------------------------------------
/test/assets/stringify/quotes_keys_test.hjson:
--------------------------------------------------------------------------------
1 | {
2 | "foo": "bar",
3 | "unicorn": "rainbow",
4 | "cat": 1,
5 | "hello": [
6 | "world",
7 | "!"
8 | ]
9 | }
--------------------------------------------------------------------------------
/test/assets/extra/separator_result.json:
--------------------------------------------------------------------------------
1 | {
2 | "foo": "bar",
3 | "unicorn": "rainbow",
4 | "cat": 1,
5 | "hello": [
6 | "world",
7 | "!"
8 | ]
9 | }
--------------------------------------------------------------------------------
/test/assets/stringify/quotes_strings_test.hjson:
--------------------------------------------------------------------------------
1 | {
2 | "foo": "bar",
3 | "unicorn": "rainbow",
4 | "cat": 1,
5 | "hello": [
6 | "world",
7 | "!"
8 | ]
9 | }
--------------------------------------------------------------------------------
/test/assets/extra/separator_result.hjson:
--------------------------------------------------------------------------------
1 | {
2 | foo: "bar",
3 | unicorn: "rainbow",
4 | cat: 1,
5 | hello:
6 | [
7 | "world",
8 | "!"
9 | ]
10 | }
--------------------------------------------------------------------------------
/test/assets/oa_result.json:
--------------------------------------------------------------------------------
1 | [
2 | "a",
3 | {},
4 | {},
5 | [],
6 | [],
7 | {
8 | "b": 1,
9 | "c": [],
10 | "d": {}
11 | },
12 | []
13 | ]
--------------------------------------------------------------------------------
/test/assets/stringify/quotes_all_result.json:
--------------------------------------------------------------------------------
1 | {
2 | "foo": "bar",
3 | "unicorn": "rainbow",
4 | "cat": 1,
5 | "hello": [
6 | "world",
7 | "!"
8 | ]
9 | }
--------------------------------------------------------------------------------
/test/assets/stringify/quotes_always_result.json:
--------------------------------------------------------------------------------
1 | {
2 | "foo": "bar",
3 | "unicorn": "rainbow",
4 | "cat": 1,
5 | "hello": [
6 | "world",
7 | "!"
8 | ]
9 | }
--------------------------------------------------------------------------------
/test/assets/stringify/quotes_keys_result.json:
--------------------------------------------------------------------------------
1 | {
2 | "foo": "bar",
3 | "unicorn": "rainbow",
4 | "cat": 1,
5 | "hello": [
6 | "world",
7 | "!"
8 | ]
9 | }
--------------------------------------------------------------------------------
/test/assets/stringify/quotes_strings_result.json:
--------------------------------------------------------------------------------
1 | {
2 | "foo": "bar",
3 | "unicorn": "rainbow",
4 | "cat": 1,
5 | "hello": [
6 | "world",
7 | "!"
8 | ]
9 | }
--------------------------------------------------------------------------------
/test/assets/stringify/quotes_always_result.hjson:
--------------------------------------------------------------------------------
1 | {
2 | foo: "bar"
3 | unicorn: "rainbow"
4 | cat: 1
5 | hello:
6 | [
7 | "world"
8 | "!"
9 | ]
10 | }
--------------------------------------------------------------------------------
/test/assets/stringify/quotes_keys_result.hjson:
--------------------------------------------------------------------------------
1 | {
2 | "foo": bar
3 | "unicorn": rainbow
4 | "cat": 1
5 | "hello":
6 | [
7 | world
8 | !
9 | ]
10 | }
--------------------------------------------------------------------------------
/test/assets/stringify/quotes_strings_result.hjson:
--------------------------------------------------------------------------------
1 | {
2 | foo: "bar"
3 | unicorn: "rainbow"
4 | cat: 1
5 | hello:
6 | [
7 | "world"
8 | "!"
9 | ]
10 | }
--------------------------------------------------------------------------------
/test/assets/stringify/quotes_all_result.hjson:
--------------------------------------------------------------------------------
1 | {
2 | "foo": "bar"
3 | "unicorn": "rainbow"
4 | "cat": 1
5 | "hello":
6 | [
7 | "world"
8 | "!"
9 | ]
10 | }
--------------------------------------------------------------------------------
/test/assets/pass3_result.hjson:
--------------------------------------------------------------------------------
1 | {
2 | "JSON Test Pattern pass3":
3 | {
4 | "The outermost value": must be an object or array.
5 | "In this test": It is an object.
6 | }
7 | }
--------------------------------------------------------------------------------
/test/assets/pass3_result.json:
--------------------------------------------------------------------------------
1 | {
2 | "JSON Test Pattern pass3": {
3 | "The outermost value": "must be an object or array.",
4 | "In this test": "It is an object."
5 | }
6 | }
--------------------------------------------------------------------------------
/test/assets/pass3_test.json:
--------------------------------------------------------------------------------
1 | {
2 | "JSON Test Pattern pass3": {
3 | "The outermost value": "must be an object or array.",
4 | "In this test": "It is an object."
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/test/assets/failStr6c_test.hjson:
--------------------------------------------------------------------------------
1 | [
2 | # invalid quoteless string
3 | # note that if there were a preceding value the comma would
4 | # be allowed/ignored as a separator/trailing comma
5 | ,
6 | ]
7 |
--------------------------------------------------------------------------------
/test/assets/failStr6d_test.hjson:
--------------------------------------------------------------------------------
1 | [
2 | # invalid quoteless string
3 | # note that if there were a preceding value the comma would
4 | # be allowed/ignored as a separator/trailing comma
5 | ,x
6 | ]
7 |
--------------------------------------------------------------------------------
/test/assets/stringify/quotes_always_test.hjson:
--------------------------------------------------------------------------------
1 | // Test if `always` keeps working as before
2 | {
3 | "foo": "bar",
4 | "unicorn": "rainbow",
5 | "cat": 1,
6 | "hello": [
7 | "world",
8 | "!"
9 | ]
10 | }
--------------------------------------------------------------------------------
/test/assets/trail_test.hjson:
--------------------------------------------------------------------------------
1 | {
2 | // the following line contains trailing whitespace:
3 | foo: 0 -- this string starts at 0 and ends at 1, preceding and trailing whitespace is ignored -- 1
4 | }
5 |
--------------------------------------------------------------------------------
/test/assets/charset2_result.hjson:
--------------------------------------------------------------------------------
1 | {
2 | uescape: "\u0000,\u0001,\uffff"
3 | French: ° î â ê Î Â Ê é É è à ù È À Ù ë Ë ç Ç œ « »
4 | German: ä Ä ö Ö ü Ü ß
5 | Italian: ° é ç à è ì ò ù À È Ì Ò Ù
6 | Spanish: ñ Ñ ü Ü á é í ó ú Á É Í Ó Ú º ¿ ¡
7 | hex: ģ䕧覫췯ꯍ
8 | }
--------------------------------------------------------------------------------
/test/assets/charset2_result.json:
--------------------------------------------------------------------------------
1 | {
2 | "uescape": "\u0000,\u0001,",
3 | "French": "° î â ê Î Â Ê é É è à ù È À Ù ë Ë ç Ç œ « »",
4 | "German": "ä Ä ö Ö ü Ü ß",
5 | "Italian": "° é ç à è ì ò ù À È Ì Ò Ù",
6 | "Spanish": "ñ Ñ ü Ü á é í ó ú Á É Í Ó Ú º ¿ ¡",
7 | "hex": "ģ䕧覫췯ꯍ"
8 | }
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 | node_js:
3 | - node
4 | - "8"
5 | - "7"
6 | - "6"
7 | - "5"
8 | - "4"
9 | - "0.12"
10 | - "0.11"
11 | - "0.10"
12 | script:
13 | - npm install
14 | - if [[ $TRAVIS_NODE_VERSION == 0* ]]; then npm test; else npm run build; fi
15 |
16 |
--------------------------------------------------------------------------------
/test/assets/charset2_test.hjson:
--------------------------------------------------------------------------------
1 | {
2 | uescape: "\u0000,\u0001,\uffff"
3 | French: ° î â ê Î Â Ê é É è à ù È À Ù ë Ë ç Ç œ « »
4 | German: ä Ä ö Ö ü Ü ß
5 | Italian: ° é ç à è ì ò ù À È Ì Ò Ù
6 | Spanish: ñ Ñ ü Ü á é í ó ú Á É Í Ó Ú º ¿ ¡
7 | hex: "\u0123\u4567\u89AB\uCDEF\uabcd\uef4A"
8 | }
9 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 |
2 | # EditorConfig http://EditorConfig.org
3 | root = true
4 |
5 | [*]
6 | end_of_line = lf
7 | insert_final_newline = true
8 |
9 | [*.{js,hjson,json}]
10 | charset = utf-8
11 |
12 | [{*.js,*.json,bin/*}]
13 | indent_style = space
14 | indent_size = 2
15 |
16 | # no style is set for Hjson test files
17 | # as some require tabs
18 |
19 |
--------------------------------------------------------------------------------
/test/assets/charset_result.hjson:
--------------------------------------------------------------------------------
1 | {
2 | ql-ascii: ! "#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~
3 | js-ascii: ! "#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~
4 | ml-ascii: ! "#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~
5 | }
--------------------------------------------------------------------------------
/test/assets/charset_result.json:
--------------------------------------------------------------------------------
1 | {
2 | "ql-ascii": "! \"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~",
3 | "js-ascii": "! \"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~",
4 | "ml-ascii": "! \"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~"
5 | }
--------------------------------------------------------------------------------
/lib/require-config.js:
--------------------------------------------------------------------------------
1 | var fs=require("fs");
2 | var Hjson=require("./hjson");
3 |
4 | // allows you to require a hjson file, e.g.:
5 | // require("hjson/lib/require-config");
6 | // var cfg=require("./test.hjson");
7 |
8 | require.extensions[".hjson"]=function(module, filename) {
9 | var content=fs.readFileSync(filename, "utf8");
10 | module.exports=Hjson.parse(content);
11 | };
12 |
--------------------------------------------------------------------------------
/test/assets/charset_test.hjson:
--------------------------------------------------------------------------------
1 | {
2 | ql-ascii: ! "#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~
3 | js-ascii: "! \"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~"
4 | ml-ascii:
5 | '''
6 | ! "#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~
7 | '''
8 | }
9 |
--------------------------------------------------------------------------------
/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "env": {
3 | "browser": true,
4 | "node": true
5 | },
6 | "extends": "eslint:recommended",
7 | "rules": {
8 | "indent": [
9 | "error",
10 | 2,
11 | { "SwitchCase": 1 }
12 | ],
13 | "linebreak-style": [
14 | "error",
15 | "unix"
16 | ],
17 | "semi": [
18 | "error",
19 | "always"
20 | ],
21 | "no-empty": "off"
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/test/assets/kan_result.hjson:
--------------------------------------------------------------------------------
1 | {
2 | numbers:
3 | [
4 | 0
5 | 0
6 | 0
7 | 42
8 | 42.1
9 | -5
10 | -5.1
11 | 1701
12 | -1701
13 | 12.345
14 | -12.345
15 | ]
16 | native:
17 | [
18 | true
19 | true
20 | false
21 | false
22 | null
23 | null
24 | ]
25 | strings:
26 | [
27 | x 0
28 | .0
29 | 00
30 | 01
31 | 0 0 0
32 | 42 x
33 | 42.1 asdf
34 | 1.2.3
35 | -5 0 -
36 | -5.1 --
37 | 17.01e2 +
38 | -17.01e2 :
39 | 12345e-3 @
40 | -12345e-3 $
41 | true true
42 | x true
43 | false false
44 | x false
45 | null null
46 | x null
47 | ]
48 | }
--------------------------------------------------------------------------------
/sample/sample.js:
--------------------------------------------------------------------------------
1 |
2 | var Hjson=require("hjson");
3 | var fs=require("fs");
4 | var text=fs.readFileSync("test.hjson", "utf8");
5 |
6 | // parse either JSON or Hjson
7 | var data=Hjson.parse(text);
8 | console.log(data.hello);
9 | console.log();
10 |
11 | // convert to JSON
12 | console.log("--- JSON output:");
13 | console.log(JSON.stringify(data, null, 2));
14 | console.log();
15 |
16 | // convert to Hjson
17 | console.log("\n--- Hjson output:");
18 | console.log(Hjson.stringify(data));
19 |
20 | // parse, keep whitespace and comments
21 | data=Hjson.rt.parse(text);
22 |
23 | // modify like you normally would
24 | data.foo="text";
25 |
26 | console.log("\n--- Hjson output with comments:");
27 | console.log(Hjson.rt.stringify(data));
28 |
--------------------------------------------------------------------------------
/test/assets/kan_result.json:
--------------------------------------------------------------------------------
1 | {
2 | "numbers": [
3 | 0,
4 | 0,
5 | 0,
6 | 42,
7 | 42.1,
8 | -5,
9 | -5.1,
10 | 1701,
11 | -1701,
12 | 12.345,
13 | -12.345
14 | ],
15 | "native": [
16 | true,
17 | true,
18 | false,
19 | false,
20 | null,
21 | null
22 | ],
23 | "strings": [
24 | "x 0",
25 | ".0",
26 | "00",
27 | "01",
28 | "0 0 0",
29 | "42 x",
30 | "42.1 asdf",
31 | "1.2.3",
32 | "-5 0 -",
33 | "-5.1 --",
34 | "17.01e2 +",
35 | "-17.01e2 :",
36 | "12345e-3 @",
37 | "-12345e-3 $",
38 | "true true",
39 | "x true",
40 | "false false",
41 | "x false",
42 | "null null",
43 | "x null"
44 | ]
45 | }
--------------------------------------------------------------------------------
/test/assets/keys_result.hjson:
--------------------------------------------------------------------------------
1 | {
2 | unquoted_key: test
3 | _unquoted: test
4 | test-key: test
5 | -test: test
6 | .key: test
7 | trailing: test
8 | trailing2: test
9 | "#c1": test
10 | "foo#bar": test
11 | "//bar": test
12 | "foo//bar": test
13 | "/*foo*/": test
14 | "foo/*foo*/bar": test
15 | "/*": test
16 | "foo/*bar": test
17 | "\"": test
18 | "foo\"bar": test
19 | "'''": test
20 | "foo'''bar": test
21 | "'": test
22 | "'foo": test
23 | "foo'bar": test
24 | ":": test
25 | "foo:bar": test
26 | "{": test
27 | "foo{bar": test
28 | "}": test
29 | "foo}bar": test
30 | "[": test
31 | "foo[bar": test
32 | "]": test
33 | "foo]bar": test
34 | nl1: test
35 | nl2: test
36 | nl3: test
37 | }
--------------------------------------------------------------------------------
/test/assets/kan_test.hjson:
--------------------------------------------------------------------------------
1 | {
2 | # the comma forces a whitespace check
3 | numbers:
4 | [
5 | 0
6 | 0 ,
7 | -0
8 | 42 ,
9 | 42.1 ,
10 | -5
11 | -5.1
12 | 17.01e2
13 | -17.01e2
14 | 12345e-3 ,
15 | -12345e-3 ,
16 | ]
17 | native:
18 | [
19 | true ,
20 | true
21 | false ,
22 | false
23 | null ,
24 | null
25 | ]
26 | strings:
27 | [
28 | x 0
29 | .0
30 | 00
31 | 01
32 | 0 0 0
33 | 42 x
34 | 42.1 asdf
35 | 1.2.3
36 | -5 0 -
37 | -5.1 --
38 | 17.01e2 +
39 | -17.01e2 :
40 | 12345e-3 @
41 | -12345e-3 $
42 | true true
43 | x true
44 | false false
45 | x false
46 | null null
47 | x null
48 | ]
49 | }
50 |
--------------------------------------------------------------------------------
/test/assets/strings2_result.hjson:
--------------------------------------------------------------------------------
1 | {
2 | key1: a key in single quotes
3 | "key 2": a key in single quotes
4 | "key \"": a key in single quotes
5 | text:
6 | [
7 | single quoted string
8 | '''You need quotes for escapes'''
9 | " untrimmed "
10 | "untrimmed "
11 | containing " double quotes
12 | containing " double quotes
13 | containing " double quotes
14 | '''"containing more " double quotes"'''
15 | containing ' single quotes
16 | containing ' single quotes
17 | containing ' single quotes
18 | "'containing more ' single quotes'"
19 | "'containing more ' single quotes'"
20 | "\n"
21 | " \n"
22 | "\n \n \n \n"
23 | "\t\n"
24 | ]
25 | foo3a: asdf'''
26 | foo3b: "'''asdf"
27 | foo4a: "asdf'''\nasdf"
28 | foo4b: "asdf\n'''asdf"
29 | }
--------------------------------------------------------------------------------
/test/assets/comments_result.hjson:
--------------------------------------------------------------------------------
1 | {
2 | foo1: This is a string value. # part of the string
3 | foo2: This is a string value.
4 | bar1: This is a string value. // part of the string
5 | bar2: This is a string value.
6 | foobar1: This is a string value./* part of the string */
7 | foobar2: This is a string value.
8 | rem1: "# test"
9 | rem2: "// test"
10 | rem3: "/* test */"
11 | num1: 0
12 | num2: 0
13 | num3: 2
14 | true1: true
15 | true2: true
16 | true3: true
17 | false1: false
18 | false2: false
19 | false3: false
20 | null1: null
21 | null2: null
22 | null3: null
23 | str1: 00 # part of the string
24 | str2: 00.0 // part of the string
25 | str3: 02 /* part of the string */
26 | URL1: http://example.com
27 | URL2: http://example.com
28 | URL3: http://example.com
29 | URL4: http://example.com
30 | }
--------------------------------------------------------------------------------
/test/assets/strings2_result.json:
--------------------------------------------------------------------------------
1 | {
2 | "key1": "a key in single quotes",
3 | "key 2": "a key in single quotes",
4 | "key \"": "a key in single quotes",
5 | "text": [
6 | "single quoted string",
7 | "You need quotes\tfor escapes",
8 | " untrimmed ",
9 | "untrimmed ",
10 | "containing \" double quotes",
11 | "containing \" double quotes",
12 | "containing \" double quotes",
13 | "\"containing more \" double quotes\"",
14 | "containing ' single quotes",
15 | "containing ' single quotes",
16 | "containing ' single quotes",
17 | "'containing more ' single quotes'",
18 | "'containing more ' single quotes'",
19 | "\n",
20 | " \n",
21 | "\n \n \n \n",
22 | "\t\n"
23 | ],
24 | "foo3a": "asdf'''",
25 | "foo3b": "'''asdf",
26 | "foo4a": "asdf'''\nasdf",
27 | "foo4b": "asdf\n'''asdf"
28 | }
--------------------------------------------------------------------------------
/test/assets/keys_result.json:
--------------------------------------------------------------------------------
1 | {
2 | "unquoted_key": "test",
3 | "_unquoted": "test",
4 | "test-key": "test",
5 | "-test": "test",
6 | ".key": "test",
7 | "trailing": "test",
8 | "trailing2": "test",
9 | "#c1": "test",
10 | "foo#bar": "test",
11 | "//bar": "test",
12 | "foo//bar": "test",
13 | "/*foo*/": "test",
14 | "foo/*foo*/bar": "test",
15 | "/*": "test",
16 | "foo/*bar": "test",
17 | "\"": "test",
18 | "foo\"bar": "test",
19 | "'''": "test",
20 | "foo'''bar": "test",
21 | "'": "test",
22 | "'foo": "test",
23 | "foo'bar": "test",
24 | ":": "test",
25 | "foo:bar": "test",
26 | "{": "test",
27 | "foo{bar": "test",
28 | "}": "test",
29 | "foo}bar": "test",
30 | "[": "test",
31 | "foo[bar": "test",
32 | "]": "test",
33 | "foo]bar": "test",
34 | "nl1": "test",
35 | "nl2": "test",
36 | "nl3": "test"
37 | }
--------------------------------------------------------------------------------
/test/assets/strings2_test.hjson:
--------------------------------------------------------------------------------
1 | {
2 | # Hjson 3 allows the use of single quotes
3 |
4 | 'key1': a key in single quotes
5 | 'key 2': a key in single quotes
6 | 'key "': a key in single quotes
7 |
8 | text: [
9 | 'single quoted string'
10 | 'You need quotes\tfor escapes'
11 | ' untrimmed '
12 | 'untrimmed '
13 | 'containing " double quotes'
14 | 'containing \" double quotes'
15 | "containing \" double quotes"
16 | '"containing more " double quotes"'
17 | 'containing \' single quotes'
18 | "containing ' single quotes"
19 | "containing \' single quotes"
20 | "'containing more ' single quotes'"
21 | "\'containing more \' single quotes\'"
22 |
23 | '\n'
24 | ' \n'
25 | '\n \n \n \n'
26 | '\t\n'
27 | ]
28 |
29 | # escapes/no escape
30 |
31 | foo3a: 'asdf\'\'\''
32 | foo3b: '\'\'\'asdf'
33 |
34 | foo4a: 'asdf\'\'\'\nasdf'
35 | foo4b: 'asdf\n\'\'\'asdf'
36 | }
37 |
--------------------------------------------------------------------------------
/test/assets/comments_result.json:
--------------------------------------------------------------------------------
1 | {
2 | "foo1": "This is a string value. # part of the string",
3 | "foo2": "This is a string value.",
4 | "bar1": "This is a string value. // part of the string",
5 | "bar2": "This is a string value.",
6 | "foobar1": "This is a string value./* part of the string */",
7 | "foobar2": "This is a string value.",
8 | "rem1": "# test",
9 | "rem2": "// test",
10 | "rem3": "/* test */",
11 | "num1": 0,
12 | "num2": 0,
13 | "num3": 2,
14 | "true1": true,
15 | "true2": true,
16 | "true3": true,
17 | "false1": false,
18 | "false2": false,
19 | "false3": false,
20 | "null1": null,
21 | "null2": null,
22 | "null3": null,
23 | "str1": "00 # part of the string",
24 | "str2": "00.0 // part of the string",
25 | "str3": "02 /* part of the string */",
26 | "URL1": "http://example.com",
27 | "URL2": "http://example.com",
28 | "URL3": "http://example.com",
29 | "URL4": "http://example.com"
30 | }
--------------------------------------------------------------------------------
/test/assets/keys_test.hjson:
--------------------------------------------------------------------------------
1 | {
2 | # unquoted keys
3 | unquoted_key: test
4 | _unquoted: test
5 | test-key: test
6 | -test: test
7 | .key: test
8 | # trailing spaces in key names are ignored
9 | trailing : test
10 | trailing2 : test
11 | # comment char in key name
12 | "#c1": test
13 | "foo#bar": test
14 | "//bar": test
15 | "foo//bar": test
16 | "/*foo*/": test
17 | "foo/*foo*/bar": test
18 | "/*": test
19 | "foo/*bar": test
20 | # quotes in key name
21 | "\"": test
22 | "foo\"bar": test
23 | "'''": test
24 | "foo'''bar": test
25 | "'": test
26 | "'foo": test
27 | "foo'bar": test
28 | # control char in key name
29 | ":": test
30 | "foo:bar": test
31 | "{": test
32 | "foo{bar": test
33 | "}": test
34 | "foo}bar": test
35 | "[": test
36 | "foo[bar": test
37 | "]": test
38 | "foo]bar": test
39 | # newline
40 | nl1:
41 | test
42 | nl2
43 | :
44 | test
45 |
46 | nl3
47 |
48 | :
49 |
50 | test
51 | }
52 |
--------------------------------------------------------------------------------
/test/assets/pass2_result.hjson:
--------------------------------------------------------------------------------
1 | [
2 | [
3 | [
4 | [
5 | [
6 | [
7 | [
8 | [
9 | [
10 | [
11 | [
12 | [
13 | [
14 | [
15 | [
16 | [
17 | [
18 | [
19 | [
20 | Not too deep
21 | ]
22 | ]
23 | ]
24 | ]
25 | ]
26 | ]
27 | ]
28 | ]
29 | ]
30 | ]
31 | ]
32 | ]
33 | ]
34 | ]
35 | ]
36 | ]
37 | ]
38 | ]
39 | ]
--------------------------------------------------------------------------------
/test/assets/pass2_result.json:
--------------------------------------------------------------------------------
1 | [
2 | [
3 | [
4 | [
5 | [
6 | [
7 | [
8 | [
9 | [
10 | [
11 | [
12 | [
13 | [
14 | [
15 | [
16 | [
17 | [
18 | [
19 | [
20 | "Not too deep"
21 | ]
22 | ]
23 | ]
24 | ]
25 | ]
26 | ]
27 | ]
28 | ]
29 | ]
30 | ]
31 | ]
32 | ]
33 | ]
34 | ]
35 | ]
36 | ]
37 | ]
38 | ]
39 | ]
--------------------------------------------------------------------------------
/test/assets/stringify1_result.hjson:
--------------------------------------------------------------------------------
1 | {
2 | quotes:
3 | {
4 | num1: "1,2"
5 | num2: "-1.1 ,"
6 | num3: "1e10 ,2"
7 | num4: "-1e-10,"
8 | kw1: "true,"
9 | kw2: "false ,"
10 | kw3: "null,123"
11 | close1: "1}"
12 | close1b: "1 }"
13 | close2: "1]"
14 | close2b: "1 ]"
15 | close3: "1,"
16 | close3b: "1 ,"
17 | comment1: "1#str"
18 | comment2: "1//str"
19 | comment3: "1/*str*/"
20 | punc1: "{"
21 | punc1b: "{foo"
22 | punc2: "}"
23 | punc2b: "}foo"
24 | punc3: "["
25 | punc3b: "[foo"
26 | punc4: "]"
27 | punc4b: "]foo"
28 | punc5: ","
29 | punc5b: ",foo"
30 | punc6: ":"
31 | punc6b: ":foo"
32 | }
33 | noquotes:
34 | {
35 | num0: .1,2
36 | num1: 1.1.1,2
37 | num2: -.1,
38 | num3: 1e10e,2
39 | num4: -1e--10,
40 | kw1: true1,
41 | kw2: false0,
42 | kw3: null0,
43 | close1: a}
44 | close2: a]
45 | comment1: a#str
46 | comment2: a//str
47 | comment3: a/*str*/
48 | }
49 | }
--------------------------------------------------------------------------------
/sample/test.hjson:
--------------------------------------------------------------------------------
1 | {
2 | # comments are treated like whitespace - they are not parsed
3 |
4 | hello: Hello Human!
5 |
6 | // js style comment
7 |
8 | /*
9 | multiline comment
10 | multiline comment
11 | */
12 |
13 | # text
14 | text: This is a valid string value.
15 | quote: "You need quotes\tfor escapes"
16 | otherwise:
life without escapes is bliss!
17 |
18 | # keys
19 | abc-123: no quotes for keys
20 |
21 | # comma
22 | commas: "can be omitted at the end of the line"
23 | but: [ 1, 2, 3 ] # not between elements on the same line
24 | trailing: [ 1, 2, 3, ] # a trailing comma is OK
25 |
26 | # multiline string
27 | multiline:
28 | '''
29 | first line
30 | indented line
31 | third line
32 | '''
33 |
34 | # numbers, keywords and arrays work just like in JSON
35 | number: 5
36 | negative: -4.2
37 | yes: true
38 | no: false
39 | null: null
40 | array: [ 1, 2 ]
41 | array2: [
42 | 1
43 | 2
44 | ]
45 | }
46 |
--------------------------------------------------------------------------------
/test/assets/stringify1_test.hjson:
--------------------------------------------------------------------------------
1 | // test if stringify produces correct output
2 | {
3 | quotes:
4 | {
5 | num1: "1,2"
6 | num2: "-1.1 ,"
7 | num3: "1e10 ,2"
8 | num4: "-1e-10,"
9 | kw1: "true,"
10 | kw2: "false ,"
11 | kw3: "null,123"
12 | close1: "1}"
13 | close1b: "1 }"
14 | close2: "1]"
15 | close2b: "1 ]"
16 | close3: "1,"
17 | close3b: "1 ,"
18 | comment1: "1#str"
19 | comment2: "1//str"
20 | comment3: "1/*str*/"
21 | punc1: "{"
22 | punc1b: "{foo"
23 | punc2: "}"
24 | punc2b: "}foo"
25 | punc3: "["
26 | punc3b: "[foo"
27 | punc4: "]"
28 | punc4b: "]foo"
29 | punc5: ","
30 | punc5b: ",foo"
31 | punc6: ":"
32 | punc6b: ":foo"
33 | }
34 | noquotes:
35 | {
36 | num0: ".1,2"
37 | num1: "1.1.1,2"
38 | num2: "-.1,"
39 | num3: "1e10e,2"
40 | num4: "-1e--10,"
41 | kw1: "true1,"
42 | kw2: "false0,"
43 | kw3: "null0,"
44 | close1: "a}"
45 | close2: "a]"
46 | comment1: "a#str"
47 | comment2: "a//str"
48 | comment3: "a/*str*/"
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/test/assets/stringify1_result.json:
--------------------------------------------------------------------------------
1 | {
2 | "quotes": {
3 | "num1": "1,2",
4 | "num2": "-1.1 ,",
5 | "num3": "1e10 ,2",
6 | "num4": "-1e-10,",
7 | "kw1": "true,",
8 | "kw2": "false ,",
9 | "kw3": "null,123",
10 | "close1": "1}",
11 | "close1b": "1 }",
12 | "close2": "1]",
13 | "close2b": "1 ]",
14 | "close3": "1,",
15 | "close3b": "1 ,",
16 | "comment1": "1#str",
17 | "comment2": "1//str",
18 | "comment3": "1/*str*/",
19 | "punc1": "{",
20 | "punc1b": "{foo",
21 | "punc2": "}",
22 | "punc2b": "}foo",
23 | "punc3": "[",
24 | "punc3b": "[foo",
25 | "punc4": "]",
26 | "punc4b": "]foo",
27 | "punc5": ",",
28 | "punc5b": ",foo",
29 | "punc6": ":",
30 | "punc6b": ":foo"
31 | },
32 | "noquotes": {
33 | "num0": ".1,2",
34 | "num1": "1.1.1,2",
35 | "num2": "-.1,",
36 | "num3": "1e10e,2",
37 | "num4": "-1e--10,",
38 | "kw1": "true1,",
39 | "kw2": "false0,",
40 | "kw3": "null0,",
41 | "close1": "a}",
42 | "close2": "a]",
43 | "comment1": "a#str",
44 | "comment2": "a//str",
45 | "comment3": "a/*str*/"
46 | }
47 | }
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2014-2017 Christian Zangl
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/test/assets/comments_test.hjson:
--------------------------------------------------------------------------------
1 | // test
2 | # all
3 | // comment
4 | /*
5 | styles
6 | */
7 | # with lf
8 |
9 |
10 |
11 | # !
12 |
13 | {
14 | # hjson style comment
15 | foo1: This is a string value. # part of the string
16 | foo2: "This is a string value." # a comment
17 |
18 | // js style comment
19 | bar1: This is a string value. // part of the string
20 | bar2: "This is a string value." // a comment
21 |
22 | /* js block style comments */foobar1:/* more */This is a string value./* part of the string */
23 | /* js block style comments */foobar2:/* more */"This is a string value."/* a comment */
24 |
25 | rem1: "# test"
26 | rem2: "// test"
27 | rem3: "/* test */"
28 |
29 | num1: 0 # comment
30 | num2: 0.0 // comment
31 | num3: 2 /* comment */
32 |
33 | true1: true # comment
34 | true2: true // comment
35 | true3: true /* comment */
36 |
37 | false1: false # comment
38 | false2: false // comment
39 | false3: false /* comment */
40 |
41 | null1: null # comment
42 | null2: null // comment
43 | null3: null /* comment */
44 |
45 | str1: 00 # part of the string
46 | str2: 00.0 // part of the string
47 | str3: 02 /* part of the string */
48 |
49 | # this causes problems with the syntax definitions for some editors:
50 | URL1: "http://example.com",
51 | "URL2": "http://example.com",
52 | URL3: http://example.com
53 | "URL4": http://example.com
54 | }
55 |
--------------------------------------------------------------------------------
/test/assets/strings_result.json:
--------------------------------------------------------------------------------
1 | {
2 | "text1": "This is a valid string value.",
3 | "text2": "a \\ is just a \\",
4 | "text3": "You need quotes\tfor escapes",
5 | "text4a": " untrimmed ",
6 | "text4b": " untrimmed",
7 | "text4c": "untrimmed ",
8 | "notml1": "\n",
9 | "notml2": " \n",
10 | "notml3": "\n \n \n \n",
11 | "notml4": "\t\n",
12 | "multiline1": "first line\n indented line\nlast line",
13 | "multiline2": "first line\n indented line\nlast line",
14 | "multiline3": "first line\n indented line\nlast line\n",
15 | "foo1a": "asdf\\\"'a\\s\\w",
16 | "foo1b": "asdf\\\"'a\\s\\w",
17 | "foo1c": "asdf\\\"'a\\s\\w",
18 | "foo2a": "\"asdf\"",
19 | "foo2b": "\"asdf\"",
20 | "foo3a": "asdf'''",
21 | "foo3b": "'''asdf",
22 | "foo4a": "asdf'''\nasdf",
23 | "foo4b": "asdf\n'''asdf",
24 | "arr": [
25 | "one",
26 | "two",
27 | "three",
28 | "four"
29 | ],
30 | "not": {
31 | "number": 5,
32 | "negative": -4.2,
33 | "yes": true,
34 | "no": false,
35 | "null": null,
36 | "array": [
37 | 1,
38 | 2,
39 | 3,
40 | 4,
41 | 5,
42 | 6,
43 | 7,
44 | 8,
45 | 9,
46 | 0,
47 | -1,
48 | 0.5
49 | ]
50 | },
51 | "special": {
52 | "true": "true",
53 | "false": "false",
54 | "null": "null",
55 | "one": "1",
56 | "two": "2",
57 | "minus": "-3"
58 | }
59 | }
--------------------------------------------------------------------------------
/test/assets/strings_result.hjson:
--------------------------------------------------------------------------------
1 | {
2 | text1: This is a valid string value.
3 | text2: a \ is just a \
4 | text3: '''You need quotes for escapes'''
5 | text4a: " untrimmed "
6 | text4b: " untrimmed"
7 | text4c: "untrimmed "
8 | notml1: "\n"
9 | notml2: " \n"
10 | notml3: "\n \n \n \n"
11 | notml4: "\t\n"
12 | multiline1:
13 | '''
14 | first line
15 | indented line
16 | last line
17 | '''
18 | multiline2:
19 | '''
20 | first line
21 | indented line
22 | last line
23 | '''
24 | multiline3:
25 | '''
26 | first line
27 | indented line
28 | last line
29 |
30 | '''
31 | foo1a: asdf\"'a\s\w
32 | foo1b: asdf\"'a\s\w
33 | foo1c: asdf\"'a\s\w
34 | foo2a: '''"asdf"'''
35 | foo2b: '''"asdf"'''
36 | foo3a: asdf'''
37 | foo3b: "'''asdf"
38 | foo4a: "asdf'''\nasdf"
39 | foo4b: "asdf\n'''asdf"
40 | arr:
41 | [
42 | one
43 | two
44 | three
45 | four
46 | ]
47 | not:
48 | {
49 | number: 5
50 | negative: -4.2
51 | yes: true
52 | no: false
53 | null: null
54 | array:
55 | [
56 | 1
57 | 2
58 | 3
59 | 4
60 | 5
61 | 6
62 | 7
63 | 8
64 | 9
65 | 0
66 | -1
67 | 0.5
68 | ]
69 | }
70 | special:
71 | {
72 | true: "true"
73 | false: "false"
74 | null: "null"
75 | one: "1"
76 | two: "2"
77 | minus: "-3"
78 | }
79 | }
--------------------------------------------------------------------------------
/test/assets/pass1_result.hjson:
--------------------------------------------------------------------------------
1 | [
2 | JSON Test Pattern pass1
3 | {
4 | "object with 1 member":
5 | [
6 | array with 1 element
7 | ]
8 | }
9 | {}
10 | []
11 | -42
12 | true
13 | false
14 | null
15 | {
16 | integer: 1234567890
17 | real: -9876.54321
18 | e: 1.23456789e-13
19 | E: 1.23456789e+34
20 | -: 2.3456789012e+76
21 | zero: 0
22 | one: 1
23 | space: " "
24 | quote: '''"'''
25 | backslash: \
26 | controls: "\b\f\n\r\t"
27 | slash: / & /
28 | alpha: abcdefghijklmnopqrstuvwyz
29 | ALPHA: ABCDEFGHIJKLMNOPQRSTUVWYZ
30 | digit: 0123456789
31 | 0123456789: digit
32 | special: `1~!@#$%^&*()_+-={':[,]}|;.>?
33 | hex: ģ䕧覫췯ꯍ
34 | true: true
35 | false: false
36 | null: null
37 | array: []
38 | object: {}
39 | address: 50 St. James Street
40 | url: http://www.JSON.org/
41 | comment: "// /* */": " "
43 | " s p a c e d ":
44 | [
45 | 1
46 | 2
47 | 3
48 | 4
49 | 5
50 | 6
51 | 7
52 | ]
53 | compact:
54 | [
55 | 1
56 | 2
57 | 3
58 | 4
59 | 5
60 | 6
61 | 7
62 | ]
63 | jsontext: '''{"object with 1 member":["array with 1 element"]}'''
64 | quotes: " " %22 0x22 034 "
65 | "/\\\"쫾몾ꮘﳞ볚\b\f\n\r\t`1~!@#$%^&*()_+-=[]{}|;:',./<>?": A key can be any string
66 | }
67 | 0.5
68 | 98.6
69 | 99.44
70 | 1066
71 | 10
72 | 1
73 | 0.1
74 | 1
75 | 2
76 | 2
77 | rosebud
78 | ]
--------------------------------------------------------------------------------
/test/assets/strings_test.hjson:
--------------------------------------------------------------------------------
1 | {
2 | # simple
3 |
4 | text1: This is a valid string value.
5 | text2:a \ is just a \
6 |
7 | text3: "You need quotes\tfor escapes"
8 |
9 | text4a: " untrimmed "
10 | text4b: " untrimmed"
11 | text4c: "untrimmed "
12 |
13 | notml1: "\n"
14 | notml2: " \n"
15 | notml3: "\n \n \n \n"
16 | notml4: "\t\n"
17 |
18 | # multiline string
19 |
20 | multiline1:
21 | '''
22 | first line
23 | indented line
24 | last line
25 | '''
26 |
27 | multiline2:
28 | '''first line
29 | indented line
30 | last line'''
31 |
32 | multiline3:
33 | '''
34 | first line
35 | indented line
36 | last line
37 |
38 | ''' # trailing lf
39 |
40 | # escapes/no escape
41 |
42 | foo1a: asdf\"'a\s\w
43 | foo1b: '''asdf\"'a\s\w'''
44 | foo1c: "asdf\\\"'a\\s\\w"
45 |
46 | foo2a: "\"asdf\""
47 | foo2b: '''"asdf"'''
48 |
49 | foo3a: "asdf'''"
50 | foo3b: "'''asdf"
51 |
52 | foo4a: "asdf'''\nasdf"
53 | foo4b: "asdf\n'''asdf"
54 |
55 | # in arrays
56 | arr:
57 | [
58 | one
59 | two
60 | "three"
61 | '''four'''
62 | ]
63 |
64 | # not strings
65 | not:
66 | {
67 | number: 5
68 | negative: -4.2
69 | yes: true
70 | no: false
71 | null: null
72 | array: [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, -1, 0.5 ]
73 | }
74 |
75 | # special quoted
76 | special:
77 | {
78 | true: "true"
79 | false: "false"
80 | null: "null"
81 | one: "1"
82 | two: "2"
83 | minus: "-3"
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/test/assets/pass1_result.json:
--------------------------------------------------------------------------------
1 | [
2 | "JSON Test Pattern pass1",
3 | {
4 | "object with 1 member": [
5 | "array with 1 element"
6 | ]
7 | },
8 | {},
9 | [],
10 | -42,
11 | true,
12 | false,
13 | null,
14 | {
15 | "integer": 1234567890,
16 | "real": -9876.54321,
17 | "e": 1.23456789e-13,
18 | "E": 1.23456789e+34,
19 | "-": 2.3456789012e+76,
20 | "zero": 0,
21 | "one": 1,
22 | "space": " ",
23 | "quote": "\"",
24 | "backslash": "\\",
25 | "controls": "\b\f\n\r\t",
26 | "slash": "/ & /",
27 | "alpha": "abcdefghijklmnopqrstuvwyz",
28 | "ALPHA": "ABCDEFGHIJKLMNOPQRSTUVWYZ",
29 | "digit": "0123456789",
30 | "0123456789": "digit",
31 | "special": "`1~!@#$%^&*()_+-={':[,]}|;.>?",
32 | "hex": "ģ䕧覫췯ꯍ",
33 | "true": true,
34 | "false": false,
35 | "null": null,
36 | "array": [],
37 | "object": {},
38 | "address": "50 St. James Street",
39 | "url": "http://www.JSON.org/",
40 | "comment": "// /* */": " ",
42 | " s p a c e d ": [
43 | 1,
44 | 2,
45 | 3,
46 | 4,
47 | 5,
48 | 6,
49 | 7
50 | ],
51 | "compact": [
52 | 1,
53 | 2,
54 | 3,
55 | 4,
56 | 5,
57 | 6,
58 | 7
59 | ],
60 | "jsontext": "{\"object with 1 member\":[\"array with 1 element\"]}",
61 | "quotes": "" \" %22 0x22 034 "",
62 | "/\\\"쫾몾ꮘﳞ볚\b\f\n\r\t`1~!@#$%^&*()_+-=[]{}|;:',./<>?": "A key can be any string"
63 | },
64 | 0.5,
65 | 98.6,
66 | 99.44,
67 | 1066,
68 | 10,
69 | 1,
70 | 0.1,
71 | 1,
72 | 2,
73 | 2,
74 | "rosebud"
75 | ]
--------------------------------------------------------------------------------
/test/assets/pass1_test.json:
--------------------------------------------------------------------------------
1 | [
2 | "JSON Test Pattern pass1",
3 | {"object with 1 member":["array with 1 element"]},
4 | {},
5 | [],
6 | -42,
7 | true,
8 | false,
9 | null,
10 | {
11 | "integer": 1234567890,
12 | "real": -9876.543210,
13 | "e": 0.123456789e-12,
14 | "E": 1.234567890E+34,
15 | "-": 23456789012E66,
16 | "zero": 0,
17 | "one": 1,
18 | "space": " ",
19 | "quote": "\"",
20 | "backslash": "\\",
21 | "controls": "\b\f\n\r\t",
22 | "slash": "/ & \/",
23 | "alpha": "abcdefghijklmnopqrstuvwyz",
24 | "ALPHA": "ABCDEFGHIJKLMNOPQRSTUVWYZ",
25 | "digit": "0123456789",
26 | "0123456789": "digit",
27 | "special": "`1~!@#$%^&*()_+-={':[,]}|;.>?",
28 | "hex": "\u0123\u4567\u89AB\uCDEF\uabcd\uef4A",
29 | "true": true,
30 | "false": false,
31 | "null": null,
32 | "array":[ ],
33 | "object":{ },
34 | "address": "50 St. James Street",
35 | "url": "http://www.JSON.org/",
36 | "comment": "// /* */": " ",
38 | " s p a c e d " :[1,2 , 3
39 |
40 | ,
41 |
42 | 4 , 5 , 6 ,7 ],"compact":[1,2,3,4,5,6,7],
43 | "jsontext": "{\"object with 1 member\":[\"array with 1 element\"]}",
44 | "quotes": "" \u0022 %22 0x22 034 "",
45 | "\/\\\"\uCAFE\uBABE\uAB98\uFCDE\ubcda\uef4A\b\f\n\r\t`1~!@#$%^&*()_+-=[]{}|;:',./<>?"
46 | : "A key can be any string"
47 | },
48 | 0.5 ,98.6
49 | ,
50 | 99.44
51 | ,
52 |
53 | 1066,
54 | 1e1,
55 | 0.1e1,
56 | 1e-1,
57 | 1e00,2e+00,2e-00
58 | ,"rosebud"]
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "hjson",
3 | "description": "A user interface for JSON.",
4 | "main": "./lib/hjson.js",
5 | "author": "Christian Zangl",
6 | "version": "3.2.2",
7 | "keywords": [
8 | "json",
9 | "comments",
10 | "config",
11 | "hjson",
12 | "parser",
13 | "serializer",
14 | "human"
15 | ],
16 | "bin": {
17 | "hjson": "./bin/hjson"
18 | },
19 | "scripts": {
20 | "test": "node ./test/test.js",
21 | "lint": "node_modules/eslint/bin/eslint.js -f unix bin/hjson lib/*.js",
22 | "build_v1": "node -e 'console.log(\"module.exports=\\\"\"+eval(\"(\"+process.argv[1]+\")\").version+\"\\\";\");' -- \"`cat package.json`\" > lib/hjson-version.js",
23 | "build_v2": "node -e 'var v=\" * Hjson v\"+eval(\"(\"+process.argv[1]+\")\").version; if (v!==process.argv[2]) throw new Error(\"ver\");' -- \"`cat package.json`\" \"`grep -E '\\* Hjson v.*$' lib/hjson.js`\"",
24 | "build_bundle": "node_modules/browserify/bin/cmd.js -p browserify-header --ignore os -s Hjson -o bundle/hjson.js lib/hjson.js",
25 | "build_min": "node node_modules/uglify-js/bin/uglifyjs bundle/hjson.js --comments=/^!/ -c -m -o bundle/hjson.min.js",
26 | "build": "npm run build_v1 && npm run build_v2 && npm run test && npm run lint && npm run build_bundle && npm run build_min"
27 | },
28 | "homepage": "https://hjson.github.io",
29 | "repository": {
30 | "type": "git",
31 | "url": "https://github.com/hjson/hjson-js.git"
32 | },
33 | "bugs": {
34 | "url": "https://github.com/hjson/hjson-js/issues"
35 | },
36 | "license": "MIT",
37 | "devDependencies": {
38 | "browserify": "^13.3.0",
39 | "browserify-header": "0.9.2",
40 | "eslint": "^3.13.1",
41 | "uglify-js": "^2.7.5"
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/test/assets/testlist.txt:
--------------------------------------------------------------------------------
1 | charset2_test.hjson
2 | charset_test.hjson
3 | comments_test.hjson
4 | empty_test.hjson
5 | failCharset1_test.hjson
6 | failJSON02_test.json
7 | failJSON05_test.json
8 | failJSON06_test.json
9 | failJSON07_test.json
10 | failJSON08_test.json
11 | failJSON10_test.json
12 | failJSON11_test.json
13 | failJSON12_test.json
14 | failJSON13_test.json
15 | failJSON14_test.json
16 | failJSON15_test.json
17 | failJSON16_test.json
18 | failJSON17_test.json
19 | failJSON19_test.json
20 | failJSON20_test.json
21 | failJSON21_test.json
22 | failJSON22_test.json
23 | failJSON23_test.json
24 | failJSON26_test.json
25 | failJSON28_test.json
26 | failJSON29_test.json
27 | failJSON30_test.json
28 | failJSON31_test.json
29 | failJSON32_test.json
30 | failJSON33_test.json
31 | failJSON34_test.json
32 | failKey1_test.hjson
33 | failKey2_test.hjson
34 | failKey3_test.hjson
35 | failKey4_test.hjson
36 | failKey5_test.hjson
37 | failMLStr1_test.hjson
38 | failObj1_test.hjson
39 | failObj2_test.hjson
40 | failObj3_test.hjson
41 | failStr1a_test.hjson
42 | failStr1b_test.hjson
43 | failStr1c_test.hjson
44 | failStr1d_test.hjson
45 | failStr2a_test.hjson
46 | failStr2b_test.hjson
47 | failStr2c_test.hjson
48 | failStr2d_test.hjson
49 | failStr3a_test.hjson
50 | failStr3b_test.hjson
51 | failStr3c_test.hjson
52 | failStr3d_test.hjson
53 | failStr4a_test.hjson
54 | failStr4b_test.hjson
55 | failStr4c_test.hjson
56 | failStr4d_test.hjson
57 | failStr5a_test.hjson
58 | failStr5b_test.hjson
59 | failStr5c_test.hjson
60 | failStr5d_test.hjson
61 | failStr6a_test.hjson
62 | failStr6b_test.hjson
63 | failStr6c_test.hjson
64 | failStr6d_test.hjson
65 | failStr7a_test.hjson
66 | failStr8a_test.hjson
67 | kan_test.hjson
68 | keys_test.hjson
69 | mltabs_test.json
70 | oa_test.hjson
71 | pass1_test.json
72 | pass2_test.json
73 | pass3_test.json
74 | pass4_test.json
75 | passSingle_test.hjson
76 | stringify1_test.hjson
77 | strings2_test.hjson
78 | strings_test.hjson
79 | trail_test.hjson
80 | stringify/quotes_all_test.hjson
81 | stringify/quotes_always_test.hjson
82 | stringify/quotes_keys_test.hjson
83 | stringify/quotes_strings_ml_test.json
84 | stringify/quotes_strings_test.hjson
85 | extra/notabs_test.json
86 | extra/root_test.hjson
87 | extra/separator_test.json
--------------------------------------------------------------------------------
/lib/hjson-common.js:
--------------------------------------------------------------------------------
1 | /* Hjson https://hjson.github.io */
2 | "use strict";
3 |
4 | var os=require('os'); // will be {} when used in a browser
5 |
6 | function tryParseNumber(text, stopAtNext) {
7 |
8 | // try to parse a number
9 |
10 | var number, string = '', leadingZeros = 0, testLeading = true;
11 | var at = 0;
12 | var ch;
13 | function next() {
14 | ch = text.charAt(at);
15 | at++;
16 | return ch;
17 | }
18 |
19 | next();
20 | if (ch === '-') {
21 | string = '-';
22 | next();
23 | }
24 | while (ch >= '0' && ch <= '9') {
25 | if (testLeading) {
26 | if (ch == '0') leadingZeros++;
27 | else testLeading = false;
28 | }
29 | string += ch;
30 | next();
31 | }
32 | if (testLeading) leadingZeros--; // single 0 is allowed
33 | if (ch === '.') {
34 | string += '.';
35 | while (next() && ch >= '0' && ch <= '9')
36 | string += ch;
37 | }
38 | if (ch === 'e' || ch === 'E') {
39 | string += ch;
40 | next();
41 | if (ch === '-' || ch === '+') {
42 | string += ch;
43 | next();
44 | }
45 | while (ch >= '0' && ch <= '9') {
46 | string += ch;
47 | next();
48 | }
49 | }
50 |
51 | // skip white/to (newline)
52 | while (ch && ch <= ' ') next();
53 |
54 | if (stopAtNext) {
55 | // end scan if we find a punctuator character like ,}] or a comment
56 | if (ch === ',' || ch === '}' || ch === ']' ||
57 | ch === '#' || ch === '/' && (text[at] === '/' || text[at] === '*')) ch = 0;
58 | }
59 |
60 | number = +string;
61 | if (ch || leadingZeros || !isFinite(number)) return undefined;
62 | else return number;
63 | }
64 |
65 | function createComment(value, comment) {
66 | if (Object.defineProperty) Object.defineProperty(value, "__COMMENTS__", { enumerable: false, writable: true });
67 | return (value.__COMMENTS__ = comment||{});
68 | }
69 |
70 | function removeComment(value) {
71 | Object.defineProperty(value, "__COMMENTS__", { value: undefined });
72 | }
73 |
74 | function getComment(value) {
75 | return value.__COMMENTS__;
76 | }
77 |
78 | function forceComment(text) {
79 | if (!text) return "";
80 | var a = text.split('\n');
81 | var str, i, j, len;
82 | for (j = 0; j < a.length; j++) {
83 | str = a[j];
84 | len = str.length;
85 | for (i = 0; i < len; i++) {
86 | var c = str[i];
87 | if (c === '#') break;
88 | else if (c === '/' && (str[i+1] === '/' || str[i+1] === '*')) {
89 | if (str[i+1] === '*') j = a.length; // assume /**/ covers whole block, bail out
90 | break;
91 | }
92 | else if (c > ' ') {
93 | a[j] = '# ' + str;
94 | break;
95 | }
96 | }
97 | }
98 | return a.join('\n');
99 | }
100 |
101 | module.exports = {
102 | EOL: os.EOL || '\n',
103 | tryParseNumber: tryParseNumber,
104 | createComment: createComment,
105 | removeComment: removeComment,
106 | getComment: getComment,
107 | forceComment: forceComment,
108 | };
109 |
--------------------------------------------------------------------------------
/test/test.js:
--------------------------------------------------------------------------------
1 |
2 | var Hjson = require("..");
3 | var fs = require("fs");
4 | var path = require("path");
5 | var rootDir = path.normalize(path.join(__dirname, "assets"));
6 |
7 | var args={}, argv=[];
8 | process.argv.slice(2).forEach(function(x) { if (x[0]==="-") { var i=x.indexOf("="); args[x.substr(1, i>0?i-1:undefined)]=i>0?x.substr(i+1):true; } else argv.push(x); });
9 |
10 | var filter=argv[0];
11 | var success=true;
12 | var defaultOptions = { legacyRoot: false };
13 |
14 | function failErr(name, type, s1, s2, msg) {
15 | msg=msg||" "+name+" "+type+" FAILED!";
16 | console.log(msg);
17 | if (s1 || s2) {
18 | var i=0;
19 | while (i0?i-1:undefined)]=i>0?x.substr(i+1):true; }
12 | else if (x[0]==="+") { i=x.indexOf("="); args[x.substr(0, i>0?i:undefined)]=i>0?x.substr(i+1):true; }
13 | else argv.push(x);
14 | });
15 |
16 | if (args["-help"] || args["?"] || args.h) {
17 | console.error("Hjson, the Human JSON.");
18 | console.error();
19 | console.error("Usage:");
20 | console.error(" hjson [OPTIONS]");
21 | console.error(" hjson [OPTIONS] INPUT");
22 | console.error(" hjson (-h | --help | -?)");
23 | console.error(" hjson (-V | --version)");
24 | console.error();
25 | console.error("INPUT can be in JSON or Hjson format. If no file is given it will read from stdin.");
26 | console.error("The default is to output as Hjson.");
27 | console.error();
28 | console.error("Options:");
29 | console.error(" (-j | -json) output as formatted JSON.");
30 | console.error(" (-c | -json=compact) output as JSON.");
31 | console.error("Options for Hjson output:");
32 | console.error(" -sl output the opening brace on the same line");
33 | console.error(" -quote quote all strings");
34 | console.error(" -quote=all quote keys as well");
35 | console.error(" -js output in JavaScript/JSON compatible format");
36 | console.error(" can be used with -rt and // comments");
37 | console.error(" -rt round trip comments");
38 | console.error(" -nocol disable colors");
39 | console.error(" -cond=n set condense option (default 60, 0 to disable)");
40 | console.error("");
41 | console.error("Domain specific formats are optional extensions to Hjson and can be enabled with the following options:");
42 | Object.keys(Hjson.dsf).forEach(function(name) {
43 | console.error(" +"+name+": "+Hjson.dsf[name].description);
44 | });
45 | return 0;
46 | }
47 | else if (args.V || args["-version"]) {
48 | console.log("Hjson.js " + Hjson.version);
49 | return 0;
50 | }
51 |
52 | if (args["+math"]) dsf.push(Hjson.dsf.math());
53 | if (args["+date"]) dsf.push(Hjson.dsf.date({free:false}));
54 | if (args["+hex"]) dsf.push(Hjson.dsf.hex({out:false}));
55 |
56 | var text;
57 | if (argv.length) {
58 | text=fs.readFileSync(argv[0], "utf8");
59 | convert(text);
60 | }
61 | else {
62 | var stdin = process.openStdin();
63 | stdin.setEncoding('utf-8');
64 | text = '';
65 | stdin.on('data', function(chunk) { text += chunk; });
66 | stdin.on('end', function() { convert(text); });
67 | }
68 |
69 | function convert(text) {
70 | var obj;
71 | try { obj=Hjson.parse(text, { keepWsc: args.rt, dsf: dsf }); }
72 | catch (e) {
73 | console.error(e.toString());
74 | if (e.hint) console.error("\nhint: "+e.hint);
75 | process.exit(1); // set exit code
76 | return;
77 | }
78 |
79 | var result;
80 | if (args.c || args.json==="compact") result = JSON.stringify(obj);
81 | else if (args.j || args.json) result = JSON.stringify(obj, null, 2);
82 | else {
83 | if (args.js) args.quote="all";
84 | if (args.quote===true) args.quote="strings";
85 | result = Hjson.stringify(obj, {
86 | condense: args.cond || 60,
87 | bracesSameLine: args.sl,
88 | quotes: args.quote,
89 | separator: args.js,
90 | keepWsc: args.rt,
91 | colors: !args.nocol && process.stdout.isTTY,
92 | dsf: dsf,
93 | });
94 | }
95 |
96 | process.stdout.write(result + os.EOL);
97 | }
98 |
99 |
--------------------------------------------------------------------------------
/history.md:
--------------------------------------------------------------------------------
1 | # hjson-js History
2 |
3 | - v3.2.1
4 | - fix stringifying with comments
5 | - v3.2.0
6 | - add `sortProps` option to deterministically sort object properties
7 | - v3.1.1
8 | - set exit code for cli tool
9 | - v3.1.0
10 | - add condense mode for stringify
11 | - v3.0.2
12 | - fix stringify for keys containing single quotes
13 | - v3.0.1
14 | - add option to turn off legacy support for omitting root braces
15 | - v3.0.0
16 | - add support for single quoted strings
17 | - v2.4.3
18 | - fix throw error on string containing newline
19 | - v2.4.2
20 | - add error hint for incorrect single quotes
21 | - v2.4.1
22 | - fix tty colors
23 | - v2.4.0
24 | - new stringify options:
25 | - quotes for keys and strings (SamVerschueren)
26 | - comma separator (SamVerschueren)
27 | - multiline strings output (hmalphettes)
28 | - v2.3.1
29 | - add comments api (merge/extract)
30 | - v2.3.0
31 | - improved comment round trip
32 | - v2.2.0
33 | - stringify will always emit root braces
34 | - v2.1.0
35 | - add DSF (domain specific formats), experimental
36 | - refactor, use browserify for output (see bundle)
37 | - fix emit root braces by default (was off)
38 | - v2.0.8 (not released)
39 | - v2.0.7
40 | - added stringify color option (CLI)
41 | - v2.0.6
42 | - show better messages for parsing errors on a root object without braces
43 | - include error hint when a missing closing } or ] is part of a string
44 | - v2.0.5
45 | - fix stringify for strings staring with a punctuator char
46 | - v2.0.4
47 | - move to hjson org
48 | - v2.0.3
49 | - fix stringify regression
50 | - add test
51 | - v2.0.2
52 | - remove obsoletes
53 | - v2.0.1
54 | - simpler stringify
55 | - v2.0.0
56 | - add stricter check for {}[],: at the start of a quoteless string
57 | - v1.8.4
58 | - fix multiline stringify
59 | - v1.8.3
60 | - fix stringify for key names containing comments/control characters
61 | - v1.8.2
62 | - better parse for single JSON values
63 | - v1.8.1
64 | - detect EOF when looking for a key name
65 | - v1.7.6
66 | - fix trailing whitespace in keyname
67 | - v1.7.4
68 | - fix trailing space in quoteless strings
69 | - fix default braces
70 | - v1.7.3
71 | - fix root check
72 | - better error messages
73 | - v1.7.2
74 | - fixed stringify, see hjson/hjson#29
75 | - optional root braces, see hjson/hjson#28
76 | - v1.6.3
77 | - added stringify options
78 | - v1.6.1
79 | - fixed stringify with options===null
80 | - v1.6.0
81 | - Added `rt` (roundtrip) shortcut.
82 | - v1.5.0
83 | - Added support for the simplified syntax for keys. Previously only alphanumeric keys were allowed without quotes.
84 | - Fixed multiline strings: OS/file independent (EOL is always `\n`). Also the last LF is removed.
85 | - v1.4.0
86 | - Changed the browser interface to match the node api (which didn't change).
87 | - Fixed parse for leading zeros ("00") and trailing comments.
88 | - Fixed stringify for /**/ and //
89 | - Added more test cases.
90 | - v1.3.0
91 | - Added support for the simplified syntax.
92 | - v1.2.0
93 | - Added old fashioned /**/ comments.
94 | - Fixed the missing EOL (cli only).
95 | - v1.1.0
96 | - add // support
97 | - v1.0.2
98 | - stringify bug fixes
99 | - v1.0.0
100 | - Switched to v1 for semver.
101 | - Adds editing support via the `{ keepWsc: true }` option.
102 | - Removes stringify(value, replacer, space) replacer support
103 | - You can still use this syntax but replacer will no longer be called. This was removed in favor of editing support and because replacer provided an incomplete solution.
104 |
--------------------------------------------------------------------------------
/lib/hjson-dsf.js:
--------------------------------------------------------------------------------
1 | /* Hjson https://hjson.github.io */
2 | "use strict";
3 |
4 | function loadDsf(col, type) {
5 |
6 | if (Object.prototype.toString.apply(col) !== '[object Array]') {
7 | if (col) throw new Error("dsf option must contain an array!");
8 | else return nopDsf;
9 | } else if (col.length === 0) return nopDsf;
10 |
11 | var dsf = [];
12 | function isFunction(f) { return {}.toString.call(f) === '[object Function]'; }
13 |
14 | col.forEach(function(x) {
15 | if (!x.name || !isFunction(x.parse) || !isFunction(x.stringify))
16 | throw new Error("extension does not match the DSF interface");
17 | dsf.push(function() {
18 | try {
19 | if (type == "parse") {
20 | return x.parse.apply(null, arguments);
21 | } else if (type == "stringify") {
22 | var res=x.stringify.apply(null, arguments);
23 | // check result
24 | if (res !== undefined && (typeof res !== "string" ||
25 | res.length === 0 ||
26 | res[0] === '"' ||
27 | [].some.call(res, function(c) { return isInvalidDsfChar(c); })))
28 | throw new Error("value may not be empty, start with a quote or contain a punctuator character except colon: " + res);
29 | return res;
30 | } else throw new Error("Invalid type");
31 | } catch (e) {
32 | throw new Error("DSF-"+x.name+" failed; "+e.message);
33 | }
34 | });
35 | });
36 |
37 | return runDsf.bind(null, dsf);
38 | }
39 |
40 | function runDsf(dsf, value) {
41 | if (dsf) {
42 | for (var i = 0; i < dsf.length; i++) {
43 | var res = dsf[i](value);
44 | if (res !== undefined) return res;
45 | }
46 | }
47 | }
48 |
49 | function nopDsf(/*value*/) {
50 | }
51 |
52 | function isInvalidDsfChar(c) {
53 | return c === '{' || c === '}' || c === '[' || c === ']' || c === ',';
54 | }
55 |
56 |
57 | function math(/*opt*/) {
58 | return {
59 | name: "math",
60 | parse: function (value) {
61 | switch (value) {
62 | case "+inf":
63 | case "inf":
64 | case "+Inf":
65 | case "Inf": return Infinity;
66 | case "-inf":
67 | case "-Inf": return -Infinity;
68 | case "nan":
69 | case "NaN": return NaN;
70 | }
71 | },
72 | stringify: function (value) {
73 | if (typeof value !== 'number') return;
74 | if (1 / value === -Infinity) return "-0"; // 0 === -0
75 | if (value === Infinity) return "Inf";
76 | if (value === -Infinity) return "-Inf";
77 | if (isNaN(value)) return "NaN";
78 | },
79 | };
80 | }
81 | math.description="support for Inf/inf, -Inf/-inf, Nan/naN and -0";
82 |
83 | function hex(opt) {
84 | var out=opt && opt.out;
85 | return {
86 | name: "hex",
87 | parse: function (value) {
88 | if (/^0x[0-9A-Fa-f]+$/.test(value))
89 | return parseInt(value, 16);
90 | },
91 | stringify: function (value) {
92 | if (out && Number.isInteger(value))
93 | return "0x"+value.toString(16);
94 | },
95 | };
96 | }
97 | hex.description="parse hexadecimal numbers prefixed with 0x";
98 |
99 | function date(/*opt*/) {
100 | return {
101 | name: "date",
102 | parse: function (value) {
103 | if (/^\d{4}-\d{2}-\d{2}$/.test(value) ||
104 | /^\d{4}-\d{2}-\d{2}T\d{2}\:\d{2}\:\d{2}(?:.\d+)(?:Z|[+-]\d{2}:\d{2})$/.test(value)) {
105 | var dt = Date.parse(value);
106 | if (!isNaN(dt)) return new Date(dt);
107 | }
108 | },
109 | stringify: function (value) {
110 | if (Object.prototype.toString.call(value) === '[object Date]') {
111 | var dt = value.toISOString();
112 | if (dt.indexOf("T00:00:00.000Z", dt.length - 14) !== -1) return dt.substr(0, 10);
113 | else return dt;
114 | }
115 | },
116 | };
117 | }
118 | date.description="support ISO dates";
119 |
120 | module.exports = {
121 | loadDsf: loadDsf,
122 | std: {
123 | math: math,
124 | hex: hex,
125 | date: date,
126 | },
127 | };
128 |
--------------------------------------------------------------------------------
/lib/hjson.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * Hjson v3.2.1
3 | * https://hjson.github.io
4 | *
5 | * Copyright 2014-2017 Christian Zangl, MIT license
6 | * Details and documentation:
7 | * https://github.com/hjson/hjson-js
8 | *
9 | * This code is based on the the JSON version by Douglas Crockford:
10 | * https://github.com/douglascrockford/JSON-js (json_parse.js, json2.js)
11 | */
12 |
13 | /*
14 |
15 | This file creates a Hjson object:
16 |
17 |
18 | Hjson.parse(text, options)
19 |
20 | options {
21 | keepWsc boolean, keep white space and comments. This is useful
22 | if you want to edit an hjson file and save it while
23 | preserving comments (default false)
24 |
25 | dsf array of DSF (see Hjson.dsf)
26 |
27 | legacyRoot boolean, support omitting root braces (default true)
28 | }
29 |
30 | This method parses Hjson text to produce an object or array.
31 | It can throw a SyntaxError exception.
32 |
33 |
34 | Hjson.stringify(value, options)
35 |
36 | value any JavaScript value, usually an object or array.
37 |
38 | options { all options are
39 |
40 | keepWsc boolean, keep white space. See parse.
41 |
42 | condense integer, will try to fit objects/arrays onto one line
43 | when the output is shorter than condense characters
44 | and the fragment contains no comments. Default 0 (off).
45 |
46 | bracesSameLine
47 | boolean, makes braces appear on the same line as the key
48 | name. Default false.
49 |
50 | quotes string, controls how strings are displayed.
51 | setting separator implies "strings"
52 | "min" - no quotes whenever possible (default)
53 | "keys" - use quotes around keys
54 | "strings" - use quotes around string values
55 | "all" - use quotes around keys and string values
56 |
57 | multiline string, controls how multiline strings are displayed.
58 | setting quotes implies "off"
59 | "std" - strings containing \n are shown in
60 | multiline format (default)
61 | "no-tabs" - like std but disallow tabs
62 | "off" - show in JSON format
63 |
64 | separator boolean, output a comma separator between elements. Default false.
65 |
66 | space specifies the indentation of nested structures. If it is
67 | a number, it will specify the number of spaces to indent
68 | at each level. If it is a string (such as '\t' or ' '),
69 | it contains the characters used to indent at each level.
70 |
71 | eol specifies the EOL sequence (default is set by
72 | Hjson.setEndOfLine())
73 |
74 | colors boolean, output ascii color codes
75 |
76 | dsf array of DSF (see Hjson.dsf)
77 |
78 | emitRootBraces
79 | obsolete: will always emit braces
80 |
81 | sortProps
82 | When serializing objects into hjson, order the keys based on
83 | their UTF-16 code units order
84 | }
85 |
86 | This method produces Hjson text from a JavaScript value.
87 |
88 | Values that do not have JSON representations, such as undefined or
89 | functions, will not be serialized. Such values in objects will be
90 | dropped; in arrays they will be replaced with null.
91 | stringify(undefined) returns undefined.
92 |
93 |
94 | Hjson.endOfLine()
95 | Hjson.setEndOfLine(eol)
96 |
97 | Gets or sets the stringify EOL sequence ('\n' or '\r\n').
98 | When running with node.js this defaults to os.EOL.
99 |
100 |
101 | Hjson.rt { parse, stringify }
102 |
103 | This is a shortcut to roundtrip your comments when reading and updating
104 | a config file. It is the same as specifying the keepWsc option for the
105 | parse and stringify functions.
106 |
107 |
108 | Hjson.version
109 |
110 | The version of this library.
111 |
112 |
113 | Hjson.dsf
114 |
115 | Domain specific formats are extensions to the Hjson syntax (see
116 | hjson.github.io). These formats will be parsed and made available to
117 | the application in place of strings (e.g. enable math to allow
118 | NaN values).
119 |
120 | Hjson.dsf ontains standard DSFs that can be passed to parse
121 | and stringify.
122 |
123 |
124 | Hjson.dsf.math()
125 |
126 | Enables support for Inf/inf, -Inf/-inf, Nan/naN and -0.
127 | Will output as Inf, -Inf, NaN and -0.
128 |
129 |
130 | Hjson.dsf.hex(options)
131 |
132 | Parse hexadecimal numbers prefixed with 0x.
133 | set options.out = true to stringify _all_ integers as hex.
134 |
135 |
136 | Hjson.dsf.date(options)
137 |
138 | support ISO dates
139 |
140 |
141 | This is a reference implementation. You are free to copy, modify, or
142 | redistribute.
143 |
144 | */
145 |
146 | "use strict";
147 |
148 | var common = require("./hjson-common");
149 | var version = require("./hjson-version");
150 | var parse = require("./hjson-parse");
151 | var stringify = require("./hjson-stringify");
152 | var comments = require("./hjson-comments");
153 | var dsf = require("./hjson-dsf");
154 |
155 | module.exports={
156 |
157 | parse: parse,
158 | stringify: stringify,
159 |
160 | endOfLine: function() { return common.EOL; },
161 | setEndOfLine: function(eol) {
162 | if (eol === '\n' || eol === '\r\n') common.EOL = eol;
163 | },
164 |
165 | version: version,
166 |
167 | // round trip shortcut
168 | rt: {
169 | parse: function(text, options) {
170 | (options=options||{}).keepWsc=true;
171 | return parse(text, options);
172 | },
173 | stringify: function(value, options) {
174 | (options=options||{}).keepWsc=true;
175 | return stringify(value, options);
176 | },
177 | },
178 |
179 | comments: comments,
180 |
181 | dsf: dsf.std,
182 |
183 | };
184 |
--------------------------------------------------------------------------------
/lib/hjson-comments.js:
--------------------------------------------------------------------------------
1 | /* Hjson https://hjson.github.io */
2 | "use strict";
3 |
4 | var common=require("./hjson-common");
5 |
6 | function makeComment(b, a, x) {
7 | var c;
8 | if (b) c={ b: b };
9 | if (a) (c=c||{}).a=a;
10 | if (x) (c=c||{}).x=x;
11 | return c;
12 | }
13 |
14 | function extractComments(value, root) {
15 |
16 | if (value===null || typeof value!=='object') return;
17 | var comments=common.getComment(value);
18 | if (comments) common.removeComment(value);
19 |
20 | var i, length; // loop
21 | var any, res;
22 | if (Object.prototype.toString.apply(value) === '[object Array]') {
23 | res={ a: {} };
24 | for (i=0, length=value.length; i0) {
82 | var text=rootComment(value, null, 1);
83 | text+="\n# Orphaned comments:\n";
84 | dropped.forEach(function(c) {
85 | text+=("# "+c.path.join('/')+": "+mergeStr(c.b, c.a, c.e)).replace("\n", "\\n ")+"\n";
86 | });
87 | rootComment(value, text, 1);
88 | }
89 | }
90 |
91 | function saveComment(res, key, item, col) {
92 | var c=makeComment(item?item[0]:undefined, item?item[1]:undefined, col);
93 | if (c) res[key]=c;
94 | return c;
95 | }
96 |
97 | function droppedComment(path, c) {
98 | var res=makeComment(c.b, c.a);
99 | res.path=path;
100 | return res;
101 | }
102 |
103 | function dropAll(comments, dropped, path) {
104 |
105 | if (!comments) return;
106 |
107 | var i, length; // loop
108 |
109 | if (comments.a) {
110 |
111 | for (i=0, length=comments.a.length; i test.json` to convert to JSON
88 | - run `hjson test.json > test.hjson` to convert to Hjson
89 | - run `hjson test.json` to view colorized output
90 |
91 |
92 | # API
93 |
94 | The API is the same for the browser and node.js version.
95 |
96 | **NOTE that the DSF api is considered experimental**
97 |
98 | ### Hjson.parse(text, options)
99 |
100 | This method parses *JSON* or *Hjson* text to produce an object or array.
101 |
102 | - *text*: the string to parse as JSON or Hjson
103 | - *options*: object
104 | - *keepWsc*: boolean, keep white space and comments. This is useful if you want to edit an hjson file and save it while preserving comments (default false)
105 |
106 | ### Hjson.stringify(value, options)
107 |
108 | This method produces Hjson text from a JavaScript value.
109 |
110 | - *value*: any JavaScript value, usually an object or array.
111 | - *options*: object
112 | - *keepWsc*: boolean, keep white space. See parse.
113 | - *condense*: integer, will try to fit objects/arrays onto one line. Default 0 (off).
114 | - *bracesSameLine*: boolean, makes braces appear on the same line as the key name. Default false.
115 | - *emitRootBraces*: boolean, show braces for the root object. Default true.
116 | - *quotes*: string, controls how strings are displayed. (setting separator implies "strings")
117 | - "min": no quotes whenever possible (default)
118 | - "keys": use quotes around keys
119 | - "strings": use quotes around string values
120 | - "all": use quotes around keys and string values
121 | - *multiline*: string, controls how multiline strings are displayed. (setting quotes implies "off")
122 | - "std": strings containing \n are shown in multiline format (default)
123 | - "no-tabs": like std but disallow tabs
124 | - "off": show in JSON format
125 | - *separator*: boolean, output a comma separator between elements. Default false
126 | - *space*: specifies the indentation of nested structures. If it is a number, it will specify the number of spaces to indent at each level. If it is a string (such as '\t' or ' '), it contains the characters used to indent at each level.
127 | - *eol*: specifies the EOL sequence (default is set by Hjson.setEndOfLine())
128 | - *colors*: boolean, output ascii color codes
129 | - *sortProps*: boolean, when serializing objects into hjson, order the keys based on their UTF-16 code units order. Default false.
130 |
131 | ### Hjson.endOfLine(), .setEndOfLine(eol)
132 |
133 | Gets or sets the stringify EOL sequence ('\n' or '\r\n'). When running with node.js this defaults to os.EOL.
134 |
135 | ### Hjson.rt { parse, stringify }
136 |
137 | This is a shortcut to roundtrip your comments when reading and updating a config file. It is the same as specifying the keepWsc option for the parse and stringify functions.
138 |
139 | ### Hjson.version
140 |
141 | The version number.
142 |
143 | ### require-hook
144 |
145 | Require a config file directly.
146 |
147 | ```
148 | require("hjson/lib/require-config");
149 | var cfg=require("./config.hjson");
150 | ```
151 |
152 | ## modify & keep comments
153 |
154 | You can modify a Hjson file and keep the whitespace & comments intact (round trip). This is useful if an app updates its config file.
155 |
156 | ```
157 | // parse, keep whitespace and comments
158 | // (they are stored in a non enumerable __COMMENTS__ member)
159 | var data = Hjson.rt.parse(text);
160 |
161 | // modify like you normally would
162 | data.foo = "text";
163 |
164 | // convert back to Hjson
165 | console.log(Hjson.rt.stringify(data));
166 | ```
167 | # Build
168 |
169 | To run all tests and create the bundle output, first install the dev dependencies with `npm i` and then run `npm run build`.
170 |
171 | # History
172 |
173 | [see history.md](history.md)
174 |
175 |
--------------------------------------------------------------------------------
/lib/hjson-parse.js:
--------------------------------------------------------------------------------
1 | /* Hjson https://hjson.github.io */
2 | "use strict";
3 |
4 | module.exports = function(source, opt) {
5 |
6 | var common = require("./hjson-common");
7 | var dsf = require("./hjson-dsf");
8 |
9 | var text;
10 | var at; // The index of the current character
11 | var ch; // The current character
12 | var escapee = {
13 | '"': '"',
14 | "'": "'",
15 | '\\': '\\',
16 | '/': '/',
17 | b: '\b',
18 | f: '\f',
19 | n: '\n',
20 | r: '\r',
21 | t: '\t'
22 | };
23 |
24 | var keepComments;
25 | var runDsf; // domain specific formats
26 |
27 | function resetAt() {
28 | at = 0;
29 | ch = ' ';
30 | }
31 |
32 | function isPunctuatorChar(c) {
33 | return c === '{' || c === '}' || c === '[' || c === ']' || c === ',' || c === ':';
34 | }
35 |
36 | // Call error when something is wrong.
37 | function error(m) {
38 | var i, col=0, line=1;
39 | for (i = at-1; i > 0 && text[i] !== '\n'; i--, col++) {}
40 | for (; i > 0; i--) if (text[i] === '\n') line++;
41 | throw new Error(m + " at line " + line + "," + col + " >>>" + text.substr(at-col, 20) + " ...");
42 | }
43 |
44 | function next() {
45 | // get the next character.
46 | ch = text.charAt(at);
47 | at++;
48 | return ch;
49 | }
50 |
51 | function peek(offs) {
52 | // range check is not required
53 | return text.charAt(at + offs);
54 | }
55 |
56 | function string(allowML) {
57 | // Parse a string value.
58 | // callers make sure that (ch === '"' || ch === "'")
59 | var string = '';
60 |
61 | // When parsing for string values, we must look for "/' and \ characters.
62 | var exitCh = ch;
63 | while (next()) {
64 | if (ch === exitCh) {
65 | next();
66 | if (allowML && exitCh === "'" && ch === "'" && string.length === 0) {
67 | // ''' indicates a multiline string
68 | next();
69 | return mlString();
70 | } else return string;
71 | }
72 | if (ch === '\\') {
73 | next();
74 | if (ch === 'u') {
75 | var uffff = 0;
76 | for (var i = 0; i < 4; i++) {
77 | next();
78 | var c = ch.charCodeAt(0), hex;
79 | if (ch >= '0' && ch <= '9') hex = c - 48;
80 | else if (ch >= 'a' && ch <= 'f') hex = c - 97 + 0xa;
81 | else if (ch >= 'A' && ch <= 'F') hex = c - 65 + 0xa;
82 | else error("Bad \\u char " + ch);
83 | uffff = uffff * 16 + hex;
84 | }
85 | string += String.fromCharCode(uffff);
86 | } else if (typeof escapee[ch] === 'string') {
87 | string += escapee[ch];
88 | } else break;
89 | } else if (ch === '\n' || ch === '\r') {
90 | error("Bad string containing newline");
91 | } else {
92 | string += ch;
93 | }
94 | }
95 | error("Bad string");
96 | }
97 |
98 | function mlString() {
99 | // Parse a multiline string value.
100 | var string = '', triple = 0;
101 |
102 | // we are at ''' +1 - get indent
103 | var indent = 0;
104 | for (;;) {
105 | var c=peek(-indent-5);
106 | if (!c || c === '\n') break;
107 | indent++;
108 | }
109 |
110 | function skipIndent() {
111 | var skip = indent;
112 | while (ch && ch <= ' ' && ch !== '\n' && skip-- > 0) next();
113 | }
114 |
115 | // skip white/to (newline)
116 | while (ch && ch <= ' ' && ch !== '\n') next();
117 | if (ch === '\n') { next(); skipIndent(); }
118 |
119 | // When parsing multiline string values, we must look for ' characters.
120 | for (;;) {
121 | if (!ch) {
122 | error("Bad multiline string");
123 | } else if (ch === '\'') {
124 | triple++;
125 | next();
126 | if (triple === 3) {
127 | if (string.slice(-1) === '\n') string=string.slice(0, -1); // remove last EOL
128 | return string;
129 | } else continue;
130 | } else {
131 | while (triple > 0) {
132 | string += '\'';
133 | triple--;
134 | }
135 | }
136 | if (ch === '\n') {
137 | string += '\n';
138 | next();
139 | skipIndent();
140 | } else {
141 | if (ch !== '\r') string += ch;
142 | next();
143 | }
144 | }
145 | }
146 |
147 | function keyname() {
148 | // quotes for keys are optional in Hjson
149 | // unless they include {}[],: or whitespace.
150 |
151 | if (ch === '"' || ch === "'") return string(false);
152 |
153 | var name = "", start = at, space = -1;
154 | for (;;) {
155 | if (ch === ':') {
156 | if (!name) error("Found ':' but no key name (for an empty key name use quotes)");
157 | else if (space >=0 && space !== name.length) { at = start + space; error("Found whitespace in your key name (use quotes to include)"); }
158 | return name;
159 | } else if (ch <= ' ') {
160 | if (!ch) error("Found EOF while looking for a key name (check your syntax)");
161 | else if (space < 0) space = name.length;
162 | } else if (isPunctuatorChar(ch)) {
163 | error("Found '" + ch + "' where a key name was expected (check your syntax or use quotes if the key name includes {}[],: or whitespace)");
164 | } else {
165 | name += ch;
166 | }
167 | next();
168 | }
169 | }
170 |
171 | function white() {
172 | while (ch) {
173 | // Skip whitespace.
174 | while (ch && ch <= ' ') next();
175 | // Hjson allows comments
176 | if (ch === '#' || ch === '/' && peek(0) === '/') {
177 | while (ch && ch !== '\n') next();
178 | } else if (ch === '/' && peek(0) === '*') {
179 | next(); next();
180 | while (ch && !(ch === '*' && peek(0) === '/')) next();
181 | if (ch) { next(); next(); }
182 | } else break;
183 | }
184 | }
185 |
186 | function tfnns() {
187 | // Hjson strings can be quoteless
188 | // returns string, true, false, or null.
189 | var value = ch;
190 | if (isPunctuatorChar(ch))
191 | error("Found a punctuator character '" + ch + "' when expecting a quoteless string (check your syntax)");
192 |
193 | for(;;) {
194 | next();
195 | // (detection of ml strings was moved to string())
196 | var isEol = ch === '\r' || ch === '\n' || ch === '';
197 | if (isEol ||
198 | ch === ',' || ch === '}' || ch === ']' ||
199 | ch === '#' ||
200 | ch === '/' && (peek(0) === '/' || peek(0) === '*')
201 | ) {
202 | // this tests for the case of {true|false|null|num}
203 | // followed by { ',' | '}' | ']' | '#' | '//' | '/*' }
204 | // which needs to be parsed as the specified value
205 | var chf = value[0];
206 | switch (chf) {
207 | case 'f': if (value.trim() === "false") return false; break;
208 | case 'n': if (value.trim() === "null") return null; break;
209 | case 't': if (value.trim() === "true") return true; break;
210 | default:
211 | if (chf === '-' || chf >= '0' && chf <= '9') {
212 | var n = common.tryParseNumber(value);
213 | if (n !== undefined) return n;
214 | }
215 | }
216 | if (isEol) {
217 | // remove any whitespace at the end (ignored in quoteless strings)
218 | value = value.trim();
219 | var dsfValue = runDsf(value);
220 | return dsfValue !== undefined ? dsfValue : value;
221 | }
222 | }
223 | value += ch;
224 | }
225 | }
226 |
227 | function getComment(cAt, first) {
228 | var i;
229 | cAt--;
230 | // remove trailing whitespace
231 | // but only up to EOL
232 | for (i = at - 2; i > cAt && text[i] <= ' ' && text[i] !== '\n'; i--);
233 | if (text[i] === '\n') i--;
234 | if (text[i] === '\r') i--;
235 | var res = text.substr(cAt, i-cAt+1);
236 | // return if we find anything other than whitespace
237 | for (i = 0; i < res.length; i++) {
238 | if (res[i] > ' ') {
239 | var j = res.indexOf('\n');
240 | if (j >= 0) {
241 | var c = [res.substr(0, j), res.substr(j+1)];
242 | if (first && c[0].trim().length === 0) c.shift();
243 | return c;
244 | } else return [res];
245 | }
246 | }
247 | return [];
248 | }
249 |
250 | function errorClosingHint(value) {
251 | function search(value, ch) {
252 | var i, k, length, res;
253 | switch (typeof value) {
254 | case 'string':
255 | if (value.indexOf(ch) >= 0) res = value;
256 | break;
257 | case 'object':
258 | if (Object.prototype.toString.apply(value) === '[object Array]') {
259 | for (i = 0, length = value.length; i < length; i++) {
260 | res=search(value[i], ch) || res;
261 | }
262 | } else {
263 | for (k in value) {
264 | if (!Object.prototype.hasOwnProperty.call(value, k)) continue;
265 | res=search(value[k], ch) || res;
266 | }
267 | }
268 | }
269 | return res;
270 | }
271 |
272 | function report(ch) {
273 | var possibleErr=search(value, ch);
274 | if (possibleErr) {
275 | return "found '"+ch+"' in a string value, your mistake could be with:\n"+
276 | " > "+possibleErr+"\n"+
277 | " (unquoted strings contain everything up to the next line!)";
278 | } else return "";
279 | }
280 |
281 | return report('}') || report(']');
282 | }
283 |
284 | function array() {
285 | // Parse an array value.
286 | // assuming ch === '['
287 |
288 | var array = [];
289 | var comments, cAt, nextComment;
290 | try {
291 | if (keepComments) comments = common.createComment(array, { a: [] });
292 |
293 | next();
294 | cAt = at;
295 | white();
296 | if (comments) nextComment = getComment(cAt, true).join('\n');
297 | if (ch === ']') {
298 | next();
299 | if (comments) comments.e = [nextComment];
300 | return array; // empty array
301 | }
302 |
303 | while (ch) {
304 | array.push(value());
305 | cAt = at;
306 | white();
307 | // in Hjson the comma is optional and trailing commas are allowed
308 | // note that we do not keep comments before the , if there are any
309 | if (ch === ',') { next(); cAt = at; white(); }
310 | if (comments) {
311 | var c = getComment(cAt);
312 | comments.a.push([nextComment||"", c[0]||""]);
313 | nextComment = c[1];
314 | }
315 | if (ch === ']') {
316 | next();
317 | if (comments) comments.a[comments.a.length-1][1] += nextComment||"";
318 | return array;
319 | }
320 | white();
321 | }
322 |
323 | error("End of input while parsing an array (missing ']')");
324 | } catch (e) {
325 | e.hint=e.hint||errorClosingHint(array);
326 | throw e;
327 | }
328 | }
329 |
330 | function object(withoutBraces) {
331 | // Parse an object value.
332 |
333 | var key = "", object = {};
334 | var comments, cAt, nextComment;
335 |
336 | try {
337 | if (keepComments) comments = common.createComment(object, { c: {}, o: [] });
338 |
339 | if (!withoutBraces) {
340 | // assuming ch === '{'
341 | next();
342 | cAt = at;
343 | } else cAt = 1;
344 |
345 | white();
346 | if (comments) nextComment = getComment(cAt, true).join('\n');
347 | if (ch === '}' && !withoutBraces) {
348 | if (comments) comments.e = [nextComment];
349 | next();
350 | return object; // empty object
351 | }
352 | while (ch) {
353 | key = keyname();
354 | white();
355 | if (ch !== ':') error("Expected ':' instead of '" + ch + "'");
356 | next();
357 | // duplicate keys overwrite the previous value
358 | object[key] = value();
359 | cAt = at;
360 | white();
361 | // in Hjson the comma is optional and trailing commas are allowed
362 | // note that we do not keep comments before the , if there are any
363 | if (ch === ',') { next(); cAt = at; white(); }
364 | if (comments) {
365 | var c = getComment(cAt);
366 | comments.c[key] = [nextComment||"", c[0]||""];
367 | nextComment = c[1];
368 | comments.o.push(key);
369 | }
370 | if (ch === '}' && !withoutBraces) {
371 | next();
372 | if (comments) comments.c[key][1] += nextComment||"";
373 | return object;
374 | }
375 | white();
376 | }
377 |
378 | if (withoutBraces) return object;
379 | else error("End of input while parsing an object (missing '}')");
380 | } catch (e) {
381 | e.hint=e.hint||errorClosingHint(object);
382 | throw e;
383 | }
384 | }
385 |
386 | function value() {
387 | // Parse a Hjson value. It could be an object, an array, a string, a number or a word.
388 |
389 | white();
390 | switch (ch) {
391 | case '{': return object();
392 | case '[': return array();
393 | case "'":
394 | case '"': return string(true);
395 | default: return tfnns();
396 | }
397 | }
398 |
399 | function checkTrailing(v, c) {
400 | var cAt = at;
401 | white();
402 | if (ch) error("Syntax error, found trailing characters");
403 | if (keepComments) {
404 | var b = c.join('\n'), a = getComment(cAt).join('\n');
405 | if (a || b) {
406 | var comments = common.createComment(v, common.getComment(v));
407 | comments.r = [b, a];
408 | }
409 | }
410 | return v;
411 | }
412 |
413 | function rootValue() {
414 | white();
415 | var c = keepComments ? getComment(1) : null;
416 | switch (ch) {
417 | case '{': return checkTrailing(object(), c);
418 | case '[': return checkTrailing(array(), c);
419 | default: return checkTrailing(value(), c);
420 | }
421 | }
422 |
423 | function legacyRootValue() {
424 | // Braces for the root object are optional
425 | white();
426 | var c = keepComments ? getComment(1) : null;
427 | switch (ch) {
428 | case '{': return checkTrailing(object(), c);
429 | case '[': return checkTrailing(array(), c);
430 | }
431 |
432 | try {
433 | // assume we have a root object without braces
434 | return checkTrailing(object(true), c);
435 | } catch (e) {
436 | // test if we are dealing with a single JSON value instead (true/false/null/num/"")
437 | resetAt();
438 | try { return checkTrailing(value(), c); }
439 | catch (e2) { throw e; } // throw original error
440 | }
441 | }
442 |
443 | if (typeof source!=="string") throw new Error("source is not a string");
444 | var dsfDef = null;
445 | var legacyRoot = true;
446 | if (opt && typeof opt === 'object') {
447 | keepComments = opt.keepWsc;
448 | dsfDef = opt.dsf;
449 | legacyRoot = opt.legacyRoot !== false; // default true
450 | }
451 | runDsf = dsf.loadDsf(dsfDef, "parse");
452 | text = source;
453 | resetAt();
454 | return legacyRoot ? legacyRootValue() : rootValue();
455 | };
456 |
--------------------------------------------------------------------------------
/lib/hjson-stringify.js:
--------------------------------------------------------------------------------
1 | /* Hjson https://hjson.github.io */
2 | "use strict";
3 |
4 | module.exports = function(data, opt) {
5 |
6 | var common = require("./hjson-common");
7 | var dsf = require("./hjson-dsf");
8 |
9 | var plainToken = {
10 | obj: [ '{', '}' ],
11 | arr: [ '[', ']' ],
12 | key: [ '', '' ],
13 | qkey: [ '"', '"' ],
14 | col: [ ':', '' ],
15 | com: [ ',', '' ],
16 | str: [ '', '' ],
17 | qstr: [ '"', '"' ],
18 | mstr: [ "'''", "'''" ],
19 | num: [ '', '' ],
20 | lit: [ '', '' ],
21 | dsf: [ '', '' ],
22 | esc: [ '\\', '' ],
23 | uni: [ '\\u', '' ],
24 | rem: [ '', '' ],
25 | };
26 |
27 | // options
28 | var eol = common.EOL;
29 | var indent = ' ';
30 | var keepComments = false;
31 | var bracesSameLine = false;
32 | var quoteKeys = false;
33 | var quoteStrings = false;
34 | var condense = 0;
35 | var multiline = 1; // std=1, no-tabs=2, off=0
36 | var separator = ''; // comma separator
37 | var dsfDef = null;
38 | var sortProps = false;
39 | var token = plainToken;
40 |
41 | if (opt && typeof opt === 'object') {
42 | opt.quotes = opt.quotes === 'always' ? 'strings' : opt.quotes; // legacy
43 |
44 | if (opt.eol === '\n' || opt.eol === '\r\n') eol = opt.eol;
45 | keepComments = opt.keepWsc;
46 | condense = opt.condense || 0;
47 | bracesSameLine = opt.bracesSameLine;
48 | quoteKeys = opt.quotes === 'all' || opt.quotes === 'keys';
49 | quoteStrings = opt.quotes === 'all' || opt.quotes === 'strings' || opt.separator === true;
50 | if (quoteStrings || opt.multiline == 'off') multiline = 0;
51 | else multiline = opt.multiline == 'no-tabs' ? 2 : 1;
52 | separator = opt.separator === true ? token.com[0] : '';
53 | dsfDef = opt.dsf;
54 | sortProps = opt.sortProps;
55 |
56 | // If the space parameter is a number, make an indent string containing that
57 | // many spaces. If it is a string, it will be used as the indent string.
58 |
59 | if (typeof opt.space === 'number') {
60 | indent = new Array(opt.space + 1).join(' ');
61 | } else if (typeof opt.space === 'string') {
62 | indent = opt.space;
63 | }
64 |
65 | if (opt.colors === true) {
66 | token = {
67 | obj: [ '\x1b[37m{\x1b[0m', '\x1b[37m}\x1b[0m' ],
68 | arr: [ '\x1b[37m[\x1b[0m', '\x1b[37m]\x1b[0m' ],
69 | key: [ '\x1b[33m', '\x1b[0m' ],
70 | qkey: [ '\x1b[33m"', '"\x1b[0m' ],
71 | col: [ '\x1b[37m:\x1b[0m', '' ],
72 | com: [ '\x1b[37m,\x1b[0m', '' ],
73 | str: [ '\x1b[37;1m', '\x1b[0m' ],
74 | qstr: [ '\x1b[37;1m"', '"\x1b[0m' ],
75 | mstr: [ "\x1b[37;1m'''", "'''\x1b[0m" ],
76 | num: [ '\x1b[36;1m', '\x1b[0m' ],
77 | lit: [ '\x1b[36m', '\x1b[0m' ],
78 | dsf: [ '\x1b[37m', '\x1b[0m' ],
79 | esc: [ '\x1b[31m\\', '\x1b[0m' ],
80 | uni: [ '\x1b[31m\\u', '\x1b[0m' ],
81 | rem: [ '\x1b[35m', '\x1b[0m' ],
82 | };
83 | }
84 |
85 | var i, ckeys=Object.keys(plainToken);
86 | for (i = ckeys.length - 1; i >= 0; i--) {
87 | var k = ckeys[i];
88 | token[k].push(plainToken[k][0].length, plainToken[k][1].length);
89 | }
90 | }
91 |
92 | //
93 | var runDsf; // domain specific formats
94 |
95 | var commonRange='\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff';
96 | // needsEscape tests if the string can be written without escapes
97 | var needsEscape = new RegExp('[\\\\\\"\x00-\x1f'+commonRange+']', 'g');
98 | // needsQuotes tests if the string can be written as a quoteless string (like needsEscape but without \\ and \")
99 | var needsQuotes = new RegExp('^\\s|^"|^\'|^#|^\\/\\*|^\\/\\/|^\\{|^\\}|^\\[|^\\]|^:|^,|\\s$|[\x00-\x1f'+commonRange+']', 'g');
100 | // needsEscapeML tests if the string can be written as a multiline string (like needsEscape but without \n, \r, \\, \", \t unless multines is 'std')
101 | var needsEscapeML = new RegExp('\'\'\'|^[\\s]+$|[\x00-'+(multiline === 2 ? '\x09' : '\x08')+'\x0b\x0c\x0e-\x1f'+commonRange+']', 'g');
102 | // starts with a keyword and optionally is followed by a comment
103 | var startsWithKeyword = new RegExp('^(true|false|null)\\s*((,|\\]|\\}|#|//|/\\*).*)?$');
104 | var meta = {
105 | // table of character substitutions
106 | '\b': 'b',
107 | '\t': 't',
108 | '\n': 'n',
109 | '\f': 'f',
110 | '\r': 'r',
111 | '"' : '"',
112 | '\\': '\\'
113 | };
114 | var needsEscapeName = /[,\{\[\}\]\s:#"']|\/\/|\/\*/;
115 | var gap = '';
116 | //
117 | var wrapLen = 0;
118 |
119 | function wrap(tk, v) {
120 | wrapLen += tk[0].length + tk[1].length - tk[2] - tk[3];
121 | return tk[0] + v + tk[1];
122 | }
123 |
124 | function quoteReplace(string) {
125 | return string.replace(needsEscape, function (a) {
126 | var c = meta[a];
127 | if (typeof c === 'string') return wrap(token.esc, c);
128 | else return wrap(token.uni, ('0000' + a.charCodeAt(0).toString(16)).slice(-4));
129 | });
130 | }
131 |
132 | function quote(string, gap, hasComment, isRootObject) {
133 | if (!string) return wrap(token.qstr, '');
134 |
135 | needsQuotes.lastIndex = 0;
136 | startsWithKeyword.lastIndex = 0;
137 |
138 | // Check if we can insert this string without quotes
139 | // see hjson syntax (must not parse as true, false, null or number)
140 |
141 | if (quoteStrings || hasComment ||
142 | needsQuotes.test(string) ||
143 | common.tryParseNumber(string, true) !== undefined ||
144 | startsWithKeyword.test(string)) {
145 |
146 | // If the string contains no control characters, no quote characters, and no
147 | // backslash characters, then we can safely slap some quotes around it.
148 | // Otherwise we first check if the string can be expressed in multiline
149 | // format or we must replace the offending characters with safe escape
150 | // sequences.
151 |
152 | needsEscape.lastIndex = 0;
153 | needsEscapeML.lastIndex = 0;
154 | if (!needsEscape.test(string)) return wrap(token.qstr, string);
155 | else if (!needsEscapeML.test(string) && !isRootObject && multiline) return mlString(string, gap);
156 | else return wrap(token.qstr, quoteReplace(string));
157 | } else {
158 | // return without quotes
159 | return wrap(token.str, string);
160 | }
161 | }
162 |
163 | function mlString(string, gap) {
164 | // wrap the string into the ''' (multiline) format
165 |
166 | var i, a = string.replace(/\r/g, "").split('\n');
167 | gap += indent;
168 |
169 | if (a.length === 1) {
170 | // The string contains only a single line. We still use the multiline
171 | // format as it avoids escaping the \ character (e.g. when used in a
172 | // regex).
173 | return wrap(token.mstr, a[0]);
174 | } else {
175 | var res = eol + gap + token.mstr[0];
176 | for (i = 0; i < a.length; i++) {
177 | res += eol;
178 | if (a[i]) res += gap + a[i];
179 | }
180 | return res + eol + gap + token.mstr[1];
181 | }
182 | }
183 |
184 | function quoteKey(name) {
185 | if (!name) return '""';
186 |
187 | // Check if we can insert this key without quotes
188 |
189 | if (quoteKeys || needsEscapeName.test(name)) {
190 | needsEscape.lastIndex = 0;
191 | return wrap(token.qkey, needsEscape.test(name) ? quoteReplace(name) : name);
192 | } else {
193 | // return without quotes
194 | return wrap(token.key, name);
195 | }
196 | }
197 |
198 | function str(value, hasComment, noIndent, isRootObject) {
199 | // Produce a string from value.
200 |
201 | function startsWithNL(str) { return str && str[str[0] === '\r' ? 1 : 0] === '\n'; }
202 | function commentOnThisLine(str) { return str && !startsWithNL(str); }
203 | function makeComment(str, prefix, trim) {
204 | if (!str) return "";
205 | str = common.forceComment(str);
206 | var i, len = str.length;
207 | for (i = 0; i < len && str[i] <= ' '; i++) {}
208 | if (trim && i > 0) str = str.substr(i);
209 | if (i < len) return prefix + wrap(token.rem, str);
210 | else return str;
211 | }
212 |
213 | // What happens next depends on the value's type.
214 |
215 | // check for DSF
216 | var dsfValue = runDsf(value);
217 | if (dsfValue !== undefined) return wrap(token.dsf, dsfValue);
218 |
219 | switch (typeof value) {
220 | case 'string':
221 | return quote(value, gap, hasComment, isRootObject);
222 |
223 | case 'number':
224 | // JSON numbers must be finite. Encode non-finite numbers as null.
225 | return isFinite(value) ? wrap(token.num, String(value)) : wrap(token.lit, 'null');
226 |
227 | case 'boolean':
228 | return wrap(token.lit, String(value));
229 |
230 | case 'object':
231 | // If the type is 'object', we might be dealing with an object or an array or
232 | // null.
233 |
234 | // Due to a specification blunder in ECMAScript, typeof null is 'object',
235 | // so watch out for that case.
236 |
237 | if (!value) return wrap(token.lit, 'null');
238 |
239 | var comments; // whitespace & comments
240 | if (keepComments) comments = common.getComment(value);
241 |
242 | var isArray = Object.prototype.toString.apply(value) === '[object Array]';
243 |
244 | // Make an array to hold the partial results of stringifying this object value.
245 | var mind = gap;
246 | gap += indent;
247 | var eolMind = eol + mind;
248 | var eolGap = eol + gap;
249 | var prefix = noIndent || bracesSameLine ? '' : eolMind;
250 | var partial = [];
251 | var setsep;
252 | // condense helpers:
253 | var cpartial = condense ? [] : null;
254 | var saveQuoteStrings = quoteStrings, saveMultiline = multiline;
255 | var iseparator = separator ? '' : token.com[0];
256 | var cwrapLen = 0;
257 |
258 | var i, length; // loop
259 | var k, v, vs; // key, value
260 | var c, ca;
261 | var res, cres;
262 |
263 | if (isArray) {
264 | // The value is an array. Stringify every element. Use null as a placeholder
265 | // for non-JSON values.
266 |
267 | for (i = 0, length = value.length; i < length; i++) {
268 | setsep = i < length -1;
269 | if (comments) {
270 | c = comments.a[i]||[];
271 | ca = commentOnThisLine(c[1]);
272 | partial.push(makeComment(c[0], "\n") + eolGap);
273 | if (cpartial && (c[0] || c[1] || ca)) cpartial = null;
274 | }
275 | else partial.push(eolGap);
276 | wrapLen = 0;
277 | v = value[i];
278 | partial.push(str(v, comments ? ca : false, true) + (setsep ? separator : ''));
279 | if (cpartial) {
280 | // prepare the condensed version
281 | switch (typeof v) {
282 | case 'string':
283 | wrapLen = 0;
284 | quoteStrings = true; multiline = 0;
285 | cpartial.push(str(v, false, true) + (setsep ? token.com[0] : ''));
286 | quoteStrings = saveQuoteStrings; multiline = saveMultiline;
287 | break;
288 | case 'object': if (v) { cpartial = null; break; } // falls through
289 | default: cpartial.push(partial[partial.length - 1] + (setsep ? iseparator : '')); break;
290 | }
291 | if (setsep) wrapLen += token.com[0].length - token.com[2];
292 | cwrapLen += wrapLen;
293 | }
294 | if (comments && c[1]) partial.push(makeComment(c[1], ca ? " " : "\n", ca));
295 | }
296 |
297 | if (length === 0) {
298 | // when empty
299 | if (comments && comments.e) partial.push(makeComment(comments.e[0], "\n") + eolMind);
300 | }
301 | else partial.push(eolMind);
302 |
303 | // Join all of the elements together, separated with newline, and wrap them in
304 | // brackets.
305 |
306 | if (partial.length === 0) res = wrap(token.arr, '');
307 | else {
308 | res = prefix + wrap(token.arr, partial.join(''));
309 | // try if the condensed version can fit (parent key name is not included)
310 | if (cpartial) {
311 | cres = cpartial.join(' ');
312 | if (cres.length - cwrapLen <= condense) res = wrap(token.arr, cres);
313 | }
314 | }
315 | } else {
316 | // Otherwise, iterate through all of the keys in the object.
317 | var commentKeys = comments ? comments.o.slice() : [];
318 | var objectKeys = [];
319 | for (k in value) {
320 | if (Object.prototype.hasOwnProperty.call(value, k) && commentKeys.indexOf(k) < 0)
321 | objectKeys.push(k);
322 | }
323 | if(sortProps) {
324 | objectKeys.sort();
325 | }
326 | var keys = commentKeys.concat(objectKeys);
327 |
328 | for (i = 0, length = keys.length; i < length; i++) {
329 | setsep = i < length - 1;
330 | k = keys[i];
331 | if (comments) {
332 | c = comments.c[k]||[];
333 | ca = commentOnThisLine(c[1]);
334 | partial.push(makeComment(c[0], "\n") + eolGap);
335 | if (cpartial && (c[0] || c[1] || ca)) cpartial = null;
336 | }
337 | else partial.push(eolGap);
338 |
339 | wrapLen = 0;
340 | v = value[k];
341 | vs = str(v, comments && ca);
342 | partial.push(quoteKey(k) + token.col[0] + (startsWithNL(vs) ? '' : ' ') + vs + (setsep ? separator : ''));
343 | if (comments && c[1]) partial.push(makeComment(c[1], ca ? " " : "\n", ca));
344 | if (cpartial) {
345 | // prepare the condensed version
346 | switch (typeof v) {
347 | case 'string':
348 | wrapLen = 0;
349 | quoteStrings = true; multiline = 0;
350 | vs = str(v, false);
351 | quoteStrings = saveQuoteStrings; multiline = saveMultiline;
352 | cpartial.push(quoteKey(k) + token.col[0] + ' ' + vs + (setsep ? token.com[0] : ''));
353 | break;
354 | case 'object': if (v) { cpartial = null; break; } // falls through
355 | default: cpartial.push(partial[partial.length - 1] + (setsep ? iseparator : '')); break;
356 | }
357 | wrapLen += token.col[0].length - token.col[2];
358 | if (setsep) wrapLen += token.com[0].length - token.com[2];
359 | cwrapLen += wrapLen;
360 | }
361 | }
362 | if (length === 0) {
363 | // when empty
364 | if (comments && comments.e) partial.push(makeComment(comments.e[0], "\n") + eolMind);
365 | }
366 | else partial.push(eolMind);
367 |
368 | // Join all of the member texts together, separated with newlines
369 | if (partial.length === 0) {
370 | res = wrap(token.obj, '');
371 | } else {
372 | // and wrap them in braces
373 | res = prefix + wrap(token.obj, partial.join(''));
374 | // try if the condensed version can fit
375 | if (cpartial) {
376 | cres = cpartial.join(' ');
377 | if (cres.length - cwrapLen <= condense) res = wrap(token.obj, cres);
378 | }
379 | }
380 | }
381 |
382 | gap = mind;
383 | return res;
384 | }
385 | }
386 |
387 |
388 | runDsf = dsf.loadDsf(dsfDef, 'stringify');
389 |
390 | var res = "";
391 | var comments = keepComments ? comments = (common.getComment(data) || {}).r : null;
392 | if (comments && comments[0]) res = comments[0] + '\n';
393 |
394 | // get the result of stringifying the data.
395 | res += str(data, null, true, true);
396 |
397 | if (comments) res += comments[1]||"";
398 |
399 | return res;
400 | };
401 |
--------------------------------------------------------------------------------
/bundle/hjson.min.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * Hjson v3.2.1
3 | * https://hjson.github.io
4 | *
5 | * Copyright 2014-2017 Christian Zangl, MIT license
6 | * Details and documentation:
7 | * https://github.com/hjson/hjson-js
8 | *
9 | * This code is based on the the JSON version by Douglas Crockford:
10 | * https://github.com/douglascrockford/JSON-js (json_parse.js, json2.js)
11 | */
12 | !function(n){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=n();else if("function"==typeof define&&define.amd)define([],n);else{var r;r="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this,r.Hjson=n()}}(function(){return function(){function n(r,e,t){function o(a,s){if(!e[a]){if(!r[a]){var u="function"==typeof require&&require;if(!s&&u)return u(a,!0);if(i)return i(a,!0);var f=new Error("Cannot find module '"+a+"'");throw f.code="MODULE_NOT_FOUND",f}var c=e[a]={exports:{}};r[a][0].call(c.exports,function(n){return o(r[a][1][n]||n)},c,c.exports,n,r,e,t)}return e[a].exports}for(var i="function"==typeof require&&require,a=0;a0){var t=l(r,null,1);t+="\n# Orphaned comments:\n",e.forEach(function(n){t+=("# "+n.path.join("/")+": "+i(n.b,n.a,n.e)).replace("\n","\\n ")+"\n"}),l(r,t,1)}}function s(n,r,e,o){var i=t(e?e[0]:void 0,e?e[1]:void 0,o);return i&&(n[r]=i),i}function u(n,r){var e=t(r.b,r.a);return e.path=n,e}function f(n,r,e){if(n){var t,o;if(n.a)for(t=0,o=n.a.length;t="0"&&o<="9";)s&&("0"==o?a++:s=!1),i+=o,e();if(s&&a--,"."===o)for(i+=".";e()&&o>="0"&&o<="9";)i+=o;if("e"===o||"E"===o)for(i+=o,e(),"-"!==o&&"+"!==o||(i+=o,e());o>="0"&&o<="9";)i+=o,e();for(;o&&o<=" ";)e();return r&&(","!==o&&"}"!==o&&"]"!==o&&"#"!==o&&("/"!==o||"/"!==n[u]&&"*"!==n[u])||(o=0)),t=+i,o||a||!isFinite(t)?void 0:t}function o(n,r){return Object.defineProperty&&Object.defineProperty(n,"__COMMENTS__",{enumerable:!1,writable:!0}),n.__COMMENTS__=r||{}}function i(n){Object.defineProperty(n,"__COMMENTS__",{value:void 0})}function a(n){return n.__COMMENTS__}function s(n){if(!n)return"";var r,e,t,o,i=n.split("\n");for(t=0;t" "){i[t]="# "+r;break}}return i.join("\n")}var u=n("os");r.exports={EOL:u.EOL||"\n",tryParseNumber:t,createComment:o,removeComment:i,getComment:a,forceComment:s}},{os:8}],3:[function(n,r,e){"use strict";function t(n,r){function e(n){return"[object Function]"==={}.toString.call(n)}if("[object Array]"!==Object.prototype.toString.apply(n)){if(n)throw new Error("dsf option must contain an array!");return i}if(0===n.length)return i;var t=[];return n.forEach(function(n){if(!n.name||!e(n.parse)||!e(n.stringify))throw new Error("extension does not match the DSF interface");t.push(function(){try{if("parse"==r)return n.parse.apply(null,arguments);if("stringify"==r){var e=n.stringify.apply(null,arguments);if(void 0!==e&&("string"!=typeof e||0===e.length||'"'===e[0]||[].some.call(e,function(n){return a(n)})))throw new Error("value may not be empty, start with a quote or contain a punctuator character except colon: "+e);return e}throw new Error("Invalid type")}catch(r){throw new Error("DSF-"+n.name+" failed; "+r.message)}})}),o.bind(null,t)}function o(n,r){if(n)for(var e=0;e0&&"\n"!==b[r];r--,e++);for(;r>0;r--)"\n"===b[r]&&t++;throw new Error(n+" at line "+t+","+e+" >>>"+b.substr(j-e,20)+" ...")}function a(){return w=b.charAt(j),j++,w}function s(n){return b.charAt(j+n)}function u(n){for(var r="",e=w;a();){if(w===e)return a(),n&&"'"===e&&"'"===w&&0===r.length?(a(),f()):r;if("\\"===w)if(a(),"u"===w){for(var t=0,o=0;o<4;o++){a();var s,u=w.charCodeAt(0);w>="0"&&w<="9"?s=u-48:w>="a"&&w<="f"?s=u-97+10:w>="A"&&w<="F"?s=u-65+10:i("Bad \\u char "+w),t=16*t+s}r+=String.fromCharCode(t)}else{if("string"!=typeof C[w])break;r+=C[w]}else"\n"===w||"\r"===w?i("Bad string containing newline"):r+=w}i("Bad string")}function f(){function n(){for(var n=t;w&&w<=" "&&"\n"!==w&&n-- >0;)a()}for(var r="",e=0,t=0;;){var o=s(-t-5);if(!o||"\n"===o)break;t++}for(;w&&w<=" "&&"\n"!==w;)a();for("\n"===w&&(a(),n());;){if(w){if("'"===w){if(e++,a(),3===e)return"\n"===r.slice(-1)&&(r=r.slice(0,-1)),r;continue}for(;e>0;)r+="'",e--}else i("Bad multiline string");"\n"===w?(r+="\n",a(),n()):("\r"!==w&&(r+=w),a())}}function c(){if('"'===w||"'"===w)return u(!1);for(var n="",r=j,e=-1;;){if(":"===w)return n?e>=0&&e!==n.length&&(j=r+e,i("Found whitespace in your key name (use quotes to include)")):i("Found ':' but no key name (for an empty key name use quotes)"),n;w<=" "?w?e<0&&(e=n.length):i("Found EOF while looking for a key name (check your syntax)"):o(w)?i("Found '"+w+"' where a key name was expected (check your syntax or use quotes if the key name includes {}[],: or whitespace)"):n+=w,a()}}function l(){for(;w;){for(;w&&w<=" ";)a();if("#"===w||"/"===w&&"/"===s(0))for(;w&&"\n"!==w;)a();else{if("/"!==w||"*"!==s(0))break;for(a(),a();w&&("*"!==w||"/"!==s(0));)a();w&&(a(),a())}}}function h(){var n=w;for(o(w)&&i("Found a punctuator character '"+w+"' when expecting a quoteless string (check your syntax)");;){a();var r="\r"===w||"\n"===w||""===w;if(r||","===w||"}"===w||"]"===w||"#"===w||"/"===w&&("/"===s(0)||"*"===s(0))){var e=n[0];switch(e){case"f":if("false"===n.trim())return!1;break;case"n":if("null"===n.trim())return null;break;case"t":if("true"===n.trim())return!0;break;default:if("-"===e||e>="0"&&e<="9"){var t=k.tryParseNumber(n);if(void 0!==t)return t}}if(r){n=n.trim();var u=O(n);return void 0!==u?u:n}}n+=w}}function p(n,r){var e;for(n--,e=j-2;e>n&&b[e]<=" "&&"\n"!==b[e];e--);"\n"===b[e]&&e--,"\r"===b[e]&&e--;var t=b.substr(n,e-n+1);for(e=0;e" "){var o=t.indexOf("\n");if(o>=0){var i=[t.substr(0,o),t.substr(o+1)];return r&&0===i[0].trim().length&&i.shift(),i}return[t]}return[]}function m(n){function r(n,e){var t,o,i,a;switch(typeof n){case"string":n.indexOf(e)>=0&&(a=n);break;case"object":if("[object Array]"===Object.prototype.toString.apply(n))for(t=0,i=n.length;t "+t+"\n (unquoted strings contain everything up to the next line!)":""}return e("}")||e("]")}function d(){var n,r,e,t=[];try{if(x&&(n=k.createComment(t,{a:[]})),a(),r=j,l(),n&&(e=p(r,!0).join("\n")),"]"===w)return a(),n&&(n.e=[e]),t;for(;w;){if(t.push(v()),r=j,l(),","===w&&(a(),r=j,l()),n){var o=p(r);n.a.push([e||"",o[0]||""]),e=o[1]}if("]"===w)return a(),n&&(n.a[n.a.length-1][1]+=e||""),t;l()}i("End of input while parsing an array (missing ']')")}catch(n){throw n.hint=n.hint||m(t),n}}function g(n){var r,e,t,o="",s={};try{if(x&&(r=k.createComment(s,{c:{},o:[]})),n?e=1:(a(),e=j),l(),r&&(t=p(e,!0).join("\n")),"}"===w&&!n)return r&&(r.e=[t]),a(),s;for(;w;){if(o=c(),l(),":"!==w&&i("Expected ':' instead of '"+w+"'"),a(),s[o]=v(),e=j,l(),","===w&&(a(),e=j,l()),r){var u=p(e);r.c[o]=[t||"",u[0]||""],t=u[1],r.o.push(o)}if("}"===w&&!n)return a(),r&&(r.c[o][1]+=t||""),s;l()}if(n)return s;i("End of input while parsing an object (missing '}')")}catch(n){throw n.hint=n.hint||m(s),n}}function v(){switch(l(),w){case"{":return g();case"[":return d();case"'":case'"':return u(!0);default:return h()}}function y(n,r){var e=j;if(l(),w&&i("Syntax error, found trailing characters"),x){var t=r.join("\n"),o=p(e).join("\n");if(o||t){k.createComment(n,k.getComment(n)).r=[t,o]}}return n}var b,j,w,x,O,k=n("./hjson-common"),E=n("./hjson-dsf"),C={'"':'"',"'":"'","\\":"\\","/":"/",b:"\b",f:"\f",n:"\n",r:"\r",t:"\t"};if("string"!=typeof r)throw new Error("source is not a string");var q=null,S=!0;return e&&"object"==typeof e&&(x=e.keepWsc,q=e.dsf,S=!1!==e.legacyRoot),O=E.loadDsf(q,"parse"),b=r,t(),S?function(){l();var n=x?p(1):null;switch(w){case"{":return y(g(),n);case"[":return y(d(),n)}try{return y(g(!0),n)}catch(r){t();try{return y(v(),n)}catch(n){throw r}}}():function(){l();var n=x?p(1):null;switch(w){case"{":return y(g(),n);case"[":return y(d(),n);default:return y(v(),n)}}()}},{"./hjson-common":2,"./hjson-dsf":3}],5:[function(n,r,e){"use strict";r.exports=function(r,e){function t(n,r){return L+=n[0].length+n[1].length-n[2]-n[3],n[0]+r+n[1]}function o(n){return n.replace(N,function(n){var r=A[n];return"string"==typeof r?t(O.esc,r):t(O.uni,("0000"+n.charCodeAt(0).toString(16)).slice(-4))})}function i(n,r,e,i){return n?(I.lastIndex=0,F.lastIndex=0,v||e||I.test(n)||void 0!==f.tryParseNumber(n,!0)||F.test(n)?(N.lastIndex=0,_.lastIndex=0,N.test(n)?_.test(n)||i||!b?t(O.qstr,o(n)):a(n,r):t(O.qstr,n)):t(O.str,n)):t(O.qstr,"")}function a(n,r){var e,o=n.replace(/\r/g,"").split("\n");if(r+=p,1===o.length)return t(O.mstr,o[0]);var i=h+r+O.mstr[0];for(e=0;e0&&(n=n.substr(o)),o=0;k--){var C=E[k];O[C].push(l[C][0].length,l[C][1].length)}}var q,S="--឴឵-\u2028- -\ufeff-",N=new RegExp('[\\\\\\"\0-'+S+"]","g"),I=new RegExp("^\\s|^\"|^'|^#|^\\/\\*|^\\/\\/|^\\{|^\\}|^\\[|^\\]|^:|^,|\\s$|[\0-"+S+"]","g"),_=new RegExp("'''|^[\\s]+$|[\0-"+(2===b?"\t":"\b")+"\v\f-"+S+"]","g"),F=new RegExp("^(true|false|null)\\s*((,|\\]|\\}|#|//|/\\*).*)?$"),A={"\b":"b","\t":"t","\n":"n","\f":"f","\r":"r",'"':'"',"\\":"\\"},P=/[,\{\[\}\]\s:#"']|\/\/|\/\*/,D="",L=0;q=c.loadDsf(w,"stringify");var M="",T=m?T=(f.getComment(r)||{}).r:null;return T&&T[0]&&(M=T[0]+"\n"),M+=u(r,null,!0,!0),T&&(M+=T[1]||""),M}},{"./hjson-common":2,"./hjson-dsf":3}],6:[function(n,r,e){r.exports="3.2.1"},{}],7:[function(n,r,e){/*!
13 | * Hjson v3.2.1
14 | * https://hjson.github.io
15 | *
16 | * Copyright 2014-2017 Christian Zangl, MIT license
17 | * Details and documentation:
18 | * https://github.com/hjson/hjson-js
19 | *
20 | * This code is based on the the JSON version by Douglas Crockford:
21 | * https://github.com/douglascrockford/JSON-js (json_parse.js, json2.js)
22 | */
23 | "use strict";var t=n("./hjson-common"),o=n("./hjson-version"),i=n("./hjson-parse"),a=n("./hjson-stringify"),s=n("./hjson-comments"),u=n("./hjson-dsf");r.exports={parse:i,stringify:a,endOfLine:function(){return t.EOL},setEndOfLine:function(n){"\n"!==n&&"\r\n"!==n||(t.EOL=n)},version:o,rt:{parse:function(n,r){return(r=r||{}).keepWsc=!0,i(n,r)},stringify:function(n,r){return(r=r||{}).keepWsc=!0,a(n,r)}},comments:s,dsf:u.std}},{"./hjson-comments":1,"./hjson-common":2,"./hjson-dsf":3,"./hjson-parse":4,"./hjson-stringify":5,"./hjson-version":6}],8:[function(n,r,e){},{}]},{},[7])(7)});
24 |
--------------------------------------------------------------------------------
/bundle/hjson.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * Hjson v3.2.1
3 | * https://hjson.github.io
4 | *
5 | * Copyright 2014-2017 Christian Zangl, MIT license
6 | * Details and documentation:
7 | * https://github.com/hjson/hjson-js
8 | *
9 | * This code is based on the the JSON version by Douglas Crockford:
10 | * https://github.com/douglascrockford/JSON-js (json_parse.js, json2.js)
11 | */
12 |
13 | (function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f();}else if(typeof define==="function"&&define.amd){define([],f);}else{var g;if(typeof window!=="undefined"){g=window;}else if(typeof global!=="undefined"){g=global;}else if(typeof self!=="undefined"){g=self;}else{g=this;}g.Hjson = f();}})(function(){var define,module,exports;return (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a;}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r);},p,p.exports,r,e,n,t);}return n[i].exports;}for(var u="function"==typeof require&&require,i=0;i0) {
95 | var text=rootComment(value, null, 1);
96 | text+="\n# Orphaned comments:\n";
97 | dropped.forEach(function(c) {
98 | text+=("# "+c.path.join('/')+": "+mergeStr(c.b, c.a, c.e)).replace("\n", "\\n ")+"\n";
99 | });
100 | rootComment(value, text, 1);
101 | }
102 | }
103 |
104 | function saveComment(res, key, item, col) {
105 | var c=makeComment(item?item[0]:undefined, item?item[1]:undefined, col);
106 | if (c) res[key]=c;
107 | return c;
108 | }
109 |
110 | function droppedComment(path, c) {
111 | var res=makeComment(c.b, c.a);
112 | res.path=path;
113 | return res;
114 | }
115 |
116 | function dropAll(comments, dropped, path) {
117 |
118 | if (!comments) return;
119 |
120 | var i, length; // loop
121 |
122 | if (comments.a) {
123 |
124 | for (i=0, length=comments.a.length; i= '0' && ch <= '9') {
242 | if (testLeading) {
243 | if (ch == '0') leadingZeros++;
244 | else testLeading = false;
245 | }
246 | string += ch;
247 | next();
248 | }
249 | if (testLeading) leadingZeros--; // single 0 is allowed
250 | if (ch === '.') {
251 | string += '.';
252 | while (next() && ch >= '0' && ch <= '9')
253 | string += ch;
254 | }
255 | if (ch === 'e' || ch === 'E') {
256 | string += ch;
257 | next();
258 | if (ch === '-' || ch === '+') {
259 | string += ch;
260 | next();
261 | }
262 | while (ch >= '0' && ch <= '9') {
263 | string += ch;
264 | next();
265 | }
266 | }
267 |
268 | // skip white/to (newline)
269 | while (ch && ch <= ' ') next();
270 |
271 | if (stopAtNext) {
272 | // end scan if we find a punctuator character like ,}] or a comment
273 | if (ch === ',' || ch === '}' || ch === ']' ||
274 | ch === '#' || ch === '/' && (text[at] === '/' || text[at] === '*')) ch = 0;
275 | }
276 |
277 | number = +string;
278 | if (ch || leadingZeros || !isFinite(number)) return undefined;
279 | else return number;
280 | }
281 |
282 | function createComment(value, comment) {
283 | if (Object.defineProperty) Object.defineProperty(value, "__COMMENTS__", { enumerable: false, writable: true });
284 | return (value.__COMMENTS__ = comment||{});
285 | }
286 |
287 | function removeComment(value) {
288 | Object.defineProperty(value, "__COMMENTS__", { value: undefined });
289 | }
290 |
291 | function getComment(value) {
292 | return value.__COMMENTS__;
293 | }
294 |
295 | function forceComment(text) {
296 | if (!text) return "";
297 | var a = text.split('\n');
298 | var str, i, j, len;
299 | for (j = 0; j < a.length; j++) {
300 | str = a[j];
301 | len = str.length;
302 | for (i = 0; i < len; i++) {
303 | var c = str[i];
304 | if (c === '#') break;
305 | else if (c === '/' && (str[i+1] === '/' || str[i+1] === '*')) {
306 | if (str[i+1] === '*') j = a.length; // assume /**/ covers whole block, bail out
307 | break;
308 | }
309 | else if (c > ' ') {
310 | a[j] = '# ' + str;
311 | break;
312 | }
313 | }
314 | }
315 | return a.join('\n');
316 | }
317 |
318 | module.exports = {
319 | EOL: os.EOL || '\n',
320 | tryParseNumber: tryParseNumber,
321 | createComment: createComment,
322 | removeComment: removeComment,
323 | getComment: getComment,
324 | forceComment: forceComment,
325 | };
326 |
327 | },{"os":8}],3:[function(require,module,exports){
328 | /* Hjson https://hjson.github.io */
329 | "use strict";
330 |
331 | function loadDsf(col, type) {
332 |
333 | if (Object.prototype.toString.apply(col) !== '[object Array]') {
334 | if (col) throw new Error("dsf option must contain an array!");
335 | else return nopDsf;
336 | } else if (col.length === 0) return nopDsf;
337 |
338 | var dsf = [];
339 | function isFunction(f) { return {}.toString.call(f) === '[object Function]'; }
340 |
341 | col.forEach(function(x) {
342 | if (!x.name || !isFunction(x.parse) || !isFunction(x.stringify))
343 | throw new Error("extension does not match the DSF interface");
344 | dsf.push(function() {
345 | try {
346 | if (type == "parse") {
347 | return x.parse.apply(null, arguments);
348 | } else if (type == "stringify") {
349 | var res=x.stringify.apply(null, arguments);
350 | // check result
351 | if (res !== undefined && (typeof res !== "string" ||
352 | res.length === 0 ||
353 | res[0] === '"' ||
354 | [].some.call(res, function(c) { return isInvalidDsfChar(c); })))
355 | throw new Error("value may not be empty, start with a quote or contain a punctuator character except colon: " + res);
356 | return res;
357 | } else throw new Error("Invalid type");
358 | } catch (e) {
359 | throw new Error("DSF-"+x.name+" failed; "+e.message);
360 | }
361 | });
362 | });
363 |
364 | return runDsf.bind(null, dsf);
365 | }
366 |
367 | function runDsf(dsf, value) {
368 | if (dsf) {
369 | for (var i = 0; i < dsf.length; i++) {
370 | var res = dsf[i](value);
371 | if (res !== undefined) return res;
372 | }
373 | }
374 | }
375 |
376 | function nopDsf(/*value*/) {
377 | }
378 |
379 | function isInvalidDsfChar(c) {
380 | return c === '{' || c === '}' || c === '[' || c === ']' || c === ',';
381 | }
382 |
383 |
384 | function math(/*opt*/) {
385 | return {
386 | name: "math",
387 | parse: function (value) {
388 | switch (value) {
389 | case "+inf":
390 | case "inf":
391 | case "+Inf":
392 | case "Inf": return Infinity;
393 | case "-inf":
394 | case "-Inf": return -Infinity;
395 | case "nan":
396 | case "NaN": return NaN;
397 | }
398 | },
399 | stringify: function (value) {
400 | if (typeof value !== 'number') return;
401 | if (1 / value === -Infinity) return "-0"; // 0 === -0
402 | if (value === Infinity) return "Inf";
403 | if (value === -Infinity) return "-Inf";
404 | if (isNaN(value)) return "NaN";
405 | },
406 | };
407 | }
408 | math.description="support for Inf/inf, -Inf/-inf, Nan/naN and -0";
409 |
410 | function hex(opt) {
411 | var out=opt && opt.out;
412 | return {
413 | name: "hex",
414 | parse: function (value) {
415 | if (/^0x[0-9A-Fa-f]+$/.test(value))
416 | return parseInt(value, 16);
417 | },
418 | stringify: function (value) {
419 | if (out && Number.isInteger(value))
420 | return "0x"+value.toString(16);
421 | },
422 | };
423 | }
424 | hex.description="parse hexadecimal numbers prefixed with 0x";
425 |
426 | function date(/*opt*/) {
427 | return {
428 | name: "date",
429 | parse: function (value) {
430 | if (/^\d{4}-\d{2}-\d{2}$/.test(value) ||
431 | /^\d{4}-\d{2}-\d{2}T\d{2}\:\d{2}\:\d{2}(?:.\d+)(?:Z|[+-]\d{2}:\d{2})$/.test(value)) {
432 | var dt = Date.parse(value);
433 | if (!isNaN(dt)) return new Date(dt);
434 | }
435 | },
436 | stringify: function (value) {
437 | if (Object.prototype.toString.call(value) === '[object Date]') {
438 | var dt = value.toISOString();
439 | if (dt.indexOf("T00:00:00.000Z", dt.length - 14) !== -1) return dt.substr(0, 10);
440 | else return dt;
441 | }
442 | },
443 | };
444 | }
445 | date.description="support ISO dates";
446 |
447 | module.exports = {
448 | loadDsf: loadDsf,
449 | std: {
450 | math: math,
451 | hex: hex,
452 | date: date,
453 | },
454 | };
455 |
456 | },{}],4:[function(require,module,exports){
457 | /* Hjson https://hjson.github.io */
458 | "use strict";
459 |
460 | module.exports = function(source, opt) {
461 |
462 | var common = require("./hjson-common");
463 | var dsf = require("./hjson-dsf");
464 |
465 | var text;
466 | var at; // The index of the current character
467 | var ch; // The current character
468 | var escapee = {
469 | '"': '"',
470 | "'": "'",
471 | '\\': '\\',
472 | '/': '/',
473 | b: '\b',
474 | f: '\f',
475 | n: '\n',
476 | r: '\r',
477 | t: '\t'
478 | };
479 |
480 | var keepComments;
481 | var runDsf; // domain specific formats
482 |
483 | function resetAt() {
484 | at = 0;
485 | ch = ' ';
486 | }
487 |
488 | function isPunctuatorChar(c) {
489 | return c === '{' || c === '}' || c === '[' || c === ']' || c === ',' || c === ':';
490 | }
491 |
492 | // Call error when something is wrong.
493 | function error(m) {
494 | var i, col=0, line=1;
495 | for (i = at-1; i > 0 && text[i] !== '\n'; i--, col++) {}
496 | for (; i > 0; i--) if (text[i] === '\n') line++;
497 | throw new Error(m + " at line " + line + "," + col + " >>>" + text.substr(at-col, 20) + " ...");
498 | }
499 |
500 | function next() {
501 | // get the next character.
502 | ch = text.charAt(at);
503 | at++;
504 | return ch;
505 | }
506 |
507 | function peek(offs) {
508 | // range check is not required
509 | return text.charAt(at + offs);
510 | }
511 |
512 | function string(allowML) {
513 | // Parse a string value.
514 | // callers make sure that (ch === '"' || ch === "'")
515 | var string = '';
516 |
517 | // When parsing for string values, we must look for "/' and \ characters.
518 | var exitCh = ch;
519 | while (next()) {
520 | if (ch === exitCh) {
521 | next();
522 | if (allowML && exitCh === "'" && ch === "'" && string.length === 0) {
523 | // ''' indicates a multiline string
524 | next();
525 | return mlString();
526 | } else return string;
527 | }
528 | if (ch === '\\') {
529 | next();
530 | if (ch === 'u') {
531 | var uffff = 0;
532 | for (var i = 0; i < 4; i++) {
533 | next();
534 | var c = ch.charCodeAt(0), hex;
535 | if (ch >= '0' && ch <= '9') hex = c - 48;
536 | else if (ch >= 'a' && ch <= 'f') hex = c - 97 + 0xa;
537 | else if (ch >= 'A' && ch <= 'F') hex = c - 65 + 0xa;
538 | else error("Bad \\u char " + ch);
539 | uffff = uffff * 16 + hex;
540 | }
541 | string += String.fromCharCode(uffff);
542 | } else if (typeof escapee[ch] === 'string') {
543 | string += escapee[ch];
544 | } else break;
545 | } else if (ch === '\n' || ch === '\r') {
546 | error("Bad string containing newline");
547 | } else {
548 | string += ch;
549 | }
550 | }
551 | error("Bad string");
552 | }
553 |
554 | function mlString() {
555 | // Parse a multiline string value.
556 | var string = '', triple = 0;
557 |
558 | // we are at ''' +1 - get indent
559 | var indent = 0;
560 | for (;;) {
561 | var c=peek(-indent-5);
562 | if (!c || c === '\n') break;
563 | indent++;
564 | }
565 |
566 | function skipIndent() {
567 | var skip = indent;
568 | while (ch && ch <= ' ' && ch !== '\n' && skip-- > 0) next();
569 | }
570 |
571 | // skip white/to (newline)
572 | while (ch && ch <= ' ' && ch !== '\n') next();
573 | if (ch === '\n') { next(); skipIndent(); }
574 |
575 | // When parsing multiline string values, we must look for ' characters.
576 | for (;;) {
577 | if (!ch) {
578 | error("Bad multiline string");
579 | } else if (ch === '\'') {
580 | triple++;
581 | next();
582 | if (triple === 3) {
583 | if (string.slice(-1) === '\n') string=string.slice(0, -1); // remove last EOL
584 | return string;
585 | } else continue;
586 | } else {
587 | while (triple > 0) {
588 | string += '\'';
589 | triple--;
590 | }
591 | }
592 | if (ch === '\n') {
593 | string += '\n';
594 | next();
595 | skipIndent();
596 | } else {
597 | if (ch !== '\r') string += ch;
598 | next();
599 | }
600 | }
601 | }
602 |
603 | function keyname() {
604 | // quotes for keys are optional in Hjson
605 | // unless they include {}[],: or whitespace.
606 |
607 | if (ch === '"' || ch === "'") return string(false);
608 |
609 | var name = "", start = at, space = -1;
610 | for (;;) {
611 | if (ch === ':') {
612 | if (!name) error("Found ':' but no key name (for an empty key name use quotes)");
613 | else if (space >=0 && space !== name.length) { at = start + space; error("Found whitespace in your key name (use quotes to include)"); }
614 | return name;
615 | } else if (ch <= ' ') {
616 | if (!ch) error("Found EOF while looking for a key name (check your syntax)");
617 | else if (space < 0) space = name.length;
618 | } else if (isPunctuatorChar(ch)) {
619 | error("Found '" + ch + "' where a key name was expected (check your syntax or use quotes if the key name includes {}[],: or whitespace)");
620 | } else {
621 | name += ch;
622 | }
623 | next();
624 | }
625 | }
626 |
627 | function white() {
628 | while (ch) {
629 | // Skip whitespace.
630 | while (ch && ch <= ' ') next();
631 | // Hjson allows comments
632 | if (ch === '#' || ch === '/' && peek(0) === '/') {
633 | while (ch && ch !== '\n') next();
634 | } else if (ch === '/' && peek(0) === '*') {
635 | next(); next();
636 | while (ch && !(ch === '*' && peek(0) === '/')) next();
637 | if (ch) { next(); next(); }
638 | } else break;
639 | }
640 | }
641 |
642 | function tfnns() {
643 | // Hjson strings can be quoteless
644 | // returns string, true, false, or null.
645 | var value = ch;
646 | if (isPunctuatorChar(ch))
647 | error("Found a punctuator character '" + ch + "' when expecting a quoteless string (check your syntax)");
648 |
649 | for(;;) {
650 | next();
651 | // (detection of ml strings was moved to string())
652 | var isEol = ch === '\r' || ch === '\n' || ch === '';
653 | if (isEol ||
654 | ch === ',' || ch === '}' || ch === ']' ||
655 | ch === '#' ||
656 | ch === '/' && (peek(0) === '/' || peek(0) === '*')
657 | ) {
658 | // this tests for the case of {true|false|null|num}
659 | // followed by { ',' | '}' | ']' | '#' | '//' | '/*' }
660 | // which needs to be parsed as the specified value
661 | var chf = value[0];
662 | switch (chf) {
663 | case 'f': if (value.trim() === "false") return false; break;
664 | case 'n': if (value.trim() === "null") return null; break;
665 | case 't': if (value.trim() === "true") return true; break;
666 | default:
667 | if (chf === '-' || chf >= '0' && chf <= '9') {
668 | var n = common.tryParseNumber(value);
669 | if (n !== undefined) return n;
670 | }
671 | }
672 | if (isEol) {
673 | // remove any whitespace at the end (ignored in quoteless strings)
674 | value = value.trim();
675 | var dsfValue = runDsf(value);
676 | return dsfValue !== undefined ? dsfValue : value;
677 | }
678 | }
679 | value += ch;
680 | }
681 | }
682 |
683 | function getComment(cAt, first) {
684 | var i;
685 | cAt--;
686 | // remove trailing whitespace
687 | // but only up to EOL
688 | for (i = at - 2; i > cAt && text[i] <= ' ' && text[i] !== '\n'; i--);
689 | if (text[i] === '\n') i--;
690 | if (text[i] === '\r') i--;
691 | var res = text.substr(cAt, i-cAt+1);
692 | // return if we find anything other than whitespace
693 | for (i = 0; i < res.length; i++) {
694 | if (res[i] > ' ') {
695 | var j = res.indexOf('\n');
696 | if (j >= 0) {
697 | var c = [res.substr(0, j), res.substr(j+1)];
698 | if (first && c[0].trim().length === 0) c.shift();
699 | return c;
700 | } else return [res];
701 | }
702 | }
703 | return [];
704 | }
705 |
706 | function errorClosingHint(value) {
707 | function search(value, ch) {
708 | var i, k, length, res;
709 | switch (typeof value) {
710 | case 'string':
711 | if (value.indexOf(ch) >= 0) res = value;
712 | break;
713 | case 'object':
714 | if (Object.prototype.toString.apply(value) === '[object Array]') {
715 | for (i = 0, length = value.length; i < length; i++) {
716 | res=search(value[i], ch) || res;
717 | }
718 | } else {
719 | for (k in value) {
720 | if (!Object.prototype.hasOwnProperty.call(value, k)) continue;
721 | res=search(value[k], ch) || res;
722 | }
723 | }
724 | }
725 | return res;
726 | }
727 |
728 | function report(ch) {
729 | var possibleErr=search(value, ch);
730 | if (possibleErr) {
731 | return "found '"+ch+"' in a string value, your mistake could be with:\n"+
732 | " > "+possibleErr+"\n"+
733 | " (unquoted strings contain everything up to the next line!)";
734 | } else return "";
735 | }
736 |
737 | return report('}') || report(']');
738 | }
739 |
740 | function array() {
741 | // Parse an array value.
742 | // assuming ch === '['
743 |
744 | var array = [];
745 | var comments, cAt, nextComment;
746 | try {
747 | if (keepComments) comments = common.createComment(array, { a: [] });
748 |
749 | next();
750 | cAt = at;
751 | white();
752 | if (comments) nextComment = getComment(cAt, true).join('\n');
753 | if (ch === ']') {
754 | next();
755 | if (comments) comments.e = [nextComment];
756 | return array; // empty array
757 | }
758 |
759 | while (ch) {
760 | array.push(value());
761 | cAt = at;
762 | white();
763 | // in Hjson the comma is optional and trailing commas are allowed
764 | // note that we do not keep comments before the , if there are any
765 | if (ch === ',') { next(); cAt = at; white(); }
766 | if (comments) {
767 | var c = getComment(cAt);
768 | comments.a.push([nextComment||"", c[0]||""]);
769 | nextComment = c[1];
770 | }
771 | if (ch === ']') {
772 | next();
773 | if (comments) comments.a[comments.a.length-1][1] += nextComment||"";
774 | return array;
775 | }
776 | white();
777 | }
778 |
779 | error("End of input while parsing an array (missing ']')");
780 | } catch (e) {
781 | e.hint=e.hint||errorClosingHint(array);
782 | throw e;
783 | }
784 | }
785 |
786 | function object(withoutBraces) {
787 | // Parse an object value.
788 |
789 | var key = "", object = {};
790 | var comments, cAt, nextComment;
791 |
792 | try {
793 | if (keepComments) comments = common.createComment(object, { c: {}, o: [] });
794 |
795 | if (!withoutBraces) {
796 | // assuming ch === '{'
797 | next();
798 | cAt = at;
799 | } else cAt = 1;
800 |
801 | white();
802 | if (comments) nextComment = getComment(cAt, true).join('\n');
803 | if (ch === '}' && !withoutBraces) {
804 | if (comments) comments.e = [nextComment];
805 | next();
806 | return object; // empty object
807 | }
808 | while (ch) {
809 | key = keyname();
810 | white();
811 | if (ch !== ':') error("Expected ':' instead of '" + ch + "'");
812 | next();
813 | // duplicate keys overwrite the previous value
814 | object[key] = value();
815 | cAt = at;
816 | white();
817 | // in Hjson the comma is optional and trailing commas are allowed
818 | // note that we do not keep comments before the , if there are any
819 | if (ch === ',') { next(); cAt = at; white(); }
820 | if (comments) {
821 | var c = getComment(cAt);
822 | comments.c[key] = [nextComment||"", c[0]||""];
823 | nextComment = c[1];
824 | comments.o.push(key);
825 | }
826 | if (ch === '}' && !withoutBraces) {
827 | next();
828 | if (comments) comments.c[key][1] += nextComment||"";
829 | return object;
830 | }
831 | white();
832 | }
833 |
834 | if (withoutBraces) return object;
835 | else error("End of input while parsing an object (missing '}')");
836 | } catch (e) {
837 | e.hint=e.hint||errorClosingHint(object);
838 | throw e;
839 | }
840 | }
841 |
842 | function value() {
843 | // Parse a Hjson value. It could be an object, an array, a string, a number or a word.
844 |
845 | white();
846 | switch (ch) {
847 | case '{': return object();
848 | case '[': return array();
849 | case "'":
850 | case '"': return string(true);
851 | default: return tfnns();
852 | }
853 | }
854 |
855 | function checkTrailing(v, c) {
856 | var cAt = at;
857 | white();
858 | if (ch) error("Syntax error, found trailing characters");
859 | if (keepComments) {
860 | var b = c.join('\n'), a = getComment(cAt).join('\n');
861 | if (a || b) {
862 | var comments = common.createComment(v, common.getComment(v));
863 | comments.r = [b, a];
864 | }
865 | }
866 | return v;
867 | }
868 |
869 | function rootValue() {
870 | white();
871 | var c = keepComments ? getComment(1) : null;
872 | switch (ch) {
873 | case '{': return checkTrailing(object(), c);
874 | case '[': return checkTrailing(array(), c);
875 | default: return checkTrailing(value(), c);
876 | }
877 | }
878 |
879 | function legacyRootValue() {
880 | // Braces for the root object are optional
881 | white();
882 | var c = keepComments ? getComment(1) : null;
883 | switch (ch) {
884 | case '{': return checkTrailing(object(), c);
885 | case '[': return checkTrailing(array(), c);
886 | }
887 |
888 | try {
889 | // assume we have a root object without braces
890 | return checkTrailing(object(true), c);
891 | } catch (e) {
892 | // test if we are dealing with a single JSON value instead (true/false/null/num/"")
893 | resetAt();
894 | try { return checkTrailing(value(), c); }
895 | catch (e2) { throw e; } // throw original error
896 | }
897 | }
898 |
899 | if (typeof source!=="string") throw new Error("source is not a string");
900 | var dsfDef = null;
901 | var legacyRoot = true;
902 | if (opt && typeof opt === 'object') {
903 | keepComments = opt.keepWsc;
904 | dsfDef = opt.dsf;
905 | legacyRoot = opt.legacyRoot !== false; // default true
906 | }
907 | runDsf = dsf.loadDsf(dsfDef, "parse");
908 | text = source;
909 | resetAt();
910 | return legacyRoot ? legacyRootValue() : rootValue();
911 | };
912 |
913 | },{"./hjson-common":2,"./hjson-dsf":3}],5:[function(require,module,exports){
914 | /* Hjson https://hjson.github.io */
915 | "use strict";
916 |
917 | module.exports = function(data, opt) {
918 |
919 | var common = require("./hjson-common");
920 | var dsf = require("./hjson-dsf");
921 |
922 | var plainToken = {
923 | obj: [ '{', '}' ],
924 | arr: [ '[', ']' ],
925 | key: [ '', '' ],
926 | qkey: [ '"', '"' ],
927 | col: [ ':', '' ],
928 | com: [ ',', '' ],
929 | str: [ '', '' ],
930 | qstr: [ '"', '"' ],
931 | mstr: [ "'''", "'''" ],
932 | num: [ '', '' ],
933 | lit: [ '', '' ],
934 | dsf: [ '', '' ],
935 | esc: [ '\\', '' ],
936 | uni: [ '\\u', '' ],
937 | rem: [ '', '' ],
938 | };
939 |
940 | // options
941 | var eol = common.EOL;
942 | var indent = ' ';
943 | var keepComments = false;
944 | var bracesSameLine = false;
945 | var quoteKeys = false;
946 | var quoteStrings = false;
947 | var condense = 0;
948 | var multiline = 1; // std=1, no-tabs=2, off=0
949 | var separator = ''; // comma separator
950 | var dsfDef = null;
951 | var sortProps = false;
952 | var token = plainToken;
953 |
954 | if (opt && typeof opt === 'object') {
955 | opt.quotes = opt.quotes === 'always' ? 'strings' : opt.quotes; // legacy
956 |
957 | if (opt.eol === '\n' || opt.eol === '\r\n') eol = opt.eol;
958 | keepComments = opt.keepWsc;
959 | condense = opt.condense || 0;
960 | bracesSameLine = opt.bracesSameLine;
961 | quoteKeys = opt.quotes === 'all' || opt.quotes === 'keys';
962 | quoteStrings = opt.quotes === 'all' || opt.quotes === 'strings' || opt.separator === true;
963 | if (quoteStrings || opt.multiline == 'off') multiline = 0;
964 | else multiline = opt.multiline == 'no-tabs' ? 2 : 1;
965 | separator = opt.separator === true ? token.com[0] : '';
966 | dsfDef = opt.dsf;
967 | sortProps = opt.sortProps;
968 |
969 | // If the space parameter is a number, make an indent string containing that
970 | // many spaces. If it is a string, it will be used as the indent string.
971 |
972 | if (typeof opt.space === 'number') {
973 | indent = new Array(opt.space + 1).join(' ');
974 | } else if (typeof opt.space === 'string') {
975 | indent = opt.space;
976 | }
977 |
978 | if (opt.colors === true) {
979 | token = {
980 | obj: [ '\x1b[37m{\x1b[0m', '\x1b[37m}\x1b[0m' ],
981 | arr: [ '\x1b[37m[\x1b[0m', '\x1b[37m]\x1b[0m' ],
982 | key: [ '\x1b[33m', '\x1b[0m' ],
983 | qkey: [ '\x1b[33m"', '"\x1b[0m' ],
984 | col: [ '\x1b[37m:\x1b[0m', '' ],
985 | com: [ '\x1b[37m,\x1b[0m', '' ],
986 | str: [ '\x1b[37;1m', '\x1b[0m' ],
987 | qstr: [ '\x1b[37;1m"', '"\x1b[0m' ],
988 | mstr: [ "\x1b[37;1m'''", "'''\x1b[0m" ],
989 | num: [ '\x1b[36;1m', '\x1b[0m' ],
990 | lit: [ '\x1b[36m', '\x1b[0m' ],
991 | dsf: [ '\x1b[37m', '\x1b[0m' ],
992 | esc: [ '\x1b[31m\\', '\x1b[0m' ],
993 | uni: [ '\x1b[31m\\u', '\x1b[0m' ],
994 | rem: [ '\x1b[35m', '\x1b[0m' ],
995 | };
996 | }
997 |
998 | var i, ckeys=Object.keys(plainToken);
999 | for (i = ckeys.length - 1; i >= 0; i--) {
1000 | var k = ckeys[i];
1001 | token[k].push(plainToken[k][0].length, plainToken[k][1].length);
1002 | }
1003 | }
1004 |
1005 | //
1006 | var runDsf; // domain specific formats
1007 |
1008 | var commonRange='\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff';
1009 | // needsEscape tests if the string can be written without escapes
1010 | var needsEscape = new RegExp('[\\\\\\"\x00-\x1f'+commonRange+']', 'g');
1011 | // needsQuotes tests if the string can be written as a quoteless string (like needsEscape but without \\ and \")
1012 | var needsQuotes = new RegExp('^\\s|^"|^\'|^#|^\\/\\*|^\\/\\/|^\\{|^\\}|^\\[|^\\]|^:|^,|\\s$|[\x00-\x1f'+commonRange+']', 'g');
1013 | // needsEscapeML tests if the string can be written as a multiline string (like needsEscape but without \n, \r, \\, \", \t unless multines is 'std')
1014 | var needsEscapeML = new RegExp('\'\'\'|^[\\s]+$|[\x00-'+(multiline === 2 ? '\x09' : '\x08')+'\x0b\x0c\x0e-\x1f'+commonRange+']', 'g');
1015 | // starts with a keyword and optionally is followed by a comment
1016 | var startsWithKeyword = new RegExp('^(true|false|null)\\s*((,|\\]|\\}|#|//|/\\*).*)?$');
1017 | var meta = {
1018 | // table of character substitutions
1019 | '\b': 'b',
1020 | '\t': 't',
1021 | '\n': 'n',
1022 | '\f': 'f',
1023 | '\r': 'r',
1024 | '"' : '"',
1025 | '\\': '\\'
1026 | };
1027 | var needsEscapeName = /[,\{\[\}\]\s:#"']|\/\/|\/\*/;
1028 | var gap = '';
1029 | //
1030 | var wrapLen = 0;
1031 |
1032 | function wrap(tk, v) {
1033 | wrapLen += tk[0].length + tk[1].length - tk[2] - tk[3];
1034 | return tk[0] + v + tk[1];
1035 | }
1036 |
1037 | function quoteReplace(string) {
1038 | return string.replace(needsEscape, function (a) {
1039 | var c = meta[a];
1040 | if (typeof c === 'string') return wrap(token.esc, c);
1041 | else return wrap(token.uni, ('0000' + a.charCodeAt(0).toString(16)).slice(-4));
1042 | });
1043 | }
1044 |
1045 | function quote(string, gap, hasComment, isRootObject) {
1046 | if (!string) return wrap(token.qstr, '');
1047 |
1048 | needsQuotes.lastIndex = 0;
1049 | startsWithKeyword.lastIndex = 0;
1050 |
1051 | // Check if we can insert this string without quotes
1052 | // see hjson syntax (must not parse as true, false, null or number)
1053 |
1054 | if (quoteStrings || hasComment ||
1055 | needsQuotes.test(string) ||
1056 | common.tryParseNumber(string, true) !== undefined ||
1057 | startsWithKeyword.test(string)) {
1058 |
1059 | // If the string contains no control characters, no quote characters, and no
1060 | // backslash characters, then we can safely slap some quotes around it.
1061 | // Otherwise we first check if the string can be expressed in multiline
1062 | // format or we must replace the offending characters with safe escape
1063 | // sequences.
1064 |
1065 | needsEscape.lastIndex = 0;
1066 | needsEscapeML.lastIndex = 0;
1067 | if (!needsEscape.test(string)) return wrap(token.qstr, string);
1068 | else if (!needsEscapeML.test(string) && !isRootObject && multiline) return mlString(string, gap);
1069 | else return wrap(token.qstr, quoteReplace(string));
1070 | } else {
1071 | // return without quotes
1072 | return wrap(token.str, string);
1073 | }
1074 | }
1075 |
1076 | function mlString(string, gap) {
1077 | // wrap the string into the ''' (multiline) format
1078 |
1079 | var i, a = string.replace(/\r/g, "").split('\n');
1080 | gap += indent;
1081 |
1082 | if (a.length === 1) {
1083 | // The string contains only a single line. We still use the multiline
1084 | // format as it avoids escaping the \ character (e.g. when used in a
1085 | // regex).
1086 | return wrap(token.mstr, a[0]);
1087 | } else {
1088 | var res = eol + gap + token.mstr[0];
1089 | for (i = 0; i < a.length; i++) {
1090 | res += eol;
1091 | if (a[i]) res += gap + a[i];
1092 | }
1093 | return res + eol + gap + token.mstr[1];
1094 | }
1095 | }
1096 |
1097 | function quoteKey(name) {
1098 | if (!name) return '""';
1099 |
1100 | // Check if we can insert this key without quotes
1101 |
1102 | if (quoteKeys || needsEscapeName.test(name)) {
1103 | needsEscape.lastIndex = 0;
1104 | return wrap(token.qkey, needsEscape.test(name) ? quoteReplace(name) : name);
1105 | } else {
1106 | // return without quotes
1107 | return wrap(token.key, name);
1108 | }
1109 | }
1110 |
1111 | function str(value, hasComment, noIndent, isRootObject) {
1112 | // Produce a string from value.
1113 |
1114 | function startsWithNL(str) { return str && str[str[0] === '\r' ? 1 : 0] === '\n'; }
1115 | function commentOnThisLine(str) { return str && !startsWithNL(str); }
1116 | function makeComment(str, prefix, trim) {
1117 | if (!str) return "";
1118 | str = common.forceComment(str);
1119 | var i, len = str.length;
1120 | for (i = 0; i < len && str[i] <= ' '; i++) {}
1121 | if (trim && i > 0) str = str.substr(i);
1122 | if (i < len) return prefix + wrap(token.rem, str);
1123 | else return str;
1124 | }
1125 |
1126 | // What happens next depends on the value's type.
1127 |
1128 | // check for DSF
1129 | var dsfValue = runDsf(value);
1130 | if (dsfValue !== undefined) return wrap(token.dsf, dsfValue);
1131 |
1132 | switch (typeof value) {
1133 | case 'string':
1134 | return quote(value, gap, hasComment, isRootObject);
1135 |
1136 | case 'number':
1137 | // JSON numbers must be finite. Encode non-finite numbers as null.
1138 | return isFinite(value) ? wrap(token.num, String(value)) : wrap(token.lit, 'null');
1139 |
1140 | case 'boolean':
1141 | return wrap(token.lit, String(value));
1142 |
1143 | case 'object':
1144 | // If the type is 'object', we might be dealing with an object or an array or
1145 | // null.
1146 |
1147 | // Due to a specification blunder in ECMAScript, typeof null is 'object',
1148 | // so watch out for that case.
1149 |
1150 | if (!value) return wrap(token.lit, 'null');
1151 |
1152 | var comments; // whitespace & comments
1153 | if (keepComments) comments = common.getComment(value);
1154 |
1155 | var isArray = Object.prototype.toString.apply(value) === '[object Array]';
1156 |
1157 | // Make an array to hold the partial results of stringifying this object value.
1158 | var mind = gap;
1159 | gap += indent;
1160 | var eolMind = eol + mind;
1161 | var eolGap = eol + gap;
1162 | var prefix = noIndent || bracesSameLine ? '' : eolMind;
1163 | var partial = [];
1164 | var setsep;
1165 | // condense helpers:
1166 | var cpartial = condense ? [] : null;
1167 | var saveQuoteStrings = quoteStrings, saveMultiline = multiline;
1168 | var iseparator = separator ? '' : token.com[0];
1169 | var cwrapLen = 0;
1170 |
1171 | var i, length; // loop
1172 | var k, v, vs; // key, value
1173 | var c, ca;
1174 | var res, cres;
1175 |
1176 | if (isArray) {
1177 | // The value is an array. Stringify every element. Use null as a placeholder
1178 | // for non-JSON values.
1179 |
1180 | for (i = 0, length = value.length; i < length; i++) {
1181 | setsep = i < length -1;
1182 | if (comments) {
1183 | c = comments.a[i]||[];
1184 | ca = commentOnThisLine(c[1]);
1185 | partial.push(makeComment(c[0], "\n") + eolGap);
1186 | if (cpartial && (c[0] || c[1] || ca)) cpartial = null;
1187 | }
1188 | else partial.push(eolGap);
1189 | wrapLen = 0;
1190 | v = value[i];
1191 | partial.push(str(v, comments ? ca : false, true) + (setsep ? separator : ''));
1192 | if (cpartial) {
1193 | // prepare the condensed version
1194 | switch (typeof v) {
1195 | case 'string':
1196 | wrapLen = 0;
1197 | quoteStrings = true; multiline = 0;
1198 | cpartial.push(str(v, false, true) + (setsep ? token.com[0] : ''));
1199 | quoteStrings = saveQuoteStrings; multiline = saveMultiline;
1200 | break;
1201 | case 'object': if (v) { cpartial = null; break; } // falls through
1202 | default: cpartial.push(partial[partial.length - 1] + (setsep ? iseparator : '')); break;
1203 | }
1204 | if (setsep) wrapLen += token.com[0].length - token.com[2];
1205 | cwrapLen += wrapLen;
1206 | }
1207 | if (comments && c[1]) partial.push(makeComment(c[1], ca ? " " : "\n", ca));
1208 | }
1209 |
1210 | if (length === 0) {
1211 | // when empty
1212 | if (comments && comments.e) partial.push(makeComment(comments.e[0], "\n") + eolMind);
1213 | }
1214 | else partial.push(eolMind);
1215 |
1216 | // Join all of the elements together, separated with newline, and wrap them in
1217 | // brackets.
1218 |
1219 | if (partial.length === 0) res = wrap(token.arr, '');
1220 | else {
1221 | res = prefix + wrap(token.arr, partial.join(''));
1222 | // try if the condensed version can fit (parent key name is not included)
1223 | if (cpartial) {
1224 | cres = cpartial.join(' ');
1225 | if (cres.length - cwrapLen <= condense) res = wrap(token.arr, cres);
1226 | }
1227 | }
1228 | } else {
1229 | // Otherwise, iterate through all of the keys in the object.
1230 | var commentKeys = comments ? comments.o.slice() : [];
1231 | var objectKeys = [];
1232 | for (k in value) {
1233 | if (Object.prototype.hasOwnProperty.call(value, k) && commentKeys.indexOf(k) < 0)
1234 | objectKeys.push(k);
1235 | }
1236 | if(sortProps) {
1237 | objectKeys.sort();
1238 | }
1239 | var keys = commentKeys.concat(objectKeys);
1240 |
1241 | for (i = 0, length = keys.length; i < length; i++) {
1242 | setsep = i < length - 1;
1243 | k = keys[i];
1244 | if (comments) {
1245 | c = comments.c[k]||[];
1246 | ca = commentOnThisLine(c[1]);
1247 | partial.push(makeComment(c[0], "\n") + eolGap);
1248 | if (cpartial && (c[0] || c[1] || ca)) cpartial = null;
1249 | }
1250 | else partial.push(eolGap);
1251 |
1252 | wrapLen = 0;
1253 | v = value[k];
1254 | vs = str(v, comments && ca);
1255 | partial.push(quoteKey(k) + token.col[0] + (startsWithNL(vs) ? '' : ' ') + vs + (setsep ? separator : ''));
1256 | if (comments && c[1]) partial.push(makeComment(c[1], ca ? " " : "\n", ca));
1257 | if (cpartial) {
1258 | // prepare the condensed version
1259 | switch (typeof v) {
1260 | case 'string':
1261 | wrapLen = 0;
1262 | quoteStrings = true; multiline = 0;
1263 | vs = str(v, false);
1264 | quoteStrings = saveQuoteStrings; multiline = saveMultiline;
1265 | cpartial.push(quoteKey(k) + token.col[0] + ' ' + vs + (setsep ? token.com[0] : ''));
1266 | break;
1267 | case 'object': if (v) { cpartial = null; break; } // falls through
1268 | default: cpartial.push(partial[partial.length - 1] + (setsep ? iseparator : '')); break;
1269 | }
1270 | wrapLen += token.col[0].length - token.col[2];
1271 | if (setsep) wrapLen += token.com[0].length - token.com[2];
1272 | cwrapLen += wrapLen;
1273 | }
1274 | }
1275 | if (length === 0) {
1276 | // when empty
1277 | if (comments && comments.e) partial.push(makeComment(comments.e[0], "\n") + eolMind);
1278 | }
1279 | else partial.push(eolMind);
1280 |
1281 | // Join all of the member texts together, separated with newlines
1282 | if (partial.length === 0) {
1283 | res = wrap(token.obj, '');
1284 | } else {
1285 | // and wrap them in braces
1286 | res = prefix + wrap(token.obj, partial.join(''));
1287 | // try if the condensed version can fit
1288 | if (cpartial) {
1289 | cres = cpartial.join(' ');
1290 | if (cres.length - cwrapLen <= condense) res = wrap(token.obj, cres);
1291 | }
1292 | }
1293 | }
1294 |
1295 | gap = mind;
1296 | return res;
1297 | }
1298 | }
1299 |
1300 |
1301 | runDsf = dsf.loadDsf(dsfDef, 'stringify');
1302 |
1303 | var res = "";
1304 | var comments = keepComments ? comments = (common.getComment(data) || {}).r : null;
1305 | if (comments && comments[0]) res = comments[0] + '\n';
1306 |
1307 | // get the result of stringifying the data.
1308 | res += str(data, null, true, true);
1309 |
1310 | if (comments) res += comments[1]||"";
1311 |
1312 | return res;
1313 | };
1314 |
1315 | },{"./hjson-common":2,"./hjson-dsf":3}],6:[function(require,module,exports){
1316 | module.exports="3.2.1";
1317 |
1318 | },{}],7:[function(require,module,exports){
1319 | /*!
1320 | * Hjson v3.2.1
1321 | * https://hjson.github.io
1322 | *
1323 | * Copyright 2014-2017 Christian Zangl, MIT license
1324 | * Details and documentation:
1325 | * https://github.com/hjson/hjson-js
1326 | *
1327 | * This code is based on the the JSON version by Douglas Crockford:
1328 | * https://github.com/douglascrockford/JSON-js (json_parse.js, json2.js)
1329 | */
1330 |
1331 | /*
1332 |
1333 | This file creates a Hjson object:
1334 |
1335 |
1336 | Hjson.parse(text, options)
1337 |
1338 | options {
1339 | keepWsc boolean, keep white space and comments. This is useful
1340 | if you want to edit an hjson file and save it while
1341 | preserving comments (default false)
1342 |
1343 | dsf array of DSF (see Hjson.dsf)
1344 |
1345 | legacyRoot boolean, support omitting root braces (default true)
1346 | }
1347 |
1348 | This method parses Hjson text to produce an object or array.
1349 | It can throw a SyntaxError exception.
1350 |
1351 |
1352 | Hjson.stringify(value, options)
1353 |
1354 | value any JavaScript value, usually an object or array.
1355 |
1356 | options { all options are
1357 |
1358 | keepWsc boolean, keep white space. See parse.
1359 |
1360 | condense integer, will try to fit objects/arrays onto one line
1361 | when the output is shorter than condense characters
1362 | and the fragment contains no comments. Default 0 (off).
1363 |
1364 | bracesSameLine
1365 | boolean, makes braces appear on the same line as the key
1366 | name. Default false.
1367 |
1368 | quotes string, controls how strings are displayed.
1369 | setting separator implies "strings"
1370 | "min" - no quotes whenever possible (default)
1371 | "keys" - use quotes around keys
1372 | "strings" - use quotes around string values
1373 | "all" - use quotes around keys and string values
1374 |
1375 | multiline string, controls how multiline strings are displayed.
1376 | setting quotes implies "off"
1377 | "std" - strings containing \n are shown in
1378 | multiline format (default)
1379 | "no-tabs" - like std but disallow tabs
1380 | "off" - show in JSON format
1381 |
1382 | separator boolean, output a comma separator between elements. Default false.
1383 |
1384 | space specifies the indentation of nested structures. If it is
1385 | a number, it will specify the number of spaces to indent
1386 | at each level. If it is a string (such as '\t' or ' '),
1387 | it contains the characters used to indent at each level.
1388 |
1389 | eol specifies the EOL sequence (default is set by
1390 | Hjson.setEndOfLine())
1391 |
1392 | colors boolean, output ascii color codes
1393 |
1394 | dsf array of DSF (see Hjson.dsf)
1395 |
1396 | emitRootBraces
1397 | obsolete: will always emit braces
1398 |
1399 | sortProps
1400 | When serializing objects into hjson, order the keys based on
1401 | their UTF-16 code units order
1402 | }
1403 |
1404 | This method produces Hjson text from a JavaScript value.
1405 |
1406 | Values that do not have JSON representations, such as undefined or
1407 | functions, will not be serialized. Such values in objects will be
1408 | dropped; in arrays they will be replaced with null.
1409 | stringify(undefined) returns undefined.
1410 |
1411 |
1412 | Hjson.endOfLine()
1413 | Hjson.setEndOfLine(eol)
1414 |
1415 | Gets or sets the stringify EOL sequence ('\n' or '\r\n').
1416 | When running with node.js this defaults to os.EOL.
1417 |
1418 |
1419 | Hjson.rt { parse, stringify }
1420 |
1421 | This is a shortcut to roundtrip your comments when reading and updating
1422 | a config file. It is the same as specifying the keepWsc option for the
1423 | parse and stringify functions.
1424 |
1425 |
1426 | Hjson.version
1427 |
1428 | The version of this library.
1429 |
1430 |
1431 | Hjson.dsf
1432 |
1433 | Domain specific formats are extensions to the Hjson syntax (see
1434 | hjson.github.io). These formats will be parsed and made available to
1435 | the application in place of strings (e.g. enable math to allow
1436 | NaN values).
1437 |
1438 | Hjson.dsf ontains standard DSFs that can be passed to parse
1439 | and stringify.
1440 |
1441 |
1442 | Hjson.dsf.math()
1443 |
1444 | Enables support for Inf/inf, -Inf/-inf, Nan/naN and -0.
1445 | Will output as Inf, -Inf, NaN and -0.
1446 |
1447 |
1448 | Hjson.dsf.hex(options)
1449 |
1450 | Parse hexadecimal numbers prefixed with 0x.
1451 | set options.out = true to stringify _all_ integers as hex.
1452 |
1453 |
1454 | Hjson.dsf.date(options)
1455 |
1456 | support ISO dates
1457 |
1458 |
1459 | This is a reference implementation. You are free to copy, modify, or
1460 | redistribute.
1461 |
1462 | */
1463 |
1464 | "use strict";
1465 |
1466 | var common = require("./hjson-common");
1467 | var version = require("./hjson-version");
1468 | var parse = require("./hjson-parse");
1469 | var stringify = require("./hjson-stringify");
1470 | var comments = require("./hjson-comments");
1471 | var dsf = require("./hjson-dsf");
1472 |
1473 | module.exports={
1474 |
1475 | parse: parse,
1476 | stringify: stringify,
1477 |
1478 | endOfLine: function() { return common.EOL; },
1479 | setEndOfLine: function(eol) {
1480 | if (eol === '\n' || eol === '\r\n') common.EOL = eol;
1481 | },
1482 |
1483 | version: version,
1484 |
1485 | // round trip shortcut
1486 | rt: {
1487 | parse: function(text, options) {
1488 | (options=options||{}).keepWsc=true;
1489 | return parse(text, options);
1490 | },
1491 | stringify: function(value, options) {
1492 | (options=options||{}).keepWsc=true;
1493 | return stringify(value, options);
1494 | },
1495 | },
1496 |
1497 | comments: comments,
1498 |
1499 | dsf: dsf.std,
1500 |
1501 | };
1502 |
1503 | },{"./hjson-comments":1,"./hjson-common":2,"./hjson-dsf":3,"./hjson-parse":4,"./hjson-stringify":5,"./hjson-version":6}],8:[function(require,module,exports){
1504 |
1505 | },{}]},{},[7])(7);
1506 | });
1507 |
--------------------------------------------------------------------------------