????
Current Path : C:/inetpub/vhost/qnquyhoach.nextform.vn/api/node_modules/comment-json/src/ |
Current File : C:/inetpub/vhost/qnquyhoach.nextform.vn/api/node_modules/comment-json/src/stringify.js |
const { isArray, isObject, isFunction, isNumber, isString } = require('core-util-is') const repeat = require('repeat-string') const { PREFIX_BEFORE_ALL, PREFIX_BEFORE, PREFIX_AFTER_PROP, PREFIX_AFTER_COLON, PREFIX_AFTER_VALUE, PREFIX_AFTER, PREFIX_AFTER_ALL, BRACKET_OPEN, BRACKET_CLOSE, CURLY_BRACKET_OPEN, CURLY_BRACKET_CLOSE, COLON, COMMA, EMPTY, UNDEFINED } = require('./common') // eslint-disable-next-line no-control-regex, no-misleading-character-class const ESCAPABLE = /[\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g // String constants const SPACE = ' ' const LF = '\n' const STR_NULL = 'null' // Symbol tags const BEFORE = prop => `${PREFIX_BEFORE}:${prop}` const AFTER_PROP = prop => `${PREFIX_AFTER_PROP}:${prop}` const AFTER_COLON = prop => `${PREFIX_AFTER_COLON}:${prop}` const AFTER_VALUE = prop => `${PREFIX_AFTER_VALUE}:${prop}` const AFTER = prop => `${PREFIX_AFTER}:${prop}` // table of character substitutions const meta = { '\b': '\\b', '\t': '\\t', '\n': '\\n', '\f': '\\f', '\r': '\\r', '"': '\\"', '\\': '\\\\' } const escape = string => { ESCAPABLE.lastIndex = 0 if (!ESCAPABLE.test(string)) { return string } return string.replace(ESCAPABLE, a => { const c = meta[a] return typeof c === 'string' ? c : a }) } // Escape no control characters, no quote characters, // and no backslash characters, // then we can safely slap some quotes around it. const quote = string => `"${escape(string)}"` const comment_stringify = (value, line) => line ? `//${value}` : `/*${value}*/` // display_block `boolean` whether the // WHOLE block of comments is always a block group const process_comments = (host, symbol_tag, deeper_gap, display_block) => { const comments = host[Symbol.for(symbol_tag)] if (!comments || !comments.length) { return EMPTY } let is_line_comment = false const str = comments.reduce((prev, { inline, type, value }) => { const delimiter = inline ? SPACE : LF + deeper_gap is_line_comment = type === 'LineComment' return prev + delimiter + comment_stringify(value, is_line_comment) }, EMPTY) return display_block // line comment should always end with a LF || is_line_comment ? str + LF + deeper_gap : str } let replacer = null let indent = EMPTY const clean = () => { replacer = null indent = EMPTY } const join = (one, two, gap) => one ? two // Symbol.for('before') and Symbol.for('before:prop') // might both exist if user mannually add comments to the object // and make a mistake. // SO, we are not to only trimRight but trim for both sides ? one + two.trim() + LF + gap : one.trimRight() + LF + gap : two ? two.trimRight() + LF + gap : EMPTY const join_content = (inside, value, gap) => { const comment = process_comments(value, PREFIX_BEFORE, gap + indent, true) return join(comment, inside, gap) } // | deeper_gap | // | gap | indent | // [ // "foo", // "bar" // ] const array_stringify = (value, gap) => { const deeper_gap = gap + indent const {length} = value // From the item to before close let inside = EMPTY let after_comma = EMPTY // Never use Array.prototype.forEach, // that we should iterate all items for (let i = 0; i < length; i ++) { if (i !== 0) { inside += COMMA } const before = join( after_comma, process_comments(value, BEFORE(i), deeper_gap), deeper_gap ) inside += before || (LF + deeper_gap) // JSON.stringify([undefined]) => [null] inside += stringify(i, value, deeper_gap) || STR_NULL inside += process_comments(value, AFTER_VALUE(i), deeper_gap) after_comma = process_comments(value, AFTER(i), deeper_gap) } inside += join( after_comma, process_comments(value, PREFIX_AFTER, deeper_gap), deeper_gap ) return BRACKET_OPEN + join_content(inside, value, gap) + BRACKET_CLOSE } // | deeper_gap | // | gap | indent | // { // "foo": 1, // "bar": 2 // } const object_stringify = (value, gap) => { // Due to a specification blunder in ECMAScript, typeof null is 'object', // so watch out for that case. if (!value) { return 'null' } const deeper_gap = gap + indent // From the first element to before close let inside = EMPTY let after_comma = EMPTY let first = true const keys = isArray(replacer) ? replacer : Object.keys(value) const iteratee = key => { // Stringified value const sv = stringify(key, value, deeper_gap) // If a value is undefined, then the key-value pair should be ignored if (sv === UNDEFINED) { return } // The treat ment if (!first) { inside += COMMA } first = false const before = join( after_comma, process_comments(value, BEFORE(key), deeper_gap), deeper_gap ) inside += before || (LF + deeper_gap) inside += quote(key) + process_comments(value, AFTER_PROP(key), deeper_gap) + COLON + process_comments(value, AFTER_COLON(key), deeper_gap) + SPACE + sv + process_comments(value, AFTER_VALUE(key), deeper_gap) after_comma = process_comments(value, AFTER(key), deeper_gap) } keys.forEach(iteratee) // if (after_comma) { // inside += COMMA // } inside += join( after_comma, process_comments(value, PREFIX_AFTER, deeper_gap), deeper_gap ) return CURLY_BRACKET_OPEN + join_content(inside, value, gap) + CURLY_BRACKET_CLOSE } // @param {string} key // @param {Object} holder // @param {function()|Array} replacer // @param {string} indent // @param {string} gap function stringify (key, holder, gap) { let value = holder[key] // If the value has a toJSON method, call it to obtain a replacement value. if (isObject(value) && isFunction(value.toJSON)) { value = value.toJSON(key) } // If we were called with a replacer function, then call the replacer to // obtain a replacement value. if (isFunction(replacer)) { value = replacer.call(holder, key, value) } switch (typeof value) { case 'string': return quote(value) case 'number': // JSON numbers must be finite. Encode non-finite numbers as null. return Number.isFinite(value) ? String(value) : STR_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) // If the type is 'object', we might be dealing with an object or an array or // null. case 'object': return isArray(value) ? array_stringify(value, gap) : object_stringify(value, gap) // undefined default: // JSON.stringify(undefined) === undefined // JSON.stringify('foo', () => undefined) === undefined } } const get_indent = space => isString(space) // If the space parameter is a string, it will be used as the indent string. ? space : isNumber(space) ? repeat(SPACE, space) : EMPTY const {toString} = Object.prototype const PRIMITIVE_OBJECT_TYPES = [ '[object Number]', '[object String]', '[object Boolean]' ] const is_primitive_object = subject => { if (typeof subject !== 'object') { return false } const str = toString.call(subject) return PRIMITIVE_OBJECT_TYPES.includes(str) } // @param {function()|Array} replacer // @param {string|number} space module.exports = (value, replacer_, space) => { // The stringify method takes a value and an optional replacer, and an optional // space parameter, and returns a JSON 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. // If the space parameter is a number, make an indent string containing that // many spaces. const indent_ = get_indent(space) if (!indent_) { return JSON.stringify(value, replacer_) } // vanilla `JSON.parse` allow invalid replacer if (!isFunction(replacer_) && !isArray(replacer_)) { replacer_ = null } replacer = replacer_ indent = indent_ const str = is_primitive_object(value) ? JSON.stringify(value) : stringify('', {'': value}, EMPTY) clean() return isObject(value) ? process_comments(value, PREFIX_BEFORE_ALL, EMPTY).trimLeft() + str + process_comments(value, PREFIX_AFTER_ALL, EMPTY).trimRight() : str }