Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

hjson

Package Overview
Dependencies
Maintainers
1
Versions
54
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

hjson - npm Package Compare versions

Comparing version 1.3.0 to 1.4.0

test/assets/comments_result.hjson

1025

lib/hjson.js

@@ -8,6 +8,6 @@ /*

This file creates a hjson_parse and a hjson_stringify function.
This file creates a Hjson object:
hjson_parse(text, options)
Hjson.parse(text, options)

@@ -27,3 +27,3 @@ options {

hjson_stringify(value, options)
Hjson.stringify(value, options)
obsolete: hjson_stringify(value, replacer, space)

@@ -56,83 +56,51 @@

This is a reference implementation. You are free to copy, modify, or
redistribute.
Hjson.endOfLine()
Hjson.setEndOfLine(eol)
This code should be minified before deployment.
*/
Gets or sets the EOL character ('\n' or '\r\n').
var hjson_EOL = '\n';
var hjson_bracesSameLine = false;
var hjson_parse = (function () {
"use strict";
Hjson.bracesSameLine()
Hjson.setBracesSameLine(b)
// This is a function that can parse a Hjson text, producing a JavaScript
// data structure. It is a simple, recursive descent parser. It does not use
// eval or regular expressions, so it can be used as a model for implementing
// a JSON parser in other languages.
Gets or sets if braces should appear on the same line (for stringify).
// We are defining the function inside of another function to avoid creating
// global variables.
var text;
var at; // The index of the current character
var ch; // The current character
var escapee = {
'"': '"',
'\\': '\\',
'/': '/',
b: '\b',
f: '\f',
n: '\n',
r: '\r',
t: '\t'
};
var keepWsc; // keep whitespace
This is a reference implementation. You are free to copy, modify, or
redistribute.
// Call error when something is wrong.
var error = function (m) {
var i, col=0, line=1;
for (i = at-1; i > 0 && text[i] !== '\n'; i--, col++) {}
for (; i > 0; i--) if (text[i] === '\n') line++;
throw new Error(m + " at line " + line + "," + col + " >>>" + text.substr(at-col, 20) + " ...");
};
This code should be minified before deployment.
*/
var next = function (c) {
// If a c parameter is provided, verify that it matches the current character.
var Hjson = (function () {
if (c && c !== ch)
error("Expected '" + c + "' instead of '" + ch + "'");
var EOL = '\n';
var bracesSameLine = false;
// Get the next character. When there are no more characters,
// return the empty string.
ch = text.charAt(at);
at++;
return ch;
};
var peek = function (offs) {
// range check is not required
return text.charAt(at + offs);
}
var move = function (pos) {
at = pos - 1;
return next();
};
var number = function () {
var tryParseNumber = function (text) {
// Parse a number value.
var number, string = '';
var pos = at;
var number, string = '', leadingZeros = 0, testLeading = true;
var at = 0;
var ch;
function next() {
ch = text.charAt(at);
at++;
return ch;
}
next();
if (ch === '-') {
string = '-';
next('-');
next();
}
while (ch >= '0' && ch <= '9') {
if (testLeading) {
if (ch == '0') leadingZeros++;
else testLeading = false;
}
string += ch;
next();
}
if (testLeading) leadingZeros--; // single 0 is allowed
if (ch === '.') {

@@ -157,10 +125,7 @@ string += '.';

// skip white/to (newline)
while (ch && ch <= ' ' && ch !== '\n') next();
while (ch && ch <= ' ') next();
if (ch === '\n' || ch === ',' || ch === '}' || ch ===']') number = +string;
if (!isFinite(number)) {
// treat as a string
move(pos);
return wordOrString();
number = +string;
if (ch || leadingZeros || !isFinite(number)) {
return undefined;
}

@@ -170,530 +135,600 @@ else return number;

var string = function () {
// Parse a string value.
var hex, i, string = '', uffff;
var hjson_parse = (function () {
"use strict";
// When parsing for string values, we must look for " and \ characters.
if (ch === '"') {
while (next()) {
if (ch === '"') {
next();
return string;
}
if (ch === '\\') {
next();
if (ch === 'u') {
uffff = 0;
for (i = 0; i < 4; i++) {
hex = parseInt(next(), 16);
if (!isFinite(hex))
break;
uffff = uffff * 16 + hex;
// This is a function that can parse a Hjson text, producing a JavaScript
// data structure. It is a simple, recursive descent parser. It does not use
// eval or regular expressions, so it can be used as a model for implementing
// a JSON parser in other languages.
// We are defining the function inside of another function to avoid creating
// global variables.
var text;
var at; // The index of the current character
var ch; // The current character
var escapee = {
'"': '"',
'\\': '\\',
'/': '/',
b: '\b',
f: '\f',
n: '\n',
r: '\r',
t: '\t'
};
var keepWsc; // keep whitespace
// Call error when something is wrong.
var error = function (m) {
var i, col=0, line=1;
for (i = at-1; i > 0 && text[i] !== '\n'; i--, col++) {}
for (; i > 0; i--) if (text[i] === '\n') line++;
throw new Error(m + " at line " + line + "," + col + " >>>" + text.substr(at-col, 20) + " ...");
};
var next = function (c) {
// If a c parameter is provided, verify that it matches the current character.
if (c && c !== ch)
error("Expected '" + c + "' instead of '" + ch + "'");
// Get the next character. When there are no more characters,
// return the empty string.
ch = text.charAt(at);
at++;
return ch;
};
var peek = function (offs) {
// range check is not required
return text.charAt(at + offs);
}
var string = function () {
// Parse a string value.
var hex, i, string = '', uffff;
// When parsing for string values, we must look for " and \ characters.
if (ch === '"') {
while (next()) {
if (ch === '"') {
next();
return string;
}
if (ch === '\\') {
next();
if (ch === 'u') {
uffff = 0;
for (i = 0; i < 4; i++) {
hex = parseInt(next(), 16);
if (!isFinite(hex))
break;
uffff = uffff * 16 + hex;
}
string += String.fromCharCode(uffff);
}
string += String.fromCharCode(uffff);
else if (typeof escapee[ch] === 'string') string += escapee[ch];
else break;
}
else if (typeof escapee[ch] === 'string') string += escapee[ch];
else break;
else string += ch;
}
else string += ch;
}
}
error("Bad string");
};
error("Bad string");
};
var mlString = function () {
// Parse a multiline string value.
var string = '', triple = 0;
var mlString = function () {
// Parse a multiline string value.
var string = '', triple = 0;
// we are at ''' +1 - get indent
var indent = 0;
while (true) {
var c=peek(-indent-5);
if (!c || c=='\n') break;
indent++;
}
// we are at ''' +1 - get indent
var indent = 0;
while (true) {
var c=peek(-indent-5);
if (!c || c=='\n') break;
indent++;
}
var skipIndent = function () {
var skip = indent;
while (ch && ch <= ' ' && ch !== '\n' && skip-- > 0) next();
}
var skipIndent = function () {
var skip = indent;
while (ch && ch <= ' ' && ch !== '\n' && skip-- > 0) next();
}
// skip white/to (newline)
while (ch && ch <= ' ' && ch !== '\n') next();
if (ch === '\n') { next(); skipIndent(); }
// skip white/to (newline)
while (ch && ch <= ' ' && ch !== '\n') next();
if (ch === '\n') { next(); skipIndent(); }
// When parsing multiline string values, we must look for ' characters.
while (true) {
if (!ch) error("Bad multiline string");
else if (ch === '\'') {
triple++;
next();
if (triple === 3) return string;
else continue;
// When parsing multiline string values, we must look for ' characters.
while (true) {
if (!ch) error("Bad multiline string");
else if (ch === '\'') {
triple++;
next();
if (triple === 3) return string;
else continue;
}
else while (triple > 0) {
string += '\'';
triple--;
}
if (ch === '\n') {
string += ch;
next();
skipIndent();
}
else {
string += ch;
next();
}
}
else while (triple > 0) {
string += '\'';
triple--;
}
if (ch === '\n') {
string += ch;
next();
skipIndent();
}
else {
string += ch;
next();
}
}
};
};
var keyname = function () {
// quotes for keys that consist only of letters and digits are optional in Hjson
var keyname = function () {
// quotes for keys that consist only of letters and digits are optional in Hjson
if (ch === '"') return string();
if (ch === '"') return string();
var name = ch;
while (next()) {
if (ch === ':') return name;
else if (ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z' || ch >= '0' && ch <= '9')
name += ch;
else error("Bad name");
}
error("Bad name");
};
var name = ch;
while (next()) {
if (ch === ':') return name;
else if (ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z' || ch >= '0' && ch <= '9')
name += ch;
else error("Bad name");
}
error("Bad name");
};
var white = function () {
while (ch) {
// Skip whitespace.
while (ch && ch <= ' ') next();
// Hjson allows comments
if (ch === "#" || ch === "/" && peek(0) === "/") {
while (ch && ch !== '\n') next();
var white = function () {
while (ch) {
// Skip whitespace.
while (ch && ch <= ' ') next();
// Hjson allows comments
if (ch === '#' || ch === '/' && peek(0) === '/') {
while (ch && ch !== '\n') next();
}
else if (ch === '/' && peek(0) === '*')
{
next(); next();
while (ch && !(ch === '*' && peek(0) === '/')) next();
if (ch) { next(); next(); }
}
else break;
}
else if (ch === "/" && peek(0) === "*")
{
next(); next();
while (ch && !(ch === '*' && peek(0) === "/")) next();
if (ch) { next(); next(); }
}
else break;
}
};
};
var wordOrString = function () {
// Hjson strings can be quoteless
// returns string, true, false, or null.
var value = ch;
while (next()) {
if (value.length === 3 && value === "'''") return mlString();
if (ch === '\r' || ch === '\n' || ch === ',' || ch === '}' || ch ===']') {
switch (value[0]) {
case 'f': if (value.trim() === "false") return false; break;
case 'n': if (value.trim() === "null") return null; break;
case 't': if (value.trim() === "true") return true; break;
var tfnns = function () {
// Hjson strings can be quoteless
// returns string, true, false, or null.
var value = ch;
while (next()) {
if (value.length === 3 && value === "'''") return mlString();
var isEol=ch === '\r' || ch === '\n';
if (isEol || ch === ',' ||
ch === '}' || ch === ']' ||
ch === '#' ||
ch === '/' && (peek(0) === '/' || peek(0) === '*')
) {
var chf = value[0];
switch (chf) {
case 'f': if (value.trim() === "false") return false; break;
case 'n': if (value.trim() === "null") return null; break;
case 't': if (value.trim() === "true") return true; break;
default:
if (chf === '-' || chf >= '0' && chf <= '9') {
var n = tryParseNumber(value);
if (n !== undefined) return n;
}
}
if (isEol) return value;
}
if (ch === '\r' || ch === '\n') return value;
value += ch;
}
value += ch;
}
error("Bad value");
};
error("Bad value");
};
var getComment = function (wat) {
wat--;
// remove trailing whitespace
for (var i=at-2; i > wat && text[i] <= ' ' && text[i] !== '\n'; i--);
// but only up to EOL
if (text[i] === '\n') i--;
if (text[i] === '\r') i--;
var res = text.substr(wat, i-wat+1);
for (var i=0; i < res.length; i++)
if (res[i] > ' ') return res;
return "";
}
var getComment = function (wat) {
wat--;
// remove trailing whitespace
for (var i=at-2; i > wat && text[i] <= ' ' && text[i] !== '\n'; i--);
// but only up to EOL
if (text[i] === '\n') i--;
if (text[i] === '\r') i--;
var res = text.substr(wat, i-wat+1);
for (var i=0; i < res.length; i++)
if (res[i] > ' ') return res;
return "";
}
var array = function () {
// Parse an array value.
var array = function () {
// Parse an array value.
var array = [];
var kw, wat;
if (keepWsc) {
if (Object.defineProperty) Object.defineProperty(array, "__WSC__", { enumerable: false, writable: true });
array.__WSC__ = kw = [];
}
var array = [];
var kw, wat;
if (keepWsc) {
if (Object.defineProperty) Object.defineProperty(array, "__WSC__", { enumerable: false, writable: true });
array.__WSC__ = kw = [];
}
if (ch === '[') {
next('[');
wat = at;
white();
if (kw) kw.push(getComment(wat));
if (ch === ']') {
next(']');
return array; // empty array
}
while (ch) {
array.push(value());
if (ch === '[') {
next();
wat = at;
white();
// in Hjson the comma is optional and trailing commas are allowed
if (ch === ',') { next(); wat = at; white(); }
if (kw) kw.push(getComment(wat));
if (ch === ']') {
next(']');
return array;
next();
return array; // empty array
}
white();
while (ch) {
array.push(value());
wat = at;
white();
// in Hjson the comma is optional and trailing commas are allowed
if (ch === ',') { next(); wat = at; white(); }
if (kw) kw.push(getComment(wat));
if (ch === ']') {
next();
return array;
}
white();
}
}
}
error("Bad array");
};
error("Bad array");
};
var object = function () {
// Parse an object value.
var object = function () {
// Parse an object value.
var key, object = {};
var kw, wat;
if (keepWsc) {
if (Object.defineProperty) Object.defineProperty(object, "__WSC__", { enumerable: false, writable: true });
object.__WSC__ = kw = { c: {}, o: [] };
}
var key, object = {};
var kw, wat;
if (keepWsc) {
if (Object.defineProperty) Object.defineProperty(object, "__WSC__", { enumerable: false, writable: true });
object.__WSC__ = kw = { c: {}, o: [] };
}
function pushWhite(key) { kw.c[key]=getComment(wat); if (key) kw.o.push(key); }
function pushWhite(key) { kw.c[key]=getComment(wat); if (key) kw.o.push(key); }
if (ch === '{') {
next('{');
wat = at;
white();
if (kw) pushWhite("");
if (ch === '}') {
next('}');
return object; // empty object
}
while (ch) {
key = keyname();
white();
next(':');
// duplicate keys overwrite the previous value
object[key] = value();
if (ch === '{') {
next();
wat = at;
white();
// in Hjson the comma is optional and trailing commas are allowed
if (ch === ',') { next(); wat = at; white(); }
if (kw) pushWhite(key);
if (kw) pushWhite("");
if (ch === '}') {
next('}');
return object;
next();
return object; // empty object
}
white();
while (ch) {
key = keyname();
white();
next(':');
// duplicate keys overwrite the previous value
object[key] = value();
wat = at;
white();
// in Hjson the comma is optional and trailing commas are allowed
if (ch === ',') { next(); wat = at; white(); }
if (kw) pushWhite(key);
if (ch === '}') {
next();
return object;
}
white();
}
}
}
error("Bad object");
};
error("Bad object");
};
var value = function () {
// Parse a Hjson value. It could be an object, an array, a string, a number or a word.
var value = function () {
// Parse a Hjson value. It could be an object, an array, a string, a number or a word.
white();
switch (ch) {
case '{': return object();
case '[': return array();
case '"': return string();
case '-': return number();
default: return ch >= '0' && ch <= '9' ? number() : wordOrString();
}
};
white();
switch (ch) {
case '{': return object();
case '[': return array();
case '"': return string();
default: return tfnns();
}
};
// Return the hjson_parse function. It will have access to all of the above
// functions and variables.
// Return the hjson_parse function. It will have access to all of the above
// functions and variables.
return function (source, options) {
var result;
return function (source, options) {
var result;
keepWsc = options && options.keepWsc;
text = source;
at = 0;
ch = ' ';
result = value();
white();
if (ch) error("Syntax error");
keepWsc = options && options.keepWsc;
text = source;
at = 0;
ch = ' ';
result = value();
white();
if (ch) error("Syntax error");
return result;
};
}());
return result;
};
}());
var hjson_stringify = (function () {
"use strict";
var hjson_stringify = (function () {
"use strict";
var needsEscape = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;
var needsQuotes = /[\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g; // like needsEscape but without \\ and \"
var needsEscapeML = /'''|[\x00-\x09\x0b\x0c\x0e-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g; // ''' || (needsQuotes but without \n and \r)
var meta =
{ // table of character substitutions
'\b': '\\b',
'\t': '\\t',
'\n': '\\n',
'\f': '\\f',
'\r': '\\r',
'"' : '\\"',
'\\': '\\\\'
};
var needsEscapeName = /[^a-zA-Z0-9]/;
var gap = '';
var indent = ' ';
var keepWsc;
var needsEscape = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;
var needsQuotes = /[\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g; // like needsEscape but without \\ and \"
var needsEscapeML = /'''|[\x00-\x09\x0b\x0c\x0e-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g; // ''' || (needsQuotes but without \n and \r)
var meta =
{ // table of character substitutions
'\b': '\\b',
'\t': '\\t',
'\n': '\\n',
'\f': '\\f',
'\r': '\\r',
'"' : '\\"',
'\\': '\\\\'
};
var needsEscapeName = /[^a-zA-Z0-9]/;
var gap = '';
var indent = ' ';
var keepWsc;
function isWhite(c) { return c <= ' '; }
function isDigit(c) { return c >= '0' && c <= '9'; }
function isKeyword(value) { return value == 'true' || value == 'false' || value == 'null'; }
function isWhite(c) { return c <= ' '; }
function isKeyword(value) { return value == 'true' || value == 'false' || value == 'null'; }
function quoteReplace(string) {
return string.replace(needsEscape, function (a) {
var c = meta[a];
return typeof c === 'string'
? c
: '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
});
}
function quoteReplace(string) {
return string.replace(needsEscape, function (a) {
var c = meta[a];
return typeof c === 'string'
? c
: '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
});
}
function quote(string, gap, hasComment) {
if (!string) return '""';
function quote(string, gap, hasComment) {
if (!string) return '""';
needsQuotes.lastIndex = 0;
var doEscape = hasComment || needsQuotes.test(string);
needsQuotes.lastIndex = 0;
var doEscape = hasComment || needsQuotes.test(string);
// Check if we can insert this string without quotes
// Check if we can insert this string without quotes
// see hjson syntax (must not parse as true, false, null or number)
var first = string[0], last = string[string.length-1];
if (doEscape ||
isWhite(first) ||
isDigit(first) ||
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 first check if the string can be expressed in multiline
// format or we must replace the offending characters with safe escape
// sequences.
var first = string[0], last = string[string.length-1];
if (doEscape ||
isWhite(first) ||
first === '"' ||
first === '#' ||
first === '/' && (string[1] === '*' || string[1] === '/') ||
first === '{' ||
first === '[' ||
isWhite(last) ||
tryParseNumber(string) !== undefined ||
isKeyword(string)) {
needsEscape.lastIndex = 0;
needsEscapeML.lastIndex = 0;
if (!needsEscape.test(string)) return '"' + string + '"';
else if (!needsEscapeML.test(string)) return mlString(string, gap);
else return '"' + quoteReplace(string) + '"';
}
else {
// return without quotes
return 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 first check if the string can be expressed in multiline
// format or we must replace the offending characters with safe escape
// sequences.
function mlString(string, gap) {
// wrap the string into the ''' (multiline) format
var i, a = string.replace(/\r/g, "").split('\n');
gap += indent;
var res;
if (a.length === 1) {
// The string contains only a single line. We still use the multiline
// format as it avoids escaping the \ character (e.g. when used in a
// regex).
res = "'''" + a[0];
needsEscape.lastIndex = 0;
needsEscapeML.lastIndex = 0;
if (!needsEscape.test(string)) return '"' + string + '"';
else if (!needsEscapeML.test(string)) return mlString(string, gap);
else return '"' + quoteReplace(string) + '"';
}
else {
// return without quotes
return string;
}
}
else {
res = hjson_EOL + gap + "'''";
for (i = 0; i < a.length; i++)
res += hjson_EOL + gap + a[i];
}
return res + "'''";
}
function mlString(string, gap) {
// wrap the string into the ''' (multiline) format
function quoteName(name) {
if (!name) return '""';
var i, a = string.replace(/\r/g, "").split('\n');
gap += indent;
// Check if we can insert this name without quotes
var res;
if (a.length === 1) {
// The string contains only a single line. We still use the multiline
// format as it avoids escaping the \ character (e.g. when used in a
// regex).
res = "'''" + a[0];
}
else {
res = EOL + gap + "'''";
for (i = 0; i < a.length; i++)
res += EOL + gap + a[i];
}
if (needsEscapeName.test(name)) {
needsEscape.lastIndex = 0;
return '"' + (needsEscape.test(name) ? quoteReplace(name) : name) + '"';
return res + "'''";
}
else {
// return without quotes
return name;
}
}
function str(value, hasComment, rootObject) {
// Produce a string from value.
function quoteName(name) {
if (!name) return '""';
function startsWithNL(str) { return str && str[str[0] === '\r' ? 1 : 0] === '\n'; }
function testWsc(str) { return str && !startsWithNL(str); }
function wsc(str) {
if (!str) return "";
for (var i = 0; i < str.length; i++) {
var c = str[i];
if (c === '\n' || c === '#') break;
if (c > ' ') return ' # ' + str;
// Check if we can insert this name without quotes
if (needsEscapeName.test(name)) {
needsEscape.lastIndex = 0;
return '"' + (needsEscape.test(name) ? quoteReplace(name) : name) + '"';
}
return str;
else {
// return without quotes
return name;
}
}
// What happens next depends on the value's type.
function str(value, hasComment, rootObject) {
// Produce a string from value.
switch (typeof value) {
case 'string':
return quote(value, gap, hasComment);
function startsWithNL(str) { return str && str[str[0] === '\r' ? 1 : 0] === '\n'; }
function testWsc(str) { return str && !startsWithNL(str); }
function wsc(str) {
if (!str) return "";
for (var i = 0; i < str.length; i++) {
var c = str[i];
if (c === '\n' || c === '#') break;
if (c > ' ') return ' # ' + str;
}
return str;
}
case 'number':
// JSON numbers must be finite. Encode non-finite numbers as null.
return isFinite(value) ? String(value) : 'null';
// What happens next depends on the value's type.
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);
switch (typeof value) {
case 'string':
return quote(value, gap, hasComment);
case 'object':
// If the type is 'object', we might be dealing with an object or an array or
// null.
case 'number':
// JSON numbers must be finite. Encode non-finite numbers as null.
return isFinite(value) ? String(value) : 'null';
// Due to a specification blunder in ECMAScript, typeof null is 'object',
// so watch out for that case.
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);
if (!value) return 'null';
case 'object':
// If the type is 'object', we might be dealing with an object or an array or
// null.
// Make an array to hold the partial results of stringifying this object value.
var mind = gap;
gap += indent;
var eolMind = hjson_EOL + mind;
var eolGap = hjson_EOL + gap;
var prefix = rootObject || hjson_bracesSameLine ? '' : eolMind;
var partial = [];
// Due to a specification blunder in ECMAScript, typeof null is 'object',
// so watch out for that case.
var i, length; // loop
var k, v; // key, value
var kw, kwl; // whitespace & comments
if (!value) return 'null';
// Is the value an array?
// Make an array to hold the partial results of stringifying this object value.
var mind = gap;
gap += indent;
var eolMind = EOL + mind;
var eolGap = EOL + gap;
var prefix = rootObject || bracesSameLine ? '' : eolMind;
var partial = [];
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.
var i, length; // loop
var k, v; // key, value
var kw, kwl; // whitespace & comments
if (keepWsc) kw = value.__WSC__;
// Is the value an array?
for (i = 0, length = value.length; i < length; i++) {
if (kw) partial.push(wsc(kw[i]) + eolGap);
partial.push(str(value[i], kw ? testWsc(kw[i + 1]) : false) || 'null');
}
if (kw) partial.push(wsc(kw[i]) + eolMind);
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.
// Join all of the elements together, separated with newline, and wrap them in
// brackets.
if (keepWsc) kw = value.__WSC__;
if (kw) v = prefix + '[' + partial.join('') + ']';
else if (partial.length === 0) v = '[]';
else v = prefix + '[' + eolGap + partial.join(eolGap) + eolMind + ']';
}
else {
// Otherwise, iterate through all of the keys in the object.
if (keepWsc && value.__WSC__) {
kw = value.__WSC__;
kwl = wsc(kw.c[""]);
var keys=kw.o.slice();
for (k in value) {
if (Object.prototype.hasOwnProperty.call(value, k) && keys.indexOf(k) < 0)
keys.push(k);
for (i = 0, length = value.length; i < length; i++) {
if (kw) partial.push(wsc(kw[i]) + eolGap);
partial.push(str(value[i], kw ? testWsc(kw[i + 1]) : false) || 'null');
}
if (kw) partial.push(wsc(kw[i]) + eolMind);
for (i = 0, length = keys.length; i < length; i++) {
k = keys[i];
partial.push(kwl + eolGap);
kwl = wsc(kw.c[k]);
v = str(value[k], testWsc(kwl));
if (v) partial.push(quoteName(k) + (startsWithNL(v) ? ':' : ': ') + v);
}
partial.push(kwl + eolMind);
// Join all of the elements together, separated with newline, and wrap them in
// brackets.
if (kw) v = prefix + '[' + partial.join('') + ']';
else if (partial.length === 0) v = '[]';
else v = prefix + '[' + eolGap + partial.join(eolGap) + eolMind + ']';
}
else {
for (k in value) {
if (Object.prototype.hasOwnProperty.call(value, k)) {
v = str(value[k]);
// Otherwise, iterate through all of the keys in the object.
if (keepWsc && value.__WSC__) {
kw = value.__WSC__;
kwl = wsc(kw.c[""]);
var keys=kw.o.slice();
for (k in value) {
if (Object.prototype.hasOwnProperty.call(value, k) && keys.indexOf(k) < 0)
keys.push(k);
}
for (i = 0, length = keys.length; i < length; i++) {
k = keys[i];
partial.push(kwl + eolGap);
kwl = wsc(kw.c[k]);
v = str(value[k], testWsc(kwl));
if (v) partial.push(quoteName(k) + (startsWithNL(v) ? ':' : ': ') + v);
}
partial.push(kwl + eolMind);
}
}
else {
for (k in value) {
if (Object.prototype.hasOwnProperty.call(value, k)) {
v = str(value[k]);
if (v) partial.push(quoteName(k) + (startsWithNL(v) ? ':' : ': ') + v);
}
}
}
// Join all of the member texts together, separated with newlines,
// and wrap them in braces.
// Join all of the member texts together, separated with newlines,
// and wrap them in braces.
if (kw) v = prefix + '{' + partial.join('') + '}';
else if (partial.length === 0) v = '{}';
else v = prefix + '{' + eolGap + partial.join(eolGap) + eolMind + '}';
}
if (kw) v = prefix + '{' + partial.join('') + '}';
else if (partial.length === 0) v = '{}';
else v = prefix + '{' + eolGap + partial.join(eolGap) + eolMind + '}';
}
gap = mind;
return v;
gap = mind;
return v;
}
}
}
// Return the hjson_stringify function. It will have access to all of the above
// functions and variables.
// Return the hjson_stringify function. It will have access to all of the above
// functions and variables.
return function (value, opt, 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.
return function (value, opt, 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;
var i;
indent = ' ';
keepWsc = false;
indent = ' ';
keepWsc = false;
if (typeof opt === 'object') {
indent = opt.space || ' ';
keepWsc = opt.keepWsc;
}
if (typeof opt === 'object') {
indent = opt.space || ' ';
keepWsc = opt.keepWsc;
}
// 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 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++) indent += ' ';
}
else if (typeof space === 'string')
indent = space;
if (typeof space === 'number') {
indent = '';
for (i = 0; i < space; i++) indent += ' ';
}
else if (typeof space === 'string')
indent = space;
// Return the result of stringifying the value.
return str(value, null, true);
// Return the result of stringifying the value.
return str(value, null, true);
};
}());
return {
parse: hjson_parse,
stringify: hjson_stringify,
endOfLine: function() { return EOL; },
setEndOfLine: function(eol) {
if (eol === '\n' || eol === '\r\n') EOL = eol;
},
bracesSameLine: function() { return bracesSameLine; },
setBracesSameLine: function(v) { bracesSameLine = v; },
};
}());
// node.js
if (typeof module!=='undefined' && module.exports) {
var os=require('os');
hjson_EOL=os.EOL;
module.exports= {
parse: hjson_parse,
stringify: hjson_stringify,
endOfLine: function() { return hjson_EOL; },
setEndOfLine: function(eol) { hjson_EOL = eol; },
bracesSameLine: function() { return hjson_bracesSameLine; },
setBracesSameLine: function(v) { hjson_bracesSameLine = v; },
};
if (typeof module === "object") {
if (typeof require === "function") {
var os=require('os');
Hjson.setEndOfLine(os.EOL);
}
module.exports=Hjson;
}

@@ -6,3 +6,3 @@ {

"author": "Christian Zangl",
"version": "1.3.0",
"version": "1.4.0",
"tags": [

@@ -9,0 +9,0 @@ "json",

@@ -49,5 +49,5 @@ # hjson-js

Also see lib/hjson.js
The API is the same for the browser and node version.
## Hjson.parse(text, options)
### Hjson.parse(text, options)

@@ -60,3 +60,3 @@ This method parses *JSON* or *Hjson* text to produce an object or array.

## Hjson.stringify(value, options)
### Hjson.stringify(value, options)

@@ -70,2 +70,10 @@ This method produces Hjson text from a JavaScript value.

### Hjson.endOfLine(), .setEndOfLine(eol)
Gets or sets the EOL character ('\n' or '\r\n').
### Hjson.bracesSameLine(), .setBracesSameLine(b)
Gets or sets if braces should appear on the same line (for stringify).
## modify & keep comments

@@ -103,23 +111,38 @@

## v1.2.0
- v1.4.0
- add old fashioned /**/ comments
- fix cli eol
Changed the browser interface to match the node api (which didn't change).
## v1.1.0
Fixed parse for leading zeros ("00") and trailing comments.
- add // support
Fixed stringify for /**/ and //
## v1.0.2
Added more test cases.
- stringify bug fixes
- v1.3.0
## v1.0.0
Added support for the simplified syntax.
- Switched to v1 for semver
- v1.2.0
- Adds editing support via the `{ keepWsc: true }` option.
Added old fashioned /**/ comments.
- Removes stringify(value, replacer, space) replacer support
Fixed the missing EOL (cli only).
- v1.1.0
add // support
- v1.0.2
stringify bug fixes
- v1.0.0
Switched to v1 for semver.
Adds editing support via the `{ keepWsc: true }` option.
Removes stringify(value, replacer, space) replacer support
You can still use this syntax but replacer will no longer be called. This was removed in favor of editing support and because replacer provided an incomplete solution.

@@ -5,37 +5,57 @@

var path = require("path");
var rootDir = path.normalize(path.join(__dirname, "asset"));
var rootDir = path.normalize(path.join(__dirname, "assets"));
var argv=process.argv.slice(2)
var filter=argv[0];
Hjson.setEndOfLine("\n");
function showErr(cap, s1, s2) {
console.log(cap+" FAILED!");
console.log("--- actual:");
console.log(s1);
console.log("--- expected:");
console.log(s2);
function failErr(name, type, s1, s2) {
console.log(name+" "+type+" FAILED!");
if (s1 || s2) {
console.log("--- actual:");
console.log(s1);
console.log("--- expected:");
console.log(s2);
}
process.exit(1);
}
console.log("running tests...");
fs.readdirSync(rootDir).forEach(function(file) {
var name = file.split("_test.hjson");
if (name.length !== 2) return;
var name = file.split("_test.");
if (name.length < 2) return;
var isJson = name[2] === "json";
name = name[0];
if (filter && name.indexOf(filter) < 0) return; // ignore
var text = fs.readFileSync(path.join(rootDir, file), "utf8");
var result = JSON.parse(fs.readFileSync(path.join(rootDir, name+"_result.json"), "utf8"));
var shouldFail = name.substr(0, 4) === "fail";
try {
var data = Hjson.parse(text);
var data1 = JSON.stringify(data, null, 2), data2 = JSON.stringify(result.data, null, 2);
var data1 = JSON.stringify(data, null, 2);
var hjson1 = Hjson.stringify(data);
var hjson2 = fs.readFileSync(path.join(rootDir, name+"_result.txt"), "utf8");
if (data1 !== data2) showErr(name+" parse", data1, data2);
else if (hjson1 !== hjson2) showErr(name+" stringify", hjson1, hjson2);
else console.log(name+" SUCCESS");
if (!shouldFail) {
var result = JSON.parse(fs.readFileSync(path.join(rootDir, name+"_result.json"), "utf8"));
var data2 = JSON.stringify(result, null, 2);
var hjson2 = fs.readFileSync(path.join(rootDir, name+"_result.hjson"), "utf8");
if (data1 !== data2) failErr(name, "parse", data1, data2);
if (hjson1 !== hjson2) failErr(name, "stringify", hjson1, hjson2);
if (isJson) {
var json1 = JSON.stringify(data), json2 = JSON.stringify(JSON.parse(text));
if (json1 !== json2) failErr(name, "json chk", json1, json2);
}
}
else failErr(name, "should fail");
}
catch (err) {
if (result.err) console.log(name+" SUCCESS");
else showErr(name+" exception", err.toString(), "");
if (!shouldFail) failErr(name, "exception", err.toString(), "");
}
console.log("- "+name+" OK");
});
console.log("ALL OK!");
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc