Repository: aseemk/json5
Branch: main
Commit: b935d4a280ea
Files: 38
Total size: 137.2 KB
Directory structure:
gitextract_m1gwni37/
├── .editorconfig
├── .eslintignore
├── .eslintrc.json
├── .github/
│ ├── issue_template.md
│ └── pull_request_template.md
├── .gitignore
├── .travis.yml
├── CHANGELOG.md
├── CONTRIBUTING.md
├── LICENSE.md
├── README.md
├── SECURITY.md
├── build/
│ ├── es5.js
│ ├── package.js
│ └── unicode.js
├── lib/
│ ├── cli.js
│ ├── index.d.ts
│ ├── index.js
│ ├── parse.d.ts
│ ├── parse.js
│ ├── register.js
│ ├── require.js
│ ├── stringify.d.ts
│ ├── stringify.js
│ ├── unicode.d.ts
│ ├── unicode.js
│ ├── util.d.ts
│ └── util.js
├── package.json
├── package.json5
├── rollup.config.js
└── test/
├── cli.js
├── errors.js
├── invalid.json5
├── parse.js
├── require.js
├── stringify.js
└── test.json5
================================================
FILE CONTENTS
================================================
================================================
FILE: .editorconfig
================================================
# EditorConfig is awesome: http://EditorConfig.org
root = true
[*]
indent_style = space
indent_size = 4
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[package.json]
indent_size = 2
[*.md]
indent_size = 2
trim_trailing_whitespace = false
[*.yml]
indent_size = 2
================================================
FILE: .eslintignore
================================================
coverage/
dist/
================================================
FILE: .eslintrc.json
================================================
{
"root": true,
"extends": [
"standard",
"plugin:node/recommended"
],
"rules": {
"array-bracket-spacing": [
"error",
"never"
],
"arrow-parens": [
"error",
"as-needed"
],
"comma-dangle": [
"error",
"always-multiline"
],
"indent": [
"error",
4
],
"no-process-exit": "off",
"object-curly-spacing": [
"error",
"never"
]
}
}
================================================
FILE: .github/issue_template.md
================================================
If you are reporting a security vulnerability, please do not submit an issue.
Instead, follow the guidelines described in our
[security policy](../blob/main/SECURITY.md).
If you are submitting a bug report because you are receiving an error or because
this project is incompatible with the [official JSON5 specification][spec],
please continue.
If you are submitting a feature request or code improvement that is compatible
with the [official JSON5 specification][spec], please continue.
> An example of this is adding a `quote` option to `stringify()` that allows the
> user to chose which quote character is used.
If you are submitting a feature request or code improvement that is
*incompatible* with the [official JSON5 specification][spec], please open an
issue on the [specification repository](https://github.com/json5/json5-spec)
instead.
> An example of this is adding first class support for `Date` or `RegExp`
> objects to the JSON5 format. This is outside the scope of this project.
[spec]: https://json5.github.io/json5-spec/
Thank you for your cooperation. You may delete this message and the instructions
above.
================================================
FILE: .github/pull_request_template.md
================================================
If you are patching a security vulnerability, please do not submit a pull
request. Instead, follow the guidelines described in our
[security policy](../blob/main/SECURITY.md).
If you are submitting a bug fix for an error or fixing an incompatibility
with the [official JSON5 specification][spec], please continue.
If you are submitting a feature request or code improvement that is compatible
with the [official JSON5 specification][spec], please continue.
> An example of this is adding a `quote` option to `stringify()` that allows the
> user to chose which quote character is used.
If you are submitting a feature request or code improvement that is
*incompatible* with the [official JSON5 specification][spec], please open a pull
request on the [specification repository](https://github.com/json5/json5-spec)
instead.
> An example of this is adding first class support for `Date` or `RegExp`
> objects to the JSON5 format. This is outside the scope of this project.
[spec]: https://json5.github.io/json5-spec/
Thank you for your cooperation. You may delete this message and the instructions
above.
================================================
FILE: .gitignore
================================================
# Logs
logs
*.log
npm-debug.log*
# Runtime data
pids
*.pid
*.seed
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
# nyc test coverage
.nyc_output
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# node-waf configuration
.lock-wscript
# Compiled binary addons (http://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules
jspm_packages
# Optional npm cache directory
.npm
# Optional REPL history
.node_repl_history
.vscode/
dist/
test/output.json
test/test.json
================================================
FILE: .travis.yml
================================================
language: node_js
node_js:
- "11"
- "10"
- "8"
================================================
FILE: CHANGELOG.md
================================================
### Unreleased [[code][c-unreleased], [diff][d-unreleased]]
[c-unreleased]: https://github.com/json5/json5/tree/main
[d-unreleased]: https://github.com/json5/json5/compare/v2.2.3...HEAD
### v2.2.3 [[code][c2.2.3], [diff][d2.2.3]]
[c2.2.3]: https://github.com/json5/json5/tree/v2.2.3
[d2.2.3]: https://github.com/json5/json5/compare/v2.2.2...v2.2.3
- Fix: json5@2.2.3 is now the 'latest' release according to npm instead of
v1.0.2. ([#299])
### v2.2.2 [[code][c2.2.2], [diff][d2.2.2]]
[c2.2.2]: https://github.com/json5/json5/tree/v2.2.2
[d2.2.2]: https://github.com/json5/json5/compare/v2.2.1...v2.2.2
- Fix: Properties with the name `__proto__` are added to objects and arrays.
([#199]) This also fixes a prototype pollution vulnerability reported by
Jonathan Gregson! ([#295]).
### v2.2.1 [[code][c2.2.1], [diff][d2.2.1]]
[c2.2.1]: https://github.com/json5/json5/tree/v2.2.1
[d2.2.1]: https://github.com/json5/json5/compare/v2.2.0...v2.2.1
- Fix: Removed dependence on minimist to patch CVE-2021-44906. ([#266])
### v2.2.0 [[code][c2.2.0], [diff][d2.2.0]]
[c2.2.0]: https://github.com/json5/json5/tree/v2.2.0
[d2.2.0]: https://github.com/json5/json5/compare/v2.1.3...v2.2.0
- New: Accurate and documented TypeScript declarations are now included. There
is no need to install `@types/json5`. ([#236], [#244])
### v2.1.3 [[code][c2.1.3], [diff][d2.1.3]]
[c2.1.3]: https://github.com/json5/json5/tree/v2.1.3
[d2.1.3]: https://github.com/json5/json5/compare/v2.1.2...v2.1.3
- Fix: An out of memory bug when parsing numbers has been fixed. ([#228],
[#229])
### v2.1.2 [[code][c2.1.2], [diff][d2.1.2]]
[c2.1.2]: https://github.com/json5/json5/tree/v2.1.2
[d2.1.2]: https://github.com/json5/json5/compare/v2.1.1...v2.1.2
- Fix: Bump `minimist` to `v1.2.5`. ([#222])
### v2.1.1 [[code][c2.1.1], [diff][d2.1.1]]
[c2.1.1]: https://github.com/json5/json5/tree/v2.1.1
[d2.1.1]: https://github.com/json5/json5/compare/v2.0.1...v2.1.1
- New: `package.json` and `package.json5` include a `module` property so
bundlers like webpack, rollup and parcel can take advantage of the ES Module
build. ([#208])
- Fix: `stringify` outputs `\0` as `\\x00` when followed by a digit. ([#210])
- Fix: Spelling mistakes have been fixed. ([#196])
### v2.1.0 [[code][c2.1.0], [diff][d2.1.0]]
[c2.1.0]: https://github.com/json5/json5/tree/v2.1.0
[d2.1.0]: https://github.com/json5/json5/compare/v2.0.1...v2.1.0
- New: The `index.mjs` and `index.min.mjs` browser builds in the `dist`
directory support ES6 modules. ([#187])
### v2.0.1 [[code][c2.0.1], [diff][d2.0.1]]
[c2.0.1]: https://github.com/json5/json5/tree/v2.0.1
[d2.0.1]: https://github.com/json5/json5/compare/v2.0.0...v2.0.1
- Fix: The browser builds in the `dist` directory support ES5. ([#182])
### v2.0.0 [[code][c2.0.0], [diff][d2.0.0]]
[c2.0.0]: https://github.com/json5/json5/tree/v2.0.0
[d2.0.0]: https://github.com/json5/json5/compare/v1.0.1...v2.0.0
- **Major**: JSON5 officially supports Node.js v6 and later. Support for Node.js
v4 has been dropped. Since Node.js v6 supports ES5 features, the code has been
rewritten in native ES5, and the dependence on Babel has been eliminated.
- New: Support for Unicode 10 has been added.
- New: The test framework has been migrated from Mocha to Tap.
- New: The browser build at `dist/index.js` is no longer minified by default. A
minified version is available at `dist/index.min.js`. ([#181])
- Fix: The warning has been made clearer when line and paragraph separators are
used in strings.
- Fix: `package.json5` has been restored, and it is automatically generated and
committed when the version is bumped. A new `build-package` NPM script has
been added to facilitate this.
### v1.0.1 [[code][c1.0.1], [diff][d1.0.1]]
[c1.0.1]: https://github.com/json5/json5/tree/v1.0.1
[d1.0.1]: https://github.com/json5/json5/compare/v1.0.0...v1.0.1
This release includes a bug fix and minor change.
- Fix: `parse` throws on unclosed objects and arrays.
- New: `package.json5` has been removed until an easier way to keep it in sync
with `package.json` is found.
### v1.0.0 [[code][c1.0.0], [diff][d1.0.0]]
[c1.0.0]: https://github.com/json5/json5/tree/v1.0.0
[d1.0.0]: https://github.com/json5/json5/compare/v0.5.1...v1.0.0
This release includes major internal changes and public API enhancements.
- **Major**: JSON5 officially supports Node.js v4 and later. Support for Node.js
v0.10 and v0.12 have been dropped.
- New: Unicode property names and Unicode escapes in property names are
supported. ([#1])
- New: `stringify` outputs trailing commas in objects and arrays when a `space`
option is provided. ([#66])
- New: JSON5 allows line and paragraph separator characters (U+2028 and U+2029)
in strings in order to be compatible with JSON. However, ES5 does not allow
these characters in strings, so JSON5 gives a warning when they are parsed and
escapes them when they are stringified. ([#70])
- New: `stringify` accepts an options object as its second argument. The
supported options are `replacer`, `space`, and a new `quote` option that
specifies the quote character used in strings. ([#71])
- New: The CLI supports STDIN and STDOUT and adds `--out-file`, `--space`, and
`--validate` options. See `json5 --help` for more information. ([#72], [#84],
and [#108])
- New: In addition to the white space characters space `\t`, `\v`, `\f`, `\n`,
`\r`, and `\xA0`, the additional white space characters `\u2028`, `\u2029`,
and all other characters in the Space Separator Unicode category are allowed.
- New: In addition to the character escapes `\'`, `\"`, `\\`, `\b`, `\f`, `\n`,
`\r`, and `\t`, the additional character escapes `\v` and `\0`, hexadecimal
escapes like `\x0F`, and unnecessary escapes like `\a` are allowed in string
values and string property names.
- New: `stringify` outputs strings with single quotes by default but
intelligently uses double quotes if there are more single quotes than double
quotes inside the string. (i.e. `stringify('Stay here.')` outputs
`'Stay here.'` while `stringify('Let\'s go.')` outputs `"Let's go."`)
- New: When a character is not allowed in a string, `stringify` outputs a
character escape like `\t` when available, a hexadecimal escape like `\x0F`
when the Unicode code point is less than 256, or a Unicode character escape
like `\u01FF`, in that order.
- New: `stringify` checks for a `toJSON5` method on objects and, if it exists,
stringifies its return value instead of the object. `toJSON5` overrides
`toJSON` if they both exist.
- New: To `require` or `import` JSON5 files, use `require('json5/lib/register')`
or `import 'json5/lib/register'`. Previous versions used `json5/lib/require`,
which still exists for backward compatibility but is deprecated and will give
a warning.
- New: To use JSON5 in browsers, use the file at `dist/index.js` or
`https://unpkg.com/json5@^1.0.0`.
- Fix: `stringify` properly outputs `Infinity` and `NaN`. ([#67])
- Fix: `isWord` no longer becomes a property of `JSON5` after calling
`stringify`. ([#68] and [#89])
- Fix: `stringify` no longer throws when an object does not have a `prototype`.
([#154])
- Fix: `stringify` properly handles the `key` argument of `toJSON(key)` methods.
`toJSON5(key)` follows this pattern.
- Fix: `stringify` accepts `Number` and `String` objects as its `space`
argument.
- Fix: In addition to a function, `stringify` also accepts an array of keys to
include in the output as its `replacer` argument. Numbers, `Number` objects,
and `String` objects will be converted to a string if they are given as array
values.
### v0.5.1 [[code][c0.5.1], [diff][d0.5.1]]
[c0.5.1]: https://github.com/json5/json5/tree/v0.5.1
[d0.5.1]: https://github.com/json5/json5/compare/v0.5.0...v0.5.1
This release includes a minor fix for indentations when stringifying empty
arrays.
- Fix: Indents no longer appear in empty arrays when stringified. ([#134])
### v0.5.0 [[code][c0.5.0], [diff][d0.5.0]]
[c0.5.0]: https://github.com/json5/json5/tree/v0.5.0
[d0.5.0]: https://github.com/json5/json5/compare/v0.4.0...v0.5.0
This release includes major internal changes and public API enhancements.
- **Major:** JSON5 officially supports Node.js v4 LTS and v5. Support for
Node.js v0.6 and v0.8 have been dropped, while support for v0.10 and v0.12
remain.
- Fix: YUI Compressor no longer fails when compressing json5.js. ([#97])
- New: `parse` and the CLI provide line and column numbers when displaying error
messages. ([#101]; awesome work by [@amb26].)
### v0.4.0 [[code][c0.4.0], [diff][d0.4.0]]
[c0.4.0]: https://github.com/json5/json5/tree/v0.4.0
[d0.4.0]: https://github.com/json5/json5/compare/v0.2.0...v0.4.0
Note that v0.3.0 was tagged, but never published to npm, so this v0.4.0
changelog entry includes v0.3.0 features.
This is a massive release that adds `stringify` support, among other things.
- **Major:** `JSON5.stringify()` now exists!
This method is analogous to the native `JSON.stringify()`;
it just avoids quoting keys where possible.
See the [usage documentation](./README.md#usage) for more.
([#32]; huge thanks and props [@aeisenberg]!)
- New: `NaN` and `-NaN` are now allowed number literals.
([#30]; thanks [@rowanhill].)
- New: Duplicate object keys are now allowed; the last value is used.
This is the same behavior as JSON. ([#57]; thanks [@jordanbtucker].)
- Fix: Properly handle various whitespace and newline cases now.
E.g. JSON5 now properly supports escaped CR and CRLF newlines in strings,
and JSON5 now accepts the same whitespace as JSON (stricter than ES5).
([#58], [#60], and [#63]; thanks [@jordanbtucker].)
- New: Negative hexadecimal numbers (e.g. `-0xC8`) are allowed again.
(They were disallowed in v0.2.0; see below.)
It turns out they *are* valid in ES5, so JSON5 supports them now too.
([#36]; thanks [@jordanbtucker]!)
### v0.2.0 [[code][c0.2.0], [diff][d0.2.0]]
[c0.2.0]: https://github.com/json5/json5/tree/v0.2.0
[d0.2.0]: https://github.com/json5/json5/compare/v0.1.0...v0.2.0
This release fixes some bugs and adds some more utility features to help you
express data more easily:
- **Breaking:** Negative hexadecimal numbers (e.g. `-0xC8`) are rejected now.
While V8 (e.g. Chrome and Node) supported them, it turns out they're invalid
in ES5. This has been [fixed in V8][v8-hex-fix] (and by extension, Chrome
and Node), so JSON5 officially rejects them now, too. ([#36])
- New: Trailing decimal points in decimal numbers are allowed again.
(They were disallowed in v0.1.0; see below.)
They're allowed by ES5, and differentiating between integers and floats may
make sense on some platforms. ([#16]; thanks [@Midar].)
- New: `Infinity` and `-Infinity` are now allowed number literals.
([#30]; thanks [@pepkin88].)
- New: Plus signs (`+`) in front of numbers are now allowed, since it can
be helpful in some contexts to explicitly mark numbers as positive.
(E.g. when a property represents changes or deltas.)
- Fix: unescaped newlines in strings are rejected now.
([#24]; thanks [@Midar].)
### v0.1.0 [[code][c0.1.0], [diff][d0.1.0]]
[c0.1.0]: https://github.com/json5/json5/tree/v0.1.0
[d0.1.0]: https://github.com/json5/json5/compare/v0.0.1...v0.1.0
This release tightens JSON5 support and adds helpful utility features:
- New: Support hexadecimal numbers. (Thanks [@MaxNanasy].)
- Fix: Reject octal numbers properly now. Previously, they were accepted but
improperly parsed as base-10 numbers. (Thanks [@MaxNanasy].)
- **Breaking:** Reject "noctal" numbers now (base-10 numbers that begin with a
leading zero). These are disallowed by both JSON5 and JSON, as well as by
ES5's strict mode. (Thanks [@MaxNanasy].)
- New: Support leading decimal points in decimal numbers.
(Thanks [@MaxNanasy].)
- **Breaking:** Reject trailing decimal points in decimal numbers now. These
are disallowed by both JSON5 and JSON. (Thanks [@MaxNanasy].)
- **Breaking:** Reject omitted elements in arrays now. These are disallowed by
both JSON5 and JSON.
- Fix: Throw proper `SyntaxError` instances on errors now.
- New: Add Node.js `require()` hook. Register via `json5/lib/require`.
- New: Add Node.js `json5` executable to compile JSON5 files to JSON.
### v0.0.1 [[code][c0.0.1], [diff][d0.0.1]]
[c0.0.1]: https://github.com/json5/json5/tree/v0.0.1
[d0.0.1]: https://github.com/json5/json5/compare/v0.0.0...v0.0.1
This was the first implementation of this JSON5 parser.
- Support unquoted object keys, including reserved words. Unicode characters
and escape sequences aren't yet supported.
- Support single-quoted strings.
- Support multi-line strings.
- Support trailing commas in arrays and objects.
- Support comments, both inline and block.
### v0.0.0 [[code](https://github.com/json5/json5/tree/v0.0.0)]
Let's consider this to be Douglas Crockford's original [json_parse.js] — a
parser for the regular JSON format.
[json_parse.js]: https://github.com/douglascrockford/JSON-js/blob/master/json_parse.js
[v8-hex-fix]: http://code.google.com/p/v8/issues/detail?id=2240
[@MaxNanasy]: https://github.com/MaxNanasy
[@Midar]: https://github.com/Midar
[@pepkin88]: https://github.com/pepkin88
[@rowanhill]: https://github.com/rowanhill
[@aeisenberg]: https://github.com/aeisenberg
[@jordanbtucker]: https://github.com/jordanbtucker
[@amb26]: https://github.com/amb26
[#1]: https://github.com/json5/json5/issues/1
[#16]: https://github.com/json5/json5/issues/16
[#24]: https://github.com/json5/json5/issues/24
[#30]: https://github.com/json5/json5/issues/30
[#32]: https://github.com/json5/json5/issues/32
[#36]: https://github.com/json5/json5/issues/36
[#57]: https://github.com/json5/json5/issues/57
[#58]: https://github.com/json5/json5/pull/58
[#60]: https://github.com/json5/json5/pull/60
[#63]: https://github.com/json5/json5/pull/63
[#66]: https://github.com/json5/json5/issues/66
[#67]: https://github.com/json5/json5/issues/67
[#68]: https://github.com/json5/json5/issues/68
[#70]: https://github.com/json5/json5/issues/70
[#71]: https://github.com/json5/json5/issues/71
[#72]: https://github.com/json5/json5/issues/72
[#84]: https://github.com/json5/json5/pull/84
[#89]: https://github.com/json5/json5/pull/89
[#97]: https://github.com/json5/json5/pull/97
[#101]: https://github.com/json5/json5/pull/101
[#108]: https://github.com/json5/json5/pull/108
[#134]: https://github.com/json5/json5/pull/134
[#154]: https://github.com/json5/json5/issues/154
[#181]: https://github.com/json5/json5/issues/181
[#182]: https://github.com/json5/json5/issues/182
[#187]: https://github.com/json5/json5/issues/187
[#196]: https://github.com/json5/json5/issues/196
[#199]: https://github.com/json5/json5/issues/199
[#208]: https://github.com/json5/json5/issues/208
[#210]: https://github.com/json5/json5/issues/210
[#222]: https://github.com/json5/json5/issues/222
[#228]: https://github.com/json5/json5/issues/228
[#229]: https://github.com/json5/json5/issues/229
[#236]: https://github.com/json5/json5/issues/236
[#244]: https://github.com/json5/json5/issues/244
[#266]: https://github.com/json5/json5/issues/266
[#295]: https://github.com/json5/json5/issues/295
[#299]: https://github.com/json5/json5/issues/299
================================================
FILE: CONTRIBUTING.md
================================================
# Contributing to JSON5
We're glad you're interested in contributing to JSON5.
## Development
```sh
git clone https://github.com/json5/json5
cd json5
npm install
```
When contributing code, please write relevant tests and run `npm test` and `npm
run lint` before submitting pull requests. Please use an editor that supports
[EditorConfig](http://editorconfig.org/).
## Issues
To report bugs or request features regarding the JSON5 data format, please
submit an issue to the [official specification
repository](https://github.com/json5/json5-spec).
To report bugs or request features regarding the JavaScript implementation of
JSON5, please submit an issue to this repository.
================================================
FILE: LICENSE.md
================================================
MIT License
Copyright (c) 2012-2018 Aseem Kishore, and [others].
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
[others]: https://github.com/json5/json5/contributors
================================================
FILE: README.md
================================================
# JSON5 – JSON for Humans
[][Build
Status] [][Coverage
Status]
JSON5 is an extension to the popular [JSON] file format that aims to be
easier to **write and maintain _by hand_ (e.g. for config files)**.
It is _not intended_ to be used for machine-to-machine communication.
(Keep using JSON or other file formats for that. 🙂)
JSON5 was started in 2012, and as of 2022, now gets **[>65M downloads/week](https://www.npmjs.com/package/json5)**,
ranks in the **[top 0.1%](https://gist.github.com/anvaka/8e8fa57c7ee1350e3491)** of the most depended-upon packages on npm,
and has been adopted by major projects like
**[Chromium](https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/renderer/platform/runtime_enabled_features.json5;drc=5de823b36e68fd99009a29281b17bc3a1d6b329c),
[Next.js](https://github.com/vercel/next.js/blob/b88f20c90bf4659b8ad5cb2a27956005eac2c7e8/packages/next/lib/find-config.ts#L43-L46),
[Babel](https://babeljs.io/docs/en/config-files#supported-file-extensions),
[Retool](https://community.retool.com/t/i-am-attempting-to-append-several-text-fields-to-a-google-sheet-but-receiving-a-json5-invalid-character-error/7626),
[WebStorm](https://www.jetbrains.com/help/webstorm/json.html),
and [more](https://github.com/json5/json5/wiki/In-the-Wild)**.
It's also natively supported on **[Apple platforms](https://developer.apple.com/documentation/foundation/jsondecoder/3766916-allowsjson5)**
like **macOS** and **iOS**.
Formally, the **[JSON5 Data Interchange Format](https://spec.json5.org/)** is a superset of JSON
(so valid JSON files will always be valid JSON5 files)
that expands its syntax to include some productions from [ECMAScript 5.1] (ES5).
It's also a _subset_ of ES5, so valid JSON5 files will always be valid ES5.[*](#ecmascript-compatibility)
This JavaScript library is a reference implementation for JSON5 parsing and serialization,
and is directly used in many of the popular projects mentioned above
(where e.g. extreme performance isn't necessary),
but others have created [many other libraries](https://github.com/json5/json5/wiki/In-the-Wild)
across many other platforms.
[Build Status]: https://app.travis-ci.com/json5/json5
[Coverage Status]: https://coveralls.io/github/json5/json5
[JSON]: https://tools.ietf.org/html/rfc7159
[ECMAScript 5.1]: https://www.ecma-international.org/ecma-262/5.1/
## Summary of Features
The following ECMAScript 5.1 features, which are not supported in JSON, have
been extended to JSON5.
### Objects
- Object keys may be an ECMAScript 5.1 _[IdentifierName]_.
- Objects may have a single trailing comma.
### Arrays
- Arrays may have a single trailing comma.
### Strings
- Strings may be single quoted.
- Strings may span multiple lines by escaping new line characters.
- Strings may include character escapes.
### Numbers
- Numbers may be hexadecimal.
- Numbers may have a leading or trailing decimal point.
- Numbers may be [IEEE 754] positive infinity, negative infinity, and NaN.
- Numbers may begin with an explicit plus sign.
### Comments
- Single and multi-line comments are allowed.
### White Space
- Additional white space characters are allowed.
[IdentifierName]: https://www.ecma-international.org/ecma-262/5.1/#sec-7.6
[IEEE 754]: http://ieeexplore.ieee.org/servlet/opac?punumber=4610933
## Example
Kitchen-sink example:
```js
{
// comments
unquoted: 'and you can quote me on that',
singleQuotes: 'I can use "double quotes" here',
lineBreaks: "Look, Mom! \
No \\n's!",
hexadecimal: 0xdecaf,
leadingDecimalPoint: .8675309, andTrailing: 8675309.,
positiveSign: +1,
trailingComma: 'in objects', andIn: ['arrays',],
"backwardsCompatible": "with JSON",
}
```
A more real-world example is [this config file](https://github.com/chromium/chromium/blob/feb3c9f670515edf9a88f185301cbd7794ee3e52/third_party/blink/renderer/platform/runtime_enabled_features.json5)
from the Chromium/Blink project.
## Specification
For a detailed explanation of the JSON5 format, please read the [official
specification](https://json5.github.io/json5-spec/).
## Installation and Usage
### Node.js
```sh
npm install json5
```
#### CommonJS
```js
const JSON5 = require('json5')
```
#### Modules
```js
import JSON5 from 'json5'
```
### Browsers
#### UMD
```html
<!-- This will create a global `JSON5` variable. -->
<script src="https://unpkg.com/json5@2/dist/index.min.js"></script>
```
#### Modules
```html
<script type="module">
import JSON5 from 'https://unpkg.com/json5@2/dist/index.min.mjs'
</script>
```
## API
The JSON5 API is compatible with the [JSON API].
[JSON API]:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON
### JSON5.parse()
Parses a JSON5 string, constructing the JavaScript value or object described by
the string. An optional reviver function can be provided to perform a
transformation on the resulting object before it is returned.
#### Syntax
JSON5.parse(text[, reviver])
#### Parameters
- `text`: The string to parse as JSON5.
- `reviver`: If a function, this prescribes how the value originally produced by
parsing is transformed, before being returned.
#### Return value
The object corresponding to the given JSON5 text.
### JSON5.stringify()
Converts a JavaScript value to a JSON5 string, optionally replacing values if a
replacer function is specified, or optionally including only the specified
properties if a replacer array is specified.
#### Syntax
JSON5.stringify(value[, replacer[, space]])
JSON5.stringify(value[, options])
#### Parameters
- `value`: The value to convert to a JSON5 string.
- `replacer`: A function that alters the behavior of the stringification
process, or an array of String and Number objects that serve as a whitelist
for selecting/filtering the properties of the value object to be included in
the JSON5 string. If this value is null or not provided, all properties of the
object are included in the resulting JSON5 string.
- `space`: A String or Number object that's used to insert white space into the
output JSON5 string for readability purposes. If this is a Number, it
indicates the number of space characters to use as white space; this number is
capped at 10 (if it is greater, the value is just 10). Values less than 1
indicate that no space should be used. If this is a String, the string (or the
first 10 characters of the string, if it's longer than that) is used as white
space. If this parameter is not provided (or is null), no white space is used.
If white space is used, trailing commas will be used in objects and arrays.
- `options`: An object with the following properties:
- `replacer`: Same as the `replacer` parameter.
- `space`: Same as the `space` parameter.
- `quote`: A String representing the quote character to use when serializing
strings.
#### Return value
A JSON5 string representing the value.
### Node.js `require()` JSON5 files
When using Node.js, you can `require()` JSON5 files by adding the following
statement.
```js
require('json5/lib/register')
```
Then you can load a JSON5 file with a Node.js `require()` statement. For
example:
```js
const config = require('./config.json5')
```
## CLI
Since JSON is more widely used than JSON5, this package includes a CLI for
converting JSON5 to JSON and for validating the syntax of JSON5 documents.
### Installation
```sh
npm install --global json5
```
### Usage
```sh
json5 [options] <file>
```
If `<file>` is not provided, then STDIN is used.
#### Options:
- `-s`, `--space`: The number of spaces to indent or `t` for tabs
- `-o`, `--out-file [file]`: Output to the specified file, otherwise STDOUT
- `-v`, `--validate`: Validate JSON5 but do not output JSON
- `-V`, `--version`: Output the version number
- `-h`, `--help`: Output usage information
## Contributing
### Development
```sh
git clone https://github.com/json5/json5
cd json5
npm install
```
When contributing code, please write relevant tests and run `npm test` and `npm
run lint` before submitting pull requests. Please use an editor that supports
[EditorConfig](http://editorconfig.org/).
### Issues
To report bugs or request features regarding the JSON5 **data format**,
please submit an issue to the official
**[_specification_ repository](https://github.com/json5/json5-spec)**.
Note that we will never add any features that make JSON5 incompatible with ES5;
that compatibility is a fundamental premise of JSON5.[*](#ecmascript-compatibility)
To report bugs or request features regarding this **JavaScript implementation**
of JSON5, please submit an issue to **_this_ repository**.
### Security Vulnerabilities and Disclosures
To report a security vulnerability, please follow the follow the guidelines
described in our [security policy](./SECURITY.md).
## ECMAScript Compatibility
While JSON5 aims to be fully compatible with ES5, there is one exception where
both JSON and JSON5 are not. Both JSON and JSON5 allow unescaped line and
paragraph separator characters (U+2028 and U+2029) in strings, however ES5 does
not. A [proposal](https://github.com/tc39/proposal-json-superset) to allow these
characters in strings was adopted into ES2019, making JSON and JSON5 fully
compatible with ES2019.
## License
MIT. See [LICENSE.md](./LICENSE.md) for details.
## Credits
[Aseem Kishore](https://github.com/aseemk) founded this project.
He wrote a [blog post](https://aseemk.substack.com/p/ignore-the-f-ing-haters-json5)
about the journey and lessons learned 10 years in.
[Michael Bolin](http://bolinfest.com/) independently arrived at and published
some of these same ideas with awesome explanations and detail. Recommended
reading: [Suggested Improvements to JSON](http://bolinfest.com/essays/json.html)
[Douglas Crockford](http://www.crockford.com/) of course designed and built
JSON, but his state machine diagrams on the [JSON website](http://json.org/), as
cheesy as it may sound, gave us motivation and confidence that building a new
parser to implement these ideas was within reach! The original
implementation of JSON5 was also modeled directly off of Doug’s open-source
[json_parse.js] parser. We’re grateful for that clean and well-documented
code.
[json_parse.js]:
https://github.com/douglascrockford/JSON-js/blob/03157639c7a7cddd2e9f032537f346f1a87c0f6d/json_parse.js
[Max Nanasy](https://github.com/MaxNanasy) has been an early and prolific
supporter, contributing multiple patches and ideas.
[Andrew Eisenberg](https://github.com/aeisenberg) contributed the original
`stringify` method.
[Jordan Tucker](https://github.com/jordanbtucker) has aligned JSON5 more closely
with ES5, wrote the official JSON5 specification, completely rewrote the
codebase from the ground up, and is actively maintaining this project.
================================================
FILE: SECURITY.md
================================================
# JSON5 Security Policy
We take security seriously. Responsible reporting and disclosure of security
vulnerabilities is important for the protection and privacy of our users. If you
discover any security vulnerabilities, please follow these guidelines.
Published security advisories are available on our [GitHub Security Advisories]
page.
To report a vulnerability, please draft a [new security advisory on GitHub]. Any
fields that you are unsure of or don't understand can be left at their default
values. The important part is that the vulnerability is reported. Once the
security advisory draft has been created, we will validate the vulnerability and
coordinate with you to fix it, release a patch, and responsibly disclose the
vulnerability to the public. Read GitHub's documentation on [privately reporting
a security vulnerability] for details.
If you are unable to draft a security advisory, or if you need help or have
security related questions, please send an email to [security@json5.org].
Please do not report undisclosed vulnerabilities on public sites or forums,
including GitHub issues and pull requests. Reporting vulnerabilities to the
public could allow attackers to exploit vulnerable applications before we have
been able to release a patch and before applications have had time to install
the patch. Once we have released a patch and sufficient time has passed for
applications to install the patch, we will disclose the vulnerability to the
public, at which time you will be free to publish details of the vulnerability
on public sites and forums.
If you have a fix for a security vulnerability, please do not submit a GitHub
pull request. Instead, report the vulnerability as described in this policy.
Once we have verified the vulnerability, we can create a [temporary private
fork] to collaborate on a patch.
We appreciate your cooperation in helping keep our users safe by following this
policy.
[github security advisories]: https://github.com/json5/json5/security/advisories
[new security advisory on github]:
https://github.com/json5/json5/security/advisories/new
[privately reporting a security vulnerability]:
https://docs.github.com/en/code-security/security-advisories/guidance-on-reporting-and-writing/privately-reporting-a-security-vulnerability
[security@json5.org]: mailto:security@json5.org
[temporary private fork]:
https://docs.github.com/en/code-security/security-advisories/repository-security-advisories/collaborating-in-a-temporary-private-fork-to-resolve-a-repository-security-vulnerability
================================================
FILE: build/es5.js
================================================
require('core-js/fn/string/code-point-at')
require('core-js/fn/string/from-code-point')
const JSON5 = require('../lib')
module.exports = JSON5
================================================
FILE: build/package.js
================================================
const fs = require('fs')
const path = require('path')
const JSON5 = require('../lib')
const pkg = require('../package.json')
let pkg5 = '// This is a generated file. Do not edit.\n'
pkg5 += pkg5 = JSON5.stringify(pkg, null, 2)
fs.writeFileSync(path.resolve(__dirname, '..', 'package.json5'), pkg5)
================================================
FILE: build/unicode.js
================================================
/* eslint-disable camelcase */
const fs = require('fs')
const path = require('path')
const regenerate = require('regenerate')
const libDir = 'lib'
const Space_Separator = regenerate()
.add(require('unicode-10.0.0/General_Category/Space_Separator/code-points'))
.remove('\t', '\v', '\f', ' ', '\u00A0', '\uFEFF')
const ID_Start = regenerate()
.add(require('unicode-10.0.0/General_Category/Uppercase_Letter/code-points'))
.add(require('unicode-10.0.0/General_Category/Lowercase_Letter/code-points'))
.add(require('unicode-10.0.0/General_Category/Titlecase_Letter/code-points'))
.add(require('unicode-10.0.0/General_Category/Modifier_Letter/code-points'))
.add(require('unicode-10.0.0/General_Category/Other_Letter/code-points'))
.add(require('unicode-10.0.0/General_Category/Letter_Number/code-points'))
.remove('$', '_')
.removeRange('A', 'Z')
.removeRange('a', 'z')
const ID_Continue = regenerate()
.add(ID_Start)
.add(require('unicode-10.0.0/General_Category/Nonspacing_Mark/code-points'))
.add(require('unicode-10.0.0/General_Category/Spacing_Mark/code-points'))
.add(require('unicode-10.0.0/General_Category/Decimal_Number/code-points'))
.add(require('unicode-10.0.0/General_Category/Connector_Punctuation/code-points'))
.remove('$', '_')
.removeRange('0', '9')
.removeRange('A', 'Z')
.removeRange('a', 'z')
const outDir = libDir
const outPath = path.join(outDir, 'unicode.js')
if (!fs.existsSync(outDir)) {
fs.mkdirSync(outDir)
}
const data = {
Space_Separator,
ID_Start,
ID_Continue,
}
let es6 = '// This is a generated file. Do not edit.\n'
es6 += Object.keys(data).map(key => `module.exports.${key} = /${data[key]}/\n`).join('')
fs.writeFileSync(outPath, es6)
================================================
FILE: lib/cli.js
================================================
#!/usr/bin/env node
const fs = require('fs')
const path = require('path')
const pkg = require('../package.json')
const JSON5 = require('./')
const argv = parseArgs()
if (argv.version) {
version()
} else if (argv.help) {
usage()
} else {
const inFilename = argv.defaults[0]
let readStream
if (inFilename) {
readStream = fs.createReadStream(inFilename)
} else {
readStream = process.stdin
}
let json5 = ''
readStream.on('data', data => {
json5 += data
})
readStream.on('end', () => {
let space
if (argv.space === 't' || argv.space === 'tab') {
space = '\t'
} else {
space = Number(argv.space)
}
let value
try {
value = JSON5.parse(json5)
if (!argv.validate) {
const json = JSON.stringify(value, null, space)
let writeStream
// --convert is for backward compatibility with v0.5.1. If
// specified with <file> and not --out-file, then a file with
// the same name but with a .json extension will be written.
if (argv.convert && inFilename && !argv.outFile) {
const parsedFilename = path.parse(inFilename)
const outFilename = path.format(
Object.assign(
parsedFilename,
{base: path.basename(parsedFilename.base, parsedFilename.ext) + '.json'}
)
)
writeStream = fs.createWriteStream(outFilename)
} else if (argv.outFile) {
writeStream = fs.createWriteStream(argv.outFile)
} else {
writeStream = process.stdout
}
writeStream.write(json)
}
} catch (err) {
console.error(err.message)
process.exit(1)
}
})
}
function parseArgs () {
let convert
let space
let validate
let outFile
let version
let help
const defaults = []
const args = process.argv.slice(2)
for (let i = 0; i < args.length; i++) {
const arg = args[i]
switch (arg) {
case '--convert':
case '-c':
convert = true
break
case '--space':
case '-s':
space = args[++i]
break
case '--validate':
case '-v':
validate = true
break
case '--out-file':
case '-o':
outFile = args[++i]
break
case '--version':
case '-V':
version = true
break
case '--help':
case '-h':
help = true
break
default:
defaults.push(arg)
break
}
}
return {
convert,
space,
validate,
outFile,
version,
help,
defaults,
}
}
function version () {
console.log(pkg.version)
}
function usage () {
console.log(
`
Usage: json5 [options] <file>
If <file> is not provided, then STDIN is used.
Options:
-s, --space The number of spaces to indent or 't' for tabs
-o, --out-file [file] Output to the specified file, otherwise STDOUT
-v, --validate Validate JSON5 but do not output JSON
-V, --version Output the version number
-h, --help Output usage information`
)
}
================================================
FILE: lib/index.d.ts
================================================
import parse = require('./parse')
import stringify = require('./stringify')
export {parse, stringify}
================================================
FILE: lib/index.js
================================================
const parse = require('./parse')
const stringify = require('./stringify')
const JSON5 = {
parse,
stringify,
}
module.exports = JSON5
================================================
FILE: lib/parse.d.ts
================================================
/**
* Parses a JSON5 string, constructing the JavaScript value or object described
* by the string.
* @template T The type of the return value.
* @param text The string to parse as JSON5.
* @param reviver A function that prescribes how the value originally produced
* by parsing is transformed before being returned.
* @returns The JavaScript value converted from the JSON5 string.
*/
declare function parse<T = any>(
text: string,
reviver?: ((this: any, key: string, value: any) => any) | null,
): T
export = parse
================================================
FILE: lib/parse.js
================================================
const util = require('./util')
let source
let parseState
let stack
let pos
let line
let column
let token
let key
let root
module.exports = function parse (text, reviver) {
source = String(text)
parseState = 'start'
stack = []
pos = 0
line = 1
column = 0
token = undefined
key = undefined
root = undefined
do {
token = lex()
// This code is unreachable.
// if (!parseStates[parseState]) {
// throw invalidParseState()
// }
parseStates[parseState]()
} while (token.type !== 'eof')
if (typeof reviver === 'function') {
return internalize({'': root}, '', reviver)
}
return root
}
function internalize (holder, name, reviver) {
const value = holder[name]
if (value != null && typeof value === 'object') {
if (Array.isArray(value)) {
for (let i = 0; i < value.length; i++) {
const key = String(i)
const replacement = internalize(value, key, reviver)
if (replacement === undefined) {
delete value[key]
} else {
Object.defineProperty(value, key, {
value: replacement,
writable: true,
enumerable: true,
configurable: true,
})
}
}
} else {
for (const key in value) {
const replacement = internalize(value, key, reviver)
if (replacement === undefined) {
delete value[key]
} else {
Object.defineProperty(value, key, {
value: replacement,
writable: true,
enumerable: true,
configurable: true,
})
}
}
}
}
return reviver.call(holder, name, value)
}
let lexState
let buffer
let doubleQuote
let sign
let c
function lex () {
lexState = 'default'
buffer = ''
doubleQuote = false
sign = 1
for (;;) {
c = peek()
// This code is unreachable.
// if (!lexStates[lexState]) {
// throw invalidLexState(lexState)
// }
const token = lexStates[lexState]()
if (token) {
return token
}
}
}
function peek () {
if (source[pos]) {
return String.fromCodePoint(source.codePointAt(pos))
}
}
function read () {
const c = peek()
if (c === '\n') {
line++
column = 0
} else if (c) {
column += c.length
} else {
column++
}
if (c) {
pos += c.length
}
return c
}
const lexStates = {
default () {
switch (c) {
case '\t':
case '\v':
case '\f':
case ' ':
case '\u00A0':
case '\uFEFF':
case '\n':
case '\r':
case '\u2028':
case '\u2029':
read()
return
case '/':
read()
lexState = 'comment'
return
case undefined:
read()
return newToken('eof')
}
if (util.isSpaceSeparator(c)) {
read()
return
}
// This code is unreachable.
// if (!lexStates[parseState]) {
// throw invalidLexState(parseState)
// }
return lexStates[parseState]()
},
comment () {
switch (c) {
case '*':
read()
lexState = 'multiLineComment'
return
case '/':
read()
lexState = 'singleLineComment'
return
}
throw invalidChar(read())
},
multiLineComment () {
switch (c) {
case '*':
read()
lexState = 'multiLineCommentAsterisk'
return
case undefined:
throw invalidChar(read())
}
read()
},
multiLineCommentAsterisk () {
switch (c) {
case '*':
read()
return
case '/':
read()
lexState = 'default'
return
case undefined:
throw invalidChar(read())
}
read()
lexState = 'multiLineComment'
},
singleLineComment () {
switch (c) {
case '\n':
case '\r':
case '\u2028':
case '\u2029':
read()
lexState = 'default'
return
case undefined:
read()
return newToken('eof')
}
read()
},
value () {
switch (c) {
case '{':
case '[':
return newToken('punctuator', read())
case 'n':
read()
literal('ull')
return newToken('null', null)
case 't':
read()
literal('rue')
return newToken('boolean', true)
case 'f':
read()
literal('alse')
return newToken('boolean', false)
case '-':
case '+':
if (read() === '-') {
sign = -1
}
lexState = 'sign'
return
case '.':
buffer = read()
lexState = 'decimalPointLeading'
return
case '0':
buffer = read()
lexState = 'zero'
return
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
buffer = read()
lexState = 'decimalInteger'
return
case 'I':
read()
literal('nfinity')
return newToken('numeric', Infinity)
case 'N':
read()
literal('aN')
return newToken('numeric', NaN)
case '"':
case "'":
doubleQuote = (read() === '"')
buffer = ''
lexState = 'string'
return
}
throw invalidChar(read())
},
identifierNameStartEscape () {
if (c !== 'u') {
throw invalidChar(read())
}
read()
const u = unicodeEscape()
switch (u) {
case '$':
case '_':
break
default:
if (!util.isIdStartChar(u)) {
throw invalidIdentifier()
}
break
}
buffer += u
lexState = 'identifierName'
},
identifierName () {
switch (c) {
case '$':
case '_':
case '\u200C':
case '\u200D':
buffer += read()
return
case '\\':
read()
lexState = 'identifierNameEscape'
return
}
if (util.isIdContinueChar(c)) {
buffer += read()
return
}
return newToken('identifier', buffer)
},
identifierNameEscape () {
if (c !== 'u') {
throw invalidChar(read())
}
read()
const u = unicodeEscape()
switch (u) {
case '$':
case '_':
case '\u200C':
case '\u200D':
break
default:
if (!util.isIdContinueChar(u)) {
throw invalidIdentifier()
}
break
}
buffer += u
lexState = 'identifierName'
},
sign () {
switch (c) {
case '.':
buffer = read()
lexState = 'decimalPointLeading'
return
case '0':
buffer = read()
lexState = 'zero'
return
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
buffer = read()
lexState = 'decimalInteger'
return
case 'I':
read()
literal('nfinity')
return newToken('numeric', sign * Infinity)
case 'N':
read()
literal('aN')
return newToken('numeric', NaN)
}
throw invalidChar(read())
},
zero () {
switch (c) {
case '.':
buffer += read()
lexState = 'decimalPoint'
return
case 'e':
case 'E':
buffer += read()
lexState = 'decimalExponent'
return
case 'x':
case 'X':
buffer += read()
lexState = 'hexadecimal'
return
}
return newToken('numeric', sign * 0)
},
decimalInteger () {
switch (c) {
case '.':
buffer += read()
lexState = 'decimalPoint'
return
case 'e':
case 'E':
buffer += read()
lexState = 'decimalExponent'
return
}
if (util.isDigit(c)) {
buffer += read()
return
}
return newToken('numeric', sign * Number(buffer))
},
decimalPointLeading () {
if (util.isDigit(c)) {
buffer += read()
lexState = 'decimalFraction'
return
}
throw invalidChar(read())
},
decimalPoint () {
switch (c) {
case 'e':
case 'E':
buffer += read()
lexState = 'decimalExponent'
return
}
if (util.isDigit(c)) {
buffer += read()
lexState = 'decimalFraction'
return
}
return newToken('numeric', sign * Number(buffer))
},
decimalFraction () {
switch (c) {
case 'e':
case 'E':
buffer += read()
lexState = 'decimalExponent'
return
}
if (util.isDigit(c)) {
buffer += read()
return
}
return newToken('numeric', sign * Number(buffer))
},
decimalExponent () {
switch (c) {
case '+':
case '-':
buffer += read()
lexState = 'decimalExponentSign'
return
}
if (util.isDigit(c)) {
buffer += read()
lexState = 'decimalExponentInteger'
return
}
throw invalidChar(read())
},
decimalExponentSign () {
if (util.isDigit(c)) {
buffer += read()
lexState = 'decimalExponentInteger'
return
}
throw invalidChar(read())
},
decimalExponentInteger () {
if (util.isDigit(c)) {
buffer += read()
return
}
return newToken('numeric', sign * Number(buffer))
},
hexadecimal () {
if (util.isHexDigit(c)) {
buffer += read()
lexState = 'hexadecimalInteger'
return
}
throw invalidChar(read())
},
hexadecimalInteger () {
if (util.isHexDigit(c)) {
buffer += read()
return
}
return newToken('numeric', sign * Number(buffer))
},
string () {
switch (c) {
case '\\':
read()
buffer += escape()
return
case '"':
if (doubleQuote) {
read()
return newToken('string', buffer)
}
buffer += read()
return
case "'":
if (!doubleQuote) {
read()
return newToken('string', buffer)
}
buffer += read()
return
case '\n':
case '\r':
throw invalidChar(read())
case '\u2028':
case '\u2029':
separatorChar(c)
break
case undefined:
throw invalidChar(read())
}
buffer += read()
},
start () {
switch (c) {
case '{':
case '[':
return newToken('punctuator', read())
// This code is unreachable since the default lexState handles eof.
// case undefined:
// return newToken('eof')
}
lexState = 'value'
},
beforePropertyName () {
switch (c) {
case '$':
case '_':
buffer = read()
lexState = 'identifierName'
return
case '\\':
read()
lexState = 'identifierNameStartEscape'
return
case '}':
return newToken('punctuator', read())
case '"':
case "'":
doubleQuote = (read() === '"')
lexState = 'string'
return
}
if (util.isIdStartChar(c)) {
buffer += read()
lexState = 'identifierName'
return
}
throw invalidChar(read())
},
afterPropertyName () {
if (c === ':') {
return newToken('punctuator', read())
}
throw invalidChar(read())
},
beforePropertyValue () {
lexState = 'value'
},
afterPropertyValue () {
switch (c) {
case ',':
case '}':
return newToken('punctuator', read())
}
throw invalidChar(read())
},
beforeArrayValue () {
if (c === ']') {
return newToken('punctuator', read())
}
lexState = 'value'
},
afterArrayValue () {
switch (c) {
case ',':
case ']':
return newToken('punctuator', read())
}
throw invalidChar(read())
},
end () {
// This code is unreachable since it's handled by the default lexState.
// if (c === undefined) {
// read()
// return newToken('eof')
// }
throw invalidChar(read())
},
}
function newToken (type, value) {
return {
type,
value,
line,
column,
}
}
function literal (s) {
for (const c of s) {
const p = peek()
if (p !== c) {
throw invalidChar(read())
}
read()
}
}
function escape () {
const c = peek()
switch (c) {
case 'b':
read()
return '\b'
case 'f':
read()
return '\f'
case 'n':
read()
return '\n'
case 'r':
read()
return '\r'
case 't':
read()
return '\t'
case 'v':
read()
return '\v'
case '0':
read()
if (util.isDigit(peek())) {
throw invalidChar(read())
}
return '\0'
case 'x':
read()
return hexEscape()
case 'u':
read()
return unicodeEscape()
case '\n':
case '\u2028':
case '\u2029':
read()
return ''
case '\r':
read()
if (peek() === '\n') {
read()
}
return ''
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
throw invalidChar(read())
case undefined:
throw invalidChar(read())
}
return read()
}
function hexEscape () {
let buffer = ''
let c = peek()
if (!util.isHexDigit(c)) {
throw invalidChar(read())
}
buffer += read()
c = peek()
if (!util.isHexDigit(c)) {
throw invalidChar(read())
}
buffer += read()
return String.fromCodePoint(parseInt(buffer, 16))
}
function unicodeEscape () {
let buffer = ''
let count = 4
while (count-- > 0) {
const c = peek()
if (!util.isHexDigit(c)) {
throw invalidChar(read())
}
buffer += read()
}
return String.fromCodePoint(parseInt(buffer, 16))
}
const parseStates = {
start () {
if (token.type === 'eof') {
throw invalidEOF()
}
push()
},
beforePropertyName () {
switch (token.type) {
case 'identifier':
case 'string':
key = token.value
parseState = 'afterPropertyName'
return
case 'punctuator':
// This code is unreachable since it's handled by the lexState.
// if (token.value !== '}') {
// throw invalidToken()
// }
pop()
return
case 'eof':
throw invalidEOF()
}
// This code is unreachable since it's handled by the lexState.
// throw invalidToken()
},
afterPropertyName () {
// This code is unreachable since it's handled by the lexState.
// if (token.type !== 'punctuator' || token.value !== ':') {
// throw invalidToken()
// }
if (token.type === 'eof') {
throw invalidEOF()
}
parseState = 'beforePropertyValue'
},
beforePropertyValue () {
if (token.type === 'eof') {
throw invalidEOF()
}
push()
},
beforeArrayValue () {
if (token.type === 'eof') {
throw invalidEOF()
}
if (token.type === 'punctuator' && token.value === ']') {
pop()
return
}
push()
},
afterPropertyValue () {
// This code is unreachable since it's handled by the lexState.
// if (token.type !== 'punctuator') {
// throw invalidToken()
// }
if (token.type === 'eof') {
throw invalidEOF()
}
switch (token.value) {
case ',':
parseState = 'beforePropertyName'
return
case '}':
pop()
}
// This code is unreachable since it's handled by the lexState.
// throw invalidToken()
},
afterArrayValue () {
// This code is unreachable since it's handled by the lexState.
// if (token.type !== 'punctuator') {
// throw invalidToken()
// }
if (token.type === 'eof') {
throw invalidEOF()
}
switch (token.value) {
case ',':
parseState = 'beforeArrayValue'
return
case ']':
pop()
}
// This code is unreachable since it's handled by the lexState.
// throw invalidToken()
},
end () {
// This code is unreachable since it's handled by the lexState.
// if (token.type !== 'eof') {
// throw invalidToken()
// }
},
}
function push () {
let value
switch (token.type) {
case 'punctuator':
switch (token.value) {
case '{':
value = {}
break
case '[':
value = []
break
}
break
case 'null':
case 'boolean':
case 'numeric':
case 'string':
value = token.value
break
// This code is unreachable.
// default:
// throw invalidToken()
}
if (root === undefined) {
root = value
} else {
const parent = stack[stack.length - 1]
if (Array.isArray(parent)) {
parent.push(value)
} else {
Object.defineProperty(parent, key, {
value,
writable: true,
enumerable: true,
configurable: true,
})
}
}
if (value !== null && typeof value === 'object') {
stack.push(value)
if (Array.isArray(value)) {
parseState = 'beforeArrayValue'
} else {
parseState = 'beforePropertyName'
}
} else {
const current = stack[stack.length - 1]
if (current == null) {
parseState = 'end'
} else if (Array.isArray(current)) {
parseState = 'afterArrayValue'
} else {
parseState = 'afterPropertyValue'
}
}
}
function pop () {
stack.pop()
const current = stack[stack.length - 1]
if (current == null) {
parseState = 'end'
} else if (Array.isArray(current)) {
parseState = 'afterArrayValue'
} else {
parseState = 'afterPropertyValue'
}
}
// This code is unreachable.
// function invalidParseState () {
// return new Error(`JSON5: invalid parse state '${parseState}'`)
// }
// This code is unreachable.
// function invalidLexState (state) {
// return new Error(`JSON5: invalid lex state '${state}'`)
// }
function invalidChar (c) {
if (c === undefined) {
return syntaxError(`JSON5: invalid end of input at ${line}:${column}`)
}
return syntaxError(`JSON5: invalid character '${formatChar(c)}' at ${line}:${column}`)
}
function invalidEOF () {
return syntaxError(`JSON5: invalid end of input at ${line}:${column}`)
}
// This code is unreachable.
// function invalidToken () {
// if (token.type === 'eof') {
// return syntaxError(`JSON5: invalid end of input at ${line}:${column}`)
// }
// const c = String.fromCodePoint(token.value.codePointAt(0))
// return syntaxError(`JSON5: invalid character '${formatChar(c)}' at ${line}:${column}`)
// }
function invalidIdentifier () {
column -= 5
return syntaxError(`JSON5: invalid identifier character at ${line}:${column}`)
}
function separatorChar (c) {
console.warn(`JSON5: '${formatChar(c)}' in strings is not valid ECMAScript; consider escaping`)
}
function formatChar (c) {
const replacements = {
"'": "\\'",
'"': '\\"',
'\\': '\\\\',
'\b': '\\b',
'\f': '\\f',
'\n': '\\n',
'\r': '\\r',
'\t': '\\t',
'\v': '\\v',
'\0': '\\0',
'\u2028': '\\u2028',
'\u2029': '\\u2029',
}
if (replacements[c]) {
return replacements[c]
}
if (c < ' ') {
const hexString = c.charCodeAt(0).toString(16)
return '\\x' + ('00' + hexString).substring(hexString.length)
}
return c
}
function syntaxError (message) {
const err = new SyntaxError(message)
err.lineNumber = line
err.columnNumber = column
return err
}
================================================
FILE: lib/register.js
================================================
const fs = require('fs')
const JSON5 = require('./')
// eslint-disable-next-line node/no-deprecated-api
require.extensions['.json5'] = function (module, filename) {
const content = fs.readFileSync(filename, 'utf8')
try {
module.exports = JSON5.parse(content)
} catch (err) {
err.message = filename + ': ' + err.message
throw err
}
}
================================================
FILE: lib/require.js
================================================
// This file is for backward compatibility with v0.5.1.
require('./register')
console.warn("'json5/require' is deprecated. Please use 'json5/register' instead.")
================================================
FILE: lib/stringify.d.ts
================================================
declare type StringifyOptions = {
/**
* A function that alters the behavior of the stringification process, or an
* array of String and Number objects that serve as a allowlist for
* selecting/filtering the properties of the value object to be included in
* the JSON5 string. If this value is null or not provided, all properties
* of the object are included in the resulting JSON5 string.
*/
replacer?:
| ((this: any, key: string, value: any) => any)
| (string | number)[]
| null
/**
* A String or Number object that's used to insert white space into the
* output JSON5 string for readability purposes. If this is a Number, it
* indicates the number of space characters to use as white space; this
* number is capped at 10 (if it is greater, the value is just 10). Values
* less than 1 indicate that no space should be used. If this is a String,
* the string (or the first 10 characters of the string, if it's longer than
* that) is used as white space. If this parameter is not provided (or is
* null), no white space is used. If white space is used, trailing commas
* will be used in objects and arrays.
*/
space?: string | number | null
/**
* A String representing the quote character to use when serializing
* strings.
*/
quote?: string | null
}
/**
* Converts a JavaScript value to a JSON5 string.
* @param value The value to convert to a JSON5 string.
* @param replacer A function that alters the behavior of the stringification
* process. If this value is null or not provided, all properties of the object
* are included in the resulting JSON5 string.
* @param space A String or Number object that's used to insert white space into
* the output JSON5 string for readability purposes. If this is a Number, it
* indicates the number of space characters to use as white space; this number
* is capped at 10 (if it is greater, the value is just 10). Values less than 1
* indicate that no space should be used. If this is a String, the string (or
* the first 10 characters of the string, if it's longer than that) is used as
* white space. If this parameter is not provided (or is null), no white space
* is used. If white space is used, trailing commas will be used in objects and
* arrays.
* @returns The JSON5 string converted from the JavaScript value.
*/
declare function stringify(
value: any,
replacer?: ((this: any, key: string, value: any) => any) | null,
space?: string | number | null,
): string
/**
* Converts a JavaScript value to a JSON5 string.
* @param value The value to convert to a JSON5 string.
* @param replacer An array of String and Number objects that serve as a
* allowlist for selecting/filtering the properties of the value object to be
* included in the JSON5 string. If this value is null or not provided, all
* properties of the object are included in the resulting JSON5 string.
* @param space A String or Number object that's used to insert white space into
* the output JSON5 string for readability purposes. If this is a Number, it
* indicates the number of space characters to use as white space; this number
* is capped at 10 (if it is greater, the value is just 10). Values less than 1
* indicate that no space should be used. If this is a String, the string (or
* the first 10 characters of the string, if it's longer than that) is used as
* white space. If this parameter is not provided (or is null), no white space
* is used. If white space is used, trailing commas will be used in objects and
* arrays.
* @returns The JSON5 string converted from the JavaScript value.
*/
declare function stringify(
value: any,
replacer: (string | number)[],
space?: string | number | null,
): string
/**
* Converts a JavaScript value to a JSON5 string.
* @param value The value to convert to a JSON5 string.
* @param options An object specifying options.
* @returns The JSON5 string converted from the JavaScript value.
*/
declare function stringify(value: any, options: StringifyOptions): string
export = stringify
================================================
FILE: lib/stringify.js
================================================
const util = require('./util')
module.exports = function stringify (value, replacer, space) {
const stack = []
let indent = ''
let propertyList
let replacerFunc
let gap = ''
let quote
if (
replacer != null &&
typeof replacer === 'object' &&
!Array.isArray(replacer)
) {
space = replacer.space
quote = replacer.quote
replacer = replacer.replacer
}
if (typeof replacer === 'function') {
replacerFunc = replacer
} else if (Array.isArray(replacer)) {
propertyList = []
for (const v of replacer) {
let item
if (typeof v === 'string') {
item = v
} else if (
typeof v === 'number' ||
v instanceof String ||
v instanceof Number
) {
item = String(v)
}
if (item !== undefined && propertyList.indexOf(item) < 0) {
propertyList.push(item)
}
}
}
if (space instanceof Number) {
space = Number(space)
} else if (space instanceof String) {
space = String(space)
}
if (typeof space === 'number') {
if (space > 0) {
space = Math.min(10, Math.floor(space))
gap = ' '.substr(0, space)
}
} else if (typeof space === 'string') {
gap = space.substr(0, 10)
}
return serializeProperty('', {'': value})
function serializeProperty (key, holder) {
let value = holder[key]
if (value != null) {
if (typeof value.toJSON5 === 'function') {
value = value.toJSON5(key)
} else if (typeof value.toJSON === 'function') {
value = value.toJSON(key)
}
}
if (replacerFunc) {
value = replacerFunc.call(holder, key, value)
}
if (value instanceof Number) {
value = Number(value)
} else if (value instanceof String) {
value = String(value)
} else if (value instanceof Boolean) {
value = value.valueOf()
}
switch (value) {
case null: return 'null'
case true: return 'true'
case false: return 'false'
}
if (typeof value === 'string') {
return quoteString(value, false)
}
if (typeof value === 'number') {
return String(value)
}
if (typeof value === 'object') {
return Array.isArray(value) ? serializeArray(value) : serializeObject(value)
}
return undefined
}
function quoteString (value) {
const quotes = {
"'": 0.1,
'"': 0.2,
}
const replacements = {
"'": "\\'",
'"': '\\"',
'\\': '\\\\',
'\b': '\\b',
'\f': '\\f',
'\n': '\\n',
'\r': '\\r',
'\t': '\\t',
'\v': '\\v',
'\0': '\\0',
'\u2028': '\\u2028',
'\u2029': '\\u2029',
}
let product = ''
for (let i = 0; i < value.length; i++) {
const c = value[i]
switch (c) {
case "'":
case '"':
quotes[c]++
product += c
continue
case '\0':
if (util.isDigit(value[i + 1])) {
product += '\\x00'
continue
}
}
if (replacements[c]) {
product += replacements[c]
continue
}
if (c < ' ') {
let hexString = c.charCodeAt(0).toString(16)
product += '\\x' + ('00' + hexString).substring(hexString.length)
continue
}
product += c
}
const quoteChar = quote || Object.keys(quotes).reduce((a, b) => (quotes[a] < quotes[b]) ? a : b)
product = product.replace(new RegExp(quoteChar, 'g'), replacements[quoteChar])
return quoteChar + product + quoteChar
}
function serializeObject (value) {
if (stack.indexOf(value) >= 0) {
throw TypeError('Converting circular structure to JSON5')
}
stack.push(value)
let stepback = indent
indent = indent + gap
let keys = propertyList || Object.keys(value)
let partial = []
for (const key of keys) {
const propertyString = serializeProperty(key, value)
if (propertyString !== undefined) {
let member = serializeKey(key) + ':'
if (gap !== '') {
member += ' '
}
member += propertyString
partial.push(member)
}
}
let final
if (partial.length === 0) {
final = '{}'
} else {
let properties
if (gap === '') {
properties = partial.join(',')
final = '{' + properties + '}'
} else {
let separator = ',\n' + indent
properties = partial.join(separator)
final = '{\n' + indent + properties + ',\n' + stepback + '}'
}
}
stack.pop()
indent = stepback
return final
}
function serializeKey (key) {
if (key.length === 0) {
return quoteString(key, true)
}
const firstChar = String.fromCodePoint(key.codePointAt(0))
if (!util.isIdStartChar(firstChar)) {
return quoteString(key, true)
}
for (let i = firstChar.length; i < key.length; i++) {
if (!util.isIdContinueChar(String.fromCodePoint(key.codePointAt(i)))) {
return quoteString(key, true)
}
}
return key
}
function serializeArray (value) {
if (stack.indexOf(value) >= 0) {
throw TypeError('Converting circular structure to JSON5')
}
stack.push(value)
let stepback = indent
indent = indent + gap
let partial = []
for (let i = 0; i < value.length; i++) {
const propertyString = serializeProperty(String(i), value)
partial.push((propertyString !== undefined) ? propertyString : 'null')
}
let final
if (partial.length === 0) {
final = '[]'
} else {
if (gap === '') {
let properties = partial.join(',')
final = '[' + properties + ']'
} else {
let separator = ',\n' + indent
let properties = partial.join(separator)
final = '[\n' + indent + properties + ',\n' + stepback + ']'
}
}
stack.pop()
indent = stepback
return final
}
}
================================================
FILE: lib/unicode.d.ts
================================================
export declare const Space_Separator: RegExp
export declare const ID_Start: RegExp
export declare const ID_Continue: RegExp
================================================
FILE: lib/unicode.js
================================================
// This is a generated file. Do not edit.
module.exports.Space_Separator = /[\u1680\u2000-\u200A\u202F\u205F\u3000]/
module.exports.ID_Start = /[\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u05D0-\u05EA\u05F0-\u05F2\u0620-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u0860-\u086A\u08A0-\u08B4\u08B6-\u08BD\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\u09FC\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0AF9\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D\u0C58-\u0C5A\u0C60\u0C61\u0C80\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D54-\u0D56\u0D5F-\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F5\u13F8-\u13FD\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u170C\u170E-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u1820-\u1877\u1880-\u1884\u1887-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191E\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u1A00-\u1A16\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4B\u1B83-\u1BA0\u1BAE\u1BAF\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1C80-\u1C88\u1CE9-\u1CEC\u1CEE-\u1CF1\u1CF5\u1CF6\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2160-\u2188\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2E2F\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303C\u3041-\u3096\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312E\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FEA\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B\uA640-\uA66E\uA67F-\uA69D\uA6A0-\uA6EF\uA717-\uA71F\uA722-\uA788\uA78B-\uA7AE\uA7B0-\uA7B7\uA7F7-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB\uA8FD\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uA9E0-\uA9E4\uA9E6-\uA9EF\uA9FA-\uA9FE\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA7E-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB65\uAB70-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]|\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDD40-\uDD74\uDE80-\uDE9C\uDEA0-\uDED0\uDF00-\uDF1F\uDF2D-\uDF4A\uDF50-\uDF75\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF\uDFD1-\uDFD5]|\uD801[\uDC00-\uDC9D\uDCB0-\uDCD3\uDCD8-\uDCFB\uDD00-\uDD27\uDD30-\uDD63\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC60-\uDC76\uDC80-\uDC9E\uDCE0-\uDCF2\uDCF4\uDCF5\uDD00-\uDD15\uDD20-\uDD39\uDD80-\uDDB7\uDDBE\uDDBF\uDE00\uDE10-\uDE13\uDE15-\uDE17\uDE19-\uDE33\uDE60-\uDE7C\uDE80-\uDE9C\uDEC0-\uDEC7\uDEC9-\uDEE4\uDF00-\uDF35\uDF40-\uDF55\uDF60-\uDF72\uDF80-\uDF91]|\uD803[\uDC00-\uDC48\uDC80-\uDCB2\uDCC0-\uDCF2]|\uD804[\uDC03-\uDC37\uDC83-\uDCAF\uDCD0-\uDCE8\uDD03-\uDD26\uDD50-\uDD72\uDD76\uDD83-\uDDB2\uDDC1-\uDDC4\uDDDA\uDDDC\uDE00-\uDE11\uDE13-\uDE2B\uDE80-\uDE86\uDE88\uDE8A-\uDE8D\uDE8F-\uDE9D\uDE9F-\uDEA8\uDEB0-\uDEDE\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3D\uDF50\uDF5D-\uDF61]|\uD805[\uDC00-\uDC34\uDC47-\uDC4A\uDC80-\uDCAF\uDCC4\uDCC5\uDCC7\uDD80-\uDDAE\uDDD8-\uDDDB\uDE00-\uDE2F\uDE44\uDE80-\uDEAA\uDF00-\uDF19]|\uD806[\uDCA0-\uDCDF\uDCFF\uDE00\uDE0B-\uDE32\uDE3A\uDE50\uDE5C-\uDE83\uDE86-\uDE89\uDEC0-\uDEF8]|\uD807[\uDC00-\uDC08\uDC0A-\uDC2E\uDC40\uDC72-\uDC8F\uDD00-\uDD06\uDD08\uDD09\uDD0B-\uDD30\uDD46]|\uD808[\uDC00-\uDF99]|\uD809[\uDC00-\uDC6E\uDC80-\uDD43]|[\uD80C\uD81C-\uD820\uD840-\uD868\uD86A-\uD86C\uD86F-\uD872\uD874-\uD879][\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2E]|\uD811[\uDC00-\uDE46]|\uD81A[\uDC00-\uDE38\uDE40-\uDE5E\uDED0-\uDEED\uDF00-\uDF2F\uDF40-\uDF43\uDF63-\uDF77\uDF7D-\uDF8F]|\uD81B[\uDF00-\uDF44\uDF50\uDF93-\uDF9F\uDFE0\uDFE1]|\uD821[\uDC00-\uDFEC]|\uD822[\uDC00-\uDEF2]|\uD82C[\uDC00-\uDD1E\uDD70-\uDEFB]|\uD82F[\uDC00-\uDC6A\uDC70-\uDC7C\uDC80-\uDC88\uDC90-\uDC99]|\uD835[\uDC00-\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-\uDFC2\uDFC4-\uDFCB]|\uD83A[\uDC00-\uDCC4\uDD00-\uDD43]|\uD83B[\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1\uDEB0-\uDFFF]|\uD87A[\uDC00-\uDFE0]|\uD87E[\uDC00-\uDE1D]/
module.exports.ID_Continue = /[\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0300-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u0483-\u0487\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u0591-\u05BD\u05BF\u05C1\u05C2\u05C4\u05C5\u05C7\u05D0-\u05EA\u05F0-\u05F2\u0610-\u061A\u0620-\u0669\u066E-\u06D3\u06D5-\u06DC\u06DF-\u06E8\u06EA-\u06FC\u06FF\u0710-\u074A\u074D-\u07B1\u07C0-\u07F5\u07FA\u0800-\u082D\u0840-\u085B\u0860-\u086A\u08A0-\u08B4\u08B6-\u08BD\u08D4-\u08E1\u08E3-\u0963\u0966-\u096F\u0971-\u0983\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BC-\u09C4\u09C7\u09C8\u09CB-\u09CE\u09D7\u09DC\u09DD\u09DF-\u09E3\u09E6-\u09F1\u09FC\u0A01-\u0A03\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A3C\u0A3E-\u0A42\u0A47\u0A48\u0A4B-\u0A4D\u0A51\u0A59-\u0A5C\u0A5E\u0A66-\u0A75\u0A81-\u0A83\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABC-\u0AC5\u0AC7-\u0AC9\u0ACB-\u0ACD\u0AD0\u0AE0-\u0AE3\u0AE6-\u0AEF\u0AF9-\u0AFF\u0B01-\u0B03\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3C-\u0B44\u0B47\u0B48\u0B4B-\u0B4D\u0B56\u0B57\u0B5C\u0B5D\u0B5F-\u0B63\u0B66-\u0B6F\u0B71\u0B82\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BBE-\u0BC2\u0BC6-\u0BC8\u0BCA-\u0BCD\u0BD0\u0BD7\u0BE6-\u0BEF\u0C00-\u0C03\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D-\u0C44\u0C46-\u0C48\u0C4A-\u0C4D\u0C55\u0C56\u0C58-\u0C5A\u0C60-\u0C63\u0C66-\u0C6F\u0C80-\u0C83\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBC-\u0CC4\u0CC6-\u0CC8\u0CCA-\u0CCD\u0CD5\u0CD6\u0CDE\u0CE0-\u0CE3\u0CE6-\u0CEF\u0CF1\u0CF2\u0D00-\u0D03\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D44\u0D46-\u0D48\u0D4A-\u0D4E\u0D54-\u0D57\u0D5F-\u0D63\u0D66-\u0D6F\u0D7A-\u0D7F\u0D82\u0D83\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0DCA\u0DCF-\u0DD4\u0DD6\u0DD8-\u0DDF\u0DE6-\u0DEF\u0DF2\u0DF3\u0E01-\u0E3A\u0E40-\u0E4E\u0E50-\u0E59\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB9\u0EBB-\u0EBD\u0EC0-\u0EC4\u0EC6\u0EC8-\u0ECD\u0ED0-\u0ED9\u0EDC-\u0EDF\u0F00\u0F18\u0F19\u0F20-\u0F29\u0F35\u0F37\u0F39\u0F3E-\u0F47\u0F49-\u0F6C\u0F71-\u0F84\u0F86-\u0F97\u0F99-\u0FBC\u0FC6\u1000-\u1049\u1050-\u109D\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u135D-\u135F\u1380-\u138F\u13A0-\u13F5\u13F8-\u13FD\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u170C\u170E-\u1714\u1720-\u1734\u1740-\u1753\u1760-\u176C\u176E-\u1770\u1772\u1773\u1780-\u17D3\u17D7\u17DC\u17DD\u17E0-\u17E9\u180B-\u180D\u1810-\u1819\u1820-\u1877\u1880-\u18AA\u18B0-\u18F5\u1900-\u191E\u1920-\u192B\u1930-\u193B\u1946-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u19D0-\u19D9\u1A00-\u1A1B\u1A20-\u1A5E\u1A60-\u1A7C\u1A7F-\u1A89\u1A90-\u1A99\u1AA7\u1AB0-\u1ABD\u1B00-\u1B4B\u1B50-\u1B59\u1B6B-\u1B73\u1B80-\u1BF3\u1C00-\u1C37\u1C40-\u1C49\u1C4D-\u1C7D\u1C80-\u1C88\u1CD0-\u1CD2\u1CD4-\u1CF9\u1D00-\u1DF9\u1DFB-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u203F\u2040\u2054\u2071\u207F\u2090-\u209C\u20D0-\u20DC\u20E1\u20E5-\u20F0\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2160-\u2188\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D7F-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2DE0-\u2DFF\u2E2F\u3005-\u3007\u3021-\u302F\u3031-\u3035\u3038-\u303C\u3041-\u3096\u3099\u309A\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312E\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FEA\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA62B\uA640-\uA66F\uA674-\uA67D\uA67F-\uA6F1\uA717-\uA71F\uA722-\uA788\uA78B-\uA7AE\uA7B0-\uA7B7\uA7F7-\uA827\uA840-\uA873\uA880-\uA8C5\uA8D0-\uA8D9\uA8E0-\uA8F7\uA8FB\uA8FD\uA900-\uA92D\uA930-\uA953\uA960-\uA97C\uA980-\uA9C0\uA9CF-\uA9D9\uA9E0-\uA9FE\uAA00-\uAA36\uAA40-\uAA4D\uAA50-\uAA59\uAA60-\uAA76\uAA7A-\uAAC2\uAADB-\uAADD\uAAE0-\uAAEF\uAAF2-\uAAF6\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB65\uAB70-\uABEA\uABEC\uABED\uABF0-\uABF9\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE00-\uFE0F\uFE20-\uFE2F\uFE33\uFE34\uFE4D-\uFE4F\uFE70-\uFE74\uFE76-\uFEFC\uFF10-\uFF19\uFF21-\uFF3A\uFF3F\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]|\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDD40-\uDD74\uDDFD\uDE80-\uDE9C\uDEA0-\uDED0\uDEE0\uDF00-\uDF1F\uDF2D-\uDF4A\uDF50-\uDF7A\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF\uDFD1-\uDFD5]|\uD801[\uDC00-\uDC9D\uDCA0-\uDCA9\uDCB0-\uDCD3\uDCD8-\uDCFB\uDD00-\uDD27\uDD30-\uDD63\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC60-\uDC76\uDC80-\uDC9E\uDCE0-\uDCF2\uDCF4\uDCF5\uDD00-\uDD15\uDD20-\uDD39\uDD80-\uDDB7\uDDBE\uDDBF\uDE00-\uDE03\uDE05\uDE06\uDE0C-\uDE13\uDE15-\uDE17\uDE19-\uDE33\uDE38-\uDE3A\uDE3F\uDE60-\uDE7C\uDE80-\uDE9C\uDEC0-\uDEC7\uDEC9-\uDEE6\uDF00-\uDF35\uDF40-\uDF55\uDF60-\uDF72\uDF80-\uDF91]|\uD803[\uDC00-\uDC48\uDC80-\uDCB2\uDCC0-\uDCF2]|\uD804[\uDC00-\uDC46\uDC66-\uDC6F\uDC7F-\uDCBA\uDCD0-\uDCE8\uDCF0-\uDCF9\uDD00-\uDD34\uDD36-\uDD3F\uDD50-\uDD73\uDD76\uDD80-\uDDC4\uDDCA-\uDDCC\uDDD0-\uDDDA\uDDDC\uDE00-\uDE11\uDE13-\uDE37\uDE3E\uDE80-\uDE86\uDE88\uDE8A-\uDE8D\uDE8F-\uDE9D\uDE9F-\uDEA8\uDEB0-\uDEEA\uDEF0-\uDEF9\uDF00-\uDF03\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3C-\uDF44\uDF47\uDF48\uDF4B-\uDF4D\uDF50\uDF57\uDF5D-\uDF63\uDF66-\uDF6C\uDF70-\uDF74]|\uD805[\uDC00-\uDC4A\uDC50-\uDC59\uDC80-\uDCC5\uDCC7\uDCD0-\uDCD9\uDD80-\uDDB5\uDDB8-\uDDC0\uDDD8-\uDDDD\uDE00-\uDE40\uDE44\uDE50-\uDE59\uDE80-\uDEB7\uDEC0-\uDEC9\uDF00-\uDF19\uDF1D-\uDF2B\uDF30-\uDF39]|\uD806[\uDCA0-\uDCE9\uDCFF\uDE00-\uDE3E\uDE47\uDE50-\uDE83\uDE86-\uDE99\uDEC0-\uDEF8]|\uD807[\uDC00-\uDC08\uDC0A-\uDC36\uDC38-\uDC40\uDC50-\uDC59\uDC72-\uDC8F\uDC92-\uDCA7\uDCA9-\uDCB6\uDD00-\uDD06\uDD08\uDD09\uDD0B-\uDD36\uDD3A\uDD3C\uDD3D\uDD3F-\uDD47\uDD50-\uDD59]|\uD808[\uDC00-\uDF99]|\uD809[\uDC00-\uDC6E\uDC80-\uDD43]|[\uD80C\uD81C-\uD820\uD840-\uD868\uD86A-\uD86C\uD86F-\uD872\uD874-\uD879][\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2E]|\uD811[\uDC00-\uDE46]|\uD81A[\uDC00-\uDE38\uDE40-\uDE5E\uDE60-\uDE69\uDED0-\uDEED\uDEF0-\uDEF4\uDF00-\uDF36\uDF40-\uDF43\uDF50-\uDF59\uDF63-\uDF77\uDF7D-\uDF8F]|\uD81B[\uDF00-\uDF44\uDF50-\uDF7E\uDF8F-\uDF9F\uDFE0\uDFE1]|\uD821[\uDC00-\uDFEC]|\uD822[\uDC00-\uDEF2]|\uD82C[\uDC00-\uDD1E\uDD70-\uDEFB]|\uD82F[\uDC00-\uDC6A\uDC70-\uDC7C\uDC80-\uDC88\uDC90-\uDC99\uDC9D\uDC9E]|\uD834[\uDD65-\uDD69\uDD6D-\uDD72\uDD7B-\uDD82\uDD85-\uDD8B\uDDAA-\uDDAD\uDE42-\uDE44]|\uD835[\uDC00-\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-\uDFC2\uDFC4-\uDFCB\uDFCE-\uDFFF]|\uD836[\uDE00-\uDE36\uDE3B-\uDE6C\uDE75\uDE84\uDE9B-\uDE9F\uDEA1-\uDEAF]|\uD838[\uDC00-\uDC06\uDC08-\uDC18\uDC1B-\uDC21\uDC23\uDC24\uDC26-\uDC2A]|\uD83A[\uDC00-\uDCC4\uDCD0-\uDCD6\uDD00-\uDD4A\uDD50-\uDD59]|\uD83B[\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1\uDEB0-\uDFFF]|\uD87A[\uDC00-\uDFE0]|\uD87E[\uDC00-\uDE1D]|\uDB40[\uDD00-\uDDEF]/
================================================
FILE: lib/util.d.ts
================================================
export declare function isSpaceSeparator(c?: string): boolean
export declare function isIdStartChar(c?: string): boolean
export declare function isIdContinueChar(c?: string): boolean
export declare function isDigit(c?: string): boolean
export declare function isHexDigit(c?: string): boolean
================================================
FILE: lib/util.js
================================================
const unicode = require('../lib/unicode')
module.exports = {
isSpaceSeparator (c) {
return typeof c === 'string' && unicode.Space_Separator.test(c)
},
isIdStartChar (c) {
return typeof c === 'string' && (
(c >= 'a' && c <= 'z') ||
(c >= 'A' && c <= 'Z') ||
(c === '$') || (c === '_') ||
unicode.ID_Start.test(c)
)
},
isIdContinueChar (c) {
return typeof c === 'string' && (
(c >= 'a' && c <= 'z') ||
(c >= 'A' && c <= 'Z') ||
(c >= '0' && c <= '9') ||
(c === '$') || (c === '_') ||
(c === '\u200C') || (c === '\u200D') ||
unicode.ID_Continue.test(c)
)
},
isDigit (c) {
return typeof c === 'string' && /[0-9]/.test(c)
},
isHexDigit (c) {
return typeof c === 'string' && /[0-9A-Fa-f]/.test(c)
},
}
================================================
FILE: package.json
================================================
{
"name": "json5",
"version": "2.2.3",
"description": "JSON for Humans",
"main": "lib/index.js",
"module": "dist/index.mjs",
"bin": "lib/cli.js",
"browser": "dist/index.js",
"types": "lib/index.d.ts",
"files": [
"lib/",
"dist/"
],
"engines": {
"node": ">=6"
},
"scripts": {
"build": "rollup -c",
"build-package": "node build/package.js",
"build-unicode": "node build/unicode.js",
"coverage": "tap --coverage-report html test",
"lint": "eslint --fix .",
"lint-report": "eslint .",
"prepublishOnly": "npm run production",
"preversion": "npm run production",
"production": "run-s test build",
"tap": "tap -Rspec --100 test",
"test": "run-s lint-report tap",
"version": "npm run build-package && git add package.json5"
},
"repository": {
"type": "git",
"url": "git+https://github.com/json5/json5.git"
},
"keywords": [
"json",
"json5",
"es5",
"es2015",
"ecmascript"
],
"author": "Aseem Kishore <aseem.kishore@gmail.com>",
"contributors": [
"Max Nanasy <max.nanasy@gmail.com>",
"Andrew Eisenberg <andrew@eisenberg.as>",
"Jordan Tucker <jordanbtucker@gmail.com>"
],
"license": "MIT",
"bugs": {
"url": "https://github.com/json5/json5/issues"
},
"homepage": "http://json5.org/",
"devDependencies": {
"core-js": "^2.6.5",
"eslint": "^5.15.3",
"eslint-config-standard": "^12.0.0",
"eslint-plugin-import": "^2.16.0",
"eslint-plugin-node": "^8.0.1",
"eslint-plugin-promise": "^4.0.1",
"eslint-plugin-standard": "^4.0.0",
"npm-run-all": "^4.1.5",
"regenerate": "^1.4.0",
"rollup": "^0.64.1",
"rollup-plugin-buble": "^0.19.6",
"rollup-plugin-commonjs": "^9.2.1",
"rollup-plugin-node-resolve": "^3.4.0",
"rollup-plugin-terser": "^1.0.1",
"sinon": "^6.3.5",
"tap": "^12.6.0",
"unicode-10.0.0": "^0.7.5"
}
}
================================================
FILE: package.json5
================================================
// This is a generated file. Do not edit.
{
name: 'json5',
version: '2.2.3',
description: 'JSON for Humans',
main: 'lib/index.js',
module: 'dist/index.mjs',
bin: 'lib/cli.js',
browser: 'dist/index.js',
types: 'lib/index.d.ts',
files: [
'lib/',
'dist/',
],
engines: {
node: '>=6',
},
scripts: {
build: 'rollup -c',
'build-package': 'node build/package.js',
'build-unicode': 'node build/unicode.js',
coverage: 'tap --coverage-report html test',
lint: 'eslint --fix .',
'lint-report': 'eslint .',
prepublishOnly: 'npm run production',
preversion: 'npm run production',
production: 'run-s test build',
tap: 'tap -Rspec --100 test',
test: 'run-s lint-report tap',
version: 'npm run build-package && git add package.json5',
},
repository: {
type: 'git',
url: 'git+https://github.com/json5/json5.git',
},
keywords: [
'json',
'json5',
'es5',
'es2015',
'ecmascript',
],
author: 'Aseem Kishore <aseem.kishore@gmail.com>',
contributors: [
'Max Nanasy <max.nanasy@gmail.com>',
'Andrew Eisenberg <andrew@eisenberg.as>',
'Jordan Tucker <jordanbtucker@gmail.com>',
],
license: 'MIT',
bugs: {
url: 'https://github.com/json5/json5/issues',
},
homepage: 'http://json5.org/',
devDependencies: {
'core-js': '^2.6.5',
eslint: '^5.15.3',
'eslint-config-standard': '^12.0.0',
'eslint-plugin-import': '^2.16.0',
'eslint-plugin-node': '^8.0.1',
'eslint-plugin-promise': '^4.0.1',
'eslint-plugin-standard': '^4.0.0',
'npm-run-all': '^4.1.5',
regenerate: '^1.4.0',
rollup: '^0.64.1',
'rollup-plugin-buble': '^0.19.6',
'rollup-plugin-commonjs': '^9.2.1',
'rollup-plugin-node-resolve': '^3.4.0',
'rollup-plugin-terser': '^1.0.1',
sinon: '^6.3.5',
tap: '^12.6.0',
'unicode-10.0.0': '^0.7.5',
},
}
================================================
FILE: rollup.config.js
================================================
const resolve = require('rollup-plugin-node-resolve')
const commonjs = require('rollup-plugin-commonjs')
const buble = require('rollup-plugin-buble')
const terser = require('rollup-plugin-terser').terser
const pkg = require('./package.json')
module.exports = [
// ES5 Non-minified
{
input: 'build/es5.js',
output: {
file: pkg.browser,
format: 'umd',
name: 'JSON5',
},
plugins: [
resolve(),
commonjs(),
buble({transforms: {dangerousForOf: true}}),
],
},
// ES5 Minified
{
input: 'build/es5.js',
output: {
file: pkg.browser.replace(/\.js$/, '.min.js'),
format: 'umd',
name: 'JSON5',
},
plugins: [
resolve(),
commonjs(),
buble({transforms: {dangerousForOf: true}}),
terser(),
],
},
// ES6 Modules Non-minified
{
input: 'lib/index.js',
output: {
file: pkg.browser.replace(/\.js$/, '.mjs'),
format: 'esm',
},
plugins: [
resolve(),
commonjs(),
],
},
// ES6 Modules Minified
{
input: 'lib/index.js',
output: {
file: pkg.browser.replace(/\.js$/, '.min.mjs'),
format: 'esm',
},
plugins: [
resolve(),
commonjs(),
terser(),
],
},
]
================================================
FILE: test/cli.js
================================================
const assert = require('assert')
const child = require('child_process')
const fs = require('fs')
const path = require('path')
const pkg = require('../package.json')
const cliPath = path.resolve(__dirname, '../lib/cli.js')
const t = require('tap')
t.test('CLI', t => {
t.test('converts JSON5 to JSON from stdin to stdout', t => {
const proc = child.spawn(process.execPath, [cliPath])
let output = ''
proc.stdout.on('data', data => {
output += data
})
proc.stdout.on('end', () => {
assert.strictEqual(output, '{"a":1,"b":2}')
t.end()
})
fs.createReadStream(path.resolve(__dirname, 'test.json5')).pipe(proc.stdin)
})
t.test('reads from the specified file', t => {
const proc = child.spawn(
process.execPath,
[
cliPath,
path.resolve(__dirname, 'test.json5'),
]
)
let output = ''
proc.stdout.on('data', data => {
output += data
})
proc.stdout.on('end', () => {
assert.strictEqual(output, '{"a":1,"b":2}')
t.end()
})
})
t.test('indents output with the number of spaces specified with -s', t => {
const proc = child.spawn(
process.execPath,
[
cliPath,
path.resolve(__dirname, 'test.json5'),
'-s',
'4',
]
)
let output = ''
proc.stdout.on('data', data => {
output += data
})
proc.stdout.on('end', () => {
assert.strictEqual(output, '{\n "a": 1,\n "b": 2\n}')
t.end()
})
})
t.test('indents output with the number of spaces specified with --space', t => {
const proc = child.spawn(
process.execPath,
[
cliPath,
path.resolve(__dirname, 'test.json5'),
'--space',
'4',
]
)
let output = ''
proc.stdout.on('data', data => {
output += data
})
proc.stdout.on('end', () => {
assert.strictEqual(output, '{\n "a": 1,\n "b": 2\n}')
t.end()
})
})
t.test('indents output with tabs when specified with -s', t => {
const proc = child.spawn(
process.execPath,
[
cliPath,
path.resolve(__dirname, 'test.json5'),
'-s',
't',
]
)
let output = ''
proc.stdout.on('data', data => {
output += data
})
proc.stdout.on('end', () => {
assert.strictEqual(output, '{\n\t"a": 1,\n\t"b": 2\n}')
t.end()
})
})
t.test('outputs to the specified file with -o', t => {
const proc = child.spawn(
process.execPath,
[
cliPath,
path.resolve(__dirname, 'test.json5'),
'-o',
path.resolve(__dirname, 'output.json'),
]
)
proc.on('exit', () => {
assert.strictEqual(
fs.readFileSync(
path.resolve(__dirname, 'output.json'),
'utf8'
),
'{"a":1,"b":2}'
)
t.end()
})
t.tearDown(() => {
try {
fs.unlinkSync(path.resolve(__dirname, 'output.json'))
} catch (err) {}
})
})
t.test('outputs to the specified file with --out-file', t => {
const proc = child.spawn(
process.execPath,
[
cliPath,
path.resolve(__dirname, 'test.json5'),
'--out-file',
path.resolve(__dirname, 'output.json'),
]
)
proc.on('exit', () => {
assert.strictEqual(
fs.readFileSync(
path.resolve(__dirname, 'output.json'),
'utf8'
),
'{"a":1,"b":2}'
)
t.end()
})
t.tearDown(() => {
try {
fs.unlinkSync(path.resolve(__dirname, 'output.json'))
} catch (err) {}
})
})
t.test('validates valid JSON5 files with -v', t => {
const proc = child.spawn(
process.execPath,
[
cliPath,
path.resolve(__dirname, 'test.json5'),
'-v',
]
)
proc.on('exit', code => {
assert.strictEqual(code, 0)
t.end()
})
})
t.test('validates valid JSON5 files with --validate', t => {
const proc = child.spawn(
process.execPath,
[
cliPath,
path.resolve(__dirname, 'test.json5'),
'--validate',
]
)
proc.on('exit', code => {
assert.strictEqual(code, 0)
t.end()
})
})
t.test('validates invalid JSON5 files with -v', t => {
const proc = child.spawn(
process.execPath,
[
cliPath,
path.resolve(__dirname, 'invalid.json5'),
'-v',
]
)
let error = ''
proc.stderr.on('data', data => {
error += data
})
proc.stderr.on('end', () => {
assert.strictEqual(error, "JSON5: invalid character 'a' at 1:1\n")
})
proc.on('exit', code => {
assert.strictEqual(code, 1)
t.end()
})
})
t.test('outputs the version number when specified with -V', t => {
const proc = child.spawn(process.execPath, [cliPath, '-V'])
let output = ''
proc.stdout.on('data', data => {
output += data
})
proc.stdout.on('end', () => {
assert.strictEqual(output, pkg.version + '\n')
t.end()
})
})
t.test('outputs the version number when specified with --version', t => {
const proc = child.spawn(process.execPath, [cliPath, '--version'])
let output = ''
proc.stdout.on('data', data => {
output += data
})
proc.stdout.on('end', () => {
assert.strictEqual(output, pkg.version + '\n')
t.end()
})
})
t.test('outputs usage information when specified with -h', t => {
const proc = child.spawn(process.execPath, [cliPath, '-h'])
let output = ''
proc.stdout.on('data', data => {
output += data
})
proc.stdout.on('end', () => {
assert(/Usage/.test(output))
t.end()
})
})
t.test('outputs usage information when specified with --help', t => {
const proc = child.spawn(process.execPath, [cliPath, '--help'])
let output = ''
proc.stdout.on('data', data => {
output += data
})
proc.stdout.on('end', () => {
assert(/Usage/.test(output))
t.end()
})
})
t.test('is backward compatible with v0.5.1 with -c', t => {
const proc = child.spawn(
process.execPath,
[
cliPath,
'-c',
path.resolve(__dirname, 'test.json5'),
]
)
proc.on('exit', () => {
assert.strictEqual(
fs.readFileSync(
path.resolve(__dirname, 'test.json'),
'utf8'
),
'{"a":1,"b":2}'
)
t.end()
})
t.tearDown(() => {
try {
fs.unlinkSync(path.resolve(__dirname, 'test.json'))
} catch (err) {}
})
})
t.test('is backward compatible with v0.5.1 with --convert', t => {
const proc = child.spawn(
process.execPath,
[
cliPath,
'--convert',
path.resolve(__dirname, 'test.json5'),
]
)
proc.on('exit', () => {
assert.strictEqual(
fs.readFileSync(
path.resolve(__dirname, 'test.json'),
'utf8'
),
'{"a":1,"b":2}'
)
t.end()
})
t.tearDown(() => {
try {
fs.unlinkSync(path.resolve(__dirname, 'test.json'))
} catch (err) {}
})
})
t.end()
})
================================================
FILE: test/errors.js
================================================
const JSON5 = require('../lib')
const t = require('tap')
t.test('JSON5', t => {
t.test('#parse()', t => {
t.test('errors', t => {
t.throws(
() => { JSON5.parse('') },
{
message: /^JSON5: invalid end of input/,
lineNumber: 1,
columnNumber: 1,
},
'throws on empty documents'
)
t.throws(
() => { JSON5.parse('//a') },
{
message: /^JSON5: invalid end of input/,
lineNumber: 1,
columnNumber: 4,
},
'throws on documents with only comments'
)
t.throws(
() => { JSON5.parse('/a') },
{
message: /^JSON5: invalid character 'a'/,
lineNumber: 1,
columnNumber: 2,
},
'throws on incomplete single line comments'
)
t.throws(
() => { JSON5.parse('/*') },
{
message: /^JSON5: invalid end of input/,
lineNumber: 1,
columnNumber: 3,
},
'throws on unterminated multiline comments'
)
t.throws(
() => { JSON5.parse('/**') },
{
message: /^JSON5: invalid end of input/,
lineNumber: 1,
columnNumber: 4,
},
'throws on unterminated multiline comment closings'
)
t.throws(
() => { JSON5.parse('a') },
{
message: /^JSON5: invalid character 'a'/,
lineNumber: 1,
columnNumber: 1,
},
'throws on invalid characters in values'
)
t.throws(
() => { JSON5.parse('{\\a:1}') },
{
message: /^JSON5: invalid character 'a'/,
lineNumber: 1,
columnNumber: 3,
},
'throws on invalid characters in identifier start escapes'
)
t.throws(
() => { JSON5.parse('{\\u0021:1}') },
{
message: /^JSON5: invalid identifier character/,
lineNumber: 1,
columnNumber: 2,
},
'throws on invalid identifier start characters'
)
t.throws(
() => { JSON5.parse('{a\\a:1}') },
{
message: /^JSON5: invalid character 'a'/,
lineNumber: 1,
columnNumber: 4,
},
'throws on invalid characters in identifier continue escapes'
)
t.throws(
() => { JSON5.parse('{a\\u0021:1}') },
{
message: /^JSON5: invalid identifier character/,
lineNumber: 1,
columnNumber: 3,
},
'throws on invalid identifier continue characters'
)
t.throws(
() => { JSON5.parse('-a') },
{
message: /^JSON5: invalid character 'a'/,
lineNumber: 1,
columnNumber: 2,
},
'throws on invalid characters following a sign'
)
t.throws(
() => { JSON5.parse('.a') },
{
message: /^JSON5: invalid character 'a'/,
lineNumber: 1,
columnNumber: 2,
},
'throws on invalid characters following a leading decimal point'
)
t.throws(
() => { JSON5.parse('1ea') },
{
message: /^JSON5: invalid character 'a'/,
lineNumber: 1,
columnNumber: 3,
},
'throws on invalid characters following an exponent indicator'
)
t.throws(
() => { JSON5.parse('1e-a') },
{
message: /^JSON5: invalid character 'a'/,
lineNumber: 1,
columnNumber: 4,
},
'throws on invalid characters following an exponent sign'
)
t.throws(
() => { JSON5.parse('0xg') },
{
message: /^JSON5: invalid character 'g'/,
lineNumber: 1,
columnNumber: 3,
},
'throws on invalid characters following a hexadecimal indicator'
)
t.throws(
() => { JSON5.parse('"\n"') },
{
message: /^JSON5: invalid character '\\n'/,
lineNumber: 2,
columnNumber: 0,
},
'throws on invalid new lines in strings'
)
t.throws(
() => { JSON5.parse('"') },
{
message: /^JSON5: invalid end of input/,
lineNumber: 1,
columnNumber: 2,
},
'throws on unterminated strings'
)
t.throws(
() => { JSON5.parse('{!:1}') },
{
message: /^JSON5: invalid character '!'/,
lineNumber: 1,
columnNumber: 2,
},
'throws on invalid identifier start characters in property names'
)
t.throws(
() => { JSON5.parse('{a!1}') },
{
message: /^JSON5: invalid character '!'/,
lineNumber: 1,
columnNumber: 3,
},
'throws on invalid characters following a property name'
)
t.throws(
() => { JSON5.parse('{a:1!}') },
{
message: /^JSON5: invalid character '!'/,
lineNumber: 1,
columnNumber: 5,
},
'throws on invalid characters following a property value'
)
t.throws(
() => { JSON5.parse('[1!]') },
{
message: /^JSON5: invalid character '!'/,
lineNumber: 1,
columnNumber: 3,
},
'throws on invalid characters following an array value'
)
t.throws(
() => { JSON5.parse('tru!') },
{
message: /^JSON5: invalid character '!'/,
lineNumber: 1,
columnNumber: 4,
},
'throws on invalid characters in literals'
)
t.throws(
() => { JSON5.parse('"\\') },
{
message: /^JSON5: invalid end of input/,
lineNumber: 1,
columnNumber: 3,
},
'throws on unterminated escapes'
)
t.throws(
() => { JSON5.parse('"\\xg"') },
{
message: /^JSON5: invalid character 'g'/,
lineNumber: 1,
columnNumber: 4,
},
'throws on invalid first digits in hexadecimal escapes'
)
t.throws(
() => { JSON5.parse('"\\x0g"') },
{
message: /^JSON5: invalid character 'g'/,
lineNumber: 1,
columnNumber: 5,
},
'throws on invalid second digits in hexadecimal escapes'
)
t.throws(
() => { JSON5.parse('"\\u000g"') },
{
message: /^JSON5: invalid character 'g'/,
lineNumber: 1,
columnNumber: 7,
},
'throws on invalid unicode escapes'
)
for (let i = 1; i <= 9; i++) {
t.throws(
() => { JSON5.parse(`'\\${i}'`) },
{
message: /^JSON5: invalid character '\d'/,
lineNumber: 1,
columnNumber: 3,
},
`throws on escaped digit ${i}`
)
}
t.throws(
() => { JSON5.parse("'\\01'") },
{
message: /^JSON5: invalid character '1'/,
lineNumber: 1,
columnNumber: 4,
},
'throws on octal escapes'
)
t.throws(
() => { JSON5.parse('1 2') },
{
message: /^JSON5: invalid character '2'/,
lineNumber: 1,
columnNumber: 3,
},
'throws on multiple values'
)
t.throws(
() => { JSON5.parse('\x01') },
{
message: /^JSON5: invalid character '\\x01'/,
lineNumber: 1,
columnNumber: 1,
},
'throws with control characters escaped in the message'
)
t.throws(
() => { JSON5.parse('{') },
{
message: /^JSON5: invalid end of input/,
lineNumber: 1,
columnNumber: 2,
},
'throws on unclosed objects before property names'
)
t.throws(
() => { JSON5.parse('{a') },
{
message: /^JSON5: invalid end of input/,
lineNumber: 1,
columnNumber: 3,
},
'throws on unclosed objects after property names'
)
t.throws(
() => { JSON5.parse('{a:') },
{
message: /^JSON5: invalid end of input/,
lineNumber: 1,
columnNumber: 4,
},
'throws on unclosed objects before property values'
)
t.throws(
() => { JSON5.parse('{a:1') },
{
message: /^JSON5: invalid end of input/,
lineNumber: 1,
columnNumber: 5,
},
'throws on unclosed objects after property values'
)
t.throws(
() => { JSON5.parse('[') },
{
message: /^JSON5: invalid end of input/,
lineNumber: 1,
columnNumber: 2,
},
'throws on unclosed arrays before values'
)
t.throws(
() => { JSON5.parse('[1') },
{
message: /^JSON5: invalid end of input/,
lineNumber: 1,
columnNumber: 3,
},
'throws on unclosed arrays after values'
)
t.end()
})
t.end()
})
t.end()
})
================================================
FILE: test/invalid.json5
================================================
a
================================================
FILE: test/parse.js
================================================
const assert = require('assert')
const sinon = require('sinon')
const JSON5 = require('../lib')
const t = require('tap')
t.test('parse(text)', t => {
t.test('objects', t => {
t.strictSame(
JSON5.parse('{}'),
{},
'parses empty objects'
)
t.strictSame(
JSON5.parse('{"a":1}'),
{a: 1},
'parses double string property names'
)
t.strictSame(
JSON5.parse("{'a':1}"),
{a: 1},
'parses single string property names'
)
t.strictSame(
JSON5.parse('{a:1}'),
{a: 1},
'parses unquoted property names'
)
t.strictSame(
JSON5.parse('{$_:1,_$:2,a\u200C:3}'),
{$_: 1, _$: 2, 'a\u200C': 3},
'parses special character property names'
)
t.strictSame(
JSON5.parse('{ùńîċõďë:9}'),
{'ùńîċõďë': 9},
'parses unicode property names'
)
t.strictSame(
JSON5.parse('{\\u0061\\u0062:1,\\u0024\\u005F:2,\\u005F\\u0024:3}'),
{ab: 1, $_: 2, _$: 3},
'parses escaped property names'
)
t.strictSame(
// eslint-disable-next-line no-proto
JSON5.parse('{"__proto__":1}').__proto__,
1,
'preserves __proto__ property names'
)
t.strictSame(
JSON5.parse('{abc:1,def:2}'),
{abc: 1, def: 2},
'parses multiple properties'
)
t.strictSame(
JSON5.parse('{a:{b:2}}'),
{a: {b: 2}},
'parses nested objects'
)
t.end()
})
t.test('arrays', t => {
t.strictSame(
JSON5.parse('[]'),
[],
'parses empty arrays'
)
t.strictSame(
JSON5.parse('[1]'),
[1],
'parses array values'
)
t.strictSame(
JSON5.parse('[1,2]'),
[1, 2],
'parses multiple array values'
)
t.strictSame(
JSON5.parse('[1,[2,3]]'),
[1, [2, 3]],
'parses nested arrays'
)
t.end()
})
t.test('nulls', t => {
t.equal(
JSON5.parse('null'),
null,
'parses nulls'
)
t.end()
})
t.test('Booleans', t => {
t.equal(
JSON5.parse('true'),
true,
'parses true'
)
t.equal(
JSON5.parse('false'),
false,
'parses false'
)
t.end()
})
t.test('numbers', t => {
t.strictSame(
JSON5.parse('[0,0.,0e0]'),
[0, 0, 0],
'parses leading zeroes'
)
t.strictSame(
JSON5.parse('[1,23,456,7890]'),
[1, 23, 456, 7890],
'parses integers'
)
t.strictSame(
JSON5.parse('[-1,+2,-.1,-0]'),
[-1, +2, -0.1, -0],
'parses signed numbers'
)
t.strictSame(
JSON5.parse('[.1,.23]'),
[0.1, 0.23],
'parses leading decimal points'
)
t.strictSame(
JSON5.parse('[1.0,1.23]'),
[1, 1.23],
'parses fractional numbers'
)
t.strictSame(
JSON5.parse('[1e0,1e1,1e01,1.e0,1.1e0,1e-1,1e+1]'),
[1, 10, 10, 1, 1.1, 0.1, 10],
'parses exponents'
)
t.strictSame(
JSON5.parse('[0x1,0x10,0xff,0xFF]'),
[1, 16, 255, 255],
'parses hexadecimal numbers'
)
t.strictSame(
JSON5.parse('[Infinity,-Infinity]'),
[Infinity, -Infinity],
'parses signed and unsigned Infinity'
)
t.ok(
isNaN(JSON5.parse('NaN')),
'parses NaN'
)
t.ok(
isNaN(JSON5.parse('-NaN')),
'parses signed NaN'
)
t.strictSame(
JSON5.parse('1'),
1,
'parses 1'
)
t.strictSame(
JSON5.parse('+1.23e100'),
1.23e100,
'parses +1.23e100'
)
t.strictSame(
JSON5.parse('0x1'),
0x1,
'parses bare hexadecimal number'
)
t.strictSame(
JSON5.parse('-0x0123456789abcdefABCDEF'),
-0x0123456789abcdefABCDEF,
'parses bare long hexadecimal number'
)
t.end()
})
t.test('strings', t => {
t.equal(
JSON5.parse('"abc"'),
'abc',
'parses double quoted strings'
)
t.equal(
JSON5.parse("'abc'"),
'abc',
'parses single quoted strings'
)
t.strictSame(
JSON5.parse(`['"',"'"]`),
['"', "'"],
'parses quotes in strings')
t.equal(
JSON5.parse(`'\\b\\f\\n\\r\\t\\v\\0\\x0f\\u01fF\\\n\\\r\n\\\r\\\u2028\\\u2029\\a\\'\\"'`),
`\b\f\n\r\t\v\0\x0f\u01FF\a'"`, // eslint-disable-line no-useless-escape
'parses escaped characters'
)
t.test('parses line and paragraph separators with a warning', t => {
const mock = sinon.mock(console)
mock
.expects('warn')
.twice()
.calledWithMatch('not valid ECMAScript')
assert.deepStrictEqual(
JSON5.parse("'\u2028\u2029'"),
'\u2028\u2029'
)
mock.verify()
mock.restore()
t.end()
})
t.end()
})
t.test('comments', t => {
t.strictSame(
JSON5.parse('{//comment\n}'),
{},
'parses single-line comments'
)
t.strictSame(
JSON5.parse('{}//comment'),
{},
'parses single-line comments at end of input'
)
t.strictSame(
JSON5.parse('{/*comment\n** */}'),
{},
'parses multi-line comments'
)
t.end()
})
t.test('whitespace', t => {
t.strictSame(
JSON5.parse('{\t\v\f \u00A0\uFEFF\n\r\u2028\u2029\u2003}'),
{},
'parses whitespace'
)
t.end()
})
t.end()
})
t.test('parse(text, reviver)', t => {
t.strictSame(
JSON5.parse('{a:1,b:2}', (k, v) => (k === 'a') ? 'revived' : v),
{a: 'revived', b: 2},
'modifies property values'
)
t.strictSame(
JSON5.parse('{a:{b:2}}', (k, v) => (k === 'b') ? 'revived' : v),
{a: {b: 'revived'}},
'modifies nested object property values'
)
t.strictSame(
JSON5.parse('{a:1,b:2}', (k, v) => (k === 'a') ? undefined : v),
{b: 2},
'deletes property values'
)
t.strictSame(
JSON5.parse('[0,1,2]', (k, v) => (k === '1') ? 'revived' : v),
[0, 'revived', 2],
'modifies array values'
)
t.strictSame(
JSON5.parse('[0,[1,2,3]]', (k, v) => (k === '2') ? 'revived' : v),
[0, [1, 2, 'revived']],
'modifies nested array values'
)
t.strictSame(
JSON5.parse('[0,1,2]', (k, v) => (k === '1') ? undefined : v),
[0, , 2], // eslint-disable-line no-sparse-arrays
'deletes array values'
)
t.equal(
JSON5.parse('1', (k, v) => (k === '') ? 'revived' : v),
'revived',
'modifies the root value'
)
t.strictSame(
JSON5.parse('{a:{b:2}}', function (k, v) { return (k === 'b' && this.b) ? 'revived' : v }),
{a: {b: 'revived'}},
'sets `this` to the parent value'
)
t.end()
})
================================================
FILE: test/require.js
================================================
const assert = require('assert')
const sinon = require('sinon')
const t = require('tap')
t.test('require(*.json5)', t => {
t.test('parses a JSON5 document', t => {
require('../lib/register')
assert.deepStrictEqual({a: 1, b: 2}, require('./test.json5'))
t.end()
})
t.test('is backward compatible with v0.5.1, but gives a deprecation warning', t => {
const mock = sinon.mock(console)
mock.expects('warn').once().withExactArgs("'json5/require' is deprecated. Please use 'json5/register' instead.")
require('../lib/require')
assert.deepStrictEqual({a: 1, b: 2}, require('./test.json5'))
mock.verify()
t.end()
})
t.test('throws on invalid JSON5', t => {
require('../lib/register')
assert.throws(() => { require('./invalid.json5') }, SyntaxError)
t.end()
})
t.end()
})
================================================
FILE: test/stringify.js
================================================
const assert = require('assert')
const JSON5 = require('../lib')
const t = require('tap')
t.test('JSON5', t => {
t.test('#stringify', t => {
t.test('objects', t => {
t.strictSame(
JSON5.stringify({}),
'{}',
'stringifies empty objects'
)
t.strictSame(
JSON5.stringify({a: 1}),
'{a:1}',
'stringifies unquoted property names'
)
t.strictSame(
JSON5.stringify({'a-b': 1}),
"{'a-b':1}",
'stringifies single quoted string property names'
)
t.strictSame(
JSON5.stringify({"a'": 1}),
`{"a'":1}`,
'stringifies double quoted string property names'
)
t.strictSame(
JSON5.stringify({'': 1}),
"{'':1}",
'stringifies empty string property names'
)
t.strictSame(
JSON5.stringify({$_: 1, _$: 2, 'a\u200C': 3}),
'{$_:1,_$:2,a\u200C:3}',
'stringifies special character property names'
)
t.strictSame(
JSON5.stringify({'ùńîċõďë': 9}),
'{ùńîċõďë:9}',
'stringifies unicode property names'
)
t.strictSame(
JSON5.stringify({'\\\b\f\n\r\t\v\0\x01': 1}),
"{'\\\\\\b\\f\\n\\r\\t\\v\\0\\x01':1}",
'stringifies escaped property names'
)
t.strictSame(
JSON5.stringify({'\0\x001': 1}),
"{'\\0\\x001':1}",
'stringifies escaped null character property names'
)
t.strictSame(
JSON5.stringify({abc: 1, def: 2}),
'{abc:1,def:2}',
'stringifies multiple properties'
)
t.strictSame(
JSON5.stringify({a: {b: 2}}),
'{a:{b:2}}',
'stringifies nested objects'
)
t.end()
})
t.test('arrays', t => {
t.strictSame(
JSON5.stringify([]),
'[]',
'stringifies empty arrays'
)
t.strictSame(
JSON5.stringify([1]),
'[1]',
'stringifies array values'
)
t.strictSame(
JSON5.stringify([1, 2]),
'[1,2]',
'stringifies multiple array values'
)
t.strictSame(
JSON5.stringify([1, [2, 3]]),
'[1,[2,3]]',
'stringifies nested arrays'
)
t.end()
})
t.strictSame(
JSON5.stringify(null),
'null',
'stringifies nulls'
)
t.strictSame(
JSON5.stringify(() => {}),
undefined,
'returns undefined for functions'
)
t.strictSame(
JSON5.stringify({a () {}}),
'{}',
'ignores function properties'
)
t.strictSame(
JSON5.stringify([() => {}]),
'[null]',
'returns null for functions in arrays'
)
t.test('Booleans', t => {
t.strictSame(
JSON5.stringify(true),
'true',
'stringifies true'
)
t.strictSame(
JSON5.stringify(false),
'false',
'stringifies false'
)
t.strictSame(
// eslint-disable-next-line no-new-wrappers
JSON5.stringify(new Boolean(true)),
'true',
'stringifies true Boolean objects'
)
t.strictSame(
// eslint-disable-next-line no-new-wrappers
JSON5.stringify(new Boolean(false)),
'false',
'stringifies false Boolean objects'
)
t.end()
})
t.test('numbers', t => {
t.strictSame(
JSON5.stringify(-1.2),
'-1.2',
'stringifies numbers'
)
t.strictSame(
JSON5.stringify([Infinity, -Infinity, NaN]),
'[Infinity,-Infinity,NaN]',
'stringifies non-finite numbers'
)
t.strictSame(
// eslint-disable-next-line no-new-wrappers
JSON5.stringify(new Number(-1.2)),
'-1.2',
'stringifies Number objects'
)
t.end()
})
t.test('strings', t => {
t.strictSame(
JSON5.stringify('abc'),
"'abc'",
'stringifies single quoted strings'
)
t.strictSame(
JSON5.stringify("abc'"),
`"abc'"`,
'stringifies double quoted strings'
)
t.strictSame(
JSON5.stringify('\\\b\f\n\r\t\v\0\x0f'),
"'\\\\\\b\\f\\n\\r\\t\\v\\0\\x0f'",
'stringifies escaped characters'
)
t.strictSame(
JSON5.stringify('\0\x001'),
"'\\0\\x001'",
'stringifies escaped null characters'
)
t.strictSame(
JSON5.stringify(`'"`),
`'\\'"'`,
'stringifies escaped single quotes'
)
t.strictSame(
JSON5.stringify(`''"`),
`"''\\""`,
'stringifies escaped double quotes'
)
t.strictSame(
JSON5.stringify('\u2028\u2029'),
"'\\u2028\\u2029'",
'stringifies escaped line and paragraph separators'
)
t.strictSame(
// eslint-disable-next-line no-new-wrappers
JSON5.stringify(new String('abc')),
"'abc'",
'stringifies String objects'
)
t.end()
})
t.strictSame(
JSON5.stringify(new Date('2016-01-01T00:00:00.000Z')),
"'2016-01-01T00:00:00.000Z'",
'stringifies using built-in toJSON methods'
)
t.test('stringifies using user defined toJSON methods', t => {
function C () {}
Object.assign(C.prototype, {toJSON () { return {a: 1, b: 2} }})
assert.strictEqual(JSON5.stringify(new C()), '{a:1,b:2}')
t.end()
})
t.test('stringifies using user defined toJSON(key) methods', t => {
function C () {}
Object.assign(C.prototype, {toJSON (key) { return (key === 'a') ? 1 : 2 }})
assert.strictEqual(JSON5.stringify({a: new C(), b: new C()}), '{a:1,b:2}')
t.end()
})
t.test('stringifies using toJSON5 methods', t => {
function C () {}
Object.assign(C.prototype, {toJSON5 () { return {a: 1, b: 2} }})
assert.strictEqual(JSON5.stringify(new C()), '{a:1,b:2}')
t.end()
})
t.test('stringifies using toJSON5(key) methods', t => {
function C () {}
Object.assign(C.prototype, {toJSON5 (key) { return (key === 'a') ? 1 : 2 }})
assert.strictEqual(JSON5.stringify({a: new C(), b: new C()}), '{a:1,b:2}')
t.end()
})
t.test('calls toJSON5 instead of toJSON if both are defined', t => {
function C () {}
Object.assign(C.prototype, {
toJSON () { return {a: 1, b: 2} },
toJSON5 () { return {a: 2, b: 2} },
})
assert.strictEqual(JSON5.stringify(new C()), '{a:2,b:2}')
t.end()
})
t.test('throws on circular objects', t => {
let a = {}
a.a = a
assert.throws(() => { JSON5.stringify(a) }, TypeError, 'Converting circular structure to JSON5')
t.end()
})
t.test('throws on circular arrays', t => {
let a = []
a[0] = a
assert.throws(() => { JSON5.stringify(a) }, TypeError, 'Converting circular structure to JSON5')
t.end()
})
t.end()
})
t.test('#stringify(value, null, space)', t => {
t.strictSame(
JSON5.stringify([1]),
'[1]',
'does not indent when no value is provided'
)
t.strictSame(
JSON5.stringify([1], null, 0),
'[1]',
'does not indent when 0 is provided'
)
t.strictSame(
JSON5.stringify([1], null, ''),
'[1]',
'does not indent when an empty string is provided'
)
t.strictSame(
JSON5.stringify([1], null, 2),
'[\n 1,\n]',
'indents n spaces when a number is provided'
)
t.strictSame(
JSON5.stringify([1], null, 11),
'[\n 1,\n]',
'does not indent more than 10 spaces when a number is provided'
)
t.strictSame(
JSON5.stringify([1], null, '\t'),
'[\n\t1,\n]',
'indents with the string provided'
)
t.strictSame(
JSON5.stringify([1], null, ' '),
'[\n 1,\n]',
'does not indent more than 10 characters of the string provided'
)
t.strictSame(
JSON5.stringify([1], null, 2),
'[\n 1,\n]',
'indents in arrays'
)
t.strictSame(
JSON5.stringify([1, [2], 3], null, 2),
'[\n 1,\n [\n 2,\n ],\n 3,\n]',
'indents in nested arrays'
)
t.strictSame(
JSON5.stringify({a: 1}, null, 2),
'{\n a: 1,\n}',
'indents in objects'
)
t.strictSame(
JSON5.stringify({a: {b: 2}}, null, 2),
'{\n a: {\n b: 2,\n },\n}',
'indents in nested objects'
)
t.strictSame(
// eslint-disable-next-line no-new-wrappers
JSON5.stringify([1], null, new Number(2)),
'[\n 1,\n]',
'accepts Number objects'
)
t.strictSame(
// eslint-disable-next-line no-new-wrappers
JSON5.stringify([1], null, new String('\t')),
'[\n\t1,\n]',
'accepts String objects'
)
t.end()
})
t.test('#stringify(value, replacer)', t => {
t.strictSame(
JSON5.stringify({a: 1, b: 2, 3: 3}, ['a', 3]),
"{a:1,'3':3}",
'filters keys when an array is provided'
)
t.strictSame(
JSON5.stringify({a: 1, b: 2, 3: 3, false: 4}, ['a', 3, false]),
"{a:1,'3':3}",
'only filters string and number keys when an array is provided'
)
t.strictSame(
// eslint-disable-next-line no-new-wrappers
JSON5.stringify({a: 1, b: 2, 3: 3}, [new String('a'), new Number(3)]),
"{a:1,'3':3}",
'accepts String and Number objects when an array is provided'
)
t.strictSame(
JSON5.stringify({a: 1, b: 2}, (key, value) => (key === 'a') ? 2 : value),
'{a:2,b:2}',
'replaces values when a function is provided'
)
t.strictSame(
JSON5.stringify({a: {b: 1}}, function (k, v) { return (k === 'b' && this.b) ? 2 : v }),
'{a:{b:2}}',
'sets `this` to the parent value'
)
t.test('is called after toJSON', t => {
function C () {}
Object.assign(C.prototype, {toJSON () { return {a: 1, b: 2} }})
assert.strictEqual(
JSON5.stringify(new C(), (key, value) => (key === 'a') ? 2 : value),
'{a:2,b:2}'
)
t.end()
})
t.test('is called after toJSON5', t => {
function C () {}
Object.assign(C.prototype, {toJSON5 () { return {a: 1, b: 2} }})
assert.strictEqual(
JSON5.stringify(new C(), (key, value) => (key === 'a') ? 2 : value),
'{a:2,b:2}'
)
t.end()
})
t.strictSame(
JSON5.stringify(
{a: 1},
(key, value) => {
JSON5.stringify({}, null, 4)
return value
},
2
),
'{\n a: 1,\n}',
'does not affect space when calls are nested'
)
t.end()
})
t.test('#stringify(value, options)', t => {
t.strictSame(
JSON5.stringify({a: 1, b: 2, 3: 3}, {replacer: ['a', 3]}),
"{a:1,'3':3}",
'accepts replacer as an option'
)
t.strictSame(
JSON5.stringify([1], {space: 2}),
'[\n 1,\n]',
'accepts space as an option'
)
t.end()
})
t.test('#stringify(value, {quote})', t => {
t.strictSame(
JSON5.stringify({'a"': '1"'}, {quote: '"'}),
'{"a\\"":"1\\""}',
'uses double quotes if provided'
)
t.strictSame(
JSON5.stringify({"a'": "1'"}, {quote: "'"}),
"{'a\\'':'1\\''}",
'uses single quotes if provided'
)
t.end()
})
t.end()
})
================================================
FILE: test/test.json5
================================================
{a: 1, b: 2}
gitextract_m1gwni37/
├── .editorconfig
├── .eslintignore
├── .eslintrc.json
├── .github/
│ ├── issue_template.md
│ └── pull_request_template.md
├── .gitignore
├── .travis.yml
├── CHANGELOG.md
├── CONTRIBUTING.md
├── LICENSE.md
├── README.md
├── SECURITY.md
├── build/
│ ├── es5.js
│ ├── package.js
│ └── unicode.js
├── lib/
│ ├── cli.js
│ ├── index.d.ts
│ ├── index.js
│ ├── parse.d.ts
│ ├── parse.js
│ ├── register.js
│ ├── require.js
│ ├── stringify.d.ts
│ ├── stringify.js
│ ├── unicode.d.ts
│ ├── unicode.js
│ ├── util.d.ts
│ └── util.js
├── package.json
├── package.json5
├── rollup.config.js
└── test/
├── cli.js
├── errors.js
├── invalid.json5
├── parse.js
├── require.js
├── stringify.js
└── test.json5
SYMBOL INDEX (92 symbols across 12 files)
FILE: build/es5.js
constant JSON5 (line 4) | const JSON5 = require('../lib')
FILE: build/package.js
constant JSON5 (line 4) | const JSON5 = require('../lib')
FILE: lib/cli.js
constant JSON5 (line 6) | const JSON5 = require('./')
function parseArgs (line 73) | function parseArgs () {
function version (line 133) | function version () {
function usage (line 137) | function usage () {
FILE: lib/index.js
constant JSON5 (line 4) | const JSON5 = {
FILE: lib/parse.js
function internalize (line 42) | function internalize (holder, name, reviver) {
function lex (line 86) | function lex () {
function peek (line 107) | function peek () {
function read (line 113) | function read () {
method default (line 133) | default () {
method comment (line 171) | comment () {
method multiLineComment (line 187) | multiLineComment () {
method multiLineCommentAsterisk (line 201) | multiLineCommentAsterisk () {
method singleLineComment (line 220) | singleLineComment () {
method value (line 238) | value () {
method identifierNameStartEscape (line 312) | identifierNameStartEscape () {
method identifierName (line 336) | identifierName () {
method identifierNameEscape (line 359) | identifierNameEscape () {
method sign (line 385) | sign () {
method zero (line 424) | zero () {
method decimalInteger (line 447) | decimalInteger () {
method decimalPointLeading (line 469) | decimalPointLeading () {
method decimalPoint (line 479) | decimalPoint () {
method decimalFraction (line 497) | decimalFraction () {
method decimalExponent (line 514) | decimalExponent () {
method decimalExponentSign (line 532) | decimalExponentSign () {
method decimalExponentInteger (line 542) | decimalExponentInteger () {
method hexadecimal (line 551) | hexadecimal () {
method hexadecimalInteger (line 561) | hexadecimalInteger () {
method string (line 570) | string () {
method start (line 611) | start () {
method beforePropertyName (line 625) | beforePropertyName () {
method afterPropertyName (line 657) | afterPropertyName () {
method beforePropertyValue (line 665) | beforePropertyValue () {
method afterPropertyValue (line 669) | afterPropertyValue () {
method beforeArrayValue (line 679) | beforeArrayValue () {
method afterArrayValue (line 687) | afterArrayValue () {
method end (line 697) | end () {
function newToken (line 708) | function newToken (type, value) {
function literal (line 717) | function literal (s) {
function escape (line 729) | function escape () {
function hexEscape (line 804) | function hexEscape () {
function unicodeEscape (line 824) | function unicodeEscape () {
method start (line 841) | start () {
method beforePropertyName (line 849) | beforePropertyName () {
method afterPropertyName (line 874) | afterPropertyName () {
method beforePropertyValue (line 887) | beforePropertyValue () {
method beforeArrayValue (line 895) | beforeArrayValue () {
method afterPropertyValue (line 908) | afterPropertyValue () {
method afterArrayValue (line 931) | afterArrayValue () {
method end (line 954) | end () {
function push (line 962) | function push () {
function pop (line 1027) | function pop () {
function invalidChar (line 1050) | function invalidChar (c) {
function invalidEOF (line 1058) | function invalidEOF () {
function invalidIdentifier (line 1072) | function invalidIdentifier () {
function separatorChar (line 1077) | function separatorChar (c) {
function formatChar (line 1081) | function formatChar (c) {
function syntaxError (line 1109) | function syntaxError (message) {
FILE: lib/register.js
constant JSON5 (line 2) | const JSON5 = require('./')
FILE: lib/stringify.d.ts
type StringifyOptions (line 1) | type StringifyOptions = {
FILE: lib/stringify.js
function serializeProperty (line 61) | function serializeProperty (key, holder) {
function quoteString (line 104) | function quoteString (value) {
function serializeObject (line 164) | function serializeObject (value) {
function serializeKey (line 208) | function serializeKey (key) {
function serializeArray (line 227) | function serializeArray (value) {
FILE: lib/util.js
method isSpaceSeparator (line 4) | isSpaceSeparator (c) {
method isIdStartChar (line 8) | isIdStartChar (c) {
method isIdContinueChar (line 17) | isIdContinueChar (c) {
method isDigit (line 28) | isDigit (c) {
method isHexDigit (line 32) | isHexDigit (c) {
FILE: test/errors.js
constant JSON5 (line 1) | const JSON5 = require('../lib')
FILE: test/parse.js
constant JSON5 (line 3) | const JSON5 = require('../lib')
FILE: test/stringify.js
constant JSON5 (line 2) | const JSON5 = require('../lib')
method a (line 119) | a () {}
function C (line 243) | function C () {}
method toJSON (line 244) | toJSON () { return {a: 1, b: 2} }
function C (line 250) | function C () {}
method toJSON (line 251) | toJSON (key) { return (key === 'a') ? 1 : 2 }
function C (line 257) | function C () {}
method toJSON5 (line 258) | toJSON5 () { return {a: 1, b: 2} }
function C (line 264) | function C () {}
method toJSON5 (line 265) | toJSON5 (key) { return (key === 'a') ? 1 : 2 }
function C (line 271) | function C () {}
method toJSON (line 273) | toJSON () { return {a: 1, b: 2} }
method toJSON5 (line 274) | toJSON5 () { return {a: 2, b: 2} }
function C (line 414) | function C () {}
method toJSON (line 415) | toJSON () { return {a: 1, b: 2} }
function C (line 424) | function C () {}
method toJSON5 (line 425) | toJSON5 () { return {a: 1, b: 2} }
Condensed preview — 38 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (150K chars).
[
{
"path": ".editorconfig",
"chars": 313,
"preview": "# EditorConfig is awesome: http://EditorConfig.org\n\nroot = true\n\n[*]\nindent_style = space\nindent_size = 4\nend_of_line = "
},
{
"path": ".eslintignore",
"chars": 16,
"preview": "coverage/\ndist/\n"
},
{
"path": ".eslintrc.json",
"chars": 564,
"preview": "{\n \"root\": true,\n \"extends\": [\n \"standard\",\n \"plugin:node/recommended\"\n ],\n \"rules\": {\n "
},
{
"path": ".github/issue_template.md",
"chars": 1134,
"preview": "If you are reporting a security vulnerability, please do not submit an issue.\nInstead, follow the guidelines described i"
},
{
"path": ".github/pull_request_template.md",
"chars": 1109,
"preview": "If you are patching a security vulnerability, please do not submit a pull\nrequest. Instead, follow the guidelines descri"
},
{
"path": ".gitignore",
"chars": 627,
"preview": "# Logs\nlogs\n*.log\nnpm-debug.log*\n\n# Runtime data\npids\n*.pid\n*.seed\n\n# Directory for instrumented libs generated by jscov"
},
{
"path": ".travis.yml",
"chars": 53,
"preview": "language: node_js\nnode_js:\n - \"11\"\n - \"10\"\n - \"8\"\n"
},
{
"path": "CHANGELOG.md",
"chars": 15286,
"preview": "### Unreleased [[code][c-unreleased], [diff][d-unreleased]]\n\n[c-unreleased]: https://github.com/json5/json5/tree/main\n[d"
},
{
"path": "CONTRIBUTING.md",
"chars": 680,
"preview": "# Contributing to JSON5\nWe're glad you're interested in contributing to JSON5.\n\n## Development\n```sh\ngit clone https://g"
},
{
"path": "LICENSE.md",
"chars": 1145,
"preview": "MIT License\n\nCopyright (c) 2012-2018 Aseem Kishore, and [others].\n\nPermission is hereby granted, free of charge, to any "
},
{
"path": "README.md",
"chars": 10905,
"preview": "# JSON5 – JSON for Humans\n\n[][Build\nStatus] [![Cov"
},
{
"path": "SECURITY.md",
"chars": 2551,
"preview": "# JSON5 Security Policy\n\nWe take security seriously. Responsible reporting and disclosure of security\nvulnerabilities is"
},
{
"path": "build/es5.js",
"chars": 145,
"preview": "require('core-js/fn/string/code-point-at')\nrequire('core-js/fn/string/from-code-point')\n\nconst JSON5 = require('../lib')"
},
{
"path": "build/package.js",
"chars": 302,
"preview": "const fs = require('fs')\nconst path = require('path')\n\nconst JSON5 = require('../lib')\n\nconst pkg = require('../package."
},
{
"path": "build/unicode.js",
"chars": 1773,
"preview": "/* eslint-disable camelcase */\n\nconst fs = require('fs')\nconst path = require('path')\nconst regenerate = require('regene"
},
{
"path": "lib/cli.js",
"chars": 3592,
"preview": "#!/usr/bin/env node\n\nconst fs = require('fs')\nconst path = require('path')\nconst pkg = require('../package.json')\nconst "
},
{
"path": "lib/index.d.ts",
"chars": 103,
"preview": "import parse = require('./parse')\nimport stringify = require('./stringify')\n\nexport {parse, stringify}\n"
},
{
"path": "lib/index.js",
"chars": 143,
"preview": "const parse = require('./parse')\nconst stringify = require('./stringify')\n\nconst JSON5 = {\n parse,\n stringify,\n}\n\n"
},
{
"path": "lib/parse.d.ts",
"chars": 533,
"preview": "/**\n * Parses a JSON5 string, constructing the JavaScript value or object described\n * by the string.\n * @template T The"
},
{
"path": "lib/parse.js",
"chars": 22402,
"preview": "const util = require('./util')\n\nlet source\nlet parseState\nlet stack\nlet pos\nlet line\nlet column\nlet token\nlet key\nlet ro"
},
{
"path": "lib/register.js",
"chars": 374,
"preview": "const fs = require('fs')\nconst JSON5 = require('./')\n\n// eslint-disable-next-line node/no-deprecated-api\nrequire.extensi"
},
{
"path": "lib/require.js",
"chars": 163,
"preview": "// This file is for backward compatibility with v0.5.1.\nrequire('./register')\n\nconsole.warn(\"'json5/require' is deprecat"
},
{
"path": "lib/stringify.d.ts",
"chars": 4157,
"preview": "declare type StringifyOptions = {\n /**\n * A function that alters the behavior of the stringification process, or "
},
{
"path": "lib/stringify.js",
"chars": 6983,
"preview": "const util = require('./util')\n\nmodule.exports = function stringify (value, replacer, space) {\n const stack = []\n "
},
{
"path": "lib/unicode.d.ts",
"chars": 124,
"preview": "export declare const Space_Separator: RegExp\nexport declare const ID_Start: RegExp\nexport declare const ID_Continue: Reg"
},
{
"path": "lib/unicode.js",
"chars": 15815,
"preview": "// This is a generated file. Do not edit.\nmodule.exports.Space_Separator = /[\\u1680\\u2000-\\u200A\\u202F\\u205F\\u3000]/\nmod"
},
{
"path": "lib/util.d.ts",
"chars": 292,
"preview": "export declare function isSpaceSeparator(c?: string): boolean\nexport declare function isIdStartChar(c?: string): boolean"
},
{
"path": "lib/util.js",
"chars": 885,
"preview": "const unicode = require('../lib/unicode')\n\nmodule.exports = {\n isSpaceSeparator (c) {\n return typeof c === 'st"
},
{
"path": "package.json",
"chars": 1916,
"preview": "{\n \"name\": \"json5\",\n \"version\": \"2.2.3\",\n \"description\": \"JSON for Humans\",\n \"main\": \"lib/index.js\",\n \"module\": \"di"
},
{
"path": "package.json5",
"chars": 1892,
"preview": "// This is a generated file. Do not edit.\n{\n name: 'json5',\n version: '2.2.3',\n description: 'JSON for Humans',\n mai"
},
{
"path": "rollup.config.js",
"chars": 1494,
"preview": "const resolve = require('rollup-plugin-node-resolve')\nconst commonjs = require('rollup-plugin-commonjs')\nconst buble = r"
},
{
"path": "test/cli.js",
"chars": 8735,
"preview": "const assert = require('assert')\nconst child = require('child_process')\nconst fs = require('fs')\nconst path = require('p"
},
{
"path": "test/errors.js",
"chars": 11813,
"preview": "const JSON5 = require('../lib')\n\nconst t = require('tap')\n\nt.test('JSON5', t => {\n t.test('#parse()', t => {\n "
},
{
"path": "test/invalid.json5",
"chars": 2,
"preview": "a\n"
},
{
"path": "test/parse.js",
"chars": 7870,
"preview": "const assert = require('assert')\nconst sinon = require('sinon')\nconst JSON5 = require('../lib')\n\nconst t = require('tap'"
},
{
"path": "test/require.js",
"chars": 892,
"preview": "const assert = require('assert')\nconst sinon = require('sinon')\n\nconst t = require('tap')\n\nt.test('require(*.json5)', t "
},
{
"path": "test/stringify.js",
"chars": 13746,
"preview": "const assert = require('assert')\nconst JSON5 = require('../lib')\n\nconst t = require('tap')\n\nt.test('JSON5', t => {\n t"
},
{
"path": "test/test.json5",
"chars": 13,
"preview": "{a: 1, b: 2}\n"
}
]
About this extraction
This page contains the full source code of the aseemk/json5 GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 38 files (137.2 KB), approximately 41.1k tokens, and a symbol index with 92 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.