Skip to content

Commit b78f84c

Browse files
committed
feat: new public method, moveComments
1 parent 65996b7 commit b78f84c

File tree

6 files changed

+77
-3
lines changed

6 files changed

+77
-3
lines changed

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -461,7 +461,7 @@ stringify(obj, null, 2)
461461
462462
### Special cases about `keys`
463463
464-
But if argument `keys` is specified and is not empty, then comment ` before all`, which belongs to no properties, will **NOT** be copied.
464+
But if argument `keys` is specified and is not empty, then comment ` before all`, which belongs to non-properties, will **NOT** be copied.
465465
466466
```js
467467
const obj = assign({
@@ -495,6 +495,7 @@ Non-property symbols include:
495495
```js
496496
Symbol.for('before-all')
497497
Symbol.for('before')
498+
Symbol.for('after') // only for stringify
498499
Symbol.for('after-all')
499500
```
500501

index.d.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,3 +111,16 @@ export function assign<TTarget, TSource>(
111111
// we set the type of `keys` stricter
112112
keys?: readonly (number | string)[]
113113
): TTarget
114+
115+
export function moveComments(
116+
source: CommentJSONValue,
117+
target: CommentJSONValue,
118+
from: {
119+
kind: string,
120+
key?: string
121+
},
122+
to: {
123+
kind: string,
124+
key?: string
125+
}, override?: boolean
126+
): void

src/common.js

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,9 @@ const COLON = ':'
4141
const UNDEFINED = undefined
4242

4343
const symbol = (prefix, key) => Symbol.for(prefix + COLON + key)
44+
const symbol_checked = (prefix, key) => key
45+
? symbol(prefix, key)
46+
: prefix
4447

4548
const define = (target, key, value) => Object.defineProperty(target, key, {
4649
value,
@@ -164,6 +167,7 @@ module.exports = {
164167

165168
is_raw_json,
166169

170+
// TODO: js doc and usage examples
167171
assign (target, source, keys) {
168172
if (!isObject(target)) {
169173
throw new TypeError('Cannot convert undefined or null to object')
@@ -174,17 +178,68 @@ module.exports = {
174178
}
175179

176180
if (keys === UNDEFINED) {
181+
// Copy all comments from source to target, including:
182+
// - non-property comments
183+
// - property comments
184+
177185
keys = Object.keys(source)
178186
// We assign non-property comments
179187
// if argument `keys` is not specified
180188
assign_non_prop_comments(target, source)
181189
} else if (!isArray(keys)) {
182190
throw new TypeError('keys must be array or undefined')
183191
} else if (keys.length === 0) {
192+
// Copy all non-property comments from source to target
193+
184194
// Or argument `keys` is an empty array
185195
assign_non_prop_comments(target, source)
186196
}
187197

198+
// Copy specified property comments from source to target
188199
return assign(target, source, keys)
200+
},
201+
202+
// TODO: js doc and usage examples
203+
moveComments (source, target, {
204+
kind: from_kind,
205+
key: from_key
206+
}, {
207+
kind: to_kind,
208+
key: to_key
209+
}, override = false) {
210+
if (!isObject(source)) {
211+
throw new TypeError('source must be an object')
212+
}
213+
214+
if (!target) {
215+
target = source
216+
}
217+
218+
if (!isObject(target)) {
219+
// No target to move to
220+
return
221+
}
222+
223+
const from_prop = symbol_checked(from_kind, from_key)
224+
const to_prop = symbol_checked(to_kind, to_key)
225+
226+
if (!Object.hasOwn(source, from_prop)) {
227+
return
228+
}
229+
230+
const source_comments = source[from_prop]
231+
delete source[from_prop]
232+
233+
if (override || !Object.hasOwn(target, to_prop)) {
234+
// Override
235+
// or the target has no existing comments
236+
define(target, to_prop, source_comments)
237+
return
238+
}
239+
240+
const target_comments = target[to_prop]
241+
if (target_comments) {
242+
target_comments.push(...source_comments)
243+
}
189244
}
190245
}

src/index.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ const {
1111
PREFIX_BEFORE_ALL,
1212
PREFIX_AFTER_ALL,
1313

14-
assign
14+
assign,
15+
moveComments
1516
} = require('./common')
1617

1718
module.exports = {
@@ -29,5 +30,6 @@ module.exports = {
2930
tokenize,
3031

3132
CommentArray,
32-
assign
33+
assign,
34+
moveComments
3335
}

src/parse.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -417,6 +417,7 @@ function walk () {
417417

418418
const isObject = subject => Object(subject) === subject
419419

420+
// TODO: js doc and usage examples
420421
const parse = (code, rev, no_comments) => {
421422
// Clean variables in closure
422423
clean()

src/stringify.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,8 @@ const is_primitive_object = subject => {
332332
return PRIMITIVE_OBJECT_TYPES.includes(str)
333333
}
334334

335+
// TODO: js doc and usage examples
336+
335337
// @param {function()|Array} replacer
336338
// @param {string|number} space
337339
module.exports = (value, replacer_, space) => {

0 commit comments

Comments
 (0)