99 lines
2.5 KiB
JavaScript
99 lines
2.5 KiB
JavaScript
// Note: This regex matches even invalid JSON strings, but since we’re
|
||
// working on the output of `JSON.stringify` we know that only valid strings
|
||
// are present (unless the user supplied a weird `options.indent` but in
|
||
// that case we don’t care since the output would be invalid anyway).
|
||
const stringOrChar = /("(?:[^\\"]|\\.)*")|[:,]/g;
|
||
|
||
export default function stringify(passedObj, options = {}) {
|
||
const indent = JSON.stringify(
|
||
[1],
|
||
undefined,
|
||
options.indent === undefined ? 2 : options.indent
|
||
).slice(2, -3);
|
||
|
||
const maxLength =
|
||
indent === ""
|
||
? Infinity
|
||
: options.maxLength === undefined
|
||
? 80
|
||
: options.maxLength;
|
||
|
||
let { replacer } = options;
|
||
|
||
return (function _stringify(obj, currentIndent, reserved) {
|
||
if (obj && typeof obj.toJSON === "function") {
|
||
obj = obj.toJSON();
|
||
}
|
||
|
||
const string = JSON.stringify(obj, replacer);
|
||
|
||
if (string === undefined) {
|
||
return string;
|
||
}
|
||
|
||
const length = maxLength - currentIndent.length - reserved;
|
||
|
||
if (string.length <= length) {
|
||
const prettified = string.replace(
|
||
stringOrChar,
|
||
(match, stringLiteral) => {
|
||
return stringLiteral || `${match} `;
|
||
}
|
||
);
|
||
if (prettified.length <= length) {
|
||
return prettified;
|
||
}
|
||
}
|
||
|
||
if (replacer != null) {
|
||
obj = JSON.parse(string);
|
||
replacer = undefined;
|
||
}
|
||
|
||
if (typeof obj === "object" && obj !== null) {
|
||
const nextIndent = currentIndent + indent;
|
||
const items = [];
|
||
let index = 0;
|
||
let start;
|
||
let end;
|
||
|
||
if (Array.isArray(obj)) {
|
||
start = "[";
|
||
end = "]";
|
||
const { length } = obj;
|
||
for (; index < length; index++) {
|
||
items.push(
|
||
_stringify(obj[index], nextIndent, index === length - 1 ? 0 : 1) ||
|
||
"null"
|
||
);
|
||
}
|
||
} else {
|
||
start = "{";
|
||
end = "}";
|
||
const keys = Object.keys(obj);
|
||
const { length } = keys;
|
||
for (; index < length; index++) {
|
||
const key = keys[index];
|
||
const keyPart = `${JSON.stringify(key)}: `;
|
||
const value = _stringify(
|
||
obj[key],
|
||
nextIndent,
|
||
keyPart.length + (index === length - 1 ? 0 : 1)
|
||
);
|
||
if (value !== undefined) {
|
||
items.push(keyPart + value);
|
||
}
|
||
}
|
||
}
|
||
|
||
if (items.length > 0) {
|
||
return [start, indent + items.join(`,\n${nextIndent}`), end].join(
|
||
`\n${currentIndent}`
|
||
);
|
||
}
|
||
}
|
||
|
||
return string;
|
||
})(passedObj, "", 0);
|
||
}
|