diff options
author | Forrest L Norvell <forrest@npmjs.com> | 2015-02-27 17:32:04 +0300 |
---|---|---|
committer | Forrest L Norvell <forrest@npmjs.com> | 2015-02-27 17:32:04 +0300 |
commit | abdd040da90932535472f593d5433a67ee074801 (patch) | |
tree | 19043a3a504ffaab0e9055cc56755e1f66b793b2 /node_modules | |
parent | 91db20b318acad9e9a268dcc9b2646146a5edd97 (diff) |
read-package-json@1.3.2
Provide more helpful error messages when JSON parse errors are
encountered by using a more forgiving JSON parser than JSON.parse.
Diffstat (limited to 'node_modules')
44 files changed, 4709 insertions, 31 deletions
diff --git a/node_modules/read-package-json/node_modules/json-parse-helpfulerror/.editorconfig b/node_modules/read-package-json/node_modules/json-parse-helpfulerror/.editorconfig new file mode 100644 index 000000000..fb7f73a83 --- /dev/null +++ b/node_modules/read-package-json/node_modules/json-parse-helpfulerror/.editorconfig @@ -0,0 +1,14 @@ +root = true + +[*] +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true + +[*.js, **/*.js] +indent_size = 4 +indent_style = space + +[{package.json,.travis.yml}] +indent_size = 2 +indent_style = space diff --git a/node_modules/read-package-json/node_modules/json-parse-helpfulerror/.npmignore b/node_modules/read-package-json/node_modules/json-parse-helpfulerror/.npmignore new file mode 100644 index 000000000..59d842baa --- /dev/null +++ b/node_modules/read-package-json/node_modules/json-parse-helpfulerror/.npmignore @@ -0,0 +1,28 @@ +# Logs +logs +*.log + +# Runtime data +pids +*.pid +*.seed + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage + +# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# Compiled binary addons (http://nodejs.org/api/addons.html) +build/Release + +# Dependency directory +# Commenting this out is preferred by some people, see +# https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git- +node_modules + +# Users Environment Variables +.lock-wscript diff --git a/node_modules/read-package-json/node_modules/json-parse-helpfulerror/LICENSE b/node_modules/read-package-json/node_modules/json-parse-helpfulerror/LICENSE new file mode 100644 index 000000000..e637724b3 --- /dev/null +++ b/node_modules/read-package-json/node_modules/json-parse-helpfulerror/LICENSE @@ -0,0 +1,22 @@ +The MIT License (MIT) + +Copyright (c) 2015 Sam Mikes + +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. + diff --git a/node_modules/read-package-json/node_modules/json-parse-helpfulerror/README.md b/node_modules/read-package-json/node_modules/json-parse-helpfulerror/README.md new file mode 100644 index 000000000..ffad93584 --- /dev/null +++ b/node_modules/read-package-json/node_modules/json-parse-helpfulerror/README.md @@ -0,0 +1,29 @@ +# json-parse-helpfulerror + +A drop-in replacement for `JSON.parse` that uses +<https://npmjs.org/jju> to provide more useful error messages in the +event of a parse error. + +# Example + +## Installation + +``` +npm i -S json-parse-helpfulerror +``` + +## Use + +```js +var jph = require('json-parse-helpfulerror'); + +var notJSON = "{'foo': 3}"; // keys must be double-quoted in JSON + +JSON.parse(notJSON); // throws unhelpful error + +jph.parse("{'foo': 3}") // throws more helpful error: "Unexpected token '\''..." +``` + +# License + +MIT
\ No newline at end of file diff --git a/node_modules/read-package-json/node_modules/json-parse-helpfulerror/index.js b/node_modules/read-package-json/node_modules/json-parse-helpfulerror/index.js new file mode 100644 index 000000000..15648b017 --- /dev/null +++ b/node_modules/read-package-json/node_modules/json-parse-helpfulerror/index.js @@ -0,0 +1,21 @@ +'use strict'; + +var jju = require('jju'); + +function parse(text, reviver) { + try { + return JSON.parse(text, reviver); + } catch (err) { + // we expect this to throw with a more informative message + jju.parse(text, { + mode: 'json', + reviver: reviver + }); + + // backup if jju is not as strict as JSON.parse; re-throw error + // data-dependent code path, I do not know how to cover it + throw err; + } +} + +exports.parse = parse; diff --git a/node_modules/read-package-json/node_modules/json-parse-helpfulerror/node_modules/jju/.editorconfig b/node_modules/read-package-json/node_modules/json-parse-helpfulerror/node_modules/jju/.editorconfig new file mode 100644 index 000000000..8de2a35e3 --- /dev/null +++ b/node_modules/read-package-json/node_modules/json-parse-helpfulerror/node_modules/jju/.editorconfig @@ -0,0 +1,19 @@ +root = true + +[*] +charset = utf-8 +end_of_line = lf +trim_trailing_whitespace = true +insert_final_newline = true + +[{.,}*.{js,json,json5,yml,yaml}] +indent_style = space +indent_size = 2 + +[*.md] +indent_style = space +indent_size = 4 +trim_trailing_whitespace = false + +[Makefile] +indent_style = tab diff --git a/node_modules/read-package-json/node_modules/json-parse-helpfulerror/node_modules/jju/.npmignore b/node_modules/read-package-json/node_modules/json-parse-helpfulerror/node_modules/jju/.npmignore new file mode 100644 index 000000000..b561496c9 --- /dev/null +++ b/node_modules/read-package-json/node_modules/json-parse-helpfulerror/node_modules/jju/.npmignore @@ -0,0 +1,6 @@ +package.json +node_modules +test/external +examples +/.eslint* +/.travis.yml diff --git a/node_modules/read-package-json/node_modules/json-parse-helpfulerror/node_modules/jju/README.md b/node_modules/read-package-json/node_modules/json-parse-helpfulerror/node_modules/jju/README.md new file mode 100644 index 000000000..85d52a2dc --- /dev/null +++ b/node_modules/read-package-json/node_modules/json-parse-helpfulerror/node_modules/jju/README.md @@ -0,0 +1,243 @@ +`jju` - a set of utilities to work with JSON / JSON5 documents + +[![npm version badge](https://img.shields.io/npm/v/jju.svg)](https://www.npmjs.org/package/jju) +[![travis badge](http://img.shields.io/travis/rlidwka/jju.svg)](https://travis-ci.org/rlidwka/jju) +[![downloads badge](http://img.shields.io/npm/dm/jju.svg)](https://www.npmjs.org/package/jju) + +## Installation + +``` +npm install jju +``` + +## Usage + +This module provides following functions: + +1. [jju.parse()](#jjuparse-function) parses json/json5 text and returns a javascript value it corresponds to +2. [jju.stringify()](#jjustringify-function) converts javascript value to an appropriate json/json5 text +3. [jju.tokenize()](#jjutokenize-function) parses json/json5 text and returns an array of tokens it consists of ([see demo](http://rlidwka.github.io/jju/tokenizer.html)) +4. [jju.analyze()](#jjuanalyze-function) parses json/json5 text and tries to guess indentation, quoting style, etc. +5. [jju.update()](#jjuupdate-function) changes json/json5 text, preserving original formatting as much as possible ([see demo](http://rlidwka.github.io/jju/editor.html)) + +All functions are able to work with a standard JSON documents. `jju.parse()` and `jju.stringify()` are better in some cases, but slower than native `JSON.parse()` and `JSON.stringify()` versions. Detailed description see below. + +### jju.parse() function + +```javascript +/* + * Main syntax: + * + * `text` - text to parse, type: String + * `options` - parser options, type: Object + */ +jju.parse(text[, options]) + +// compatibility syntax +jju.parse(text[, reviver]) +``` + +Options: + + - reserved\_keys - what to do with reserved keys (String, default="ignore") + - "ignore" - ignore reserved keys + - "throw" - throw SyntaxError in case of reserved keys + - "replace" - replace reserved keys, this is the default JSON.parse behaviour, unsafe + + Reserved keys are keys that exist in an empty object (`hasOwnProperty`, `__proto__`, etc.). + +```javascript +// 'ignore' will cause reserved keys to be ignored: +parse('{hasOwnProperty: 1}', {reserved_keys: 'ignore'}) == {} +parse('{hasOwnProperty: 1, x: 2}', {reserved_keys: 'ignore'}).hasOwnProperty('x') == true + +// 'throw' will cause SyntaxError in these cases: +parse('{hasOwnProperty: 1}', {reserved_keys: 'throw'}) == SyntaxError + +// 'replace' will replace reserved keys with new ones: +parse('{hasOwnProperty: 1}', {reserved_keys: 'throw'}) == {hasOwnProperty: 1} +parse('{hasOwnProperty: 1, x: 2}', {reserved_keys: 'ignore'}).hasOwnProperty('x') == TypeError +``` + + + - null\_prototype - create object as Object.create(null) instead of '{}' (Boolean) + + if `reserved_keys != 'replace'`, default is **false** + + if `reserved_keys == 'replace'`, default is **true** + + It is usually unsafe and not recommended to change this option to false in the last case. + + - reviver - reviver function - Function + + This function should follow JSON specification + + - mode - operation mode, set it to 'json' if you want to throw on non-strict json files (String) + +### jju.stringify() function + +```javascript +/* + * Main syntax: + * + * `value` - value to serialize, type: * + * `options` - serializer options, type: Object + */ +jju.stringify(value[, options]) + +// compatibility syntax +jju.stringify(value[, replacer [, indent]) +``` + +Options: + + - ascii - output ascii only (Boolean, default=false) + If this option is enabled, output will not have any characters except of 0x20-0x7f. + + - indent - indentation (String, Number or Boolean, default='\t') + This option follows JSON specification. + + - quote - enquoting char (String, "'" or '"', default="'") + - quote\_keys - whether keys quoting in objects is required or not (String, default=false) + If you want `{"q": 1}` instead of `{q: 1}`, set it to true. + + - sort\_keys - sort all keys while stringifying (Boolean or Function, default=false) + By default sort order will depend on implementation, with v8 it's insertion order. If set to `true`, all keys (but not arrays) will be sorted alphabetically. You can provide your own sorting function as well. + + - replacer - replacer function or array (Function or Array) + This option follows JSON specification. + + - no\_trailing\_comma = don't output trailing comma (Boolean, default=false) + If this option is set, arrays like this `[1,2,3,]` will never be generated. Otherwise they may be generated for pretty printing. + + - mode - operation mode, set it to 'json' if you want correct json in the output (String) + + Currently it's either 'json' or something else. If it is 'json', following options are implied: + + - options.quote = '"' + - options.no\_trailing\_comma = true + - options.quote\_keys = true + - '\x' literals are not used + +### jju.tokenize() function + +```javascript +/* + * Main syntax: + * + * `text` - text to tokenize, type: String + * `options` - parser options, type: Object + */ +jju.tokenize(text[, options]) +``` + +Options are the same as for the `jju.parse` function. + +Return value is an array of tokens, where each token is an object: + + - raw (String) - raw text of this token, if you join all raw's, you will get the original document + - type (String) - type of the token, can be `whitespace`, `comment`, `key`, `literal`, `separator` or `newline` + - stack (Array) - path to the current token in the syntax tree + - value - value of the token if token is a `key` or `literal` + +You can check tokenizer for yourself using [this demo](http://rlidwka.github.io/jju/tokenizer.html). + +### jju.analyze() function + +```javascript +/* + * Main syntax: + * + * `text` - text to analyze, type: String + * `options` - parser options, type: Object + */ +jju.analyze(text[, options]) +``` + +Options are the same as for the `jju.parse` function. + +Return value is an object defining a programming style in which the document was written. + + - indent (String) - preferred indentation + - newline (String) - preferred newline + - quote (String) - `"` or `'` depending on which quote is preferred + - quote\_keys (Boolean) - `true` if unquoted keys were used at least once + - has\_whitespace (Boolean) - `true` if input has a whitespace token + - has\_comments (Boolean) - `true` if input has a comment token + - has\_newlines (Boolean) - `true` if input has a newline token + - has\_trailing\_comma (Boolean) - `true` if input has at least one trailing comma + +### jju.update() function + +```javascript +/* + * Main syntax: + * + * `text` - original text, type: String + * `new_value` - new value you want to set + * `options` - parser or stringifier options, type: Object + */ +jju.update(text, new_value[, options]) +``` + +If you want to update a JSON document, here is the general approach: + +```javascript +// here is your original JSON document: +var input = '{"foo": "bar", "baz": 123}' + +// you need to parse it first: +var json = jju.parse(input, {mode: 'json'}) +// json is { foo: 'bar', baz: 123 } + +// then you can change it as you like: +json.foo = 'quux' +json.hello = 'world' + +// then you run an update function to change the original json: +var output = jju.update(input, json, {mode: 'json'}) +// output is '{"foo": "quux", "baz": 123, "hello": "world"}' +``` + +Look at [this demo](http://rlidwka.github.io/jju/editor.html) to test various types of json. + +## Advantages over existing JSON libraries + +In a few cases it makes sense to use this module instead of built-in JSON methods. + +Parser: + - better error reporting with source code and line numbers + +In case of syntax error, JSON.parse does not return any good information to the user. This module does: + +``` +$ node -e 'require("jju").parse("[1,1,1,1,invalid]")' + +SyntaxError: Unexpected token 'i' at 0:9 +[1,1,1,1,invalid] + ^ +``` + +This module is about 5 times slower, so if user experience matters to you more than performance, use this module. If you're working with a lot of machine-generated data, use JSON.parse instead. + +Stringifier: + - util.inspect-like pretty printing + +This module behaves more smart when dealing with object and arrays, and does not always print newlines in them: + +``` +$ node -e 'console.log(require("./").stringify([[,,,],,,[,,,,]], {mode:"json"}))' +[ + [null, null, null], + null, + null, + [null, null, null, null] +] +``` + +JSON.stringify will split this into 15 lines, and it's hard to read. + +Yet again, this feature comes with a performance hit, so if user experience matters to you more than performance, use this module. If your JSON will be consumed by machines, use JSON.stringify instead. + +As a rule of thumb, if you use "space" argument to indent your JSON, you'd better use this module instead. + diff --git a/node_modules/read-package-json/node_modules/json-parse-helpfulerror/node_modules/jju/benchmark/benchmark.js b/node_modules/read-package-json/node_modules/json-parse-helpfulerror/node_modules/jju/benchmark/benchmark.js new file mode 100755 index 000000000..28a6aad75 --- /dev/null +++ b/node_modules/read-package-json/node_modules/json-parse-helpfulerror/node_modules/jju/benchmark/benchmark.js @@ -0,0 +1,40 @@ +#!/usr/bin/env node + +var Benchmark = require('benchmark') +var YAML = require('js-yaml') +var JJU = require('../') +var JSON5 = require('json5') +var suite = new Benchmark.Suite + +var sample +sample = require('fs').readFileSync(__dirname + '/../package.yaml') +sample = YAML.safeLoad(sample) +sample = JSON.stringify(sample) + +var functions = { + 'JSON': function(x) { JSON.parse(x) }, + 'JSON5': function(x) { JSON5.parse(x) }, + 'JJU': function(x) { JJU.parse(x) }, + 'JS-YAML': function(x) { YAML.safeLoad(x) }, +} + +for (var name in functions) { + with ({ fn: functions[name] }) { + suite.add(name, { + onCycle: function onCycle(event) { + process.stdout.write('\r\033[2K - ' + event.target) + }, + fn: function () { + fn(sample) + }, + }) + } +} + +console.log() +suite.on('cycle', function(event) { + console.log('\r\033[2K + ' + String(event.target)) +}) +.run() + +process.on('exit', function() { console.log() }) diff --git a/node_modules/read-package-json/node_modules/json-parse-helpfulerror/node_modules/jju/benchmark/package.json b/node_modules/read-package-json/node_modules/json-parse-helpfulerror/node_modules/jju/benchmark/package.json new file mode 100644 index 000000000..7f0dcf08b --- /dev/null +++ b/node_modules/read-package-json/node_modules/json-parse-helpfulerror/node_modules/jju/benchmark/package.json @@ -0,0 +1,9 @@ +{ + "name": "benchmarks", + "private": true, + "dependencies": { + "json5": "*", + "js-yaml": "*", + "benchmark": "*" + } +} diff --git a/node_modules/read-package-json/node_modules/json-parse-helpfulerror/node_modules/jju/docs/Grammar.md b/node_modules/read-package-json/node_modules/json-parse-helpfulerror/node_modules/jju/docs/Grammar.md new file mode 100644 index 000000000..eb7c8bc66 --- /dev/null +++ b/node_modules/read-package-json/node_modules/json-parse-helpfulerror/node_modules/jju/docs/Grammar.md @@ -0,0 +1,219 @@ + +JSON5 grammar expressed in EBNF form. + +PS: I don't know what is appropriate syntax highlighter for this, so I'm using "modula2" because why not. I also inserted <ZWSP> after backslash to preserve syntax highlighting, this character has nothing to do with actual JSON5 syntax and should be ignored. + +```modula2 +json5_text = expression_with_whitespace + +expression_with_whitespace = [white_space] , expression , [white_space] + +expression = literal + | array_literal + | object_literal + +literal = null_literal + | boolean_literal + | signed_numeric_literal + | string_literal + +null_literal = 'null' + +boolean_literal = 'true' + | 'false' + +(* Source Characters *) + +source_character = . + (* any Unicode code unit *) + +line_terminator = <LF> + | <CR> + | <LS> + | <PS> + +line_terminator_sequence = <LF> + | <CR> + | <LS> + | <PS> + | <CR> , <LF> + +white_space = white_space_element + | white_space , white_space_element + +white_space_element = white_space_character + | comment + +white_space_character = <TAB> + | <VT> + | <FF> + | <SP> + | <NBSP> + | <BOM> + | <USP> + +comment = multi_line_comment + | single_line_comment + +multi_line_comment = '/*' , [multi_line_comment_chars] , '*/' + +multi_line_comment_chars = (source_character - '*') , [multi_line_comment_chars] + | '*' , [post_asterisk_comment_chars] + +post_asterisk_comment_chars = (source_character - ('*' | '/')) , [multi_line_comment_chars] + | '*' , [post_asterisk_comment_chars] + +single_line_comment = '//' , [single_line_comment_chars] + +single_line_comment_chars = single_line_comment_char , single_line_comment_chars + +single_line_comment_char = source_character - line_terminator + +(* Character classes *) + +decimal_digit = '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' + +non_zero_digit = decimal_digit - '0' + +hex_digit = '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' | 'a' + | 'b' | 'c' | 'd' | 'e' | 'f' | 'A' | 'B' | 'C' | 'D' | 'E' | 'F' + +ascii_letter = ascii_letter_lowercase + | ascii_letter_uppercase + +ascii_letter_lowercase = 'a' | 'b' | 'c' | 'd' | 'e' | 'f' | 'g' | 'h' | 'i' + | 'j' | 'k' | 'l' | 'm' | 'n' | 'o' | 'p' | 'q' | 'r' + | 's' | 't' | 'u' | 'v' | 'w' | 'x' | 'y' | 'z' + +ascii_letter_uppercase = 'A' | 'B' | 'C' | 'D' | 'E' | 'F' | 'G' | 'H' | 'I' + | 'J' | 'K' | 'L' | 'M' | 'N' | 'O' | 'P' | 'Q' | 'R' + | 'S' | 'T' | 'U' | 'V' | 'W' | 'X' | 'Y' | 'Z' + +(* Numeric Literals *) + +signed_numeric_literal = '-' , numeric_literal + | '+' , numeric_literal + | numeric_literal + +numeric_literal = decimal_literal + | hex_integer_literal + | non_finite_literal + +non_finite_literal = 'Infinity' + | 'NaN' + +decimal_literal = decimal_integer_literal , '.' , [decimal_digits] , [exponent_part] + | '.' , decimal_digits , [exponent_part] + | decimal_integer_literal , [exponent_part] + +decimal_integer_literal = '0' + | non_zero_digit , [decimal_digits] + +decimal_digits = decimal_digit + | decimal_digits , decimal_digit + +exponent_part = exponent_indicator , signed_integer + +exponent_indicator = 'e' | 'E' + +signed_integer = decimal_digits + | '+' , decimal_digits + | '-' , decimal_digits + +hex_integer_literal = '0x' , hex_digit + | '0X' , hex_digit + | hex_integer_literal , hex_digit + +(* String Literals *) + +string_literal = '"' , [double_string_characters] , '"' + | "'" , [single_string_characters] , "'" + +double_string_characters = double_string_character , [double_string_characters] + +single_string_characters = single_string_character , [single_string_characters] + +double_string_character = source_character - ('"' | '\' | line_terminator) + | '\' , escape_sequence + | line_continuation + +single_string_character = source_character - ("'" | '\' | line_terminator) + | '\' , escape_sequence + | line_continuation + +line_continuation = '\' , line_terminator_sequence + +escape_sequence = character_escape_sequence + | '0' + | hex_escape_sequence + | unicode_escape_sequence + +character_escape_sequence = single_escape_character + | non_escape_character + +single_escape_character = '"' | "'" | '\' | 'b' | 'f' | 'n' | 'r' | 't' | 'v' + +non_escape_character = source_character - (escape_character | line_terminator) + +escape_character = single_escape_character + | decimal_digit + | 'x' + | 'u' + +hex_escape_sequence = 'x' , hex_digit , hex_digit + +unicode_escape_sequence = 'u' , hex_digit , hex_digit , hex_digit , hex_digit + +(* Array Literals *) + +array_literal = '[' , [white_space] , ']' + | '[' , [white_space] , element_list , ']' + | '[' , [white_space] , element_list , ',' , [white_space] , ']' + +element_list = expression , [white_space] + | element_list , ',' , [white_space] , expression , [white_space] + +(* Object Literals *) + +object_literal = '{' , [white_space] , '}' + | '{' , [white_space] , property_name_and_value_list , '}' + | '{' , [white_space] , property_name_and_value_list , ',' , '}' + +property_name_and_value_list = property_assignment , [white_space] + | property_name_and_value_list , [white_space] , ',' , [white_space] , property_assignment , [white_space] + +property_assignment = property_name , [white_space] , ':' , [white_space] , expression + +property_name = identifier_name + | string_literal + | numeric_literal + +identifier_name = identifier_start + | identifier_name , identifier_part + +identifier_start = unicode_letter + | '$' + | '_' + | '\' , unicode_escape_sequence + +identifier_part = identifier_start + | unicode_combining_mark + | unicode_digit + | unicode_connector_punctuation + | <ZWNJ> + | <ZWJ> + +unicode_letter = ascii_letter + (* + any character in the Unicode categories "Uppercase letter (Lu)", "Lowercase letter (Ll)", "Titlecase letter (Lt)", "Modifier letter (Lm)", "Other letter (Lo)", or "Letter number (Nl)" *) + +unicode_combining_mark = + (* + any character in the Unicode categories "Non-spacing mark (Mn)" or "Combining spacing mark (Mc)" *) + +unicode_digit = decimal_digit + (* + any character in the Unicode category "Decimal number (Nd)" *) + +unicode_connector_punctuation = + (* + any character in the Unicode category "Connector punctuation (Pc)" *) + + +``` diff --git a/node_modules/read-package-json/node_modules/json-parse-helpfulerror/node_modules/jju/docs/JSON5.md b/node_modules/read-package-json/node_modules/json-parse-helpfulerror/node_modules/jju/docs/JSON5.md new file mode 100644 index 000000000..bbe18a3d8 --- /dev/null +++ b/node_modules/read-package-json/node_modules/json-parse-helpfulerror/node_modules/jju/docs/JSON5.md @@ -0,0 +1,50 @@ +## JSON5 syntax + +We support slighly modified version of JSON5, see https://groups.google.com/forum/#!topic/json5/3DjClVYI6Wg + +I started from ES5 specification and added a set of additional restrictions on top of ES5 spec. So I'd expect my implementation to be much closer to javascript. It's no longer an extension of json, but a reduction of ecmascript, which was my original intent. + +This JSON5 version is a subset of ES5 language, specification is here: + +http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf + +This is a language that defines data structures only, so following notes/restrictions are applied: + +- Literals (NullLiteral, BooleanLiteral, NumericLiteral, StringLiteral) are allowed. +- Compatibility syntax is not supported, which means octal literals are forbidden. +- ArrayLiterals and allowed, but instead of AssignmentExpressions you can only use other allowed Literals, ArrayLiterals and ObjectLiterals. Elisions are currently not supported. +- ObjectLiterals and allowed, but instead of AssignmentExpressions you can only use other allowed Literals, ArrayLiterals and ObjectLiterals. Setters and getters are forbidden. +- All other primary expressions ("this", Identifier, Expression) are forbidden. +- Two unary expressions ('-' and '+') allowed before NumericLiterals. +- Any data that has a number type can be represented, including +0, -0, +Infinity, -Infinity and NaN. +- "undefined" is forbidden, use null instead if applicable. +- Comments and whitespace are defined according to spec. + +Main authority here is ES5 spec, so strict backward JSON compatibility is not guaranteed. + + +If you're unsure whether a behaviour of this library is a bug or not, you can run this test: + +```javascript +JSON5.parse(String(something)) +``` + +Should always be equal to: + +```javascript +eval('(function(){return ('+String(something)+'\n)\n})()') +``` + +If `something` meets all rules above. Parens and newlines in the example above are carefully placed so comments and another newlines will work properly, so don't look so impressed about that. + + +## Weirdness of JSON5 + +These are the parts that I don't particulary like, but see no good way to fix: + + - no elisions, `[,,,] -> [null,null,null]` + - `[Object], [Circular]` aren't parsed + - no way of nicely representing multiline strings + - unicode property names are way to hard to implement + - Date and other custom objects + - incompatible with YAML (at least comments) diff --git a/node_modules/read-package-json/node_modules/json-parse-helpfulerror/node_modules/jju/index.js b/node_modules/read-package-json/node_modules/json-parse-helpfulerror/node_modules/jju/index.js new file mode 100644 index 000000000..50f162496 --- /dev/null +++ b/node_modules/read-package-json/node_modules/json-parse-helpfulerror/node_modules/jju/index.js @@ -0,0 +1,32 @@ + +module.exports.__defineGetter__('parse', function() { + return require('./lib/parse').parse +}) + +module.exports.__defineGetter__('stringify', function() { + return require('./lib/stringify').stringify +}) + +module.exports.__defineGetter__('tokenize', function() { + return require('./lib/parse').tokenize +}) + +module.exports.__defineGetter__('update', function() { + return require('./lib/document').update +}) + +module.exports.__defineGetter__('analyze', function() { + return require('./lib/analyze').analyze +}) + +module.exports.__defineGetter__('utils', function() { + return require('./lib/utils') +}) + +/**package +{ "name": "jju", + "version": "0.0.0", + "dependencies": {"js-yaml": "*"}, + "scripts": {"postinstall": "js-yaml package.yaml > package.json ; npm install"} +} +**/ diff --git a/node_modules/read-package-json/node_modules/json-parse-helpfulerror/node_modules/jju/lib/analyze.js b/node_modules/read-package-json/node_modules/json-parse-helpfulerror/node_modules/jju/lib/analyze.js new file mode 100644 index 000000000..9b0f9af01 --- /dev/null +++ b/node_modules/read-package-json/node_modules/json-parse-helpfulerror/node_modules/jju/lib/analyze.js @@ -0,0 +1,92 @@ +/* + * Author: Alex Kocharin <alex@kocharin.ru> + * GIT: https://github.com/rlidwka/jju + * License: WTFPL, grab your copy here: http://www.wtfpl.net/txt/copying/ + */ + +var tokenize = require('./parse').tokenize + +module.exports.analyze = function analyzeJSON(input, options) { + if (options == null) options = {} + + if (!Array.isArray(input)) { + input = tokenize(input, options) + } + + var result = { + has_whitespace: false, + has_comments: false, + has_newlines: false, + has_trailing_comma: false, + indent: '', + newline: '\n', + quote: '"', + quote_keys: true, + } + + var stats = { + indent: {}, + newline: {}, + quote: {}, + } + + for (var i=0; i<input.length; i++) { + if (input[i].type === 'newline') { + if (input[i+1] && input[i+1].type === 'whitespace') { + if (input[i+1].raw[0] === '\t') { + // if first is tab, then indent is tab + stats.indent['\t'] = (stats.indent['\t'] || 0) + 1 + } + if (input[i+1].raw.match(/^\x20+$/)) { + // if all are spaces, then indent is space + // this can fail with mixed indent (4, 2 would display 3) + var ws_len = input[i+1].raw.length + var indent_len = input[i+1].stack.length + 1 + if (ws_len % indent_len === 0) { + var t = Array(ws_len / indent_len + 1).join(' ') + stats.indent[t] = (stats.indent[t] || 0) + 1 + } + } + } + + stats.newline[input[i].raw] = (stats.newline[input[i].raw] || 0) + 1 + } + + if (input[i].type === 'newline') { + result.has_newlines = true + } + if (input[i].type === 'whitespace') { + result.has_whitespace = true + } + if (input[i].type === 'comment') { + result.has_comments = true + } + if (input[i].type === 'key') { + if (input[i].raw[0] !== '"' && input[i].raw[0] !== "'") result.quote_keys = false + } + + if (input[i].type === 'key' || input[i].type === 'literal') { + if (input[i].raw[0] === '"' || input[i].raw[0] === "'") { + stats.quote[input[i].raw[0]] = (stats.quote[input[i].raw[0]] || 0) + 1 + } + } + + if (input[i].type === 'separator' && input[i].raw === ',') { + for (var j=i+1; j<input.length; j++) { + if (input[j].type === 'literal' || input[j].type === 'key') break + if (input[j].type === 'separator') result.has_trailing_comma = true + } + } + } + + for (var k in stats) { + if (Object.keys(stats[k]).length) { + result[k] = Object.keys(stats[k]).reduce(function(a, b) { + return stats[k][a] > stats[k][b] ? a : b + }) + } + } + + return result +} + diff --git a/node_modules/read-package-json/node_modules/json-parse-helpfulerror/node_modules/jju/lib/document.js b/node_modules/read-package-json/node_modules/json-parse-helpfulerror/node_modules/jju/lib/document.js new file mode 100644 index 000000000..cfab8691f --- /dev/null +++ b/node_modules/read-package-json/node_modules/json-parse-helpfulerror/node_modules/jju/lib/document.js @@ -0,0 +1,485 @@ +/* + * Author: Alex Kocharin <alex@kocharin.ru> + * GIT: https://github.com/rlidwka/jju + * License: WTFPL, grab your copy here: http://www.wtfpl.net/txt/copying/ + */ + +var assert = require('assert') +var tokenize = require('./parse').tokenize +var stringify = require('./stringify').stringify +var analyze = require('./analyze').analyze + +function isObject(x) { + return typeof(x) === 'object' && x !== null +} + +function value_to_tokenlist(value, stack, options, is_key, indent) { + options = Object.create(options) + options._stringify_key = !!is_key + + if (indent) { + options._prefix = indent.prefix.map(function(x) { + return x.raw + }).join('') + } + + if (options._splitMin == null) options._splitMin = 0 + if (options._splitMax == null) options._splitMax = 0 + + var stringified = stringify(value, options) + + if (is_key) { + return [ { raw: stringified, type: 'key', stack: stack, value: value } ] + } + + options._addstack = stack + var result = tokenize(stringified, { + _addstack: stack, + }) + result.data = null + return result +} + +// '1.2.3' -> ['1','2','3'] +function arg_to_path(path) { + // array indexes + if (typeof(path) === 'number') path = String(path) + + if (path === '') path = [] + if (typeof(path) === 'string') path = path.split('.') + + if (!Array.isArray(path)) throw Error('Invalid path type, string or array expected') + return path +} + +// returns new [begin, end] or false if not found +// +// {x:3, xxx: 111, y: [111, {q: 1, e: 2} ,333] } +// f('y',0) returns this B^^^^^^^^^^^^^^^^^^^^^^^^E +// then f('1',1) would reduce it to B^^^^^^^^^^E +function find_element_in_tokenlist(element, lvl, tokens, begin, end) { + while(tokens[begin].stack[lvl] != element) { + if (begin++ >= end) return false + } + while(tokens[end].stack[lvl] != element) { + if (end-- < begin) return false + } + return [begin, end] +} + +function is_whitespace(token_type) { + return token_type === 'whitespace' + || token_type === 'newline' + || token_type === 'comment' +} + +function find_first_non_ws_token(tokens, begin, end) { + while(is_whitespace(tokens[begin].type)) { + if (begin++ >= end) return false + } + return begin +} + +function find_last_non_ws_token(tokens, begin, end) { + while(is_whitespace(tokens[end].type)) { + if (end-- < begin) return false + } + return end +} + +/* + * when appending a new element of an object/array, we are trying to + * figure out the style used on the previous element + * + * return {prefix, sep1, sep2, suffix} + * + * ' "key" : "element" \r\n' + * prefix^^^^ sep1^ ^^sep2 ^^^^^^^^suffix + * + * begin - the beginning of the object/array + * end - last token of the last element (value or comma usually) + */ +function detect_indent_style(tokens, is_array, begin, end, level) { + var result = { + sep1: [], + sep2: [], + suffix: [], + prefix: [], + newline: [], + } + + if (tokens[end].type === 'separator' && tokens[end].stack.length !== level+1 && tokens[end].raw !== ',') { + // either a beginning of the array (no last element) or other weird situation + // + // just return defaults + return result + } + + // ' "key" : "value" ,' + // skipping last separator, we're now here ^^ + if (tokens[end].type === 'separator') + end = find_last_non_ws_token(tokens, begin, end - 1) + if (end === false) return result + + // ' "key" : "value" ,' + // skipping value ^^^^^^^ + while(tokens[end].stack.length > level) end-- + + if (!is_array) { + while(is_whitespace(tokens[end].type)) { + if (end < begin) return result + if (tokens[end].type === 'whitespace') { + result.sep2.unshift(tokens[end]) + } else { + // newline, comment or other unrecognized codestyle + return result + } + end-- + } + + // ' "key" : "value" ,' + // skipping separator ^ + assert.equal(tokens[end].type, 'separator') + assert.equal(tokens[end].raw, ':') + while(is_whitespace(tokens[--end].type)) { + if (end < begin) return result + if (tokens[end].type === 'whitespace') { + result.sep1.unshift(tokens[end]) + } else { + // newline, comment or other unrecognized codestyle + return result + } + } + + assert.equal(tokens[end].type, 'key') + end-- + } + + // ' "key" : "value" ,' + // skipping key ^^^^^ + while(is_whitespace(tokens[end].type)) { + if (end < begin) return result + if (tokens[end].type === 'whitespace') { + result.prefix.unshift(tokens[end]) + } else if (tokens[end].type === 'newline') { + result.newline.unshift(tokens[end]) + return result + } else { + // comment or other unrecognized codestyle + return result + } + end-- + } + + return result +} + +function Document(text, options) { + var self = Object.create(Document.prototype) + + if (options == null) options = {} + //options._structure = true + var tokens = self._tokens = tokenize(text, options) + self._data = tokens.data + tokens.data = null + self._options = options + + var stats = analyze(text, options) + if (options.indent == null) { + options.indent = stats.indent + } + if (options.quote == null) { + options.quote = stats.quote + } + if (options.quote_keys == null) { + options.quote_keys = stats.quote_keys + } + if (options.no_trailing_comma == null) { + options.no_trailing_comma = !stats.has_trailing_comma + } + return self +} + +// return true if it's a proper object +// throw otherwise +function check_if_can_be_placed(key, object, is_unset) { + //if (object == null) return false + function error(add) { + return Error("You can't " + (is_unset ? 'unset' : 'set') + " key '" + key + "'" + add) + } + + if (!isObject(object)) { + throw error(' of an non-object') + } + if (Array.isArray(object)) { + // array, check boundary + if (String(key).match(/^\d+$/)) { + key = Number(String(key)) + if (object.length < key || (is_unset && object.length === key)) { + throw error(', out of bounds') + } else if (is_unset && object.length !== key+1) { + throw error(' in the middle of an array') + } else { + return true + } + } else { + throw error(' of an array') + } + } else { + // object + return true + } +} + +// usage: document.set('path.to.something', 'value') +// or: document.set(['path','to','something'], 'value') +Document.prototype.set = function(path, value) { + path = arg_to_path(path) + + // updating this._data and check for errors + if (path.length === 0) { + if (value === undefined) throw Error("can't remove root document") + this._data = value + var new_key = false + + } else { + var data = this._data + + for (var i=0; i<path.length-1; i++) { + check_if_can_be_placed(path[i], data, false) + data = data[path[i]] + } + if (i === path.length-1) { + check_if_can_be_placed(path[i], data, value === undefined) + } + + var new_key = !(path[i] in data) + + if (value === undefined) { + if (Array.isArray(data)) { + data.pop() + } else { + delete data[path[i]] + } + } else { + data[path[i]] = value + } + } + + // for inserting document + if (!this._tokens.length) + this._tokens = [ { raw: '', type: 'literal', stack: [], value: undefined } ] + + var position = [ + find_first_non_ws_token(this._tokens, 0, this._tokens.length - 1), + find_last_non_ws_token(this._tokens, 0, this._tokens.length - 1), + ] + for (var i=0; i<path.length-1; i++) { + position = find_element_in_tokenlist(path[i], i, this._tokens, position[0], position[1]) + if (position == false) throw Error('internal error, please report this') + } + // assume that i == path.length-1 here + + if (path.length === 0) { + var newtokens = value_to_tokenlist(value, path, this._options) + // all good + + } else if (!new_key) { + // replace old value with a new one (or deleting something) + var pos_old = position + position = find_element_in_tokenlist(path[i], i, this._tokens, position[0], position[1]) + + if (value === undefined && position !== false) { + // deleting element (position !== false ensures there's something) + var newtokens = [] + + if (!Array.isArray(data)) { + // removing element from an object, `{x:1, key:CURRENT} -> {x:1}` + // removing sep, literal and optional sep + // ':' + var pos2 = find_last_non_ws_token(this._tokens, pos_old[0], position[0] - 1) + assert.equal(this._tokens[pos2].type, 'separator') + assert.equal(this._tokens[pos2].raw, ':') + position[0] = pos2 + + // key + var pos2 = find_last_non_ws_token(this._tokens, pos_old[0], position[0] - 1) + assert.equal(this._tokens[pos2].type, 'key') + assert.equal(this._tokens[pos2].value, path[path.length-1]) + position[0] = pos2 + } + + // removing comma in arrays and objects + var pos2 = find_last_non_ws_token(this._tokens, pos_old[0], position[0] - 1) + assert.equal(this._tokens[pos2].type, 'separator') + if (this._tokens[pos2].raw === ',') { + position[0] = pos2 + } else { + // beginning of the array/object, so we should remove trailing comma instead + pos2 = find_first_non_ws_token(this._tokens, position[1] + 1, pos_old[1]) + assert.equal(this._tokens[pos2].type, 'separator') + if (this._tokens[pos2].raw === ',') { + position[1] = pos2 + } + } + + } else { + var indent = pos2 !== false + ? detect_indent_style(this._tokens, Array.isArray(data), pos_old[0], position[1] - 1, i) + : {} + var newtokens = value_to_tokenlist(value, path, this._options, false, indent) + } + + } else { + // insert new key, that's tricky + var path_1 = path.slice(0, i) + + // find a last separator after which we're inserting it + var pos2 = find_last_non_ws_token(this._tokens, position[0] + 1, position[1] - 1) + assert(pos2 !== false) + + var indent = pos2 !== false + ? detect_indent_style(this._tokens, Array.isArray(data), position[0] + 1, pos2, i) + : {} + + var newtokens = value_to_tokenlist(value, path, this._options, false, indent) + + // adding leading whitespaces according to detected codestyle + var prefix = [] + if (indent.newline && indent.newline.length) + prefix = prefix.concat(indent.newline) + if (indent.prefix && indent.prefix.length) + prefix = prefix.concat(indent.prefix) + + // adding '"key":' (as in "key":"value") to object values + if (!Array.isArray(data)) { + prefix = prefix.concat(value_to_tokenlist(path[path.length-1], path_1, this._options, true)) + if (indent.sep1 && indent.sep1.length) + prefix = prefix.concat(indent.sep1) + prefix.push({raw: ':', type: 'separator', stack: path_1}) + if (indent.sep2 && indent.sep2.length) + prefix = prefix.concat(indent.sep2) + } + + newtokens.unshift.apply(newtokens, prefix) + + // check if prev token is a separator AND they're at the same level + if (this._tokens[pos2].type === 'separator' && this._tokens[pos2].stack.length === path.length-1) { + // previous token is either , or [ or { + if (this._tokens[pos2].raw === ',') { + // restore ending comma + newtokens.push({raw: ',', type: 'separator', stack: path_1}) + } + } else { + // previous token isn't a separator, so need to insert one + newtokens.unshift({raw: ',', type: 'separator', stack: path_1}) + } + + if (indent.suffix && indent.suffix.length) + newtokens.push.apply(newtokens, indent.suffix) + + assert.equal(this._tokens[position[1]].type, 'separator') + position[0] = pos2+1 + position[1] = pos2 + } + + newtokens.unshift(position[1] - position[0] + 1) + newtokens.unshift(position[0]) + this._tokens.splice.apply(this._tokens, newtokens) + + return this +} + +// convenience method +Document.prototype.unset = function(path) { + return this.set(path, undefined) +} + +Document.prototype.get = function(path) { + path = arg_to_path(path) + + var data = this._data + for (var i=0; i<path.length; i++) { + if (!isObject(data)) return undefined + data = data[path[i]] + } + return data +} + +Document.prototype.has = function(path) { + path = arg_to_path(path) + + var data = this._data + for (var i=0; i<path.length; i++) { + if (!isObject(data)) return false + data = data[path[i]] + } + return data !== undefined +} + +// compare old object and new one, and change differences only +Document.prototype.update = function(value) { + var self = this + change([], self._data, value) + return self + + function change(path, old_data, new_data) { + if (!isObject(new_data) || !isObject(old_data)) { + // if source or dest is primitive, just replace + if (new_data !== old_data) + self.set(path, new_data) + + } else if (Array.isArray(new_data) != Array.isArray(old_data)) { + // old data is an array XOR new data is an array, replace as well + self.set(path, new_data) + + } else if (Array.isArray(new_data)) { + // both values are arrays here + + if (new_data.length > old_data.length) { + // adding new elements, so going forward + for (var i=0; i<new_data.length; i++) { + path.push(String(i)) + change(path, old_data[i], new_data[i]) + path.pop() + } + + } else { + // removing something, so going backward + for (var i=old_data.length-1; i>=0; i--) { + path.push(String(i)) + change(path, old_data[i], new_data[i]) + path.pop() + } + } + + } else { + // both values are objects here + for (var i in new_data) { + path.push(String(i)) + change(path, old_data[i], new_data[i]) + path.pop() + } + + for (var i in old_data) { + if (i in new_data) continue + path.push(String(i)) + change(path, old_data[i], new_data[i]) + path.pop() + } + } + } +} + +Document.prototype.toString = function() { + return this._tokens.map(function(x) { + return x.raw + }).join('') +} + +module.exports.Document = Document + +module.exports.update = function updateJSON(source, new_value, options) { + return Document(source, options).update(new_value).toString() +} + diff --git a/node_modules/read-package-json/node_modules/json-parse-helpfulerror/node_modules/jju/lib/parse.js b/node_modules/read-package-json/node_modules/json-parse-helpfulerror/node_modules/jju/lib/parse.js new file mode 100644 index 000000000..5f9fe9986 --- /dev/null +++ b/node_modules/read-package-json/node_modules/json-parse-helpfulerror/node_modules/jju/lib/parse.js @@ -0,0 +1,752 @@ +/* + * Author: Alex Kocharin <alex@kocharin.ru> + * GIT: https://github.com/rlidwka/jju + * License: WTFPL, grab your copy here: http://www.wtfpl.net/txt/copying/ + */ + +// RTFM: http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf + +var Uni = require('./unicode') + +function isHexDigit(x) { + return (x >= '0' && x <= '9') + || (x >= 'A' && x <= 'F') + || (x >= 'a' && x <= 'f') +} + +function isOctDigit(x) { + return x >= '0' && x <= '7' +} + +function isDecDigit(x) { + return x >= '0' && x <= '9' +} + +var unescapeMap = { + '\'': '\'', + '"' : '"', + '\\': '\\', + 'b' : '\b', + 'f' : '\f', + 'n' : '\n', + 'r' : '\r', + 't' : '\t', + 'v' : '\v', + '/' : '/', +} + +function formatError(input, msg, position, lineno, column, json5) { + var result = msg + ' at ' + (lineno + 1) + ':' + (column + 1) + , tmppos = position - column - 1 + , srcline = '' + , underline = '' + + var isLineTerminator = json5 ? Uni.isLineTerminator : Uni.isLineTerminatorJSON + + // output no more than 70 characters before the wrong ones + if (tmppos < position - 70) { + tmppos = position - 70 + } + + while (1) { + var chr = input[++tmppos] + + if (isLineTerminator(chr) || tmppos === input.length) { + if (position >= tmppos) { + // ending line error, so show it after the last char + underline += '^' + } + break + } + srcline += chr + + if (position === tmppos) { + underline += '^' + } else if (position > tmppos) { + underline += input[tmppos] === '\t' ? '\t' : ' ' + } + + // output no more than 78 characters on the string + if (srcline.length > 78) break + } + + return result + '\n' + srcline + '\n' + underline +} + +function parse(input, options) { + // parse as a standard JSON mode + var json5 = !(options.mode === 'json' || options.legacy) + var isLineTerminator = json5 ? Uni.isLineTerminator : Uni.isLineTerminatorJSON + var isWhiteSpace = json5 ? Uni.isWhiteSpace : Uni.isWhiteSpaceJSON + + var length = input.length + , lineno = 0 + , linestart = 0 + , position = 0 + , stack = [] + + var tokenStart = function() {} + var tokenEnd = function(v) {return v} + + /* tokenize({ + raw: '...', + type: 'whitespace'|'comment'|'key'|'literal'|'separator'|'newline', + value: 'number'|'string'|'whatever', + path: [...], + }) + */ + if (options._tokenize) { + ;(function() { + var start = null + tokenStart = function() { + if (start !== null) throw Error('internal error, token overlap') + start = position + } + + tokenEnd = function(v, type) { + if (start != position) { + var hash = { + raw: input.substr(start, position-start), + type: type, + stack: stack.slice(0), + } + if (v !== undefined) hash.value = v + options._tokenize.call(null, hash) + } + start = null + return v + } + })() + } + + function fail(msg) { + var column = position - linestart + + if (!msg) { + if (position < length) { + var token = '\'' + + JSON + .stringify(input[position]) + .replace(/^"|"$/g, '') + .replace(/'/g, "\\'") + .replace(/\\"/g, '"') + + '\'' + + if (!msg) msg = 'Unexpected token ' + token + } else { + if (!msg) msg = 'Unexpected end of input' + } + } + + var error = SyntaxError(formatError(input, msg, position, lineno, column, json5)) + error.row = lineno + 1 + error.column = column + 1 + throw error + } + + function newline(chr) { + // account for <cr><lf> + if (chr === '\r' && input[position] === '\n') position++ + linestart = position + lineno++ + } + + function parseGeneric() { + var result + + while (position < length) { + tokenStart() + var chr = input[position++] + + if (chr === '"' || (chr === '\'' && json5)) { + return tokenEnd(parseString(chr), 'literal') + + } else if (chr === '{') { + tokenEnd(undefined, 'separator') + return parseObject() + + } else if (chr === '[') { + tokenEnd(undefined, 'separator') + return parseArray() + + } else if (chr === '-' + || chr === '.' + || isDecDigit(chr) + // + number Infinity NaN + || (json5 && (chr === '+' || chr === 'I' || chr === 'N')) + ) { + return tokenEnd(parseNumber(), 'literal') + + } else if (chr === 'n') { + parseKeyword('null') + return tokenEnd(null, 'literal') + + } else if (chr === 't') { + parseKeyword('true') + return tokenEnd(true, 'literal') + + } else if (chr === 'f') { + parseKeyword('false') + return tokenEnd(false, 'literal') + + } else { + position-- + return tokenEnd(undefined) + } + } + } + + function parseKey() { + var result + + while (position < length) { + tokenStart() + var chr = input[position++] + + if (chr === '"' || (chr === '\'' && json5)) { + return tokenEnd(parseString(chr), 'key') + + } else if (chr === '{') { + tokenEnd(undefined, 'separator') + return parseObject() + + } else if (chr === '[') { + tokenEnd(undefined, 'separator') + return parseArray() + + } else if (chr === '.' + || isDecDigit(chr) + ) { + return tokenEnd(parseNumber(true), 'key') + + } else if (json5 + && Uni.isIdentifierStart(chr) || (chr === '\\' && input[position] === 'u')) { + // unicode char or a unicode sequence + var rollback = position - 1 + var result = parseIdentifier() + + if (result === undefined) { + position = rollback + return tokenEnd(undefined) + } else { + return tokenEnd(result, 'key') + } + + } else { + position-- + return tokenEnd(undefined) + } + } + } + + function skipWhiteSpace() { + tokenStart() + while (position < length) { + var chr = input[position++] + + if (isLineTerminator(chr)) { + position-- + tokenEnd(undefined, 'whitespace') + tokenStart() + position++ + newline(chr) + tokenEnd(undefined, 'newline') + tokenStart() + + } else if (isWhiteSpace(chr)) { + // nothing + + } else if (chr === '/' + && json5 + && (input[position] === '/' || input[position] === '*') + ) { + position-- + tokenEnd(undefined, 'whitespace') + tokenStart() + position++ + skipComment(input[position++] === '*') + tokenEnd(undefined, 'comment') + tokenStart() + + } else { + position-- + break + } + } + return tokenEnd(undefined, 'whitespace') + } + + function skipComment(multi) { + while (position < length) { + var chr = input[position++] + + if (isLineTerminator(chr)) { + // LineTerminator is an end of singleline comment + if (!multi) { + // let parent function deal with newline + position-- + return + } + + newline(chr) + + } else if (chr === '*' && multi) { + // end of multiline comment + if (input[position] === '/') { + position++ + return + } + + } else { + // nothing + } + } + + if (multi) { + fail('Unclosed multiline comment') + } + } + + function parseKeyword(keyword) { + // keyword[0] is not checked because it should've checked earlier + var _pos = position + var len = keyword.length + for (var i=1; i<len; i++) { + if (position >= length || keyword[i] != input[position]) { + position = _pos-1 + fail() + } + position++ + } + } + + function parseObject() { + var result = options.null_prototype ? Object.create(null) : {} + , empty_object = {} + , is_non_empty = false + + while (position < length) { + skipWhiteSpace() + var item1 = parseKey() + skipWhiteSpace() + tokenStart() + var chr = input[position++] + tokenEnd(undefined, 'separator') + + if (chr === '}' && item1 === undefined) { + if (!json5 && is_non_empty) { + position-- + fail('Trailing comma in object') + } + return result + + } else if (chr === ':' && item1 !== undefined) { + skipWhiteSpace() + stack.push(item1) + var item2 = parseGeneric() + stack.pop() + + if (item2 === undefined) fail('No value found for key ' + item1) + if (typeof(item1) !== 'string') { + if (!json5 || typeof(item1) !== 'number') { + fail('Wrong key type: ' + item1) + } + } + + if ((item1 in empty_object || empty_object[item1] != null) && options.reserved_keys !== 'replace') { + if (options.reserved_keys === 'throw') { + fail('Reserved key: ' + item1) + } else { + // silently ignore it + } + } else { + if (typeof(options.reviver) === 'function') { + item2 = options.reviver.call(null, item1, item2) + } + + if (item2 !== undefined) { + is_non_empty = true + Object.defineProperty(result, item1, { + value: item2, + enumerable: true, + configurable: true, + writable: true, + }) + } + } + + skipWhiteSpace() + + tokenStart() + var chr = input[position++] + tokenEnd(undefined, 'separator') + + if (chr === ',') { + continue + + } else if (chr === '}') { + return result + + } else { + fail() + } + + } else { + position-- + fail() + } + } + + fail() + } + + function parseArray() { + var result = [] + + while (position < length) { + skipWhiteSpace() + stack.push(result.length) + var item = parseGeneric() + stack.pop() + skipWhiteSpace() + tokenStart() + var chr = input[position++] + tokenEnd(undefined, 'separator') + + if (item !== undefined) { + if (typeof(options.reviver) === 'function') { + item = options.reviver.call(null, String(result.length), item) + } + if (item === undefined) { + result.length++ + item = true // hack for check below, not included into result + } else { + result.push(item) + } + } + + if (chr === ',') { + if (item === undefined) { + fail('Elisions are not supported') + } + + } else if (chr === ']') { + if (!json5 && item === undefined && result.length) { + position-- + fail('Trailing comma in array') + } + return result + + } else { + position-- + fail() + } + } + } + + function parseNumber() { + // rewind because we don't know first char + position-- + + var start = position + , chr = input[position++] + , t + + var to_num = function(is_octal) { + var str = input.substr(start, position - start) + + if (is_octal) { + var result = parseInt(str.replace(/^0o?/, ''), 8) + } else { + var result = Number(str) + } + + if (Number.isNaN(result)) { + position-- + fail('Bad numeric literal - "' + input.substr(start, position - start + 1) + '"') + } else if (!json5 && !str.match(/^-?(0|[1-9][0-9]*)(\.[0-9]+)?(e[+-]?[0-9]+)?$/i)) { + // additional restrictions imposed by json + position-- + fail('Non-json numeric literal - "' + input.substr(start, position - start + 1) + '"') + } else { + return result + } + } + + // ex: -5982475.249875e+29384 + // ^ skipping this + if (chr === '-' || (chr === '+' && json5)) chr = input[position++] + + if (chr === 'N' && json5) { + parseKeyword('NaN') + return NaN + } + + if (chr === 'I' && json5) { + parseKeyword('Infinity') + + // returning +inf or -inf + return to_num() + } + + if (chr >= '1' && chr <= '9') { + // ex: -5982475.249875e+29384 + // ^^^ skipping these + while (position < length && isDecDigit(input[position])) position++ + chr = input[position++] + } + + // special case for leading zero: 0.123456 + if (chr === '0') { + chr = input[position++] + + // new syntax, "0o777" old syntax, "0777" + var is_octal = chr === 'o' || chr === 'O' || isOctDigit(chr) + var is_hex = chr === 'x' || chr === 'X' + + if (json5 && (is_octal || is_hex)) { + while (position < length + && (is_hex ? isHexDigit : isOctDigit)( input[position] ) + ) position++ + + var sign = 1 + if (input[start] === '-') { + sign = -1 + start++ + } else if (input[start] === '+') { + start++ + } + + return sign * to_num(is_octal) + } + } + + if (chr === '.') { + // ex: -5982475.249875e+29384 + // ^^^ skipping these + while (position < length && isDecDigit(input[position])) position++ + chr = input[position++] + } + + if (chr === 'e' || chr === 'E') { + chr = input[position++] + if (chr === '-' || chr === '+') position++ + // ex: -5982475.249875e+29384 + // ^^^ skipping these + while (position < length && isDecDigit(input[position])) position++ + chr = input[position++] + } + + // we have char in the buffer, so count for it + position-- + return to_num() + } + + function parseIdentifier() { + // rewind because we don't know first char + position-- + + var result = '' + + while (position < length) { + var chr = input[position++] + + if (chr === '\\' + && input[position] === 'u' + && isHexDigit(input[position+1]) + && isHexDigit(input[position+2]) + && isHexDigit(input[position+3]) + && isHexDigit(input[position+4]) + ) { + // UnicodeEscapeSequence + chr = String.fromCharCode(parseInt(input.substr(position+1, 4), 16)) + position += 5 + } + + if (result.length) { + // identifier started + if (Uni.isIdentifierPart(chr)) { + result += chr + } else { + position-- + return result + } + + } else { + if (Uni.isIdentifierStart(chr)) { + result += chr + } else { + return undefined + } + } + } + + fail() + } + + function parseString(endChar) { + // 7.8.4 of ES262 spec + var result = '' + + while (position < length) { + var chr = input[position++] + + if (chr === endChar) { + return result + + } else if (chr === '\\') { + if (position >= length) fail() + chr = input[position++] + + if (unescapeMap[chr] && (json5 || (chr != 'v' && chr != "'"))) { + result += unescapeMap[chr] + + } else if (json5 && isLineTerminator(chr)) { + // line continuation + newline(chr) + + } else if (chr === 'u' || (chr === 'x' && json5)) { + // unicode/character escape sequence + var off = chr === 'u' ? 4 : 2 + + // validation for \uXXXX + for (var i=0; i<off; i++) { + if (position >= length) fail() + if (!isHexDigit(input[position])) fail('Bad escape sequence') + position++ + } + + result += String.fromCharCode(parseInt(input.substr(position-off, off), 16)) + } else if (json5 && isOctDigit(chr)) { + if (chr < '4' && isOctDigit(input[position]) && isOctDigit(input[position+1])) { + // three-digit octal + var digits = 3 + } else if (isOctDigit(input[position])) { + // two-digit octal + var digits = 2 + } else { + var digits = 1 + } + position += digits - 1 + result += String.fromCharCode(parseInt(input.substr(position-digits, digits), 8)) + /*if (!isOctDigit(input[position])) { + // \0 is allowed still + result += '\0' + } else { + fail('Octal literals are not supported') + }*/ + + } else if (json5) { + // \X -> x + result += chr + + } else { + position-- + fail() + } + + } else if (isLineTerminator(chr)) { + fail() + + } else { + if (!json5 && chr.charCodeAt(0) < 32) { + position-- + fail('Unexpected control character') + } + + // SourceCharacter but not one of " or \ or LineTerminator + result += chr + } + } + + fail() + } + + skipWhiteSpace() + var return_value = parseGeneric() + if (return_value !== undefined || position < length) { + skipWhiteSpace() + + if (position >= length) { + if (typeof(options.reviver) === 'function') { + return_value = options.reviver.call(null, '', return_value) + } + return return_value + } else { + fail() + } + + } else { + if (position) { + fail('No data, only a whitespace') + } else { + fail('No data, empty input') + } + } +} + +/* + * parse(text, options) + * or + * parse(text, reviver) + * + * where: + * text - string + * options - object + * reviver - function + */ +module.exports.parse = function parseJSON(input, options) { + // support legacy functions + if (typeof(options) === 'function') { + options = { + reviver: options + } + } + + if (input === undefined) { + // parse(stringify(x)) should be equal x + // with JSON functions it is not 'cause of undefined + // so we're fixing it + return undefined + } + + // JSON.parse compat + if (typeof(input) !== 'string') input = String(input) + if (options == null) options = {} + if (options.reserved_keys == null) options.reserved_keys = 'ignore' + + if (options.reserved_keys === 'throw' || options.reserved_keys === 'ignore') { + if (options.null_prototype == null) { + options.null_prototype = true + } + } + + try { + return parse(input, options) + } catch(err) { + // jju is a recursive parser, so JSON.parse("{{{{{{{") could blow up the stack + // + // this catch is used to skip all those internal calls + if (err instanceof SyntaxError && err.row != null && err.column != null) { + var old_err = err + err = SyntaxError(old_err.message) + err.column = old_err.column + err.row = old_err.row + } + throw err + } +} + +module.exports.tokenize = function tokenizeJSON(input, options) { + if (options == null) options = {} + + options._tokenize = function(smth) { + if (options._addstack) smth.stack.unshift.apply(smth.stack, options._addstack) + tokens.push(smth) + } + + var tokens = [] + tokens.data = module.exports.parse(input, options) + return tokens +} + diff --git a/node_modules/read-package-json/node_modules/json-parse-helpfulerror/node_modules/jju/lib/stringify.js b/node_modules/read-package-json/node_modules/json-parse-helpfulerror/node_modules/jju/lib/stringify.js new file mode 100644 index 000000000..ce89d77ee --- /dev/null +++ b/node_modules/read-package-json/node_modules/json-parse-helpfulerror/node_modules/jju/lib/stringify.js @@ -0,0 +1,383 @@ +/* + * Author: Alex Kocharin <alex@kocharin.ru> + * GIT: https://github.com/rlidwka/jju + * License: WTFPL, grab your copy here: http://www.wtfpl.net/txt/copying/ + */ + +var Uni = require('./unicode') + +// Fix Function#name on browsers that do not support it (IE) +// http://stackoverflow.com/questions/6903762/function-name-not-supported-in-ie +if (!(function f(){}).name) { + Object.defineProperty((function(){}).constructor.prototype, 'name', { + get: function() { + var name = this.toString().match(/^\s*function\s*(\S*)\s*\(/)[1] + // For better performance only parse once, and then cache the + // result through a new accessor for repeated access. + Object.defineProperty(this, 'name', { value: name }) + return name + } + }) +} + +var special_chars = { + 0: '\\0', // this is not an octal literal + 8: '\\b', + 9: '\\t', + 10: '\\n', + 11: '\\v', + 12: '\\f', + 13: '\\r', + 92: '\\\\', +} + +// for oddballs +var hasOwnProperty = Object.prototype.hasOwnProperty + +// some people escape those, so I'd copy this to be safe +var escapable = /[\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/ + +function _stringify(object, options, recursiveLvl, currentKey) { + var opt_json = options.mode === 'json' + /* + * Opinionated decision warning: + * + * Objects are serialized in the following form: + * { type: 'Class', data: DATA } + * + * Class is supposed to be a function, and new Class(DATA) is + * supposed to be equivalent to the original value + */ + /*function custom_type() { + return stringify({ + type: object.constructor.name, + data: object.toString() + }) + }*/ + + // if add, it's an internal indentation, so we add 1 level and a eol + // if !add, it's an ending indentation, so we just indent + function indent(str, add) { + var prefix = options._prefix ? options._prefix : '' + if (!options.indent) return prefix + str + var result = '' + var count = recursiveLvl + (add || 0) + for (var i=0; i<count; i++) result += options.indent + return prefix + result + str + (add ? '\n' : '') + } + + function _stringify_key(key) { + if (options.quote_keys) return _stringify_str(key) + if (String(Number(key)) == key && key[0] != '-') return key + if (key == '') return _stringify_str(key) + + var result = '' + for (var i=0; i<key.length; i++) { + if (i > 0) { + if (!Uni.isIdentifierPart(key[i])) + return _stringify_str(key) + + } else { + if (!Uni.isIdentifierStart(key[i])) + return _stringify_str(key) + } + + var chr = key.charCodeAt(i) + + if (options.ascii) { + if (chr < 0x80) { + result += key[i] + + } else { + result += '\\u' + ('0000' + chr.toString(16)).slice(-4) + } + + } else { + if (escapable.exec(key[i])) { + result += '\\u' + ('0000' + chr.toString(16)).slice(-4) + + } else { + result += key[i] + } + } + } + + return result + } + + function _stringify_str(key) { + var quote = options.quote + var quoteChr = quote.charCodeAt(0) + + var result = '' + for (var i=0; i<key.length; i++) { + var chr = key.charCodeAt(i) + + if (chr < 0x10) { + if (chr === 0 && !opt_json) { + result += '\\0' + } else if (chr >= 8 && chr <= 13 && (!opt_json || chr !== 11)) { + result += special_chars[chr] + } else if (!opt_json) { + result += '\\x0' + chr.toString(16) + } else { + result += '\\u000' + chr.toString(16) + } + + } else if (chr < 0x20) { + if (!opt_json) { + result += '\\x' + chr.toString(16) + } else { + result += '\\u00' + chr.toString(16) + } + + } else if (chr >= 0x20 && chr < 0x80) { + // ascii range + if (chr === 47 && i && key[i-1] === '<') { + // escaping slashes in </script> + result += '\\' + key[i] + + } else if (chr === 92) { + result += '\\\\' + + } else if (chr === quoteChr) { + result += '\\' + quote + + } else { + result += key[i] + } + + } else if (options.ascii || Uni.isLineTerminator(key[i]) || escapable.exec(key[i])) { + if (chr < 0x100) { + if (!opt_json) { + result += '\\x' + chr.toString(16) + } else { + result += '\\u00' + chr.toString(16) + } + + } else if (chr < 0x1000) { + result += '\\u0' + chr.toString(16) + + } else if (chr < 0x10000) { + result += '\\u' + chr.toString(16) + + } else { + throw Error('weird codepoint') + } + } else { + result += key[i] + } + } + return quote + result + quote + } + + function _stringify_object() { + if (object === null) return 'null' + var result = [] + , len = 0 + , braces + + if (Array.isArray(object)) { + braces = '[]' + for (var i=0; i<object.length; i++) { + var s = _stringify(object[i], options, recursiveLvl+1, String(i)) + if (s === undefined) s = 'null' + len += s.length + 2 + result.push(s + ',') + } + + } else { + braces = '{}' + var fn = function(key) { + var t = _stringify(object[key], options, recursiveLvl+1, key) + if (t !== undefined) { + t = _stringify_key(key) + ':' + (options.indent ? ' ' : '') + t + ',' + len += t.length + 1 + result.push(t) + } + } + + if (Array.isArray(options.replacer)) { + for (var i=0; i<options.replacer.length; i++) + if (hasOwnProperty.call(object, options.replacer[i])) + fn(options.replacer[i]) + } else { + var keys = Object.keys(object) + if (options.sort_keys) + keys = keys.sort(typeof(options.sort_keys) === 'function' + ? options.sort_keys : undefined) + keys.forEach(fn) + } + } + + // objects shorter than 30 characters are always inlined + // objects longer than 60 characters are always splitted to multiple lines + // anything in the middle depends on indentation level + len -= 2 + if (options.indent && (len > options._splitMax - recursiveLvl * options.indent.length || len > options._splitMin) ) { + // remove trailing comma in multiline if asked to + if (options.no_trailing_comma && result.length) { + result[result.length-1] = result[result.length-1].substring(0, result[result.length-1].length-1) + } + + var innerStuff = result.map(function(x) {return indent(x, 1)}).join('') + return braces[0] + + (options.indent ? '\n' : '') + + innerStuff + + indent(braces[1]) + } else { + // always remove trailing comma in one-lined arrays + if (result.length) { + result[result.length-1] = result[result.length-1].substring(0, result[result.length-1].length-1) + } + + var innerStuff = result.join(options.indent ? ' ' : '') + return braces[0] + + innerStuff + + braces[1] + } + } + + function _stringify_nonobject(object) { + if (typeof(options.replacer) === 'function') { + object = options.replacer.call(null, currentKey, object) + } + + switch(typeof(object)) { + case 'string': + return _stringify_str(object) + + case 'number': + if (object === 0 && 1/object < 0) { + // Opinionated decision warning: + // + // I want cross-platform negative zero in all js engines + // I know they're equal, but why lose that tiny bit of + // information needlessly? + return '-0' + } + if (options.mode === 'json' && !Number.isFinite(object)) { + // json don't support infinity (= sucks) + return 'null' + } + return object.toString() + + case 'boolean': + return object.toString() + + case 'undefined': + return undefined + + case 'function': +// return custom_type() + + default: + // fallback for something weird + return JSON.stringify(object) + } + } + + if (options._stringify_key) { + return _stringify_key(object) + } + + if (typeof(object) === 'object') { + if (object === null) return 'null' + + var str + if (typeof(str = object.toJSON5) === 'function' && options.mode !== 'json') { + object = str.call(object, currentKey) + + } else if (typeof(str = object.toJSON) === 'function') { + object = str.call(object, currentKey) + } + + if (object === null) return 'null' + if (typeof(object) !== 'object') return _stringify_nonobject(object) + + if (object.constructor === Number || object.constructor === Boolean || object.constructor === String) { + object = object.valueOf() + return _stringify_nonobject(object) + + } else if (object.constructor === Date) { + // only until we can't do better + return _stringify_nonobject(object.toISOString()) + + } else { + if (typeof(options.replacer) === 'function') { + object = options.replacer.call(null, currentKey, object) + if (typeof(object) !== 'object') return _stringify_nonobject(object) + } + + return _stringify_object(object) + } + } else { + return _stringify_nonobject(object) + } +} + +/* + * stringify(value, options) + * or + * stringify(value, replacer, space) + * + * where: + * value - anything + * options - object + * replacer - function or array + * space - boolean or number or string + */ +module.exports.stringify = function stringifyJSON(object, options, _space) { + // support legacy syntax + if (typeof(options) === 'function' || Array.isArray(options)) { + options = { + replacer: options + } + } else if (typeof(options) === 'object' && options !== null) { + // nothing to do + } else { + options = {} + } + if (_space != null) options.indent = _space + + if (options.indent == null) options.indent = '\t' + if (options.quote == null) options.quote = "'" + if (options.ascii == null) options.ascii = false + if (options.mode == null) options.mode = 'simple' + + if (options.mode === 'json') { + // json only supports double quotes (= sucks) + options.quote = '"' + + // json don't support trailing commas (= sucks) + options.no_trailing_comma = true + + // json don't support unquoted property names (= sucks) + options.quote_keys = true + } + + // why would anyone use such objects? + if (typeof(options.indent) === 'object') { + if (options.indent.constructor === Number + || options.indent.constructor === Boolean + || options.indent.constructor === String) + options.indent = options.indent.valueOf() + } + + // gap is capped at 10 characters + if (typeof(options.indent) === 'number') { + if (options.indent >= 0) { + options.indent = Array(Math.min(~~options.indent, 10) + 1).join(' ') + } else { + options.indent = false + } + } else if (typeof(options.indent) === 'string') { + options.indent = options.indent.substr(0, 10) + } + + if (options._splitMin == null) options._splitMin = 50 + if (options._splitMax == null) options._splitMax = 70 + + return _stringify(object, options, 0, '') +} + diff --git a/node_modules/read-package-json/node_modules/json-parse-helpfulerror/node_modules/jju/lib/unicode.js b/node_modules/read-package-json/node_modules/json-parse-helpfulerror/node_modules/jju/lib/unicode.js new file mode 100644 index 000000000..1a29143c2 --- /dev/null +++ b/node_modules/read-package-json/node_modules/json-parse-helpfulerror/node_modules/jju/lib/unicode.js @@ -0,0 +1,71 @@ + +// This is autogenerated with esprima tools, see: +// https://github.com/ariya/esprima/blob/master/esprima.js +// +// PS: oh God, I hate Unicode + +// ECMAScript 5.1/Unicode v6.3.0 NonAsciiIdentifierStart: + +var Uni = module.exports + +module.exports.isWhiteSpace = function isWhiteSpace(x) { + // section 7.2, table 2 + return x === '\u0020' + || x === '\u00A0' + || x === '\uFEFF' // <-- this is not a Unicode WS, only a JS one + || (x >= '\u0009' && x <= '\u000D') // 9 A B C D + + // + whitespace characters from unicode, category Zs + || x === '\u1680' + || x === '\u180E' + || (x >= '\u2000' && x <= '\u200A') // 0 1 2 3 4 5 6 7 8 9 A + || x === '\u2028' + || x === '\u2029' + || x === '\u202F' + || x === '\u205F' + || x === '\u3000' +} + +module.exports.isWhiteSpaceJSON = function isWhiteSpaceJSON(x) { + return x === '\u0020' + || x === '\u0009' + || x === '\u000A' + || x === '\u000D' +} + +module.exports.isLineTerminator = function isLineTerminator(x) { + // ok, here is the part when JSON is wrong + // section 7.3, table 3 + return x === '\u000A' + || x === '\u000D' + || x === '\u2028' + || x === '\u2029' +} + +module.exports.isLineTerminatorJSON = function isLineTerminatorJSON(x) { + return x === '\u000A' + || x === '\u000D' +} + +module.exports.isIdentifierStart = function isIdentifierStart(x) { + return x === '$' + || x === '_' + || (x >= 'A' && x <= 'Z') + || (x >= 'a' && x <= 'z') + || (x >= '\u0080' && Uni.NonAsciiIdentifierStart.test(x)) +} + +module.exports.isIdentifierPart = function isIdentifierPart(x) { + return x === '$' + || x === '_' + || (x >= 'A' && x <= 'Z') + || (x >= 'a' && x <= 'z') + || (x >= '0' && x <= '9') // <-- addition to Start + || (x >= '\u0080' && Uni.NonAsciiIdentifierPart.test(x)) +} + +module.exports.NonAsciiIdentifierStart = /[\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u0527\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\u08A0\u08A2-\u08AC\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0977\u0979-\u097F\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\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\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-\u0C33\u0C35-\u0C39\u0C3D\u0C58\u0C59\u0C60\u0C61\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D60\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-\u13F4\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F0\u1700-\u170C\u170E-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u1820-\u1877\u1880-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191C\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19C1-\u19C7\u1A00-\u1A16\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4B\u1B83-\u1BA0\u1BAE\u1BAF\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\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-\u312D\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FCC\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B\uA640-\uA66E\uA67F-\uA697\uA6A0-\uA6EF\uA717-\uA71F\uA722-\uA788\uA78B-\uA78E\uA790-\uA793\uA7A0-\uA7AA\uA7F8-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA80-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uABC0-\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]/ + +// ECMAScript 5.1/Unicode v6.3.0 NonAsciiIdentifierPart: + +module.exports.NonAsciiIdentifierPart = /[\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0300-\u0374\u0376\u0377\u037A-\u037D\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u0483-\u0487\u048A-\u0527\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\u08A0\u08A2-\u08AC\u08E4-\u08FE\u0900-\u0963\u0966-\u096F\u0971-\u0977\u0979-\u097F\u0981-\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\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\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\u0C01-\u0C03\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C33\u0C35-\u0C39\u0C3D-\u0C44\u0C46-\u0C48\u0C4A-\u0C4D\u0C55\u0C56\u0C58\u0C59\u0C60-\u0C63\u0C66-\u0C6F\u0C82\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\u0D02\u0D03\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D-\u0D44\u0D46-\u0D48\u0D4A-\u0D4E\u0D57\u0D60-\u0D63\u0D66-\u0D6F\u0D7A-\u0D7F\u0D82\u0D83\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0DCA\u0DCF-\u0DD4\u0DD6\u0DD8-\u0DDF\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-\u13F4\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F0\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-\u191C\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\u1B00-\u1B4B\u1B50-\u1B59\u1B6B-\u1B73\u1B80-\u1BF3\u1C00-\u1C37\u1C40-\u1C49\u1C4D-\u1C7D\u1CD0-\u1CD2\u1CD4-\u1CF6\u1D00-\u1DE6\u1DFC-\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\u200C\u200D\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-\u312D\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FCC\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA62B\uA640-\uA66F\uA674-\uA67D\uA67F-\uA697\uA69F-\uA6F1\uA717-\uA71F\uA722-\uA788\uA78B-\uA78E\uA790-\uA793\uA7A0-\uA7AA\uA7F8-\uA827\uA840-\uA873\uA880-\uA8C4\uA8D0-\uA8D9\uA8E0-\uA8F7\uA8FB\uA900-\uA92D\uA930-\uA953\uA960-\uA97C\uA980-\uA9C0\uA9CF-\uA9D9\uAA00-\uAA36\uAA40-\uAA4D\uAA50-\uAA59\uAA60-\uAA76\uAA7A\uAA7B\uAA80-\uAAC2\uAADB-\uAADD\uAAE0-\uAAEF\uAAF2-\uAAF6\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uABC0-\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-\uFE26\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]/ diff --git a/node_modules/read-package-json/node_modules/json-parse-helpfulerror/node_modules/jju/lib/utils.js b/node_modules/read-package-json/node_modules/json-parse-helpfulerror/node_modules/jju/lib/utils.js new file mode 100644 index 000000000..a8476b6c4 --- /dev/null +++ b/node_modules/read-package-json/node_modules/json-parse-helpfulerror/node_modules/jju/lib/utils.js @@ -0,0 +1,46 @@ +var FS = require('fs') +var jju = require('../') + +// this function registers json5 extension, so you +// can do `require("./config.json5")` kind of thing +module.exports.register = function() { + var r = require, e = 'extensions' + r[e]['.json5'] = function(m, f) { + /*eslint no-sync:0*/ + m.exports = jju.parse(FS.readFileSync(f, 'utf8')) + } +} + +// this function monkey-patches JSON.parse, so it +// will return an exact position of error in case +// of parse failure +module.exports.patch_JSON_parse = function() { + var _parse = JSON.parse + JSON.parse = function(text, rev) { + try { + return _parse(text, rev) + } catch(err) { + // this call should always throw + require('jju').parse(text, { + mode: 'json', + legacy: true, + reviver: rev, + reserved_keys: 'replace', + null_prototype: false, + }) + + // if it didn't throw, but original parser did, + // this is an error in this library and should be reported + throw err + } + } +} + +// this function is an express/connect middleware +// that accepts uploads in application/json5 format +module.exports.middleware = function() { + return function(req, res, next) { + throw Error('this function is removed, use express-json5 instead') + } +} + diff --git a/node_modules/read-package-json/node_modules/json-parse-helpfulerror/node_modules/jju/package.json b/node_modules/read-package-json/node_modules/json-parse-helpfulerror/node_modules/jju/package.json new file mode 100644 index 000000000..bdcdae6b4 --- /dev/null +++ b/node_modules/read-package-json/node_modules/json-parse-helpfulerror/node_modules/jju/package.json @@ -0,0 +1,63 @@ +{ + "name": "jju", + "version": "1.2.0", + "description": "a set of utilities to work with JSON / JSON5 documents", + "author": { + "name": "Alex Kocharin", + "email": "alex@kocharin.ru" + }, + "repository": { + "type": "git", + "url": "git://github.com/rlidwka/jju" + }, + "bugs": { + "url": "https://github.com/rlidwka/jju/issues" + }, + "homepage": "http://rlidwka.github.io/jju/", + "devDependencies": { + "mocha": ">=1.21.0", + "js-yaml": ">=3.1.0", + "eslint": "~0.4.2" + }, + "scripts": { + "test": "mocha test/*.js", + "lint": "eslint -c ./.eslint.yaml ./lib" + }, + "keywords": [ + "json", + "json5", + "parser", + "serializer", + "data" + ], + "publishConfig": { + "registry": "https://registry.npmjs.org/" + }, + "license": { + "type": "WTFPL", + "url": "http://www.wtfpl.net/txt/copying/" + }, + "gitHead": "6f1b2a8321cb0dfcffc50378b3632853cf529671", + "_id": "jju@1.2.0", + "_shasum": "add5b586fec853b44929d78bf94864ab577c02e9", + "_from": "jju@>=1.1.0 <2.0.0", + "_npmVersion": "2.0.1", + "_nodeVersion": "1.1.1", + "_npmUser": { + "name": "rlidwka", + "email": "alex@kocharin.ru" + }, + "maintainers": [ + { + "name": "rlidwka", + "email": "alex@kocharin.ru" + } + ], + "dist": { + "shasum": "add5b586fec853b44929d78bf94864ab577c02e9", + "tarball": "http://registry.npmjs.org/jju/-/jju-1.2.0.tgz" + }, + "directories": {}, + "_resolved": "https://registry.npmjs.org/jju/-/jju-1.2.0.tgz", + "readme": "ERROR: No README data found!" +} diff --git a/node_modules/read-package-json/node_modules/json-parse-helpfulerror/node_modules/jju/package.yaml b/node_modules/read-package-json/node_modules/json-parse-helpfulerror/node_modules/jju/package.yaml new file mode 100644 index 000000000..cab7b5d0b --- /dev/null +++ b/node_modules/read-package-json/node_modules/json-parse-helpfulerror/node_modules/jju/package.yaml @@ -0,0 +1,46 @@ +# use "yapm install ." if you're installing this from git repository + +# "jju" stands for "json/json5 utils" +name: jju + +version: 1.2.0 +description: a set of utilities to work with JSON / JSON5 documents + +author: + name: Alex Kocharin + email: alex@kocharin.ru + +repository: + type: git + url: git://github.com/rlidwka/jju + +bugs: + url: https://github.com/rlidwka/jju/issues + +homepage: http://rlidwka.github.io/jju/ + +devDependencies: + mocha: '>=1.21.0' + js-yaml: '>=3.1.0' + + # linting tools + eslint: '~0.4.2' + +scripts: + test: 'mocha test/*.js' + lint: 'eslint -c ./.eslint.yaml ./lib' + +keywords: + - json + - json5 + - parser + - serializer + - data + +publishConfig: + registry: https://registry.npmjs.org/ + +license: + type: WTFPL + url: http://www.wtfpl.net/txt/copying/ + diff --git a/node_modules/read-package-json/node_modules/json-parse-helpfulerror/node_modules/jju/test/portable-json5-tests.yaml b/node_modules/read-package-json/node_modules/json-parse-helpfulerror/node_modules/jju/test/portable-json5-tests.yaml new file mode 100644 index 000000000..5bf6ac38f --- /dev/null +++ b/node_modules/read-package-json/node_modules/json-parse-helpfulerror/node_modules/jju/test/portable-json5-tests.yaml @@ -0,0 +1,916 @@ +# vi:set ts=2 sts=2 sw=2 et: +# +# Copyright (c) JD 2456730 Alex Kocharin <alex@kocharin.ru> +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# The original file is available here: +# https://github.com/rlidwka/jju/tree/master/test/portable-json5-tests.yaml +# +# ---------------------------------------------------------------------------- +# +# Portable JSON5 test suite. +# +# This file contains an actual YAML data and it may include fancy syntax. +# If your platform does not support YAML, you might wish to pre-process it +# using a generic YAML parser. +# + +%YAML 1.2 +--- +# +# "input" is an arbitrary JSON5 you have to parse +# "output" is a normalized JSON you have to compare your result with, +# or !error (null) if your input should result in parser error +# +# Types of tests: +# +# - basic - Tests that every JSON5 parser should pass. +# +# - advanced - Tests that bring close compatibility with javascript. Not +# strictly required, but nice to have for completeness. +# +# - extra - Extra test cases you can follow at your discretion. +# +# Questionable features like elisions go to extra. All valid javascript, but +# invalid json5 also goes to extra. Feel free to ignore this section if you +# want to. Thus, eval(input) is a complete json5 parser, that should pass all +# basic and advanced tests. +# + +# Basic types in minimal form +# --------------------------- + +type-no-data: + type: extra + output: !error + input: '' + +type-null: + type: basic + output: null + input: > + null + +# undefined is not supported, +# null should be used instead +type-no-undefined: + type: extra + output: !error + input: > + undefined + +type-no-raw: + type: extra + output: !error + input: > + foobar + +type-bool-true: + type: basic + output: true + input: > + true + +type-bool-false: + type: basic + output: false + input: > + false + +type-number: + type: basic + output: 0 + input: > + 0 + +type-string: + type: basic + output: "" + input: > + "" + +type-object: + type: basic + output: {} + input: > + {} + +type-array: + type: basic + output: [] + input: > + [] + +# Numbers: special +# ---------------- + +# note: it's hard to test this +# just add `1/x < 0` check in your code somewhere +num-negative-zero: + type: extra + output: -0.0 + input: > + -0 + +num-nan: + type: basic + output: .nan + input: > + NaN + +num-signed-nan: + type: basic + output: .nan + input: > + +NaN + +num-positive-inf: + type: basic + output: +.inf + input: > + Infinity + +num-negative-inf: + type: basic + output: -.inf + input: > + -Infinity + +num-inf-exact-case: + type: extra + output: !error + input: > + INFINITY + +# Numbers: hexadecimal +# -------------------- + +num-hex-zero: + type: basic + output: 0 + input: > + 0x0 + +num-cut-hex: + type: basic + output: !error + input: > + 0x + +num-all-hex: + type: basic + output: 12841684683518 + input: > + 0xBADF00DCAFE + +num-mixed-case: + type: basic + output: 3735928559 + input: > + 0xDeAdBEef + +num-signed-hex: + type: advanced + output: 31 + input: > + +0x1F + +num-negative-hex: + type: advanced + output: -31 + input: > + -0x1f + +num-bad-hex: + type: advanced + output: !error + input: > + 0xBADxF00D + +num-no-hex-float: + type: advanced + output: !error + input: > + 0x12.345 + +# this is not actually an exponent :) +num-hex-exponent: + type: advanced + output: 4836 + input: > + 0x0012e4 + +# Numbers: octal +# -------------- + +# Octals are primarily used in config files +# to set up a file mask (like 0777) +# +# Note: they will have 0o12345 syntax instead +# of 012345 in the ES6, so we'll need to switch +# as well in the future + +num-octal: + type: extra + output: 342391 + input: > + 01234567 + +num-octal-zeroes: + type: extra + output: -24000 + input: > + -000000056700 + +num-bad-octal: + type: extra + output: !error + input: > + 012345678 + +num-no-octal-float: + type: extra + output: !error + input: > + 012.345 + +num-no-octal-exp: + type: extra + output: !error + input: > + 0123e4 + +# Numbers: floating point +# ----------------------- + +num-float: + type: basic + output: 123.456 + input: > + 123.456 + +num-signed-foat: + type: basic + output: -0.00098765 + input: > + -0.00098765 + +num-omit-trailing-mantissa: + type: basic + output: 1234000 + input: > + 1234.e3 + +num-omit-leading-mantissa: + type: advanced + output: -123.4 + input: > + -.1234e3 + +num-bad-float: + type: advanced + output: !error + input: > + 0.12.345 + +num-bad-sum: + type: extra + output: !error + input: > + 0.12+345 + +num-uc-exp: + type: advanced + output: -1230000 + input: > + -123E+4 + +num-float-exp: + type: basic + output: 123000 + input: > + 0.0123e7 + +num-bad-exp: + type: extra + output: !error + input: > + 123e7.3 + +num-bad-char: + type: extra + output: !error + input: > + 123a456 + +num-no-exp: + type: advanced + output: !error + input: > + 123e + +num-zero-exp: + type: advanced + output: -0.0 + input: > + -.00e-0 + +num-dec-base-signed-exp: + type: advanced + output: 0.00000123 + input: > + 1230000E-012 + +# String: quotes +# -------------- + +string-double-quotes: + type: basic + output: foobar + input: > + "foobar" + +string-single-quotes: + type: basic + output: foobar + input: > + 'foobar' + +string-open: + type: basic + output: !error + input: > + "\\\\\\\\\\\\\" + +string-not-open: + type: basic + output: "\\\\\\\\\\\\\\" + input: > + "\\\\\\\\\\\\\\" + +string-continuation: + type: advanced + output: " foo bar " + input: > + " foo \ + bar \ + " + +string-win-continuation: + type: advanced + output: "foobar" + input: "'foo\\\r\nbar'" + +string-win-reverse-continuation: + type: advanced + output: !error + input: "'foo\\\n\rbar'" + +string-unicode-continuation: + type: advanced + output: "foobarbaz" + input: "'foo\\\u2028bar\\\u2029baz'" + +string-multi-bad-continuation: + type: advanced + output: !error + input: > + foo\ + + bar + +string-bad-ending: + type: basic + output: !error + input: "'foo\rbar'" + +string-bad-ending-2028: + type: advanced + output: !error + input: "'foo\u2028bar'" + +string-bad-ending-2029: + type: advanced + output: !error + input: "'foo\u2029bar'" + +string-literal-unicode: + type: advanced + output: "foo\uFEFF\u2030bar\u1234" + input: "'foo\uFEFF\u2030bar\u1234'" + +string-control-char: + type: advanced + output: "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0b\x0c\x0e\x0f" + input: "'\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0b\x0c\x0e\x0f'" + +# String: escape sequences +# ------------------------ + +string-octal-escape: + type: extra + output: "\x1b[1;32mhi\x1b[m??" + input: > + '\033[1;32mhi\033[m\077\077' + +string-octal-two-digits: + type: extra + output: "\n\x1c\x2e\x07890\x01" + input: > + '\12\34\56\78\90\1' + +string-octal-three-digits: + type: extra + output: "\n34.78\xff 0" + input: > + '\01234\5678\377\400' + +string-hex-escape: + type: extra + output: "\x01\x23\xab\xcd\xef" + input: > + "\x01\x23\xab\xCd\xEF" + +# \0 is *not* an octal escape sequence, +# and is allowed even in strict mode +string-zero-point: + type: basic + output: "\0" + input: > + '\0' + +string-escape-double-quotes: + type: basic + output: "\"''" + input: > + "\"'\'" + +string-escape-single-quotes: + type: basic + output: " '\"\" " + input: > + ' \'"\" ' + +string-escape-json-chars: + type: basic + output: "\\\/\b\f\n\r\t" + input: > + "\\\/\b\f\n\r\t" + +# this character was left out of +# json spec for whatever reason +string-escape-slash-v: + type: basic + output: "\v" + input: > + "\v" + +string-unicode-escape: + type: basic + output: "\u0000\uffffx\ufeff\u1234\u9f6a\u2028\uabcd" + input: > + "\u0000\uFFFFx\uFeFf\u1234\u9F6a\u2028\uabcd" + +string-arbitrary-escape: + type: advanced + output: "X12Uqwe\r\tyiopasd\fghjklzc\u000b\b\nm9 " + input: > + '\X12\U\q\w\e\r\t\y\i\o\p\a\s\d\f\g\h\j\k\l\z\c\v\b\n\m\9\ ' + +string-bad-unicode: + type: advanced + output: !error + input: > + '\uEFGH' + +string-incomplete-unicode: + type: advanced + output: !error + input: > + '\u$' + +string-bad-hex: + type: advanced + output: !error + input: > + '\xFG' + +string-incomplete-hex: + type: advanced + output: !error + input: > + '\x$' + +# Object literals +# --------------- + +object-nested: + type: basic + output: {q:{'w':{"e":[1]}}} + input: | + {q:{'w':{"e":[1]}}} + +object-trailing-comma: + type: basic + output: {foo: 'bar'} + input: | + {foo: 'bar',} + +object-leading-comma-style: + type: basic + output: {q: 1,w: 2,e: 3} + input: | + { q: 1 + , w: 2 + , e: 3 + } + +object-incomplete: + type: basic + output: !error + input: | + {q:1,w:2,{} + +object-isnt-array: + type: basic + output: !error + input: | + {1,2} + +object-no-single-comma: + type: basic + output: !error + input: | + {,} + +object-no-elisions: + type: basic + output: !error + input: | + {q:1,,w:2} + +# Objects: keys +# ------------- + +object-singlequoted: + type: basic + output: {q: 1,w: 2,e: 3} + input: | + {'q':1,'w':2,'e':3} + +object-doublequoted: + type: basic + output: {q: 1,w: 2,e: 3} + input: | + {"q":1,"w":2,"e":3} + +object-unquoted: + type: basic + output: {$FOO_bar123: 'baz'} + input: > + {$FOO_bar123: 'baz'} + +object-no-first-digit: + type: advanced + output: !error + input: > + {123foo: bar} + +object-unquoted-unicode: + type: advanced + output: {"\u1f04\u03bb\u03c6\u03b1": baz} + input: "{\u1f04\u03bb\u03c6\u03b1:'baz'}" + +object-unicode-escape-key: + type: advanced + output: {foo: 'bar', "\u1f04\u03bb\u03c6\u03b1": baz, "qwe\u1f04rty": quux} + input: | + {foo:'bar', \u1f04\u03bb\u03c6\u03b1:'baz', qwe\u1f04rty: "quux"} + +object-no-raw-literal: + type: extra + output: !error + input: | + {foo: bar} + +object-bad-literal: + type: advanced + output: !error + input: | + {foo-bar: 123} + +object-no-space-in-key: + type: advanced + output: !error + input: | + {foo bar: 123} + +object-no-comment-in-key: + type: advanced + output: !error + input: | + {foo/*bar*/baz: 123} + +object-float-keys: + type: advanced + output: {'1': 'one', '3.1415': 'pi'} + input: | + {1:'one', 3.1415:'pi'} + +object-no-negative: + type: advanced + output: !error + input: | + {-5: 123} + +object-exponent-keys: + type: advanced + output: {'1': 'exp', '1000': 'pos', '0.001': 'neg'} + input: | + {1e0: 'exp', 1e+3: 'pos', 1e-3: 'neg'} + +object-octal-keys: + type: extra + output: {'668': 1} + input: | + {01234: 1} + +object-hex-keys: + type: advanced + output: {'51966': 1} + input: | + {0xCAFE: 1} + +object-null-keys: + type: basic + output: {'null': null} + input: | + {null: null} + +object-no-array-keys: + type: extra + output: !error + input: | + {[]: 123} + +object-no-empty-keys: + type: basic + output: !error + input: | + {: 123} + +object-empty-string-key: + type: basic + output: {s: {'': 1}, m: {'': 2}} + input: | + {s: {'': 1}, m: {"": 2}} + +object-bad-unicode-space: + type: advanced + output: !error + input: | + { \u0020foobar: 123 } + +object-bad-unicode-dash: + type: advanced + output: !error + input: | + { foo\u002dbar: 123} + +object-incomplete-unicode-sequence: + type: advanced + output: !error + input: | + { foo\u12f: 123 } + +object-double-escape: + type: advanced + output: !error + input: | + { foo\\u1234bar: 123 } + +object-we-arent-es3: + type: basic + output: {new: 1, delete: 2, throw: 3} + input: | + {new: 1, delete: 2, throw: 3} + +object-last-digits: + type: basic + output: {$123e2: 1, abc123: 2} + input: | + {$123e2: 1, abc123: 2} + +object-unicode-in-string: + type: advanced + output: {"\uff13qwe": 123} + input: | + {"\uff13qwe": 123} + +object-unicode-esc-in-string: + type: advanced + output: {"\\uff13qwe": 123} + input: | + {"\\uff13qwe": 123} + +object-unicode-digits-first-esc: + type: advanced + output: !error + input: | + {\uff13qwe: 123} + +object-unicode-digits-first-lit: + type: advanced + output: !error + input: "{\uff13qwe: 123}" + +object-unicode-weirdness-esc: + type: advanced + output: {"digit\uff13": 1, "comb\u094F": 2, "punct\u2040": 3, "zwnj\u200C": 4} + input: | + {digit\uff13: 1, comb\u094F: 2, punct\u2040: 3, zwnj\u200C: 4} + +object-unicode-weirdness-lit: + type: advanced + output: {"digit\uff13": 1, "comb\u094F": 2, "punct\u2040": 3, "zwnj\u200C": 4} + input: "{digit\uff13: 1, comb\u094F: 2, punct\u2040: 3, zwnj\u200C: 4}" + +# Array literals +# -------------- + +array-all-types: + type: basic + output: [1.2,"3,4",{},[],null,+.inf] + input: | + [1.2,"3,4",{},[],null,Infinity] + +array-trailing-comma: + type: basic + output: [1,2,3,4] + input: | + [1,2,3,4,] + +array-leading-comma-style: + type: basic + output: [quux,foo,bar,baz] + input: | + [ 'quux' + , 'foo' + , 'bar' + , 'baz' + ] + +array-incomplete: + type: basic + output: !error + input: | + [1,2,3,[] + +array-nested: + type: basic + output: [[[[[[]]]]],[[],[]]] + input: | + [[[[[[/*[]*/]]]]],[[],[]]] + +array-isnt-object: + type: extra + output: !error + input: | + [1:2] + +array-no-single-comma: + type: extra + output: !error + input: | + [,] + +array-no-elisions: + type: extra + output: !error + input: | + [1,,2,3] + +# Comments +# -------- + +comment-single: + type: basic + output: foobar + input: | + // blahblah + "foobar" + // another one + +comment-multi: + type: basic + output: foobar + input: | + /* + * 123 + */ + "foobar" + /**/ + +comment-single-newlines: + type: advanced + output: [ 123, 456, 789 ] + input: "[// foo\r123,// bar\u2028456,// baz\u2029789]" + +comment-inside: + type: advanced + output: [123, '// foo', '/* bar'] + input: > + [ + /* + " // */ 123, // ", + "// foo", + '/* bar', + ] + +comment-in-token: + type: advanced + output: !error + input: + 123/*comment*/456 + +comment-java-style: + type: basic + output: 123 + input: + /*****************/ + 123 + /****************/ + +comment-object: + type: basic + output: {q: 123} + input: /**/{/**/q/**/:/**/123/**/,/**/}// + +# Whitespace +# ---------- + +ws-no-whitespace: + type: basic + output: {"foo":bar,bar:["qwe",null,[],{}],"baz":123} + input: '{foo:"bar","bar":["qwe",null,[],{}],"baz":123}' + +ws-allow-prefix: + type: basic + output: 123 + input: " \t123" + +ws-unicode-spaces: + type: advanced + output: { foo : 123 } + input: " + \u0020\u00A0\uFEFF + { + \x09\x0A\x0B\x0C\x0D\u1680\u180E + foo + \u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A + : + \u2028\u2029\u202F\u205F\u3000 + 123 + \uFEFF + }" + +ws-unicode-newlines: + type: advanced + output: [ 123, 456 ] + input: " + [ + \u000D + 123, + \u2028 + 456, + \u2029 + ] + " + +# Multiple tokens +# --------------- + +multi-string-nospace: + type: basic + output: !error + input: '"foo""bar"' + +multi-string: + type: basic + output: !error + input: '"foo" "bar"' + +# note: valid javascript +multi-array: + type: extra + output: !error + input: '[0] [0]' + +multi-object: + type: basic + output: !error + input: '{} {}' +... diff --git a/node_modules/read-package-json/node_modules/json-parse-helpfulerror/node_modules/jju/test/test_analyze.js b/node_modules/read-package-json/node_modules/json-parse-helpfulerror/node_modules/jju/test/test_analyze.js new file mode 100644 index 000000000..2a24e01ea --- /dev/null +++ b/node_modules/read-package-json/node_modules/json-parse-helpfulerror/node_modules/jju/test/test_analyze.js @@ -0,0 +1,53 @@ +var _assert = require('assert') +var analyze = require('../').analyze + +function addTest(a, b) { + if (typeof(describe) === 'function') { + it('test_analyze: ' + a + ' == ' + b, function() { + _assert.equal(a, b) + }) + } else { + _assert.equal(a, b) + } +} + +var t = analyze(JSON.stringify(require('os').networkInterfaces())) +addTest(t.has_whitespace, false) +addTest(t.has_comments, false) +addTest(t.has_newlines, false) +addTest(t.newline, '\n') +addTest(t.quote, '"') +addTest(t.quote_keys, true) +addTest(t.indent, '') + +var t = analyze(JSON.stringify(require('os').networkInterfaces(), null, 2)) +addTest(t.has_whitespace, true) +addTest(t.has_comments, false) +addTest(t.has_newlines, true) +addTest(t.newline, '\n') +addTest(t.quote, '"') +addTest(t.quote_keys, true) +addTest(t.indent, ' ') + +var t = analyze(JSON.stringify(require('os').networkInterfaces(), null, 3)) +addTest(t.indent, ' ') + +var t = analyze(JSON.stringify(require('os').networkInterfaces(), null, '\t')) +addTest(t.indent, '\t') + +var t = analyze(JSON.stringify(require('os').networkInterfaces(), null, 3).replace(/\n/g, '\r\n')) +addTest(t.indent, ' ') +addTest(t.newline, '\r\n') + +var t = analyze(JSON.stringify(require('os').networkInterfaces()).replace(/"/g, "'")) +addTest(t.quote, "'") +addTest(t.quote_keys, true) + +var t = analyze("{foo:'bar', 'bar':\"baz\", 'baz':\"quux\"}") +addTest(t.quote, "'") +addTest(t.quote_keys, false) + +var t = analyze("{foo:'bar', \"bar\":'baz', \"baz\":\"quux\"}") +addTest(t.quote, '"') +addTest(t.quote_keys, false) + diff --git a/node_modules/read-package-json/node_modules/json-parse-helpfulerror/node_modules/jju/test/test_document.js b/node_modules/read-package-json/node_modules/json-parse-helpfulerror/node_modules/jju/test/test_document.js new file mode 100644 index 000000000..5f1ef2aaf --- /dev/null +++ b/node_modules/read-package-json/node_modules/json-parse-helpfulerror/node_modules/jju/test/test_document.js @@ -0,0 +1,214 @@ +var assert = require('assert') +var create = require('../lib/document').Document +var jju = require('..') + +var str = '{ x\r\n:\n1, y: {"..z.": 123, t: null, s:"123", a:[ 1,2,{x:3},] }}\n' +var d = create(str) +assert.equal(d + '', str) +assert.deepEqual(d.get(''), {x:1,y:{'..z.':123,t:null,s:'123',a:[1,2,{x:3}]}}) +assert.deepEqual(d.get('x'), 1) +assert.deepEqual(d.get('x.x'), undefined) +assert.deepEqual(d.get('x.x.x.x'), undefined) +assert.strictEqual(d.get('y.x'), undefined) +assert.deepEqual(d.get('y.s'), '123') +assert.strictEqual(d.get('y.t'), null) +assert.strictEqual(d.get('y.t.x'), undefined) +assert.equal(d.has(''), true) +assert.equal(d.has('x'), true) +assert.equal(d.has('x.x'), false) +assert.equal(d.has('x.x.x.x'), false) +assert.equal(d.has('y.x'), false) +assert.equal(d.has('y'), true) +assert.equal(d.has('y.s'), true) +assert.equal(d.has('y.t'), true) +assert.equal(d.has('a'), false) + +// arrays +assert.deepEqual(d.get('y.a'), [1,2,{x:3}]) +assert.deepEqual(d.get('y.a.0'), 1) +assert.deepEqual(d.get('y.a.2.x'), 3) +assert.deepEqual(d.get('y.a.10'), undefined) +assert.deepEqual(d.has('y.a.0'), true) +assert.deepEqual(d.has('y.a.10'), false) +assert.deepEqual(d.get('y.a.2'), {x:3}) +assert.deepEqual(d.get('y.a.-1'), undefined) + +// controversial +assert.strictEqual(d.get('y.s.0'), undefined) +assert.equal(d.has('y.s.0'), false) + +// paths +assert.deepEqual(d.get([]), {x:1,y:{'..z.':123,t:null,s:'123',a:[1,2,{x:3}]}}) +assert.strictEqual(d.has([]), true) +assert.strictEqual(d.get(['y','..z.']), 123) +assert.strictEqual(d.has(['y','..z.']), true) +assert.deepEqual(d.get(['y','a',2,'x']), 3) +assert.deepEqual(create('[1]').set(0, 4).get(''), [4]) +assert.deepEqual(create('[1]').set(1, 4).get(''), [1,4]) +assert.deepEqual(create('[1]').has(0), true) +assert.deepEqual(create('[1]').has(1), false) +assert.deepEqual(create('[1]').get(0), 1) + +// invalid paths +assert.throws(function() { create('[1]').set(null, 4) }, /invalid path type/i) +assert.throws(function() { create('[1]').set({}, 4) }, /invalid path type/i) +assert.throws(function() { create('[1]').set(/./, 4) }, /invalid path type/i) +assert.throws(function() { create('[1]').set(function(){}, 4) }, /invalid path type/i) +assert.throws(function() { create('[1]').set(false, 4) }, /invalid path type/i) +assert.throws(function() { create('[1]').set(undefined, 4) }, /invalid path type/i) + +// set root +assert.strictEqual(create(str).set('', 4).get(''), 4) +assert.strictEqual(create(str).set('', null).get(''), null) +assert.strictEqual(create(str).set('', {x:4}).get('x'), 4) +assert.deepEqual(create(str).set('', [1,2,3]).get(''), [1,2,3]) +assert.strictEqual(create('1').set('', 4).get(''), 4) +assert.strictEqual(create('null').set('', 4).get(''), 4) +assert.strictEqual(create('[]').set('', 4).get(''), 4) +assert.strictEqual(create('{}').set('', 4).get(''), 4) + +// set 1st level +assert.deepEqual(create('{}').set('x', 4).get('x'), 4) +assert.deepEqual(create('{a:{b:[]}}').set('a.b.0', 4).get('a'), {b:[4]}) +//assert.deepEqual(create('1').set('x', 4).get('x'), 4) +//assert.deepEqual(create('null').set('x', 4).get('x'), 4) + +// array: boundaries +assert.strictEqual(create('[]').set('0', 4).get('0'), 4) +assert.strictEqual(create('[1,2,3]').set('2', 4).get('2'), 4) +assert.strictEqual(create('[1,2,3]').set('3', 4).get('3'), 4) + +// various error cases +assert.throws(function() { create('1').set('x', 4) }, /set key .* of an non-object/) +assert.throws(function() { create('null').set('x', 4) }, /set key .* of an non-object/) +assert.throws(function() { create('[]').set('x', 4) }, /set key .* of an array/) +assert.throws(function() { create('""').set('x', 4) }, /set key .* of an non-object/) +assert.throws(function() { create('{}').set('x.x.x', 4) }, /set key .* of an non-object/) +assert.throws(function() { create('1').set('1', 4) }, /set key .* of an non-object/) +assert.throws(function() { create('null').set('1', 4) }, /set key .* of an non-object/) +assert.throws(function() { create('""').set('1', 4) }, /set key .* of an non-object/) +assert.throws(function() { create('[]').set('-1', 4) }, /set key .* of an array/) +assert.throws(function() { create('[]').set('1', 4) }, /set key .* out of bounds/) +assert.throws(function() { create('[1,2,3]').set('4', 4) }, /set key .* out of bounds/) +assert.throws(function() { create('{a:{b:[]}}').set('a.b.x', 4) }, /set key .* of an array/) + +// unsetting stuff +assert.throws(function() { create('[]').unset('') }, /can't remove root document/) + +// arrays: handling spaces correctly +assert.equal(create("[]").set(0,{})+"", '[{}]') +assert.equal(create("[0]").set(1,{})+"", '[0,{}]') +assert.equal(create("[0,]").set(1,{})+"", '[0,{},]') +assert.equal(create("[ ]").set(0,{})+"", '[{} ]') +assert.equal(create("[ 0 , ]").set(1,{})+"", '[ 0 , {}, ]') +assert.equal(create("[ 0 ]").set(1,{})+"", '[ 0, {} ]') +assert.equal(create("{}").set('y',{})+"", '{"y":{}}') +assert.equal(create("{x:1}").set('y',{})+"", '{x:1,y:{}}') +assert.equal(create("{x:1,}").set('y',{})+"", '{x:1,y:{},}') +assert.equal(create("{ }").set('y',{})+"", '{"y":{} }') +assert.equal(create("{ x:1 , }").set('y',{})+"", '{ x:1 , y:{}, }') +assert.equal(create("{ x:1 }").set('y',{})+"", '{ x:1, y:{} }') + +// deleting elements +assert.throws(function() { create('[]').unset('0') }, /unset key .* out of bounds/) +assert.throws(function() { create('[1,2]').unset('2') }, /unset key .* out of bounds/) +assert.throws(function() { create('[1,2,3]').unset('0') }, /in the middle of an array/) + +// CommonJS assert spec is "awesome" +assert.deepEqual(create('[1,2]').unset('1').get(''), [1]) +assert.deepEqual(create('[1,2]').unset('1').get('').length, 1) +assert.deepEqual(create('[1,2,3]').unset('2').unset('1').get(''), [1]) +assert.deepEqual(create('[1,2,3]').unset('2').unset('1').get('').length, 1) +assert.deepEqual(create('[1]').unset('0').get(''), []) +assert.deepEqual(create('[1]').unset('0').get('').length, 0) + +assert.deepEqual(create('{x:{y:"z"}, z:4}').unset('x').get(''), {z:4}) +assert.throws(function() { create('[1,2]').unset('') }, /root/) + +// getting crazy +//assert.deepEqual(create(str).set('a.b.c.d.e', 1).get('a'), {b:{c:{d:{e:1}}}}) + +// update: arrays +assert.deepEqual(create("[1]").update([2,3])+"", '[2,3]') +assert.deepEqual(create("[1]").update([2,3,4])+"", '[2,3,4]') +assert.deepEqual(create("[]").update([2])+"", '[2]') +assert.deepEqual(create("[2]").update([])+"", '[]') +assert.deepEqual(create("[2,3,4]").update([2,3])+"", '[2,3]') +assert.deepEqual(create("[2,3,4]").update([])+"", '[]') +assert.deepEqual(create("[]").update([2,3,4])+"", '[2,3,4]') +assert.deepEqual(create(" /*zz*/ [ 2 , 3 , 4 ] /*xx*/ ").update([])+"", ' /*zz*/ [ ] /*xx*/ ') +assert.deepEqual(create(" /*zz*/ [ ] /*xx*/ ").update([2,3,4])+"", ' /*zz*/ [2,3,4 ] /*xx*/ ') + +// update: objects +assert.deepEqual(create("{x:1}").update({x:1,y:2,z:3})+"", '{x:1,y:2,z:3}') +assert.deepEqual(create("{x:1}").update({x:2,z:3,t:4})+"", '{x:2,z:3,t:4}') +assert.deepEqual(create("{}").update({x:1,y:2})+"", '{"x":1,"y":2}') +assert.deepEqual(create("{x:1}").update({})+"", '{}') +assert.deepEqual(create("{x:1,y:2}").update({x:1})+"", '{x:1}') +assert.deepEqual(create(" /*zz*/ { x /*a*/ : /*b*/ 2 , y:3 , z //\n: 4 } /*xx*/ ").update({})+"", ' /*zz*/ { } /*xx*/ ') +assert.deepEqual(create(" /*zz*/ { } /*xx*/ ").update({x: 2, y: 3, z: 4})+"", ' /*zz*/ {"x":2,"y":3,"z":4 } /*xx*/ ') + +// remove trailing comma +assert.deepEqual(create("{x:1,}").update({})+"", '{}') +assert.deepEqual(create("[0,]").update([])+"", '[]') +assert.deepEqual(create("[0 /*z*/ , /*z*/]").update([])+"", '[ /*z*/]') + +// mode +assert.equal(create('{"test":123}', {mode:'json'}).update({q:1,w:2})+'', '{"q":1,"w":2}') + +assert.equal(create('{1:2}').update({ a: 1, b: [1,2], c: 3})+'', '{a:1,b:[1,2],c:3}') + +// undef +//assert.throws(function(){ jju.update(undefined, undefined) }, /root doc/) +assert.equal(jju.update(undefined, undefined), '') +assert.equal(jju.update(undefined, 42), '42') +assert.equal(jju.update(undefined, {x: 5}), '{"x":5}') + +/* + * real test + */ +var upd = { name: 'yapm', + version: '0.6.0', + description: 'npm wrapper allowing to use package.yaml instead of package.json', + author: { name: 'Alex Kocharin', email: 'alex@kocharin.ru' }, + keywords: + [ 'package manager', + 'modules', + 'install', + 'package.yaml', + 'package.json5', + 'yaml', + 'json5', + 'npm' ], + preferGlobal: true, + homepage: 'https://npmjs.org/doc/', + repository: { type: 'git', url: 'https://github.com/rlidwka/yapm' }, + bugs: { url: 'http://github.com/rlidwka/yapm/issues' }, + main: './yapm.js', + bin: { yapm: './yapm.js' }, + dependencies: { npm: '*', 'js-yaml': '*', through: '*', 'json5-utils': '*' }, + devDependencies: { async: '*' }, + optionalDependencies: { 'yaml-update': '*' }, + test_nonascii: 'тест' } + +assert.deepEqual(create(create('{"garbage":"garbage"}').update(upd)).get(''), upd) +assert.deepEqual(JSON.parse(create('{"garbage":"garbage"}', {mode:'json',legacy:true}).update(upd)), upd) + +//console.log(create('{"garbage":"garbage"}').update(upd)+'') + +//assert.deepEqual(create(" [ ] //").set(0,{})+"" [ ,{}] // + + +//node -e 'console.log(require("./document").Document("{}").set("",[1,2,3])+"")'[1, 2, 3] + +//alex@elu:~/json5-utils/lib$ node -e 'console.log(require("./document").Document("[]").set("0",[1,2,3]).get(""))' +//[ [ 1, 2, 3 ] ] + + +/*assert.equal(create('"test"').get(''), 'test') +assert.equal(create('"test"').get([]), 'test') +assert.equal(create('"test"').get(false), 'test') +assert.equal(create(undefined).get(''), undefined) + +//assert.equal(create('"test"').set('', 'foo').toString(), '"foo"') +*/ diff --git a/node_modules/read-package-json/node_modules/json-parse-helpfulerror/node_modules/jju/test/test_errors.js b/node_modules/read-package-json/node_modules/json-parse-helpfulerror/node_modules/jju/test/test_errors.js new file mode 100644 index 000000000..8b2cdb7dc --- /dev/null +++ b/node_modules/read-package-json/node_modules/json-parse-helpfulerror/node_modules/jju/test/test_errors.js @@ -0,0 +1,56 @@ +var assert = require('assert') +var parse = require('../').parse + +function addTest(arg, row, col, errRegExp) { + var fn = function() { + try { + parse(arg) + } catch(err) { + if (row !== undefined) assert.equal(err.row, row, 'wrong row: ' + err.row) + if (col !== undefined) assert.equal(err.column, col, 'wrong column: ' + err.column) + if (errRegExp) assert(errRegExp.exec(err.message)) + return + } + throw Error("no error") + } + + if (typeof(describe) === 'function') { + it('test_errors: ' + JSON.stringify(arg), fn) + } else { + fn() + } +} + +// semicolon will be unexpected, so it indicates an error position +addTest(';', 1, 1) +addTest('\n\n\n;', 4, 1) +addTest('\r\n;', 2, 1) +addTest('\n\r;', 3, 1) +addTest('\n\u2028;', 3, 1) +addTest('\n\u2029;', 3, 1) +addTest('[\n1\n,\n;', 4, 1) +addTest('{\n;', 2, 1) +addTest('{\n1\n:\n;', 4, 1) +addTest('.e3', 1, 3, /"\.e3"/) + +// line continuations +addTest('["\\\n",\n;', 3, 1) +addTest('["\\\r\n",\n;', 3, 1) +addTest('["\\\u2028",\n;', 3, 1) +addTest('["\\\u2029",\n;', 3, 1) + +// bareword rewind +addTest('nulz', 1, 1) + +// no data +addTest(' ', 1, 3, /No data.*whitespace/) +addTest('blah', 1, 1, /Unexpected token 'b'/) +addTest('', 1, 1, /No data.*empty input/) + +try { + parse('{{{{{{{{{') +} catch(err) { + var x = err.stack.match(/parseObject/g) + assert(!x || x.length < 2, "shouldn't blow up the stack with internal calls") +} + diff --git a/node_modules/read-package-json/node_modules/json-parse-helpfulerror/node_modules/jju/test/test_parse.js b/node_modules/read-package-json/node_modules/json-parse-helpfulerror/node_modules/jju/test/test_parse.js new file mode 100644 index 000000000..d33e61ee7 --- /dev/null +++ b/node_modules/read-package-json/node_modules/json-parse-helpfulerror/node_modules/jju/test/test_parse.js @@ -0,0 +1,171 @@ +var assert = require('assert') +var parse = require('../').parse + +function addTest(arg, bulk) { + function fn_json5() { + //console.log('testing: ', arg) + try { + var x = parse(arg) + } catch(err) { + x = 'fail' + } + try { + var z = eval('(function(){"use strict"\nreturn ('+String(arg)+'\n)\n})()') + } catch(err) { + z = 'fail' + } + assert.deepEqual(x, z) + } + + function fn_strict() { + //console.log('testing: ', arg) + try { + var x = parse(arg, {mode: 'json'}) + } catch(err) { + x = 'fail' + } + try { + var z = JSON.parse(arg) + } catch(err) { + z = 'fail' + } + assert.deepEqual(x, z) + } + + if (typeof(describe) === 'function' && !bulk) { + it('test_parse_json5: ' + JSON.stringify(arg), fn_json5) + it('test_parse_strict: ' + JSON.stringify(arg), fn_strict) + } else { + fn_json5() + fn_strict() + } +} + +addTest('"\\uaaaa\\u0000\\uFFFF\\uFaAb"') +addTest(' "\\xaa\\x00\xFF\xFa\0\0" ') +addTest('"\\\'\\"\\b\\f\\t\\n\\r\\v"') +addTest('"\\q\\w\\e\\r\\t\\y\\\\i\\o\\p\\[\\/\\\\"') +addTest('"\\\n\\\r\n\\\n"') +addTest('\'\\\n\\\r\n\\\n\'') +addTest(' null') +addTest('true ') +addTest('false') +addTest(' Infinity ') +addTest('+Infinity') +addTest('[]') +addTest('[ 0xA2, 0X024324AaBf]') +addTest('-0x12') +addTest(' [1,2,3,4,5]') +addTest('[1,2,3,4,5,] ') +addTest('[1e-13]') +addTest('[null, true, false]') +addTest(' [1,2,"3,4,",5,]') +addTest('[ 1,\n2,"3,4," \r\n,\n5,]') +addTest('[ 1 , 2 , 3 , 4 , 5 , ]') +addTest('{} ') +addTest('{"2":1,"3":null,}') +addTest('{ "2 " : 1 , "3":null , }') +addTest('{ \"2\" : 25e245 , \"3\": 23 }') +addTest('{"2":1,"3":nul,}') +addTest('{:1,"3":nul,}') +addTest('[1,2] // ssssssssss 3,4,5,] ') +addTest('[1,2 , // ssssssssss \n//xxx\n3,4,5,] ') +addTest('[1,2 /* ssssssssss 3,4,*/ /* */ , 5 ] ') +addTest('[1,2 /* ssssssssss 3,4,*/ /* * , 5 ] ') +addTest('{"3":1,"3":,}') +addTest('{ чйуач:1, щцкшчлм : 4,}') +addTest('{ qef-:1 }') +addTest('{ $$$:1 , ___: 3}') +addTest('{3:1,2:1}') +addTest('{3.4e3:1}') +addTest('{-3e3:1}') +addTest('{+3e3:1}') +addTest('{.3e3:1}') + +for (var i=0; i<200; i++) { + addTest('"' + String.fromCharCode(i) + '"', true) +} + +// strict JSON test cases +addTest('"\\xaa"') +addTest('"\\0"') +addTest('"\0"') +addTest('"\\v"') +addTest('{null: 123}') +addTest("{'null': 123}") + +assert.throws(function() { + parse('0o') +}) + +assert.strictEqual(parse('01234567'), 342391) +assert.strictEqual(parse('0o1234567'), 342391) + +// undef +assert.strictEqual(parse(undefined), undefined) + +// whitespaces +addTest('[1,\r\n2,\r3,\n]') +'\u0020\u00A0\uFEFF\x09\x0A\x0B\x0C\x0D\u1680\u180E\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u2028\u2029\u202F\u205F\u3000'.split('').forEach(function(x) { + addTest(x+'[1,'+x+'2]'+x) + addTest('"'+x+'"'+x) +}) +'\u000A\u000D\u2028\u2029'.split('').forEach(function(x) { + addTest(x+'[1,'+x+'2]'+x) + addTest('"\\'+x+'"'+x) +}) + +/* weird ES6 stuff, not working + +if (process.version > 'v0.11.7') { + assert(Array.isArray(parse('{__proto__:[]}').__proto__)) + assert.equal(parse('{__proto__:{xxx:5}}').xxx, undefined) + assert.equal(parse('{__proto__:{xxx:5}}').__proto__.xxx, 5) + + var o1 = parse('{"__proto__":[]}') + assert.deepEqual([], o1.__proto__) + assert.deepEqual(["__proto__"], Object.keys(o1)) + assert.deepEqual([], Object.getOwnPropertyDescriptor(o1, "__proto__").value) + assert.deepEqual(["__proto__"], Object.getOwnPropertyNames(o1)) + assert(o1.hasOwnProperty("__proto__")) + assert(Object.prototype.isPrototypeOf(o1)) + + // Parse a non-object value as __proto__. + var o2 = JSON.parse('{"__proto__":5}') + assert.deepEqual(5, o2.__proto__) + assert.deepEqual(["__proto__"], Object.keys(o2)) + assert.deepEqual(5, Object.getOwnPropertyDescriptor(o2, "__proto__").value) + assert.deepEqual(["__proto__"], Object.getOwnPropertyNames(o2)) + assert(o2.hasOwnProperty("__proto__")) + assert(Object.prototype.isPrototypeOf(o2)) +}*/ + +assert.throws(parse.bind(null, "{-1:42}")) + +for (var i=0; i<100; i++) { + var str = '-01.e'.split('') + + var rnd = [1,2,3,4,5].map(function(x) { + x = ~~(Math.random()*str.length) + return str[x] + }).join('') + + try { + var x = parse(rnd) + } catch(err) { + x = 'fail' + } + try { + var y = JSON.parse(rnd) + } catch(err) { + y = 'fail' + } + try { + var z = eval(rnd) + } catch(err) { + z = 'fail' + } + //console.log(rnd, x, y, z) + if (x !== y && x !== z) throw 'ERROR' +} + diff --git a/node_modules/read-package-json/node_modules/json-parse-helpfulerror/node_modules/jju/test/test_portable.js b/node_modules/read-package-json/node_modules/json-parse-helpfulerror/node_modules/jju/test/test_portable.js new file mode 100644 index 000000000..0143e7d8e --- /dev/null +++ b/node_modules/read-package-json/node_modules/json-parse-helpfulerror/node_modules/jju/test/test_portable.js @@ -0,0 +1,60 @@ +var assert = require('assert') +var FS = require('fs') +var YAML = require('js-yaml') +var jju = require('../') + +function addTest(name, fn) { + if (typeof(describe) === 'function') { + it(name, fn) + } else { + fn() + } +} + +var schema = YAML.Schema.create([ + new YAML.Type('!error', { + kind: 'scalar', + resolve: function (state) { + //state.result = null + return true + }, + }) +]) + +var tests = YAML.safeLoad(FS.readFileSync(__dirname + '/portable-json5-tests.yaml', 'utf8'), { + schema: schema +}) + +if (!Object.is) { + Object.defineProperty(Object, 'is', { + value: function(x, y) { + if (x === y) { + return x !== 0 || 1 / x === 1 / y; + } + return x !== x && y !== y; + }, + configurable: true, + enumerable: false, + writable: true, + }) +} + +for (var k in tests) { + ;(function(k) { + addTest(k, function() { + try { + var result = jju.parse(tests[k].input) + } catch(err) { + result = null + } + + // need deepStrictEqual + if (typeof(result) === 'object') { + assert.deepEqual(result, tests[k].output) + } else { + assert(Object.is(result, tests[k].output), String(result) + ' == ' + tests[k].output) + } + }) + })(k) +} + diff --git a/node_modules/read-package-json/node_modules/json-parse-helpfulerror/node_modules/jju/test/test_stringify.js b/node_modules/read-package-json/node_modules/json-parse-helpfulerror/node_modules/jju/test/test_stringify.js new file mode 100644 index 000000000..c97e38e93 --- /dev/null +++ b/node_modules/read-package-json/node_modules/json-parse-helpfulerror/node_modules/jju/test/test_stringify.js @@ -0,0 +1,89 @@ +var assert = require('assert') +var parse = require('../').parse +var stringify = require('../').stringify + +function deepEqual(x, y) { + if (Number.isNaN(x)) { + return assert(Number.isNaN(y)) + } + assert.deepEqual(x, y) +} + +function addTest(arg, arg2, arg3) { + function fn() { + deepEqual(parse(stringify(arg)), arg2 === undefined ? arg : arg2) + if (arg !== undefined) deepEqual(JSON.parse(stringify(arg, {mode: 'json', indent: false})), (arg3 === undefined ? (arg2 === undefined ? arg : arg2) : arg3)) + } + + if (typeof(describe) === 'function') { + it('test_stringify: ' + JSON.stringify(arg), fn) + } else { + fn() + } +} + +addTest(0) +addTest(-0) +addTest(NaN, undefined, null) +addTest(Infinity, undefined, null) +addTest(-Infinity, undefined, null) +addTest(123) +addTest(19508130958019385.135135) +addTest(-2e123) +addTest(null) +addTest(undefined) +addTest([]) +addTest([,,,,,,,], [null,null,null,null,null,null,null]) +addTest([undefined,null,1,2,3,], [null,null,1,2,3]) +addTest([[[[]]],[[]]]) +addTest({}) +addTest({1:2,3:4}) +addTest({1:{1:{1:{1:4}}}, 3:4}) +addTest({1:undefined, 3:undefined}, {}) +addTest(new Number(4), 4) +addTest(new Boolean(true), true) +addTest(new String('xqefxef'), 'xqefxef') +addTest(new Boolean(), false) + +var r='';for (var i=0; i<5000; i++) {r+=String.fromCharCode(i)} +addTest(r) + +assert.equal("[1, 2, 3]", stringify([1, 2, 3], {indent: 1})) +assert.equal("[1, 2, 3]", stringify([1, 2, 3], {indent: 2})) + +var oddball = Object(42) +oddball.__proto__ = { __proto__: null } +assert.equal('{}', stringify(oddball)) + +/* this WILL throw +var falseNum = Object("37") +falseNum.__proto__ = Number.prototype +assert.equal("{0: '3', 1: '7'}", stringify(falseNum))*/ + +assert.equal(stringify(Infinity), 'Infinity') +assert.equal(stringify(Infinity, {mode: 'json'}), 'null') +assert.equal(stringify(NaN), 'NaN') +assert.equal(stringify(NaN, {mode: 'json'}), 'null') +assert.equal(stringify(-0), '-0') + +assert.equal(stringify('test', null), "'test'") + +var array = [""] +var expected = "''" +for (var i = 0; i < 1000; i++) { + array.push("") + expected = "''," + expected +} +expected = '[' + expected + ']' +assert.equal(expected, stringify(array, {indent: false})) + +assert.strictEqual(stringify([1,2,3], function(){}), undefined) + +// don't stringify prototype +assert.equal('{a: 1}', stringify({a:1,__proto__:{b:2}})) + +// sort keys tests +assert.equal('{a: 1, b: 2, z: 3}', stringify({b:2,a:1,z:3}, {sort_keys: 1})) +assert.equal('{a: 1, b: {a: 2, b: 5, c: 1}, z: 3}', stringify({b:{c:1,a:2,b:5},a:1,z:3}, {sort_keys: 1})) +assert.equal('{a: [3, 5, 1], b: 2, z: 3}', stringify({b:2,a:[3,5,1],z:3}, {sort_keys: 1})) +assert.equal('{b: 2, a: 1, z: 3}', stringify({b:2,a:1,z:3}, {sort_keys: 0})) diff --git a/node_modules/read-package-json/node_modules/json-parse-helpfulerror/node_modules/jju/test/test_tokenize.js b/node_modules/read-package-json/node_modules/json-parse-helpfulerror/node_modules/jju/test/test_tokenize.js new file mode 100644 index 000000000..64fb7ec93 --- /dev/null +++ b/node_modules/read-package-json/node_modules/json-parse-helpfulerror/node_modules/jju/test/test_tokenize.js @@ -0,0 +1,99 @@ +var assert = require('assert') +var parse = require('../').parse + +function tokenize(arg) { + var result = [] + parse(arg, {_tokenize: function(smth) { + result.push(smth) + }}) + assert.deepEqual(result.map(function(x){return x.raw}).join(''), arg) + return result +} + +function addTest(x, exp) { + function fn(){assert.deepEqual(tokenize(x), exp)} + + if (typeof(describe) === 'function') { + it('test_tokenize: ' + JSON.stringify(x), fn) + } else { + fn() + } +} + +addTest('123', [ { raw: '123', value: 123, type: 'literal', stack: [] }]) + +addTest(' /* zz */\r\n true /* zz */\n', +[ { raw: ' ', type: 'whitespace', stack: [] }, + { raw: '/* zz */', type: 'comment', stack: [] }, + { raw: '\r\n', type: 'newline', stack: [] }, + { raw: ' ', type: 'whitespace', stack: [] }, + { raw: 'true', type: 'literal', value: true, stack: [] }, + { raw: ' ', type: 'whitespace', stack: [] }, + { raw: '/* zz */', type: 'comment', stack: [] }, + { raw: '\n', type: 'newline', stack: [] } ]) + +addTest('{q:123, w : /*zz*/\n\r 345 } ', +[ { raw: '{', type: 'separator', stack: [] }, + { raw: 'q', type: 'key', value: 'q', stack: [] }, + { raw: ':', type: 'separator', stack: [] }, + { raw: '123', type: 'literal', value: 123, stack: ['q'] }, + { raw: ',', type: 'separator', stack: [] }, + { raw: ' ', type: 'whitespace', stack: [] }, + { raw: 'w', type: 'key', value: 'w', stack: [] }, + { raw: ' ', type: 'whitespace', stack: [] }, + { raw: ':', type: 'separator', stack: [] }, + { raw: ' ', type: 'whitespace', stack: [] }, + { raw: '/*zz*/', type: 'comment', stack: [] }, + { raw: '\n', type: 'newline', stack: [] }, + { raw: '\r', type: 'newline', stack: [] }, + { raw: ' ', type: 'whitespace', stack: [] }, + { raw: '345', type: 'literal', value: 345, stack: ['w'] }, + { raw: ' ', type: 'whitespace', stack: [] }, + { raw: '}', type: 'separator', stack: [] }, + { raw: ' ', type: 'whitespace', stack: [] } ]) + +addTest('null /* */// xxx\n//xxx', +[ { raw: 'null', type: 'literal', value: null, stack: [] }, + { raw: ' ', type: 'whitespace', stack: [] }, + { raw: '/* */', type: 'comment', stack: [] }, + { raw: '// xxx', type: 'comment', stack: [] }, + { raw: '\n', type: 'newline', stack: [] }, + { raw: '//xxx', type: 'comment', stack: [] } ]) + +addTest('[1,2,[[],[1]],{},{1:2},{q:{q:{}}},]', +[ { raw: '[', type: 'separator', stack: [] }, + { raw: '1', type: 'literal', value: 1, stack: [0] }, + { raw: ',', type: 'separator', stack: [] }, + { raw: '2', type: 'literal', value: 2, stack: [1] }, + { raw: ',', type: 'separator', stack: [] }, + { raw: '[', type: 'separator', stack: [2] }, + { raw: '[', type: 'separator', stack: [2,0] }, + { raw: ']', type: 'separator', stack: [2,0] }, + { raw: ',', type: 'separator', stack: [2] }, + { raw: '[', type: 'separator', stack: [2,1] }, + { raw: '1', type: 'literal', value: 1, stack: [2,1,0] }, + { raw: ']', type: 'separator', stack: [2,1] }, + { raw: ']', type: 'separator', stack: [2] }, + { raw: ',', type: 'separator', stack: [] }, + { raw: '{', type: 'separator', stack: [3] }, + { raw: '}', type: 'separator', stack: [3] }, + { raw: ',', type: 'separator', stack: [] }, + { raw: '{', type: 'separator', stack: [4] }, + { raw: '1', type: 'key', value: 1, stack: [4] }, + { raw: ':', type: 'separator', stack: [4] }, + { raw: '2', type: 'literal', value: 2, stack: [4,'1'] }, + { raw: '}', type: 'separator', stack: [4] }, + { raw: ',', type: 'separator', stack: [] }, + { raw: '{', type: 'separator', stack: [5] }, + { raw: 'q', type: 'key', value: 'q', stack: [5] }, + { raw: ':', type: 'separator', stack: [5] }, + { raw: '{', type: 'separator', stack: [5,'q'] }, + { raw: 'q', type: 'key', value: 'q', stack: [5,'q'] }, + { raw: ':', type: 'separator', stack: [5,'q'] }, + { raw: '{', type: 'separator', stack: [5,'q','q'] }, + { raw: '}', type: 'separator', stack: [5,'q','q'] }, + { raw: '}', type: 'separator', stack: [5,'q'] }, + { raw: '}', type: 'separator', stack: [5] }, + { raw: ',', type: 'separator', stack: [] }, + { raw: ']', type: 'separator', stack: [] } ]) + diff --git a/node_modules/read-package-json/node_modules/json-parse-helpfulerror/node_modules/jju/test/test_updates.js b/node_modules/read-package-json/node_modules/json-parse-helpfulerror/node_modules/jju/test/test_updates.js new file mode 100644 index 000000000..b7482519a --- /dev/null +++ b/node_modules/read-package-json/node_modules/json-parse-helpfulerror/node_modules/jju/test/test_updates.js @@ -0,0 +1,22 @@ +var assert = require('assert') +var FS = require('fs') +var YAML = require('js-yaml') +var jju = require('../') + +function addTest(name, fn) { + if (typeof(describe) === 'function') { + it(name, fn) + } else { + fn() + } +} + +FS.readdirSync(__dirname + '/update').filter(function(file) { + return file.match(/^[^\.].*\.yaml$/) +}).forEach(function(file) { + addTest('update: ' + file, function() { + var test = YAML.load(FS.readFileSync(__dirname + '/update/' + file, 'utf8')) + assert.strictEqual(test.test(jju, test.input), test.output) + }) +}) + diff --git a/node_modules/read-package-json/node_modules/json-parse-helpfulerror/node_modules/jju/test/update/author.yaml b/node_modules/read-package-json/node_modules/json-parse-helpfulerror/node_modules/jju/test/update/author.yaml new file mode 100644 index 000000000..4b08bb61b --- /dev/null +++ b/node_modules/read-package-json/node_modules/json-parse-helpfulerror/node_modules/jju/test/update/author.yaml @@ -0,0 +1,31 @@ +input: | + { "name": "just-a-demo", + "version": "0.1.2", + "description": "blahblahblah", + "main": "test.js", + "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, + "author": "John Doe <whoever@google.com>", + "license": "BSD-2-Clause" } + +output: | + { "name": "just-a-demo", + "version": "0.1.2", + "description": "blahblahblah", + "main": "test.js", + "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, + "author": { + "name": "John Doe", + "email": "whoever@google.com" + }, + "license": "BSD-2-Clause" } + +test: !!js/function | + function(jju, input) { + obj = jju.parse(input) + obj.author = { + name: 'John Doe', + email: 'whoever@google.com', + } + return jju.update(input, obj) + } + diff --git a/node_modules/read-package-json/node_modules/json-parse-helpfulerror/node_modules/jju/test/update/deep-object.yaml b/node_modules/read-package-json/node_modules/json-parse-helpfulerror/node_modules/jju/test/update/deep-object.yaml new file mode 100644 index 000000000..e0795a378 --- /dev/null +++ b/node_modules/read-package-json/node_modules/json-parse-helpfulerror/node_modules/jju/test/update/deep-object.yaml @@ -0,0 +1,36 @@ +input: | + { + "foo": { + "bar": { + "baz": { + "quux": "4" + } + } + } + } + +output: | + { + "foo": { + "bar": { + "baz": { + "quux": "4" + }, + "qwe": { + "rty": { + "aaa": { + "bbb": 1 + } + } + } + } + } + } + +test: !!js/function | + function(jju, input) { + obj = jju.parse(input) + obj.foo.bar.qwe = {rty: {aaa: {bbb: 1}}} + return jju.update(input, obj, {mode:'json'}) + } + diff --git a/node_modules/read-package-json/node_modules/json-parse-helpfulerror/node_modules/jju/test/update/delete.yaml b/node_modules/read-package-json/node_modules/json-parse-helpfulerror/node_modules/jju/test/update/delete.yaml new file mode 100644 index 000000000..b964715d3 --- /dev/null +++ b/node_modules/read-package-json/node_modules/json-parse-helpfulerror/node_modules/jju/test/update/delete.yaml @@ -0,0 +1,36 @@ +input: | + { + "name": "test", + "version": "0.0.0", + "dependencies": { + "foo": "1.2.x", + "bar": ">= 1" + }, + "bundleDependencies": [ + "foo", + "bar" + ], + "license": "BSD-2-Clause" + } + +output: | + { + "name": "test", + "version": "0.0.0", + "dependencies": { + "foo": "1.2.x" + }, + "bundleDependencies": [ + "foo" + ], + "license": "BSD-2-Clause" + } + +test: !!js/function | + function(jju, input) { + obj = jju.parse(input) + obj.bundleDependencies.pop() + delete obj.dependencies.bar + return jju.update(input, obj, {mode:'json'}) + } + diff --git a/node_modules/read-package-json/node_modules/json-parse-helpfulerror/node_modules/jju/test/update/norm-array.yaml b/node_modules/read-package-json/node_modules/json-parse-helpfulerror/node_modules/jju/test/update/norm-array.yaml new file mode 100644 index 000000000..c5b9dd952 --- /dev/null +++ b/node_modules/read-package-json/node_modules/json-parse-helpfulerror/node_modules/jju/test/update/norm-array.yaml @@ -0,0 +1,32 @@ +input: | + { + "name": "test", + "version": "0.0.0", + "bundleDependencies": [ + "foo", + "bar" + ], + "license": "BSD-2-Clause" + } + +output: | + { + "name": "test", + "version": "0.0.0", + "bundleDependencies": [ + "foo", + "bar", + "baz", + "quux" + ], + "license": "BSD-2-Clause" + } + +test: !!js/function | + function(jju, input) { + obj = jju.parse(input) + obj.bundleDependencies.push('baz') + obj.bundleDependencies.push('quux') + return jju.update(input, obj, {mode:'json'}) + } + diff --git a/node_modules/read-package-json/node_modules/json-parse-helpfulerror/node_modules/jju/test/update/norm-object.yaml b/node_modules/read-package-json/node_modules/json-parse-helpfulerror/node_modules/jju/test/update/norm-object.yaml new file mode 100644 index 000000000..93878675b --- /dev/null +++ b/node_modules/read-package-json/node_modules/json-parse-helpfulerror/node_modules/jju/test/update/norm-object.yaml @@ -0,0 +1,32 @@ +input: | + { + "name": "test", + "version": "0.0.0", + "dependencies": { + "foobar": "*", + "bazquux": ">= 1.1.1" + }, + "license": "BSD-2-Clause" + } + +output: | + { + "name": "test", + "version": "0.0.0", + "dependencies": { + "foobar": "*", + "bazquux": ">= 1.1.1", + "whatever": "1.2.x", + "qwerty": "1" + }, + "license": "BSD-2-Clause" + } + +test: !!js/function | + function(jju, input) { + obj = jju.parse(input) + obj.dependencies.whatever = '1.2.x' + obj.dependencies.qwerty = '1' + return jju.update(input, obj, {mode:'json'}) + } + diff --git a/node_modules/read-package-json/node_modules/json-parse-helpfulerror/node_modules/jju/test/update/npm-array-bin.yaml b/node_modules/read-package-json/node_modules/json-parse-helpfulerror/node_modules/jju/test/update/npm-array-bin.yaml new file mode 100644 index 000000000..35e1639bf --- /dev/null +++ b/node_modules/read-package-json/node_modules/json-parse-helpfulerror/node_modules/jju/test/update/npm-array-bin.yaml @@ -0,0 +1,29 @@ +input: | + { "name":"npm-test-array-bin" + , "version":"1.2.5" + , "bin": [ "bin/array-bin" ] + , "scripts": { "test": "node test.js" } } + +# less than ideal, I know... +output: | + { "name":"npm-test-array-bin" + , "version":"1.2.5" + , "bin": {"array-bin":"bin/array-bin"} + , "scripts": { "test": "node test.js" }, "readme": "just an npm test\n", "readmeFilename": "README", "description": "just an npm test", "_id": "npm-test-array-bin@1.2.5", "dist": {"shasum":"9c426a1bd55e98718ab4ddcc01fa57ea83c649f1"}, "_from": "npm-test-array-bin/" } + +test: !!js/function | + function(jju, input) { + obj = + { name: 'npm-test-array-bin', + version: '1.2.5', + bin: { 'array-bin': 'bin/array-bin' }, + scripts: { test: 'node test.js' }, + readme: 'just an npm test\n', + readmeFilename: 'README', + description: 'just an npm test', + _id: 'npm-test-array-bin@1.2.5', + dist: { shasum: '9c426a1bd55e98718ab4ddcc01fa57ea83c649f1' }, + _from: 'npm-test-array-bin/' } + return jju.update(input, obj) + } + diff --git a/node_modules/read-package-json/node_modules/json-parse-helpfulerror/node_modules/jju/test/update/pkg-json5.yaml b/node_modules/read-package-json/node_modules/json-parse-helpfulerror/node_modules/jju/test/update/pkg-json5.yaml new file mode 100644 index 000000000..21a5c6eb1 --- /dev/null +++ b/node_modules/read-package-json/node_modules/json-parse-helpfulerror/node_modules/jju/test/update/pkg-json5.yaml @@ -0,0 +1,36 @@ +input: | + // vim:syntax=javascript + { + name: 'yapm', + version: '1.1.0-1325', // upstream npm@1.3.25 + description: 'A package manager for node (npm fork)', + } + +output: | + // vim:syntax=javascript + { + name: 'yapm', + version: '1.1.0-1325', // upstream npm@1.3.25 + description: 'A package manager for node (npm fork)', + _id: 'yapm@1.1.0-1325', + dist: { + shasum: 'd5aa31c1ad00c1e7e57e07cea1b22c1806a47111', + }, + _from: './zzz', + } + +test: !!js/function | + function(jju, input) { + var upd = { + "name": "yapm", + "version": "1.1.0-1325", + "description": "A package manager for node (npm fork)", + "_id": "yapm@1.1.0-1325", + "dist": { + "shasum": "d5aa31c1ad00c1e7e57e07cea1b22c1806a47111" + }, + "_from": "./zzz" + } + return jju.update(input, upd) + } + diff --git a/node_modules/read-package-json/node_modules/json-parse-helpfulerror/package.json b/node_modules/read-package-json/node_modules/json-parse-helpfulerror/package.json new file mode 100644 index 000000000..9ebc2ff8a --- /dev/null +++ b/node_modules/read-package-json/node_modules/json-parse-helpfulerror/package.json @@ -0,0 +1,61 @@ +{ + "name": "json-parse-helpfulerror", + "version": "1.0.3", + "description": "A drop-in replacement for JSON.parse that uses `jju` to give helpful errors", + "main": "index.js", + "scripts": { + "test": "lab -c", + "lint": "jslint --edition=latest --terse *.js" + }, + "repository": { + "type": "git", + "url": "https://github.com/smikes/json-parse-helpfulerror.git" + }, + "keywords": [ + "json", + "parse", + "line", + "doublequote", + "error" + ], + "author": { + "name": "Sam Mikes", + "email": "smikes@cubane.com" + }, + "license": "MIT", + "bugs": { + "url": "https://github.com/smikes/json-parse-helpfulerror/issues" + }, + "homepage": "https://github.com/smikes/json-parse-helpfulerror", + "devDependencies": { + "code": "^1.2.1", + "jslint": "^0.7.1", + "lab": "^5.1.1" + }, + "dependencies": { + "jju": "^1.1.0" + }, + "gitHead": "eedb116ec96b5c479be3919b526d6de0a521be5e", + "_id": "json-parse-helpfulerror@1.0.3", + "_shasum": "13f14ce02eed4e981297b64eb9e3b932e2dd13dc", + "_from": "json-parse-helpfulerror@>=1.0.2 <2.0.0", + "_npmVersion": "2.1.16", + "_nodeVersion": "0.10.35", + "_npmUser": { + "name": "smikes", + "email": "smikes@cubane.com" + }, + "maintainers": [ + { + "name": "smikes", + "email": "smikes@cubane.com" + } + ], + "dist": { + "shasum": "13f14ce02eed4e981297b64eb9e3b932e2dd13dc", + "tarball": "http://registry.npmjs.org/json-parse-helpfulerror/-/json-parse-helpfulerror-1.0.3.tgz" + }, + "directories": {}, + "_resolved": "https://registry.npmjs.org/json-parse-helpfulerror/-/json-parse-helpfulerror-1.0.3.tgz", + "readme": "ERROR: No README data found!" +} diff --git a/node_modules/read-package-json/node_modules/json-parse-helpfulerror/test/test.js b/node_modules/read-package-json/node_modules/json-parse-helpfulerror/test/test.js new file mode 100644 index 000000000..fca458ac0 --- /dev/null +++ b/node_modules/read-package-json/node_modules/json-parse-helpfulerror/test/test.js @@ -0,0 +1,32 @@ +var Code = require('code'), + Lab = require('lab'), + lab = Lab.script(), + jph = require('..'); // 'json-parse-helpfulerror' + +exports.lab = lab; + +lab.test('can parse', function (done) { + var o = jph.parse('{"foo": "bar"}'); + + Code.expect(o.foo).to.equal('bar'); + done(); +}); + +lab.test('helpful error for bad JSON', function (done) { + + var bad = "{'foo': 'bar'}"; + + Code.expect(function () { JSON.parse(bad) }).to.throw(); + + Code.expect(function () { jph.parse(bad) }).to.throw(SyntaxError, "Unexpected token '\\'' at 1:2\n" + bad + '\n ^'); + + done(); +}); + +lab.test('fails if reviver throws', function (done) { + function badReviver() { throw new ReferenceError('silly'); } + + Code.expect(function () { jph.parse('3', badReviver) }).to.throw(ReferenceError, 'silly'); + + done(); +});
\ No newline at end of file diff --git a/node_modules/read-package-json/package.json b/node_modules/read-package-json/package.json index 3c2ff0ff8..a61555cef 100644 --- a/node_modules/read-package-json/package.json +++ b/node_modules/read-package-json/package.json @@ -1,6 +1,6 @@ { "name": "read-package-json", - "version": "1.3.1", + "version": "1.3.2", "author": { "name": "Isaac Z. Schlueter", "email": "i@izs.me", @@ -19,45 +19,26 @@ "github-url-from-git": "^1.3.0", "github-url-from-username-repo": "~1.0.0", "glob": "^4.0.2", + "json-parse-helpfulerror": "^1.0.2", "lru-cache": "2", "normalize-package-data": "^1.0.0", "graceful-fs": "2 || 3" }, "devDependencies": { - "tap": "~0.2.5" + "tap": "^0.7.1" }, "optionalDependencies": { "graceful-fs": "2 || 3" }, "license": "ISC", - "gitHead": "59011e6b660cf0cc916646a08955c12a8f990174", + "readme": "# read-package-json\n\nThis is the thing that npm uses to read package.json files. It\nvalidates some stuff, and loads some default things.\n\nIt keeps a cache of the files you've read, so that you don't end\nup reading the same package.json file multiple times.\n\nNote that if you just want to see what's literally in the package.json\nfile, you can usually do `var data = require('some-module/package.json')`.\n\nThis module is basically only needed by npm, but it's handy to see what\nnpm will see when it looks at your package.\n\n## Usage\n\n```javascript\nvar readJson = require('read-package-json')\n\n// readJson(filename, [logFunction=noop], [strict=false], cb)\nreadJson('/path/to/package.json', console.error, false, function (er, data) {\n if (er) {\n console.error(\"There was an error reading the file\")\n return\n }\n\n console.error('the package data is', data)\n});\n```\n\n## readJson(file, [logFn = noop], [strict = false], cb)\n\n* `file` {String} The path to the package.json file\n* `logFn` {Function} Function to handle logging. Defaults to a noop.\n* `strict` {Boolean} True to enforce SemVer 2.0 version strings, and\n other strict requirements.\n* `cb` {Function} Gets called with `(er, data)`, as is The Node Way.\n\nReads the JSON file and does the things.\n\n## `package.json` Fields\n\nSee `man 5 package.json` or `npm help json`.\n\n## readJson.log\n\nBy default this is a reference to the `npmlog` module. But if that\nmodule can't be found, then it'll be set to just a dummy thing that does\nnothing.\n\nReplace with your own `{log,warn,error}` object for fun loggy time.\n\n## readJson.extras(file, data, cb)\n\nRun all the extra stuff relative to the file, with the parsed data.\n\nModifies the data as it does stuff. Calls the cb when it's done.\n\n## readJson.extraSet = [fn, fn, ...]\n\nArray of functions that are called by `extras`. Each one receives the\narguments `fn(file, data, cb)` and is expected to call `cb(er, data)`\nwhen done or when an error occurs.\n\nOrder is indeterminate, so each function should be completely\nindependent.\n\nMix and match!\n\n## readJson.cache\n\nThe `lru-cache` object that readJson uses to not read the same file over\nand over again. See\n[lru-cache](https://github.com/isaacs/node-lru-cache) for details.\n\n## Other Relevant Files Besides `package.json`\n\nSome other files have an effect on the resulting data object, in the\nfollowing ways:\n\n### `README?(.*)`\n\nIf there is a `README` or `README.*` file present, then npm will attach\na `readme` field to the data with the contents of this file.\n\nOwing to the fact that roughly 100% of existing node modules have\nMarkdown README files, it will generally be assumed to be Markdown,\nregardless of the extension. Please plan accordingly.\n\n### `server.js`\n\nIf there is a `server.js` file, and there is not already a\n`scripts.start` field, then `scripts.start` will be set to `node\nserver.js`.\n\n### `AUTHORS`\n\nIf there is not already a `contributors` field, then the `contributors`\nfield will be set to the contents of the `AUTHORS` file, split by lines,\nand parsed.\n\n### `bindings.gyp`\n\nIf a bindings.gyp file exists, and there is not already a\n`scripts.install` field, then the `scripts.install` field will be set to\n`node-gyp rebuild`.\n\n### `wscript`\n\nIf a wscript file exists, and there is not already a `scripts.install`\nfield, then the `scripts.install` field will be set to `node-waf clean ;\nnode-waf configure build`.\n\nNote that the `bindings.gyp` file supercedes this, since node-waf has\nbeen deprecated in favor of node-gyp.\n\n### `index.js`\n\nIf the json file does not exist, but there is a `index.js` file\npresent instead, and that file has a package comment, then it will try\nto parse the package comment, and use that as the data instead.\n\nA package comment looks like this:\n\n```javascript\n/**package\n * { \"name\": \"my-bare-module\"\n * , \"version\": \"1.2.3\"\n * , \"description\": \"etc....\" }\n **/\n\n// or...\n\n/**package\n{ \"name\": \"my-bare-module\"\n, \"version\": \"1.2.3\"\n, \"description\": \"etc....\" }\n**/\n```\n\nThe important thing is that it starts with `/**package`, and ends with\n`**/`. If the package.json file exists, then the index.js is not\nparsed.\n\n### `{directories.man}/*.[0-9]`\n\nIf there is not already a `man` field defined as an array of files or a\nsingle file, and\nthere is a `directories.man` field defined, then that directory will\nbe searched for manpages.\n\nAny valid manpages found in that directory will be assigned to the `man`\narray, and installed in the appropriate man directory at package install\ntime, when installed globally on a Unix system.\n\n### `{directories.bin}/*`\n\nIf there is not already a `bin` field defined as a string filename or a\nhash of `<name> : <filename>` pairs, then the `directories.bin`\ndirectory will be searched and all the files within it will be linked as\nexecutables at install time.\n\nWhen installing locally, npm links bins into `node_modules/.bin`, which\nis in the `PATH` environ when npm runs scripts. When\ninstalling globally, they are linked into `{prefix}/bin`, which is\npresumably in the `PATH` environment variable.\n", + "readmeFilename": "README.md", + "gitHead": "d307d827f1a4f13a3a8bc4d747bb854779ad35c8", "bugs": { "url": "https://github.com/isaacs/read-package-json/issues" }, "homepage": "https://github.com/isaacs/read-package-json", - "_id": "read-package-json@1.3.1", - "_shasum": "5a965f9fc34b25ffa5e0d93b1d0fc063af6d10b0", - "_from": "read-package-json@1.3.1", - "_npmVersion": "2.5.1", - "_nodeVersion": "0.12.0", - "_npmUser": { - "name": "othiym23", - "email": "ogd@aoaioxxysz.net" - }, - "maintainers": [ - { - "name": "isaacs", - "email": "i@izs.me" - }, - { - "name": "othiym23", - "email": "ogd@aoaioxxysz.net" - } - ], - "dist": { - "shasum": "5a965f9fc34b25ffa5e0d93b1d0fc063af6d10b0", - "tarball": "http://registry.npmjs.org/read-package-json/-/read-package-json-1.3.1.tgz" - }, - "directories": {}, - "_resolved": "https://registry.npmjs.org/read-package-json/-/read-package-json-1.3.1.tgz" + "_id": "read-package-json@1.3.2", + "_shasum": "5228bc7ad1f33ded75184ece48710036101affa2", + "_from": "read-package-json@>=1.3.2 <1.4.0" } diff --git a/node_modules/read-package-json/read-json.js b/node_modules/read-package-json/read-json.js index 863f8e8e3..98ab9f16d 100644 --- a/node_modules/read-package-json/read-json.js +++ b/node_modules/read-package-json/read-json.js @@ -14,6 +14,7 @@ readJson.cache = new LRU({max: 1000}) var path = require("path") var glob = require("glob") var normalizeData = require("normalize-package-data") +var jsonparse = require("json-parse-helpfulerror") // put more stuff on here to customize. readJson.extraSet = [ @@ -79,7 +80,7 @@ function parseJson (file, er, d, log, strict, cb) { } if (er) return cb(er); try { - d = JSON.parse(stripBOM(d)) + d = jsonparse.parse(stripBOM(d)) } catch (er) { d = parseIndex(d) if (!d) return cb(parseError(er, file)); @@ -395,7 +396,7 @@ function parseIndex (data) { data = data[0] data = data.replace(/^\s*\*/mg, "") try { - return JSON.parse(data) + return jsonparse.parse(data) } catch (er) { return null } diff --git a/node_modules/read-package-json/test/fixtures/emptybin.json b/node_modules/read-package-json/test/fixtures/emptybin.json index ef926f04d..5e12ed4e9 100644 --- a/node_modules/read-package-json/test/fixtures/emptybin.json +++ b/node_modules/read-package-json/test/fixtures/emptybin.json @@ -1,5 +1,5 @@ { - "name": "badbin-test", + "name": "emptybin-test", "description": "my desc", "repository": { "type": "git", diff --git a/node_modules/read-package-json/test/fixtures/erroneous.json b/node_modules/read-package-json/test/fixtures/erroneous.json new file mode 100644 index 000000000..212e37ec8 --- /dev/null +++ b/node_modules/read-package-json/test/fixtures/erroneous.json @@ -0,0 +1,4 @@ +{ + 'wrong': 'kind', + 'of': 'quotes' +} diff --git a/node_modules/read-package-json/test/helpful.js b/node_modules/read-package-json/test/helpful.js new file mode 100644 index 000000000..579b558d0 --- /dev/null +++ b/node_modules/read-package-json/test/helpful.js @@ -0,0 +1,17 @@ +// vim: set softtabstop=16 shiftwidth=16: +var tap = require("tap") +var readJson = require("../") +var path = require("path") +var fs = require("fs") +var p = path.resolve(__dirname, "fixtures/erroneous.json") + +var expect = {} + +console.error("readme test") +tap.test("readme test", function (t) { + readJson(p, function (er, data) { + t.ok(er instanceof Error) + t.ok(er.message.match(/Unexpected token '\\''/)) + t.end() + }) +}) |