comment-json
Advanced tools
+1
-1
| { | ||
| "name": "comment-json", | ||
| "version": "4.5.1", | ||
| "version": "4.6.0", | ||
| "description": "Parse and stringify JSON with comments. It will retain comments even after saved!", | ||
@@ -5,0 +5,0 @@ "main": "src/index.js", |
+19
-0
@@ -46,2 +46,5 @@ const { | ||
| const LINE_BREAKS_BEFORE = new WeakMap() | ||
| const LINE_BREAKS_AFTER = new WeakMap() | ||
| const symbol = (prefix, key) => Symbol.for(prefix + COLON + key) | ||
@@ -156,2 +159,15 @@ const symbol_checked = (prefix, key) => { | ||
| const set_comment_line_breaks = (comment, before, after) => { | ||
| if (isNumber(before) && before >= 0) { | ||
| LINE_BREAKS_BEFORE.set(comment, before) | ||
| } | ||
| if (isNumber(after) && after >= 0) { | ||
| LINE_BREAKS_AFTER.set(comment, after) | ||
| } | ||
| } | ||
| const get_comment_line_breaks_before = comment => LINE_BREAKS_BEFORE.get(comment) | ||
| const get_comment_line_breaks_after = comment => LINE_BREAKS_AFTER.get(comment) | ||
| module.exports = { | ||
@@ -188,2 +204,5 @@ PROP_SYMBOL_PREFIXES, | ||
| is_raw_json, | ||
| set_comment_line_breaks, | ||
| get_comment_line_breaks_before, | ||
| get_comment_line_breaks_after, | ||
@@ -190,0 +209,0 @@ /** |
+26
-1
@@ -32,2 +32,3 @@ // JSON formatting | ||
| define, | ||
| set_comment_line_breaks, | ||
| assign_non_prop_comments | ||
@@ -222,2 +223,11 @@ } = require('./common') | ||
| const previous_line = last | ||
| ? last.loc.end.line | ||
| : 1 | ||
| set_comment_line_breaks( | ||
| comment, | ||
| Math.max(0, comment.loc.start.line - previous_line) | ||
| ) | ||
| // delete comment.loc | ||
@@ -229,2 +239,17 @@ comments.push(comment) | ||
| const {length} = comments | ||
| if (length) { | ||
| const comment = comments[length - 1] | ||
| const current_line = current | ||
| ? current.loc.start.line | ||
| : comment.loc.end.line | ||
| set_comment_line_breaks( | ||
| comment, | ||
| undefined, | ||
| Math.max(0, current_line - comment.loc.end.line) | ||
| ) | ||
| } | ||
| if (remove_comments) { | ||
@@ -234,3 +259,3 @@ return | ||
| if (!comments.length) { | ||
| if (!length) { | ||
| return | ||
@@ -237,0 +262,0 @@ } |
+102
-19
@@ -23,2 +23,4 @@ const { | ||
| UNDEFINED, | ||
| get_comment_line_breaks_before, | ||
| get_comment_line_breaks_after, | ||
@@ -76,3 +78,47 @@ is_raw_json | ||
| : `/*${value}*/` | ||
| const repeat_line_breaks = (line_breaks, gap) => (LF + gap).repeat(line_breaks) | ||
| const read_line_breaks = line_breaks => isNumber(line_breaks) && line_breaks >= 0 | ||
| ? line_breaks | ||
| : null | ||
| const read_line_breaks_from_loc = (previous_comment, comment) => { | ||
| if ( | ||
| !previous_comment | ||
| || !previous_comment.loc | ||
| || !comment.loc | ||
| ) { | ||
| return null | ||
| } | ||
| const {end} = previous_comment.loc | ||
| const {start} = comment.loc | ||
| if ( | ||
| !end | ||
| || !start | ||
| || !isNumber(end.line) | ||
| || !isNumber(start.line) | ||
| ) { | ||
| return null | ||
| } | ||
| const line_breaks = start.line - end.line | ||
| return line_breaks >= 0 | ||
| ? line_breaks | ||
| : null | ||
| } | ||
| const count_trailing_line_breaks = (str, gap) => { | ||
| const unit = LF + gap | ||
| const {length} = unit | ||
| let i = str.length | ||
| let count = 0 | ||
| while (i >= length && str.slice(i - length, i) === unit) { | ||
| i -= length | ||
| count ++ | ||
| } | ||
| return count | ||
| } | ||
| // display_block `boolean` whether the | ||
@@ -86,23 +132,54 @@ // WHOLE block of comments is always a block group | ||
| let is_line_comment = false | ||
| let str = EMPTY | ||
| let last_comment = null | ||
| const str = comments.reduce((prev, { | ||
| inline, | ||
| type, | ||
| value | ||
| }) => { | ||
| const delimiter = inline | ||
| ? SPACE | ||
| : LF + deeper_gap | ||
| comments.forEach((comment, i) => { | ||
| const { | ||
| inline, | ||
| type, | ||
| value | ||
| } = comment | ||
| is_line_comment = type === 'LineComment' | ||
| let line_breaks_before = read_line_breaks( | ||
| get_comment_line_breaks_before(comment) | ||
| ) | ||
| return prev + delimiter + comment_stringify(value, is_line_comment) | ||
| }, EMPTY) | ||
| if (line_breaks_before === null) { | ||
| line_breaks_before = read_line_breaks_from_loc(last_comment, comment) | ||
| } | ||
| return display_block | ||
| // line comment should always end with a LF | ||
| || is_line_comment | ||
| ? str + LF + deeper_gap | ||
| : str | ||
| if (line_breaks_before === null) { | ||
| line_breaks_before = inline | ||
| ? 0 | ||
| : 1 | ||
| } | ||
| const delimiter = line_breaks_before > 0 | ||
| ? repeat_line_breaks(line_breaks_before, deeper_gap) | ||
| : inline | ||
| ? SPACE | ||
| // The first comment at the very beginning of the source. | ||
| : i === 0 | ||
| ? EMPTY | ||
| : LF + deeper_gap | ||
| const is_line_comment = type === 'LineComment' | ||
| str += delimiter + comment_stringify(value, is_line_comment) | ||
| last_comment = comment | ||
| }) | ||
| const default_line_breaks_after = display_block | ||
| // line comment should always end with a LF | ||
| || last_comment.type === 'LineComment' | ||
| ? 1 | ||
| : 0 | ||
| const line_breaks_after = Math.max( | ||
| default_line_breaks_after, | ||
| read_line_breaks(get_comment_line_breaks_after(last_comment)) || 0 | ||
| ) | ||
| return str + repeat_line_breaks(line_breaks_after, deeper_gap) | ||
| } | ||
@@ -126,5 +203,11 @@ | ||
| ? one + two.trim() + LF + gap | ||
| : one.trimRight() + LF + gap | ||
| : one.trimRight() + repeat_line_breaks( | ||
| Math.max(1, count_trailing_line_breaks(one, gap)), | ||
| gap | ||
| ) | ||
| : two | ||
| ? two.trimRight() + LF + gap | ||
| ? two.trimRight() + repeat_line_breaks( | ||
| Math.max(1, count_trailing_line_breaks(two, gap)), | ||
| gap | ||
| ) | ||
| : EMPTY | ||
@@ -131,0 +214,0 @@ |
66981
4.75%1586
7.09%