Comparing version 0.1.0 to 0.1.1
334
lib/hjson.js
/* | ||
hjson.js | ||
Adopted for HJSON from the JSON version: https://github.com/douglascrockford/JSON-js/blob/master/json_parse.js | ||
Public Domain. | ||
@@ -10,8 +8,69 @@ | ||
This file creates a hjson_parse function. | ||
This file creates a hjson_parse and a hjson_stringify function. | ||
json_parse(text) | ||
hjson_parse(text) | ||
This method parses HJSON text to produce an object or array. | ||
It can throw a SyntaxError exception. | ||
Code was adopted from the JSON version by Douglas Crockford: | ||
https://github.com/douglascrockford/JSON-js/blob/master/json_parse.js | ||
hjson_stringify(value, replacer, space) | ||
value any JavaScript value, usually an object or array. | ||
replacer an optional parameter that determines how object | ||
values are stringified for objects. It can be a | ||
function or an array of strings. | ||
space an optional parameter that specifies the indentation | ||
of nested structures. If it is omitted, the text will | ||
be packed without extra whitespace. If it is a number, | ||
it will specify the number of spaces to indent at each | ||
level. If it is a string (such as '\t' or ' '), | ||
it contains the characters used to indent at each level. | ||
This method produces a HJSON text from a JavaScript value. | ||
You can provide an optional replacer method. It will be passed the | ||
key and value of each member, with this bound to the containing | ||
object. The value that is returned from your method will be | ||
serialized. If your method returns undefined, then the member will | ||
be excluded from the serialization. | ||
If the replacer parameter is an array of strings, then it will be | ||
used to select the members to be serialized. It filters the results | ||
such that only members with keys listed in the replacer array are | ||
stringified. | ||
Values that do not have JSON representations, such as undefined or | ||
functions, will not be serialized. Such values in objects will be | ||
dropped; in arrays they will be replaced with null. You can use | ||
a replacer function to replace those with JSON values. | ||
JSON.stringify(undefined) returns undefined. | ||
The optional space parameter produces a stringification of the | ||
value that is filled with line breaks and indentation to make it | ||
easier to read. | ||
If the space parameter is a non-empty string, then that string will | ||
be used for indentation. If the space parameter is a number, then | ||
the indentation will be that many spaces. | ||
Example: | ||
text = JSON.stringify(['e', {pluribus: 'unum'}]); | ||
// text is '["e",{"pluribus":"unum"}]' | ||
text = JSON.stringify(['e', {pluribus: 'unum'}], null, '\t'); | ||
// text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]' | ||
Code was adopted from the JSON version by Douglas Crockford: | ||
https://github.com/douglascrockford/JSON-js/blob/master/json2.js | ||
This is a reference implementation. You are free to copy, modify, or | ||
@@ -35,2 +94,3 @@ redistribute. | ||
var text; | ||
var at; // The index of the current character | ||
@@ -50,14 +110,6 @@ var ch; // The current character | ||
var text; | ||
var error = function (m) | ||
{ | ||
// Call error when something is wrong. | ||
throw ( | ||
{ | ||
name: 'SyntaxError', | ||
message: m, | ||
at: at, | ||
text: text | ||
}); | ||
throw new SyntaxError(m + " at pos " + (at-1) + " >>>" + text.substr(at-1, 20) + "<<<"); | ||
}; | ||
@@ -173,3 +225,3 @@ | ||
name += ch; | ||
else error("Bad name; "+ch); | ||
else error("Bad name"); | ||
} | ||
@@ -317,6 +369,258 @@ error("Bad name"); | ||
var hjson_stringify = (function () | ||
{ | ||
"use strict"; | ||
var escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g; | ||
var meta = | ||
{ // table of character substitutions | ||
'\b': '\\b', | ||
'\t': '\\t', | ||
'\n': '\\n', | ||
'\f': '\\f', | ||
'\r': '\\r', | ||
'"' : '\\"', | ||
'\\': '\\\\' | ||
}; | ||
var escapableName = /[^a-zA-Z0-9]/; | ||
var gap = ''; | ||
var indent = ' '; | ||
var rep; | ||
function isWhite(c) { return c <= ' '; } | ||
function isDigit(c) { return c >= '0' && c <= '9'; } | ||
function isKeyword(value) { return value == 'true' || value == 'false' || value == 'null'; } | ||
function quoteReplace(string) | ||
{ | ||
return string.replace(escapable, function (a) | ||
{ | ||
var c = meta[a]; | ||
return typeof c === 'string' | ||
? c | ||
: '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4); | ||
}); | ||
} | ||
function quote(string) | ||
{ | ||
if (!string) return '""'; | ||
escapable.lastIndex = 0; | ||
var isEscapable = escapable.test(string); | ||
// Check if we can insert this string without quotes | ||
var first = string[0], last = string[string.length-1]; | ||
if (isEscapable || | ||
isWhite(first) || | ||
isDigit(first) || | ||
first === '#' || | ||
first === '-' || | ||
first === '{' || | ||
first === '[' || | ||
isWhite(last) || | ||
isKeyword(string)) | ||
{ | ||
// If the string contains no control characters, no quote characters, and no | ||
// backslash characters, then we can safely slap some quotes around it. | ||
// Otherwise we must also replace the offending characters with safe escape | ||
// sequences. | ||
return '"' + (isEscapable ? quoteReplace(string) : string) + '"'; | ||
} | ||
else | ||
{ | ||
// return without quotes | ||
return string; | ||
} | ||
} | ||
function quoteName(name) | ||
{ | ||
if (!name) return '""'; | ||
// Check if we can insert this name without quotes | ||
if (escapableName.test(name)) | ||
{ | ||
escapable.lastIndex = 0; | ||
var isEscapable = escapable.test(name); | ||
return '"' + (isEscapable ? quoteReplace(name) : name) + '"'; | ||
} | ||
else | ||
{ | ||
// return without quotes | ||
return name; | ||
} | ||
} | ||
function str(key, holder) | ||
{ | ||
// Produce a string from holder[key]. | ||
var i, // The loop counter. | ||
k, // The member key. | ||
v, // The member value. | ||
length, | ||
mind = gap, | ||
partial, | ||
value = holder[key]; | ||
// If we were called with a replacer function, then call the replacer to | ||
// obtain a replacement value. | ||
if (typeof rep === 'function') | ||
{ | ||
value = rep.call(holder, key, value); | ||
} | ||
// What happens next depends on the value's type. | ||
switch (typeof value) | ||
{ | ||
case 'string': | ||
return quote(value); | ||
case 'number': | ||
// JSON numbers must be finite. Encode non-finite numbers as null. | ||
return isFinite(value) ? String(value) : 'null'; | ||
case 'boolean': | ||
case 'null': | ||
// If the value is a boolean or null, convert it to a string. Note: | ||
// typeof null does not produce 'null'. The case is included here in | ||
// the remote chance that this gets fixed someday. | ||
return String(value); | ||
case 'object': | ||
// If the type is 'object', we might be dealing with an object or an array or | ||
// null. | ||
// Due to a specification blunder in ECMAScript, typeof null is 'object', | ||
// so watch out for that case. | ||
if (!value) return 'null'; | ||
// Make an array to hold the partial results of stringifying this object value. | ||
gap += indent; | ||
partial = []; | ||
// Is the value an array? | ||
if (Object.prototype.toString.apply(value) === '[object Array]') | ||
{ | ||
// The value is an array. Stringify every element. Use null as a placeholder | ||
// for non-JSON values. | ||
length = value.length; | ||
for (i = 0; i < length; i += 1) | ||
{ | ||
partial[i] = str(i, value) || 'null'; | ||
} | ||
// Join all of the elements together, separated with newline, and wrap them in | ||
// brackets. | ||
v = partial.length === 0 | ||
? '[]' | ||
: '[\n' + gap + partial.join('\n' + gap) + '\n' + mind + ']'; | ||
gap = mind; | ||
return v; | ||
} | ||
// If the replacer is an array, use it to select the members to be stringified. | ||
if (rep && typeof rep === 'object') | ||
{ | ||
length = rep.length; | ||
for (i = 0; i < length; i += 1) | ||
{ | ||
if (typeof rep[i] === 'string') | ||
{ | ||
k = rep[i]; | ||
v = str(k, value); | ||
if (v) | ||
{ | ||
partial.push(quoteName(k) + (gap ? ': ' : ':') + v); | ||
} | ||
} | ||
} | ||
} | ||
else | ||
{ | ||
// Otherwise, iterate through all of the keys in the object. | ||
for (k in value) | ||
{ | ||
if (Object.prototype.hasOwnProperty.call(value, k)) | ||
{ | ||
v = str(k, value); | ||
if (v) | ||
{ | ||
partial.push(quoteName(k) + (gap ? ': ' : ':') + v); | ||
} | ||
} | ||
} | ||
} | ||
// Join all of the member texts together, separated with newlines, | ||
// and wrap them in braces. | ||
v = partial.length === 0 | ||
? '{}' | ||
: '{\n' + gap + partial.join('\n' + gap) + '\n' + mind + '}'; | ||
gap = mind; | ||
return v; | ||
} | ||
} | ||
// Return the hjson_stringify function. It will have access to all of the above | ||
// functions and variables. | ||
return function (value, replacer, space) | ||
{ | ||
// The stringify method takes a value and an optional replacer, and an optional | ||
// space parameter, and returns a HJSON text. The replacer can be a function | ||
// that can replace values, or an array of strings that will select the keys. | ||
// A default replacer method can be provided. Use of the space parameter can | ||
// produce text that is more easily readable. | ||
var i; | ||
// If the space parameter is a number, make an indent string containing that | ||
// many spaces. If it is a string, it will be used as the indent string. | ||
if (typeof space === 'number') | ||
{ | ||
indent = ''; | ||
for (i = 0; i < space; i += 1) indent += ' '; | ||
} | ||
else if (typeof space === 'string') | ||
indent = space; | ||
// If there is a replacer, it must be a function or an array. | ||
// Otherwise, throw an error. | ||
rep = replacer; | ||
if (replacer && typeof replacer !== 'function' && | ||
(typeof replacer !== 'object' || | ||
typeof replacer.length !== 'number')) | ||
{ | ||
throw new Error('hjson_stringify'); | ||
} | ||
// Make a fake root object containing our value under the key of ''. | ||
// Return the result of stringifying the value. | ||
return str('', { '': value }); | ||
}; | ||
}()); | ||
// node.js | ||
module.exports= | ||
{ | ||
parse: hjson_parse | ||
parse: hjson_parse, | ||
stringify: hjson_stringify | ||
}; |
@@ -6,3 +6,3 @@ { | ||
"author": "Christian Zangl", | ||
"version": "0.1.0", | ||
"version": "0.1.1", | ||
"tags": [ | ||
@@ -16,2 +16,5 @@ "json", | ||
], | ||
"bin": { | ||
"hjson": "./bin/hjson" | ||
}, | ||
"homepage": "http://laktak.github.io/hjson", | ||
@@ -18,0 +21,0 @@ "repository": |
@@ -38,4 +38,24 @@ # hjson-js | ||
var obj = HJSON.parse(text); | ||
var obj = HJSON.parse(hjsonText); | ||
var text2 = HJSON.stringify(obj); | ||
``` | ||
## From the Commandline | ||
Install with `npm install hjson -g`. | ||
``` | ||
usage: hjson [-json] [INPUT] | ||
hjson can be used to convert JSON from/to HJSON. | ||
hjson will read the given JSON/HJSON input file or read from stdin. | ||
- without options: will output as HJSON. | ||
- with -json: will output as formatted JSON. | ||
- with -json=compact: will output as JSON. | ||
``` | ||
Sample: | ||
- run `hjson test.json > test.hjson` to convert to HJSON | ||
- run `hjson -json test.hjson > test.json` to convert to JSON |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
6
518
61
20081