Skip to content

Commit 74e7836

Browse files
committed
added writer configuration: emptyLineBeforeComments
1 parent 3ac9f7b commit 74e7836

File tree

8 files changed

+85
-24
lines changed

8 files changed

+85
-24
lines changed

README.md

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11

22
JSON Inline Doc
33
============================
4-
#### Add inline comments on stringified JSON, or generate from JSON schema
4+
#### Add inline comments on stringified JSON (JSONC), or generate from JSON schema
55

66
Use case: Using JSON for configuration and provide inline documentation as comments for users.
77

8-
Note: JSON does not support comments. But some editors have the so-called 'JSON with comments' support.
8+
JSONC is JSON with JavaScript style comments. Please note that original JSON does not support comments.
99

1010
Installation:
1111
--------------------------
@@ -113,6 +113,14 @@ The abstract base class of all writers.
113113
**`writer = new JSONCommentWriterBase(configuration)`**
114114
* Note: The above line of code is only for explanation. This class is abstract - do not try to `new` a instance by yourself!
115115
* `configuration`: object (optional)
116+
* `emptyLineBeforeComments`: boolean (default true)
117+
118+
Add a blank line before every `block` and `line` comment, except comments of the followings:
119+
* The root object
120+
* The first item in array
121+
* The first key-value pair in object
122+
123+
Not supported if `space` when calling `stringify` is 0.
116124
* `spaceAroundCommentSymbol`: boolean (default true)
117125

118126
Add space around '//', '/\*' and '\*/'.

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "json-inline-doc",
3-
"version": "1.0.2",
4-
"description": "Add inline comments on stringified JSON, or generate from JSON schema",
3+
"version": "2.0.0",
4+
"description": "Add inline comments on stringified JSON (JSONC), or generate from JSON schema",
55
"main": "./lib/index.js",
66
"typings": "./lib/index.d.ts",
77
"repository": {

src/defaultCommentGenerator.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,10 @@ export const defaultCommentGenerator: CommentGenerator = (schema) => {
2222
}
2323
}
2424
}
25-
return contents.length === 0 ? undefined : {
26-
type: 'block',
27-
content: contents.join('\n')
28-
};
25+
return contents.length === 0
26+
? undefined
27+
: {
28+
type: 'block',
29+
content: contents.join('\n')
30+
};
2931
};

src/jsonCommentWriterBase.ts

Lines changed: 35 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import {
1313
*/
1414
export abstract class JSONCommentWriterBase<CommentDataNodeType> {
1515
private static readonly defaultConfiguration: IJSONCommentConfiguration = {
16+
emptyLineBeforeComments: true,
1617
spaceAroundCommentSymbol: true,
1718
styledBlockComment: true,
1819
maxLineLength: 80
@@ -185,8 +186,7 @@ ${gap} */`;
185186
return 'null';
186187
}
187188
const currGap: string = gap + this.indent;
188-
const lineBreakCurrGap: string =
189-
currGap ? '\n' + currGap : '';
189+
const lineBreakCurrGap: string = currGap ? '\n' + currGap : '';
190190
const lineEndComments: { [index: number]: string } = {};
191191
const partial: string[] = [];
192192
const fnPartialToLine: (value: string, i: number) => string =
@@ -197,15 +197,27 @@ ${gap} */`;
197197
}
198198
for (let i: number = 0; i < value.length; i++) {
199199
const { comments: parts, childJSON, lineEndComment } = this.getChildJSON(value, i, currGap, node);
200-
parts.push(childJSON || 'null');
200+
201201
if (lineEndComment !== undefined) {
202202
lineEndComments[i] = lineEndComment;
203203
}
204-
partial.push(parts.join(lineBreakCurrGap));
204+
205+
parts.push(childJSON || 'null');
206+
const currentItemWithComments: string = parts.join(lineBreakCurrGap);
207+
208+
if (this.configuration.emptyLineBeforeComments && i > 0 && parts.length > 1 && currGap) {
209+
// Not the first item in array && has comment && spaces != 0
210+
// Add a empty line
211+
partial.push(lineBreakCurrGap + currentItemWithComments);
212+
} else {
213+
partial.push(currGap + currentItemWithComments);
214+
}
205215
}
206-
return currGap ? `[
207-
${currGap}${partial.map(fnPartialToLine).join(lineBreakCurrGap)}
208-
${gap}]` : `[${partial.join(',')}]`;
216+
return currGap
217+
? `[
218+
${partial.map(fnPartialToLine).join('\n')}
219+
${gap}]`
220+
: `[${partial.join(',')}]`;
209221
} else {
210222
const keys: (string | number)[] = Array.isArray(this.replacer) ? this.replacer : Object.keys(value);
211223
if (keys.length === 0) {
@@ -214,16 +226,27 @@ ${gap}]` : `[${partial.join(',')}]`;
214226
for (const k of keys) {
215227
const { comments: parts, childJSON, lineEndComment } = this.getChildJSON(value, k, currGap, node);
216228
if (childJSON) {
217-
parts.push(JSON.stringify(k) + (currGap ? ': ' : ':') + childJSON);
218229
if (lineEndComment !== undefined) {
219230
lineEndComments[partial.length] = lineEndComment;
220231
}
221-
partial.push(parts.join(lineBreakCurrGap));
232+
233+
parts.push(JSON.stringify(k) + (currGap ? ': ' : ':') + childJSON);
234+
const currentKVPairWithComments: string = parts.join(lineBreakCurrGap);
235+
236+
if (this.configuration.emptyLineBeforeComments && partial.length > 0 && parts.length > 1 && currGap) {
237+
// Not the first key-value pair in object && has comment && spaces != 0
238+
// Add a empty line
239+
partial.push(lineBreakCurrGap + currentKVPairWithComments);
240+
} else {
241+
partial.push(currGap + currentKVPairWithComments);
242+
}
222243
}
223244
}
224-
return currGap ? `{
225-
${currGap}${partial.map(fnPartialToLine).join(lineBreakCurrGap)}
226-
${gap}}` : `{${partial.join(',')}}`;
245+
return currGap
246+
? `{
247+
${partial.map(fnPartialToLine).join('\n')}
248+
${gap}}`
249+
: `{${partial.join(',')}}`;
227250
}
228251
} else {
229252
return JSON.stringify(value);

src/test/assets.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,12 @@ export const TEST_SCHEMA_COMMENTED = `/**
4141
* @description Description of the schema
4242
*/
4343
"description": "Cluster Configuration",
44+
4445
/**
4546
* @description Type of the schema
4647
*/
4748
"type": "object",
49+
4850
/**
4951
* @type object
5052
* @description Available properties of the schema
@@ -60,13 +62,15 @@ export const TEST_SCHEMA_COMMENTED = `/**
6062
* @description Type of the schema
6163
*/
6264
"type": "string",
65+
6366
/**
6467
* @type string
6568
* @description Description of the schema
6669
*/
6770
"description": "Cluster name"
6871
}
6972
},
73+
7074
/**
7175
* @type array
7276
* @default []

src/test/blockComment.test.ts

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,12 @@ describe('block comments', () => {
3636
* test4
3737
*/
3838
1,
39+
3940
/**
4041
* test3
4142
*/
4243
2,
44+
4345
/**
4446
* test4
4547
*/
@@ -59,8 +61,12 @@ describe('block comments', () => {
5961
}`);
6062
});
6163

62-
it('should reflect changes in configuration - no style and space', () => {
63-
const w: CustomCommentWriter = new CustomCommentWriter({ spaceAroundCommentSymbol: false, styledBlockComment: false });
64+
it('should reflect changes in configuration - no empty line, style and space', () => {
65+
const w: CustomCommentWriter = new CustomCommentWriter({
66+
emptyLineBeforeComments: false,
67+
spaceAroundCommentSymbol: false,
68+
styledBlockComment: false
69+
});
6470
w.addComments([], [{ type: 'block', content: 'test' }]);
6571
w.addComments(['test'], [{ type: 'block', content: 'test2' }]);
6672
w.addComments(['test', 1], [{ type: 'block', content: 'test3' }]);
@@ -94,7 +100,7 @@ describe('block comments', () => {
94100
}`);
95101
});
96102

97-
it('should reflect changes in configuration - no style but with space', () => {
103+
it('should reflect changes in configuration - no style but with empty line and space', () => {
98104
const w: CustomCommentWriter = new CustomCommentWriter({ styledBlockComment: false });
99105
w.addComments([], [{ type: 'block', content: 'test' }]);
100106
w.addComments(['test'], [{ type: 'block', content: 'test2' }]);
@@ -114,8 +120,10 @@ describe('block comments', () => {
114120
"test": [
115121
/* test4 */
116122
1,
123+
117124
/* test3 */
118125
2,
126+
119127
/* test4 */
120128
3
121129
]

src/test/lineComment.test.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,10 @@ describe('line comments', () => {
2424
"test": [
2525
// test4
2626
1,
27+
2728
// test3
2829
2,
30+
2931
// test4
3032
3
3133
]
@@ -40,7 +42,10 @@ describe('line comments', () => {
4042
});
4143

4244
it('should reflect changes in configuration', () => {
43-
const w: CustomCommentWriter = new CustomCommentWriter({ spaceAroundCommentSymbol: false });
45+
const w: CustomCommentWriter = new CustomCommentWriter({
46+
emptyLineBeforeComments: false,
47+
spaceAroundCommentSymbol: false
48+
});
4449
w.addComments([], [{ type: 'line', content: 'test' }]);
4550
w.addComments(['test'], [{ type: 'line', content: 'test2' }]);
4651
w.addComments(['test', 1], [{ type: 'line', content: 'test3' }]);

src/types.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,17 @@ export type IJSONComment = {
2525
} | string;
2626

2727
export interface IJSONCommentConfiguration {
28+
/**
29+
* @description Add a blank line before every `block` and `line` comment,
30+
* except comments of the followings:
31+
* * The root object
32+
* * The first item in array
33+
* * The first key-value pair in object
34+
* Not supported if `space` when calling `stringify` is 0.
35+
*
36+
* @default true
37+
*/
38+
emptyLineBeforeComments: boolean;
2839
/**
2940
* @description Add space around '//', '/\*' and '\*\/'.
3041
* '/\*' and '\*\/' will not be affected by this

0 commit comments

Comments
 (0)