comment-json
Advanced tools
+80
-11
@@ -9,13 +9,39 @@ // Original from DefinitelyTyped. Thanks a million | ||
| export type CommentPrefix = 'before' | ||
| | 'after-prop' | ||
| | 'after-colon' | ||
| | 'after-value' | ||
| | 'after' | ||
| // Define comment prefix constants first to avoid magic strings | ||
| declare const PREFIX_BEFORE: 'before' | ||
| declare const PREFIX_AFTER_PROP: 'after-prop' | ||
| declare const PREFIX_AFTER_COLON: 'after-colon' | ||
| declare const PREFIX_AFTER_VALUE: 'after-value' | ||
| declare const PREFIX_AFTER: 'after' | ||
| declare const PREFIX_BEFORE_ALL: 'before-all' | ||
| declare const PREFIX_AFTER_ALL: 'after-all' | ||
| export type CommentDescriptor = `${CommentPrefix}:${string}` | ||
| | 'before' | ||
| | 'before-all' | ||
| | 'after-all' | ||
| // Export the constants | ||
| export { | ||
| PREFIX_BEFORE, | ||
| PREFIX_AFTER_PROP, | ||
| PREFIX_AFTER_COLON, | ||
| PREFIX_AFTER_VALUE, | ||
| PREFIX_AFTER, | ||
| PREFIX_BEFORE_ALL, | ||
| PREFIX_AFTER_ALL | ||
| } | ||
| // Use the constant types to build CommentPrefix | ||
| export type PropertyCommentPrefix = typeof PREFIX_BEFORE | ||
| | typeof PREFIX_AFTER_PROP | ||
| | typeof PREFIX_AFTER_COLON | ||
| | typeof PREFIX_AFTER_VALUE | ||
| | typeof PREFIX_AFTER | ||
| export type NonPropertyCommentPrefix = typeof PREFIX_BEFORE | ||
| | typeof PREFIX_AFTER | ||
| | typeof PREFIX_BEFORE_ALL | ||
| | typeof PREFIX_AFTER_ALL | ||
| export type CommentPrefix = PropertyCommentPrefix | NonPropertyCommentPrefix | ||
| export type CommentDescriptor = `${PropertyCommentPrefix}:${string}` | ||
| | NonPropertyCommentPrefix | ||
| export type CommentSymbol = typeof commentSymbol | ||
@@ -64,3 +90,7 @@ | ||
| export type Reviver = (k: number | string, v: unknown) => unknown | ||
| export type Reviver = ( | ||
| k: number | string, | ||
| v: unknown, | ||
| context?: { source?: string } | ||
| ) => unknown | ||
@@ -109,8 +139,47 @@ /** | ||
| /** | ||
| * Assign properties and comments from source to target | ||
| * @param target The target object to assign to | ||
| * @param source The source object to assign from | ||
| * @param keys Optional array of keys to assign. If not provided, all keys and non-property comments are assigned | ||
| * @returns The target object | ||
| */ | ||
| export function assign<TTarget, TSource>( | ||
| target: TTarget, | ||
| source: TSource, | ||
| // Although it actually accepts more key types and filters then`, | ||
| // Although it actually accepts more key types and filters then, | ||
| // we set the type of `keys` stricter | ||
| keys?: readonly (number | string)[] | ||
| ): TTarget | ||
| interface CommentPosition { | ||
| where: CommentPrefix | ||
| key?: string | ||
| } | ||
| /** | ||
| * Move comments from one location to another | ||
| * @param source The source object containing comments | ||
| * @param target The target object to move comments to (defaults to source if not provided) | ||
| * @param from The source comment location | ||
| * @param to The target comment location | ||
| * @param override Whether to override existing comments at the target location | ||
| */ | ||
| export function moveComments( | ||
| source: CommentJSONValue, | ||
| target: CommentJSONValue | undefined, | ||
| from: CommentPosition, | ||
| to: CommentPosition, | ||
| override?: boolean | ||
| ): void | ||
| /** | ||
| * Remove comments from a specific location | ||
| * @param target The target object to remove comments from | ||
| * @param location The comment location to remove | ||
| */ | ||
| export function removeComments( | ||
| target: CommentJSONValue, | ||
| location: CommentPosition | ||
| ): void | ||
+1
-1
| { | ||
| "name": "comment-json", | ||
| "version": "4.4.1", | ||
| "version": "4.5.0", | ||
| "description": "Parse and stringify JSON with comments. It will retain comments even after saved!", | ||
@@ -5,0 +5,0 @@ "main": "src/index.js", |
+176
-3
@@ -33,2 +33,4 @@ [](https://github.com/kaelzhang/node-comment-json/actions/workflows/nodejs.yml) | ||
| - [assign](#assigntarget-object-source-object-keys-array) | ||
| - [moveComments](#movecommentssource-object-target-object-from-object-to-object-override-boolean) | ||
| - [removeComments](#removecommentstarget-object-location-object) | ||
| - [CommentArray](#commentarray) | ||
@@ -76,3 +78,5 @@ - [Change Logs](https://github.com/kaelzhang/node-comment-json/releases) | ||
| stringify, | ||
| assign | ||
| assign, | ||
| moveComments, | ||
| removeComments | ||
| } = require('comment-json') | ||
@@ -238,3 +242,3 @@ const fs = require('fs') | ||
| There are **EIGHT** kinds of symbol properties: | ||
| There are **NINE** kinds of symbol properties: | ||
@@ -272,2 +276,6 @@ ```js | ||
| // Always at the inner end of an object or an array, | ||
| // only used for stringification | ||
| Symbol.for('after') | ||
| // Comments after everything | ||
@@ -464,3 +472,3 @@ Symbol.for('after-all') | ||
| But if argument `keys` is specified and is not empty, then comment ` before all`, which belongs to no properties, will **NOT** be copied. | ||
| But if argument `keys` is specified and is not empty, then comment ` before all`, which belongs to non-properties, will **NOT** be copied. | ||
@@ -499,5 +507,170 @@ ```js | ||
| Symbol.for('before') | ||
| Symbol.for('after') // only for stringify | ||
| Symbol.for('after-all') | ||
| ``` | ||
| ## moveComments(source: object, target?: object, from: object, to: object, override?: boolean) | ||
| - **source** `object` The source object containing comments to move. | ||
| - **target?** `object` The target object to move comments to. If not provided, defaults to source (move within same object). | ||
| - **from** `object` The source comment location. | ||
| - **from.where** `CommentPrefix` The comment position (e.g., 'before', 'after', 'before-all', etc.). | ||
| - **from.key?** `string` The property key for property-specific comments. Omit for non-property comments. | ||
| - **to** `object` The target comment location. | ||
| - **to.where** `CommentPrefix` The comment position (e.g., 'before', 'after', 'before-all', etc.). | ||
| - **to.key?** `string` The property key for property-specific comments. Omit for non-property comments. | ||
| - **override?** `boolean = false` Whether to override existing comments at the target location. If false, comments will be appended. | ||
| This method is used to move comments from one location to another within objects. It's particularly useful when you need to reorganize comments or move them between different comment positions. | ||
| ```js | ||
| const {parse, stringify, moveComments} = require('comment-json') | ||
| const obj = parse(`{ | ||
| "foo": 1, // comment after foo | ||
| "bar": 2 | ||
| }`) | ||
| // Move comment from `after 'foo'` to `after` | ||
| moveComments(obj, obj, | ||
| { where: 'after', key: 'foo' }, | ||
| { where: 'after' } | ||
| ) | ||
| obj.baz = 3 | ||
| console.log(stringify(obj, null, 2)) | ||
| // { | ||
| // "foo": 1, | ||
| // "bar": 2, | ||
| // "baz": 3 | ||
| // // comment after foo | ||
| // } | ||
| ``` | ||
| ### Moving non-property comments | ||
| ```js | ||
| const obj = parse(`// top comment | ||
| { | ||
| "foo": 1 | ||
| }`) | ||
| // Move top comment to bottom | ||
| moveComments(obj, obj, | ||
| { kind: 'before-all' }, | ||
| { kind: 'after-all' } | ||
| ) | ||
| console.log(stringify(obj, null, 2)) | ||
| // { | ||
| // "foo": 1 | ||
| // } | ||
| // // top comment | ||
| ``` | ||
| ### Moving comments between objects | ||
| ```js | ||
| const source = parse(`{ | ||
| "foo": 1 // source comment | ||
| }`) | ||
| const target = { bar: 2 } | ||
| // Move comment from source to target | ||
| moveComments(source, target, | ||
| { kind: 'after-value', key: 'foo' }, | ||
| { kind: 'before', key: 'bar' } | ||
| ) | ||
| console.log(stringify(target, null, 2)) | ||
| // { | ||
| // // source comment | ||
| // "bar": 2 | ||
| // } | ||
| ``` | ||
| ### Appending vs overriding comments | ||
| ```js | ||
| const obj = parse(`{ | ||
| // existing comment | ||
| "foo": 1, // another comment | ||
| "bar": 2 | ||
| }`) | ||
| // By default, comments are appended (override = false) | ||
| moveComments(obj, obj, | ||
| { kind: 'after-value', key: 'foo' }, | ||
| { kind: 'before', key: 'foo' } | ||
| ) | ||
| console.log(stringify(obj, null, 2)) | ||
| // { | ||
| // // existing comment | ||
| // // another comment | ||
| // "foo": 1, | ||
| // "bar": 2 | ||
| // } | ||
| // With override = true, existing comments are replaced | ||
| moveComments(obj, obj, | ||
| { kind: 'before', key: 'bar' }, | ||
| { kind: 'before', key: 'foo' }, | ||
| true // override existing comments | ||
| ) | ||
| ``` | ||
| ## removeComments(target: object, location: object) | ||
| - **target** `object` The target object to remove comments from. | ||
| - **location** `object` The comment location to remove. | ||
| - **location.where** `CommentPrefix` The comment position (e.g., 'before', 'after', 'before-all', etc.). | ||
| - **location.key?** `string` The property key for property-specific comments. Omit for non-property comments. | ||
| This method is used to remove comments from a specific location within objects. It's useful for cleaning up comments or removing unwanted comment annotations. | ||
| ### Basic usage | ||
| ```js | ||
| const {parse, stringify, removeComments} = require('comment-json') | ||
| const obj = parse(`{ | ||
| // comment before foo | ||
| "foo": 1, // comment after foo | ||
| "bar": 2 | ||
| }`) | ||
| // Remove comment before 'foo' | ||
| removeComments(obj, { where: 'before', key: 'foo' }) | ||
| console.log(stringify(obj, null, 2)) | ||
| // { | ||
| // "foo": 1, // comment after foo | ||
| // "bar": 2 | ||
| // } | ||
| ``` | ||
| ### Removing non-property comments | ||
| ```js | ||
| const obj = parse(`// top comment | ||
| { | ||
| "foo": 1 | ||
| } | ||
| // bottom comment`) | ||
| // Remove top comment | ||
| removeComments(obj, { where: 'before-all' }) | ||
| // Remove bottom comment | ||
| removeComments(obj, { where: 'after-all' }) | ||
| console.log(stringify(obj, null, 2)) | ||
| // { | ||
| // "foo": 1 | ||
| // } | ||
| ``` | ||
| ## `CommentArray` | ||
@@ -504,0 +677,0 @@ |
+33
-2
@@ -5,3 +5,3 @@ const {isArray} = require('core-util-is') | ||
| const { | ||
| SYMBOL_PREFIXES, | ||
| PROP_SYMBOL_PREFIXES, | ||
@@ -72,3 +72,3 @@ UNDEFINED, | ||
| const remove_comments = (array, key) => { | ||
| SYMBOL_PREFIXES.forEach(prefix => { | ||
| PROP_SYMBOL_PREFIXES.forEach(prefix => { | ||
| const prop = symbol(prefix, key) | ||
@@ -89,2 +89,17 @@ delete array[prop] | ||
| /** | ||
| * An Array subclass that preserves comments when array operations are performed. | ||
| * | ||
| * CommentArray extends the native Array class and automatically handles comment | ||
| * preservation during array mutations like splice, slice, push, pop, etc. | ||
| * Comments are stored as symbol properties and are moved/copied appropriately | ||
| * when the array structure changes. | ||
| * | ||
| * @extends Array | ||
| * | ||
| * @example | ||
| * const arr = parse('[1, 2, 3]') // with comments | ||
| * // arr is a CommentArray instance | ||
| * arr.splice(1, 1) // Comments are preserved and repositioned correctly | ||
| */ | ||
| class CommentArray extends Array { | ||
@@ -97,2 +112,10 @@ // - deleteCount + items.length | ||
| // - slice | ||
| /** | ||
| * Changes the contents of an array by removing or replacing existing | ||
| * elements and/or adding new elements in place. | ||
| * Comments are automatically preserved and repositioned during the operation. | ||
| * | ||
| * @param {...*} args Arguments passed to Array.prototype.splice | ||
| * @returns {CommentArray} A new CommentArray containing the deleted elements. | ||
| */ | ||
| splice (...args) { | ||
@@ -143,2 +166,10 @@ const {length} = this | ||
| /** | ||
| * Returns a shallow copy of a portion of an array into a new CommentArray object. | ||
| * Comments are copied to the appropriate positions in the new array. | ||
| * | ||
| * @param {...*} args Arguments passed to Array.prototype.slice | ||
| * @returns {CommentArray} A new CommentArray containing the extracted | ||
| * elements with their comments. | ||
| */ | ||
| slice (...args) { | ||
@@ -145,0 +176,0 @@ const {length} = this |
+181
-6
@@ -26,3 +26,3 @@ const { | ||
| const SYMBOL_PREFIXES = [ | ||
| const PROP_SYMBOL_PREFIXES = [ | ||
| PREFIX_BEFORE, | ||
@@ -35,8 +35,11 @@ PREFIX_AFTER_PROP, | ||
| const NON_PROP_SYMBOL_KEYS = [ | ||
| const NON_PROP_SYMBOL_PREFIXES = [ | ||
| PREFIX_BEFORE, | ||
| PREFIX_AFTER, | ||
| PREFIX_BEFORE_ALL, | ||
| PREFIX_AFTER_ALL | ||
| ].map(Symbol.for) | ||
| ] | ||
| const NON_PROP_SYMBOL_KEYS = NON_PROP_SYMBOL_PREFIXES.map(Symbol.for) | ||
| const COLON = ':' | ||
@@ -46,3 +49,20 @@ const UNDEFINED = undefined | ||
| const symbol = (prefix, key) => Symbol.for(prefix + COLON + key) | ||
| const symbol_checked = (prefix, key) => { | ||
| if (key) { | ||
| if (PROP_SYMBOL_PREFIXES.includes(prefix)) { | ||
| return symbol(prefix, key) | ||
| } | ||
| throw new RangeError( | ||
| `Unsupported comment position ${prefix} with key ${key}` | ||
| ) | ||
| } | ||
| if (NON_PROP_SYMBOL_PREFIXES.includes(prefix)) { | ||
| return Symbol.for(prefix) | ||
| } | ||
| throw new RangeError(`Unsupported comment position ${prefix}`) | ||
| } | ||
| const define = (target, key, value) => Object.defineProperty(target, key, { | ||
@@ -76,3 +96,3 @@ value, | ||
| ) => { | ||
| SYMBOL_PREFIXES.forEach(prefix => { | ||
| PROP_SYMBOL_PREFIXES.forEach(prefix => { | ||
| copy_comments_by_kind( | ||
@@ -89,3 +109,3 @@ target, source, target_key, source_key, prefix, remove_source | ||
| SYMBOL_PREFIXES.forEach(prefix => { | ||
| PROP_SYMBOL_PREFIXES.forEach(prefix => { | ||
| const target_prop = symbol(prefix, to) | ||
@@ -141,3 +161,3 @@ if (!Object.hasOwn(array, target_prop)) { | ||
| module.exports = { | ||
| SYMBOL_PREFIXES, | ||
| PROP_SYMBOL_PREFIXES, | ||
@@ -173,2 +193,30 @@ PREFIX_BEFORE, | ||
| /** | ||
| * Assign properties and comments from source to target object. | ||
| * | ||
| * @param {Object} target The target object to assign properties and comments | ||
| * to. | ||
| * @param {Object} source The source object to copy properties and comments | ||
| * from. | ||
| * @param {Array<string|number>} [keys] Optional array of keys to assign. If | ||
| * not provided, all keys and non-property comments are assigned. If empty | ||
| * array, only non-property comments are assigned. | ||
| * @returns {Object} The target object with assigned properties and comments. | ||
| * | ||
| * @throws {TypeError} If target cannot be converted to object or keys is not | ||
| * array or undefined. | ||
| * | ||
| * @example | ||
| * const source = parse('{"a": 1 // comment a, "b": 2 // comment b}') | ||
| * const target = {} | ||
| * | ||
| * // Copy all properties and comments | ||
| * assign(target, source) | ||
| * | ||
| * // Copy only specific properties and their comments | ||
| * assign(target, source, ['a']) | ||
| * | ||
| * // Copy only non-property comments | ||
| * assign(target, source, []) | ||
| */ | ||
| assign (target, source, keys) { | ||
@@ -184,2 +232,6 @@ if (!isObject(target)) { | ||
| if (keys === UNDEFINED) { | ||
| // Copy all comments from source to target, including: | ||
| // - non-property comments | ||
| // - property comments | ||
| keys = Object.keys(source) | ||
@@ -192,2 +244,4 @@ // We assign non-property comments | ||
| } else if (keys.length === 0) { | ||
| // Copy all non-property comments from source to target | ||
| // Or argument `keys` is an empty array | ||
@@ -197,4 +251,125 @@ assign_non_prop_comments(target, source) | ||
| // Copy specified property comments from source to target | ||
| return assign(target, source, keys) | ||
| }, | ||
| /** | ||
| * Move comments from one location to another within objects. | ||
| * | ||
| * @param {Object} source The source object containing comments to move. | ||
| * @param {Object} [target] The target object to move comments to. If not | ||
| * provided, defaults to source (move within same object). | ||
| * @param {Object} from The source comment location. | ||
| * @param {string} from.where The comment position (e.g., 'before', | ||
| * 'after', 'before-all', etc.). | ||
| * @param {string} [from.key] The property key for property-specific comments. | ||
| * Omit for non-property comments. | ||
| * @param {Object} to The target comment location. | ||
| * @param {string} to.where The comment position (e.g., 'before', | ||
| * 'after', 'before-all', etc.). | ||
| * @param {string} [to.key] The property key for property-specific comments. | ||
| * Omit for non-property comments. | ||
| * @param {boolean} [override=false] Whether to override existing comments at | ||
| * the target location. If false, comments will be appended. | ||
| * | ||
| * @throws {TypeError} If source is not an object. | ||
| * @throws {RangeError} If where parameter is invalid or incompatible with key. | ||
| * | ||
| * @example | ||
| * const obj = parse('{"a": 1 // comment on a}') | ||
| * | ||
| * // Move comment from after 'a' to before 'a' | ||
| * moveComments(obj, obj, | ||
| * { where: 'after', key: 'a' }, | ||
| * { where: 'before', key: 'a' } | ||
| * ) | ||
| * | ||
| * @example | ||
| * // Move non-property comment | ||
| * moveComments(obj, obj, | ||
| * { where: 'before-all' }, | ||
| * { where: 'after-all' } | ||
| * ) | ||
| */ | ||
| moveComments (source, target, { | ||
| where: from_where, | ||
| key: from_key | ||
| }, { | ||
| where: to_where, | ||
| key: to_key | ||
| }, override = false) { | ||
| if (!isObject(source)) { | ||
| throw new TypeError('source must be an object') | ||
| } | ||
| if (!target) { | ||
| target = source | ||
| } | ||
| if (!isObject(target)) { | ||
| // No target to move to | ||
| return | ||
| } | ||
| const from_prop = symbol_checked(from_where, from_key) | ||
| const to_prop = symbol_checked(to_where, to_key) | ||
| if (!Object.hasOwn(source, from_prop)) { | ||
| return | ||
| } | ||
| const source_comments = source[from_prop] | ||
| delete source[from_prop] | ||
| if (override || !Object.hasOwn(target, to_prop)) { | ||
| // Override | ||
| // or the target has no existing comments | ||
| define(target, to_prop, source_comments) | ||
| return | ||
| } | ||
| const target_comments = target[to_prop] | ||
| if (target_comments) { | ||
| target_comments.push(...source_comments) | ||
| } | ||
| }, | ||
| /** | ||
| * Remove comments from a specific location within an object. | ||
| * | ||
| * @param {Object} target The target object to remove comments from. | ||
| * @param {Object} location The comment location to remove. | ||
| * @param {string} location.where The comment position (e.g., 'before', | ||
| * 'after', 'before-all', etc.). | ||
| * @param {string} [location.key] The property key for property-specific | ||
| * comments. Omit for non-property comments. | ||
| * | ||
| * @throws {TypeError} If target is not an object. | ||
| * @throws {RangeError} If where parameter is invalid or incompatible with key. | ||
| * | ||
| * @example | ||
| * const obj = parse('{"a": 1 // comment on a}') | ||
| * | ||
| * // Remove comment after 'a' | ||
| * removeComments(obj, { where: 'after', key: 'a' }) | ||
| * | ||
| * @example | ||
| * // Remove non-property comment | ||
| * removeComments(obj, { where: 'before-all' }) | ||
| */ | ||
| removeComments (target, { | ||
| where, | ||
| key | ||
| }) { | ||
| if (!isObject(target)) { | ||
| throw new TypeError('target must be an object') | ||
| } | ||
| const prop = symbol_checked(where, key) | ||
| if (!Object.hasOwn(target, prop)) { | ||
| return | ||
| } | ||
| delete target[prop] | ||
| } | ||
| } |
+6
-2
@@ -14,3 +14,5 @@ const {parse, tokenize} = require('./parse') | ||
| assign | ||
| assign, | ||
| moveComments, | ||
| removeComments | ||
| } = require('./common') | ||
@@ -33,3 +35,5 @@ | ||
| CommentArray, | ||
| assign | ||
| assign, | ||
| moveComments, | ||
| removeComments | ||
| } |
+40
-0
@@ -35,2 +35,13 @@ // JSON formatting | ||
| /** | ||
| * Tokenize JSON string with comments into an array of tokens. | ||
| * | ||
| * @param {string} code The JSON string with comments to tokenize. | ||
| * @returns {Array} Array of token objects containing type, value, and location | ||
| * information. | ||
| * | ||
| * @example | ||
| * const tokens = tokenize('{"a": 1 // comment}') | ||
| * // Returns array of tokens including comment tokens | ||
| */ | ||
| const tokenize = code => esprima.tokenize(code, { | ||
@@ -421,2 +432,31 @@ comment: true, | ||
| /** | ||
| * Converts a JavaScript Object Notation (JSON) string with comments into an | ||
| * object. | ||
| * | ||
| * @param {string} code A valid JSON string with comments. | ||
| * @param {function} [rev] A function that transforms the results. This function | ||
| * is called for each member of the object. If a member contains nested | ||
| * objects, the nested objects are transformed before the parent object is. | ||
| * @param {boolean} [no_comments=false] If true, the comments won't be | ||
| * maintained, which is often used when we want to get a clean object. | ||
| * @returns {*} The JavaScript object corresponding to the given JSON text with | ||
| * comments preserved as symbol properties. | ||
| * | ||
| * @example | ||
| * const result = parse('{"a": 1 // This is a comment}') | ||
| * // result.a === 1 | ||
| * // Comments are stored in symbol properties | ||
| * | ||
| * @example | ||
| * // With reviver function | ||
| * const result = parse('{"a": "1"}', (key, value) => { | ||
| * return typeof value === 'string' ? parseInt(value) : value | ||
| * }) | ||
| * | ||
| * @example | ||
| * // Without comments | ||
| * const clean = parse('{"a": 1 // comment}', null, true) | ||
| * // Returns clean object without comment symbols | ||
| */ | ||
| const parse = (code, rev, no_comments) => { | ||
@@ -423,0 +463,0 @@ // Clean variables in closure |
+27
-2
@@ -335,4 +335,29 @@ const { | ||
| // @param {function()|Array} replacer | ||
| // @param {string|number} space | ||
| /** | ||
| * Converts a JavaScript value to a JavaScript Object Notation (JSON) string | ||
| * with comments preserved. | ||
| * | ||
| * @param {*} value A JavaScript value, usually an object or array, to be | ||
| * converted. | ||
| * @param {function|Array|null} [replacer_] A function that transforms the | ||
| * results or an array of strings and numbers that acts as an approved list | ||
| * for selecting the object properties that will be stringified. | ||
| * @param {string|number} [space] Adds indentation, white space, and line | ||
| * break characters to the return-value JSON text to make it easier to read. | ||
| * @returns {string} A JSON string representing the given value with comments | ||
| * preserved. | ||
| * | ||
| * @example | ||
| * const obj = parse('{"a": 1 // comment}') | ||
| * stringify(obj, null, 2) | ||
| * // Returns: '{\n "a": 1 // comment\n}' | ||
| * | ||
| * @example | ||
| * // With replacer function | ||
| * stringify(obj, (key, value) => typeof value === 'number' ? value * 2 : value) | ||
| * | ||
| * @example | ||
| * // With replacer array | ||
| * stringify(obj, ['a', 'b']) // Only include 'a' and 'b' properties | ||
| */ | ||
| module.exports = (value, replacer_, space) => { | ||
@@ -339,0 +364,0 @@ // The stringify method takes a value and an optional replacer, and an optional |
63933
32.37%1481
27.45%806
27.33%