Spaces:
Sleeping
Sleeping
File size: 5,116 Bytes
7dfae77 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 | /*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Natsu @xiaoxiaojx
This file contains code ported from strip-json-comments:
https://github.com/sindresorhus/strip-json-comments
Original license: MIT
Original author: Sindre Sorhus
*/
"use strict";
/**
* @typedef {object} StripJsonCommentsOptions
* @property {boolean=} whitespace Replace comments with whitespace
* @property {boolean=} trailingCommas Strip trailing commas
*/
const singleComment = Symbol("singleComment");
const multiComment = Symbol("multiComment");
/**
* Strip without whitespace (returns empty string)
* @param {string} _string Unused
* @param {number} _start Unused
* @param {number} _end Unused
* @returns {string} Empty string for all input
*/
const stripWithoutWhitespace = (_string, _start, _end) => "";
/**
* Replace all characters except ASCII spaces, tabs and line endings with regular spaces to ensure valid JSON output.
* @param {string} string String to process
* @param {number} start Start index
* @param {number} end End index
* @returns {string} Processed string with comments replaced by whitespace
*/
const stripWithWhitespace = (string, start, end) =>
string.slice(start, end).replace(/[^ \t\r\n]/g, " ");
/**
* Check if a quote is escaped
* @param {string} jsonString JSON string
* @param {number} quotePosition Position of the quote
* @returns {boolean} True if the quote at the given position is escaped
*/
const isEscaped = (jsonString, quotePosition) => {
let index = quotePosition - 1;
let backslashCount = 0;
while (jsonString[index] === "\\") {
index -= 1;
backslashCount += 1;
}
return Boolean(backslashCount % 2);
};
/**
* Strip comments from JSON string
* @param {string} jsonString JSON string with potential comments
* @param {StripJsonCommentsOptions} options Options
* @returns {string} JSON string without comments
*/
function stripJsonComments(
jsonString,
{ whitespace = true, trailingCommas = false } = {},
) {
if (typeof jsonString !== "string") {
throw new TypeError(
`Expected argument \`jsonString\` to be a \`string\`, got \`${typeof jsonString}\``,
);
}
const strip = whitespace ? stripWithWhitespace : stripWithoutWhitespace;
let isInsideString = false;
/** @type {false | typeof singleComment | typeof multiComment} */
let isInsideComment = false;
let offset = 0;
let buffer = "";
let result = "";
let commaIndex = -1;
for (let index = 0; index < jsonString.length; index++) {
const currentCharacter = jsonString[index];
const nextCharacter = jsonString[index + 1];
if (!isInsideComment && currentCharacter === '"') {
// Enter or exit string
const escaped = isEscaped(jsonString, index);
if (!escaped) {
isInsideString = !isInsideString;
}
}
if (isInsideString) {
continue;
}
if (!isInsideComment && currentCharacter + nextCharacter === "//") {
// Enter single-line comment
buffer += jsonString.slice(offset, index);
offset = index;
isInsideComment = singleComment;
index++;
} else if (
isInsideComment === singleComment &&
currentCharacter + nextCharacter === "\r\n"
) {
// Exit single-line comment via \r\n
index++;
isInsideComment = false;
buffer += strip(jsonString, offset, index);
offset = index;
continue;
} else if (isInsideComment === singleComment && currentCharacter === "\n") {
// Exit single-line comment via \n
isInsideComment = false;
buffer += strip(jsonString, offset, index);
offset = index;
} else if (!isInsideComment && currentCharacter + nextCharacter === "/*") {
// Enter multiline comment
buffer += jsonString.slice(offset, index);
offset = index;
isInsideComment = multiComment;
index++;
continue;
} else if (
isInsideComment === multiComment &&
currentCharacter + nextCharacter === "*/"
) {
// Exit multiline comment
index++;
isInsideComment = false;
buffer += strip(jsonString, offset, index + 1);
offset = index + 1;
continue;
} else if (trailingCommas && !isInsideComment) {
if (commaIndex !== -1) {
if (currentCharacter === "}" || currentCharacter === "]") {
// Strip trailing comma
buffer += jsonString.slice(offset, index);
result += strip(buffer, 0, 1) + buffer.slice(1);
buffer = "";
offset = index;
commaIndex = -1;
} else if (
currentCharacter !== " " &&
currentCharacter !== "\t" &&
currentCharacter !== "\r" &&
currentCharacter !== "\n"
) {
// Hit non-whitespace following a comma; comma is not trailing
buffer += jsonString.slice(offset, index);
offset = index;
commaIndex = -1;
}
} else if (currentCharacter === ",") {
// Flush buffer prior to this point, and save new comma index
result += buffer + jsonString.slice(offset, index);
buffer = "";
offset = index;
commaIndex = index;
}
}
}
const remaining =
isInsideComment === singleComment
? strip(jsonString, offset, jsonString.length)
: jsonString.slice(offset);
return result + buffer + remaining;
}
module.exports = stripJsonComments;
|