comment-parser 1.1.1 → 1.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/browser/index.js CHANGED
@@ -200,7 +200,7 @@ var CommentParser = (function (exports) {
200
200
  tokens.type = tokens.postDelimiter.slice(offset) + type;
201
201
  tokens.postDelimiter = tokens.postDelimiter.slice(0, offset);
202
202
  }
203
- [tokens.postType, tokens.description] = splitSpace(tokens.description.slice(tokens.type.length));
203
+ [tokens.postType, tokens.description] = splitSpace(tokens.description.slice(type.length));
204
204
  parts.push(tokens.type);
205
205
  }
206
206
  parts[0] = parts[0].slice(1);
@@ -430,14 +430,6 @@ var CommentParser = (function (exports) {
430
430
  type: Math.max(w.type, t.type.length),
431
431
  name: Math.max(w.name, t.name.length),
432
432
  });
433
- // /**
434
- // * Description may go
435
- // * over multiple lines followed by @tags
436
- // *
437
- //* @my-tag {my.type} my-name description line 1
438
- // description line 2
439
- // * description line 3
440
- // */
441
433
  const space = (len) => ''.padStart(len, ' ');
442
434
  function align() {
443
435
  let intoTags = false;
@@ -463,14 +455,41 @@ var CommentParser = (function (exports) {
463
455
  tokens.start = space(w.start + 1);
464
456
  break;
465
457
  default:
466
- tokens.start = space(w.start + 3);
467
458
  tokens.delimiter = '';
459
+ tokens.start = space(w.start + 2); // compensate delimiter
468
460
  }
469
- if (intoTags) {
461
+ if (!intoTags) {
462
+ tokens.postDelimiter = tokens.description === '' ? '' : ' ';
463
+ return Object.assign(Object.assign({}, line), { tokens });
464
+ }
465
+ const nothingAfter = {
466
+ delim: false,
467
+ tag: false,
468
+ type: false,
469
+ name: false,
470
+ };
471
+ if (tokens.description === '') {
472
+ nothingAfter.name = true;
473
+ tokens.postName = '';
474
+ if (tokens.name === '') {
475
+ nothingAfter.type = true;
476
+ tokens.postType = '';
477
+ if (tokens.type === '') {
478
+ nothingAfter.tag = true;
479
+ tokens.postTag = '';
480
+ if (tokens.tag === '') {
481
+ nothingAfter.delim = true;
482
+ }
483
+ }
484
+ }
485
+ }
486
+ tokens.postDelimiter = nothingAfter.delim ? '' : ' ';
487
+ if (!nothingAfter.tag)
470
488
  tokens.postTag = space(w.tag - tokens.tag.length + 1);
489
+ if (!nothingAfter.type)
471
490
  tokens.postType = space(w.type - tokens.type.length + 1);
491
+ if (!nothingAfter.name)
472
492
  tokens.postName = space(w.name - tokens.name.length + 1);
473
- }
474
493
  return Object.assign(Object.assign({}, line), { tokens });
475
494
  }
476
495
  return (_a) => {
package/es6/index.d.ts CHANGED
@@ -7,7 +7,7 @@ import alignTransform from './transforms/align';
7
7
  import indentTransform from './transforms/indent';
8
8
  import { flow as flowTransform } from './transforms/index';
9
9
  export declare function parse(source: string, options?: Partial<ParserOptions>): import("./primitives").Block[];
10
- export declare const stringify: (block: import("./primitives").Block) => string;
10
+ export declare const stringify: import("./stringifier").Stringifier;
11
11
  export { default as inspect } from './stringifier/inspect';
12
12
  export declare const transforms: {
13
13
  flow: typeof flowTransform;
@@ -6,4 +6,5 @@ export interface Options {
6
6
  spacing: 'compact' | 'preserve';
7
7
  tokenizers: Tokenizer[];
8
8
  }
9
- export default function getParser({ startLine, fence, spacing, tokenizers, }?: Partial<Options>): (source: string) => Block[];
9
+ export declare type Parser = (source: string) => Block[];
10
+ export default function getParser({ startLine, fence, spacing, tokenizers, }?: Partial<Options>): Parser;
@@ -47,7 +47,7 @@ export default function typeTokenizer(spacing = 'compact') {
47
47
  tokens.type = tokens.postDelimiter.slice(offset) + type;
48
48
  tokens.postDelimiter = tokens.postDelimiter.slice(0, offset);
49
49
  }
50
- [tokens.postType, tokens.description] = splitSpace(tokens.description.slice(tokens.type.length));
50
+ [tokens.postType, tokens.description] = splitSpace(tokens.description.slice(type.length));
51
51
  parts.push(tokens.type);
52
52
  }
53
53
  parts[0] = parts[0].slice(1);
@@ -1,2 +1,3 @@
1
1
  import { Block } from '../primitives';
2
- export default function getStringifier(): (block: Block) => string;
2
+ export declare type Stringifier = (block: Block) => string;
3
+ export default function getStringifier(): Stringifier;
@@ -23,14 +23,6 @@ const getWidth = (w, { tokens: t }) => ({
23
23
  type: Math.max(w.type, t.type.length),
24
24
  name: Math.max(w.name, t.name.length),
25
25
  });
26
- // /**
27
- // * Description may go
28
- // * over multiple lines followed by @tags
29
- // *
30
- //* @my-tag {my.type} my-name description line 1
31
- // description line 2
32
- // * description line 3
33
- // */
34
26
  const space = (len) => ''.padStart(len, ' ');
35
27
  export default function align() {
36
28
  let intoTags = false;
@@ -56,14 +48,41 @@ export default function align() {
56
48
  tokens.start = space(w.start + 1);
57
49
  break;
58
50
  default:
59
- tokens.start = space(w.start + 3);
60
51
  tokens.delimiter = '';
52
+ tokens.start = space(w.start + 2); // compensate delimiter
61
53
  }
62
- if (intoTags) {
54
+ if (!intoTags) {
55
+ tokens.postDelimiter = tokens.description === '' ? '' : ' ';
56
+ return Object.assign(Object.assign({}, line), { tokens });
57
+ }
58
+ const nothingAfter = {
59
+ delim: false,
60
+ tag: false,
61
+ type: false,
62
+ name: false,
63
+ };
64
+ if (tokens.description === '') {
65
+ nothingAfter.name = true;
66
+ tokens.postName = '';
67
+ if (tokens.name === '') {
68
+ nothingAfter.type = true;
69
+ tokens.postType = '';
70
+ if (tokens.type === '') {
71
+ nothingAfter.tag = true;
72
+ tokens.postTag = '';
73
+ if (tokens.tag === '') {
74
+ nothingAfter.delim = true;
75
+ }
76
+ }
77
+ }
78
+ }
79
+ tokens.postDelimiter = nothingAfter.delim ? '' : ' ';
80
+ if (!nothingAfter.tag)
63
81
  tokens.postTag = space(w.tag - tokens.tag.length + 1);
82
+ if (!nothingAfter.type)
64
83
  tokens.postType = space(w.type - tokens.type.length + 1);
84
+ if (!nothingAfter.name)
65
85
  tokens.postName = space(w.name - tokens.name.length + 1);
66
- }
67
86
  return Object.assign(Object.assign({}, line), { tokens });
68
87
  }
69
88
  return (_a) => {
package/lib/index.d.ts CHANGED
@@ -7,7 +7,7 @@ import alignTransform from './transforms/align';
7
7
  import indentTransform from './transforms/indent';
8
8
  import { flow as flowTransform } from './transforms/index';
9
9
  export declare function parse(source: string, options?: Partial<ParserOptions>): import("./primitives").Block[];
10
- export declare const stringify: (block: import("./primitives").Block) => string;
10
+ export declare const stringify: import("./stringifier").Stringifier;
11
11
  export { default as inspect } from './stringifier/inspect';
12
12
  export declare const transforms: {
13
13
  flow: typeof flowTransform;
@@ -6,4 +6,5 @@ export interface Options {
6
6
  spacing: 'compact' | 'preserve';
7
7
  tokenizers: Tokenizer[];
8
8
  }
9
- export default function getParser({ startLine, fence, spacing, tokenizers, }?: Partial<Options>): (source: string) => Block[];
9
+ export declare type Parser = (source: string) => Block[];
10
+ export default function getParser({ startLine, fence, spacing, tokenizers, }?: Partial<Options>): Parser;
@@ -49,7 +49,7 @@ function typeTokenizer(spacing = 'compact') {
49
49
  tokens.type = tokens.postDelimiter.slice(offset) + type;
50
50
  tokens.postDelimiter = tokens.postDelimiter.slice(0, offset);
51
51
  }
52
- [tokens.postType, tokens.description] = util_1.splitSpace(tokens.description.slice(tokens.type.length));
52
+ [tokens.postType, tokens.description] = util_1.splitSpace(tokens.description.slice(type.length));
53
53
  parts.push(tokens.type);
54
54
  }
55
55
  parts[0] = parts[0].slice(1);
@@ -1,2 +1,3 @@
1
1
  import { Block } from '../primitives';
2
- export default function getStringifier(): (block: Block) => string;
2
+ export declare type Stringifier = (block: Block) => string;
3
+ export default function getStringifier(): Stringifier;
@@ -25,14 +25,6 @@ const getWidth = (w, { tokens: t }) => ({
25
25
  type: Math.max(w.type, t.type.length),
26
26
  name: Math.max(w.name, t.name.length),
27
27
  });
28
- // /**
29
- // * Description may go
30
- // * over multiple lines followed by @tags
31
- // *
32
- //* @my-tag {my.type} my-name description line 1
33
- // description line 2
34
- // * description line 3
35
- // */
36
28
  const space = (len) => ''.padStart(len, ' ');
37
29
  function align() {
38
30
  let intoTags = false;
@@ -58,14 +50,41 @@ function align() {
58
50
  tokens.start = space(w.start + 1);
59
51
  break;
60
52
  default:
61
- tokens.start = space(w.start + 3);
62
53
  tokens.delimiter = '';
54
+ tokens.start = space(w.start + 2); // compensate delimiter
63
55
  }
64
- if (intoTags) {
56
+ if (!intoTags) {
57
+ tokens.postDelimiter = tokens.description === '' ? '' : ' ';
58
+ return Object.assign(Object.assign({}, line), { tokens });
59
+ }
60
+ const nothingAfter = {
61
+ delim: false,
62
+ tag: false,
63
+ type: false,
64
+ name: false,
65
+ };
66
+ if (tokens.description === '') {
67
+ nothingAfter.name = true;
68
+ tokens.postName = '';
69
+ if (tokens.name === '') {
70
+ nothingAfter.type = true;
71
+ tokens.postType = '';
72
+ if (tokens.type === '') {
73
+ nothingAfter.tag = true;
74
+ tokens.postTag = '';
75
+ if (tokens.tag === '') {
76
+ nothingAfter.delim = true;
77
+ }
78
+ }
79
+ }
80
+ }
81
+ tokens.postDelimiter = nothingAfter.delim ? '' : ' ';
82
+ if (!nothingAfter.tag)
65
83
  tokens.postTag = space(w.tag - tokens.tag.length + 1);
84
+ if (!nothingAfter.type)
66
85
  tokens.postType = space(w.type - tokens.type.length + 1);
86
+ if (!nothingAfter.name)
67
87
  tokens.postName = space(w.name - tokens.name.length + 1);
68
- }
69
88
  return Object.assign(Object.assign({}, line), { tokens });
70
89
  }
71
90
  return (_a) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "comment-parser",
3
- "version": "1.1.1",
3
+ "version": "1.1.2",
4
4
  "description": "Generic JSDoc-like comment parser",
5
5
  "main": "lib/index.js",
6
6
  "types": "lib/index.d.ts",
@@ -22,6 +22,8 @@ export interface Options {
22
22
  tokenizers: Tokenizer[];
23
23
  }
24
24
 
25
+ export type Parser = (source: string) => Block[];
26
+
25
27
  export default function getParser({
26
28
  startLine = 0,
27
29
  fence = '```',
@@ -32,7 +34,7 @@ export default function getParser({
32
34
  tokenizeName(),
33
35
  tokenizeDescription(spacing),
34
36
  ],
35
- }: Partial<Options> = {}) {
37
+ }: Partial<Options> = {}): Parser {
36
38
  if (startLine < 0 || startLine % 1 > 0) throw new Error('Invalid startLine');
37
39
 
38
40
  const parseSource = sourceParser({ startLine });
@@ -71,7 +71,7 @@ export default function typeTokenizer(spacing: Spacing = 'compact'): Tokenizer {
71
71
  tokens.postDelimiter = tokens.postDelimiter.slice(0, offset);
72
72
  }
73
73
  [tokens.postType, tokens.description] = splitSpace(
74
- tokens.description.slice(tokens.type.length)
74
+ tokens.description.slice(type.length)
75
75
  );
76
76
  parts.push(tokens.type);
77
77
  }
@@ -1,5 +1,7 @@
1
1
  import { Block, Tokens } from '../primitives';
2
2
 
3
+ export type Stringifier = (block: Block) => string;
4
+
3
5
  function join(tokens: Tokens): string {
4
6
  return (
5
7
  tokens.start +
@@ -16,7 +18,7 @@ function join(tokens: Tokens): string {
16
18
  );
17
19
  }
18
20
 
19
- export default function getStringifier() {
21
+ export default function getStringifier(): Stringifier {
20
22
  return (block: Block): string =>
21
23
  block.source.map(({ tokens }) => join(tokens)).join('\n');
22
24
  }
@@ -23,15 +23,6 @@ const getWidth = (w: Width, { tokens: t }: Line) => ({
23
23
  name: Math.max(w.name, t.name.length),
24
24
  });
25
25
 
26
- // /**
27
- // * Description may go
28
- // * over multiple lines followed by @tags
29
- // *
30
- //* @my-tag {my.type} my-name description line 1
31
- // description line 2
32
- // * description line 3
33
- // */
34
-
35
26
  const space = (len: number) => ''.padStart(len, ' ');
36
27
 
37
28
  export default function align(): Transform {
@@ -62,15 +53,49 @@ export default function align(): Transform {
62
53
  tokens.start = space(w.start + 1);
63
54
  break;
64
55
  default:
65
- tokens.start = space(w.start + 3);
66
56
  tokens.delimiter = '';
57
+ tokens.start = space(w.start + 2); // compensate delimiter
58
+ }
59
+
60
+ if (!intoTags) {
61
+ tokens.postDelimiter = tokens.description === '' ? '' : ' ';
62
+ return { ...line, tokens };
63
+ }
64
+
65
+ const nothingAfter = {
66
+ delim: false,
67
+ tag: false,
68
+ type: false,
69
+ name: false,
70
+ };
71
+
72
+ if (tokens.description === '') {
73
+ nothingAfter.name = true;
74
+ tokens.postName = '';
75
+
76
+ if (tokens.name === '') {
77
+ nothingAfter.type = true;
78
+ tokens.postType = '';
79
+
80
+ if (tokens.type === '') {
81
+ nothingAfter.tag = true;
82
+ tokens.postTag = '';
83
+
84
+ if (tokens.tag === '') {
85
+ nothingAfter.delim = true;
86
+ }
87
+ }
88
+ }
67
89
  }
68
90
 
69
- if (intoTags) {
91
+ tokens.postDelimiter = nothingAfter.delim ? '' : ' ';
92
+
93
+ if (!nothingAfter.tag)
70
94
  tokens.postTag = space(w.tag - tokens.tag.length + 1);
95
+ if (!nothingAfter.type)
71
96
  tokens.postType = space(w.type - tokens.type.length + 1);
97
+ if (!nothingAfter.name)
72
98
  tokens.postName = space(w.name - tokens.name.length + 1);
73
- }
74
99
 
75
100
  return { ...line, tokens };
76
101
  }
@@ -161,9 +161,9 @@ function parse_source_exploration(source, parse, stringify, transforms) {
161
161
  }
162
162
 
163
163
  function parse_advanced_parsing(source, parse, _, _, tokenizers) {
164
- // Each '@tag ...' section results into Spec. Spec is computed by
165
- // the chain of tokenizers each contributing change to the Spec.* and Spec.tags[].tokens.
166
- // Default parse() options come with stadart tokenizers
164
+ // Each '@tag ...' section results into a Spec. The Spec is computed by
165
+ // the chain of tokenizers each contributing a change to the the Spec.* and the Spec.tags[].tokens.
166
+ // Default parse() options come with stadart tokenizers:
167
167
  // {
168
168
  // ...,
169
169
  // spacing = 'compact',
@@ -0,0 +1,29 @@
1
+ const {
2
+ parse,
3
+ stringify,
4
+ transforms: { align },
5
+ } = require('../../lib');
6
+
7
+ test('align - ignore trailing right space', () => {
8
+ const source = `
9
+ /**
10
+ * Description may go
11
+ * over multiple lines followed by @tags
12
+ * @param {string} name
13
+ * @param {any} value the value parameter
14
+ */`;
15
+
16
+ const expected = `
17
+ /**
18
+ * Description may go
19
+ * over multiple lines followed by @tags
20
+ * @param {string} name
21
+ * @param {any} value the value parameter
22
+ */`.slice(1);
23
+
24
+ const parsed = parse(source);
25
+ const aligned = align()(parsed[0]);
26
+ const stringified = stringify(aligned);
27
+
28
+ expect(stringified).toEqual(expected);
29
+ });
@@ -0,0 +1,29 @@
1
+ const {
2
+ parse,
3
+ stringify,
4
+ transforms: { align },
5
+ } = require('../../lib');
6
+
7
+ test('align - collapse postDelim', () => {
8
+ const source = `
9
+ /**
10
+ * Description may go
11
+ * over multiple lines followed by @tags
12
+ * @param {string} name the name parameter
13
+ * @param {any} value the value parameter
14
+ */`.slice(1);
15
+
16
+ const expected = `
17
+ /**
18
+ * Description may go
19
+ * over multiple lines followed by @tags
20
+ * @param {string} name the name parameter
21
+ * @param {any} value the value parameter
22
+ */`.slice(1);
23
+
24
+ const parsed = parse(source);
25
+ const aligned = align()(parsed[0]);
26
+ const stringified = stringify(aligned);
27
+
28
+ expect(stringified).toEqual(expected);
29
+ });
@@ -0,0 +1,102 @@
1
+ const { parse, inspect } = require('../../lib');
2
+
3
+ test('name cut off', () => {
4
+ const source = `
5
+ /**
6
+ * @param {{includeWhiteSpace: (boolean|undefined),
7
+ * ignoreElementOrder: (boolean|undefined)}} [options] The options.
8
+ */`.slice(1);
9
+
10
+ const tagSource = [
11
+ {
12
+ number: 1,
13
+ source: ' * @param {{includeWhiteSpace: (boolean|undefined),',
14
+ tokens: {
15
+ start: ' ',
16
+ delimiter: '*',
17
+ postDelimiter: ' ',
18
+ tag: '@param',
19
+ postTag: ' ',
20
+ type: '{{includeWhiteSpace: (boolean|undefined),',
21
+ postType: '',
22
+ name: '',
23
+ postName: '',
24
+ description: '',
25
+ end: '',
26
+ },
27
+ },
28
+ {
29
+ number: 2,
30
+ source:
31
+ ' * ignoreElementOrder: (boolean|undefined)}} [options] The options.',
32
+ tokens: {
33
+ start: ' ',
34
+ delimiter: '*',
35
+ postDelimiter: ' ',
36
+ tag: '',
37
+ postTag: '',
38
+ type: ' ignoreElementOrder: (boolean|undefined)}}',
39
+ postType: ' ',
40
+ name: '[options]',
41
+ postName: ' ',
42
+ description: 'The options.',
43
+ end: '',
44
+ },
45
+ },
46
+ {
47
+ number: 3,
48
+ source: ' */',
49
+ tokens: {
50
+ start: ' ',
51
+ delimiter: '',
52
+ postDelimiter: '',
53
+ tag: '',
54
+ postTag: '',
55
+ type: '',
56
+ postType: '',
57
+ name: '',
58
+ postName: '',
59
+ description: '',
60
+ end: '*/',
61
+ },
62
+ },
63
+ ];
64
+
65
+ const parsed = parse(source);
66
+ // console.log(inspect(parsed[0]));
67
+
68
+ expect(parsed[0]).toMatchObject({
69
+ problems: [],
70
+ tags: [
71
+ {
72
+ tag: 'param',
73
+ type:
74
+ '{includeWhiteSpace: (boolean|undefined),ignoreElementOrder: (boolean|undefined)}',
75
+ name: 'options',
76
+ optional: true,
77
+ description: 'The options.',
78
+ source: tagSource,
79
+ },
80
+ ],
81
+ source: [
82
+ {
83
+ number: 0,
84
+ source: ' /**',
85
+ tokens: {
86
+ start: ' ',
87
+ delimiter: '/**',
88
+ postDelimiter: '',
89
+ tag: '',
90
+ postTag: '',
91
+ type: '',
92
+ postType: '',
93
+ name: '',
94
+ postName: '',
95
+ description: '',
96
+ end: '',
97
+ },
98
+ },
99
+ ...tagSource,
100
+ ],
101
+ });
102
+ });
@@ -137,7 +137,7 @@ test('omit', () => {
137
137
  );
138
138
  });
139
139
 
140
- test('multiline - preserve', () => {
140
+ test('multiline', () => {
141
141
  const spec = seedSpec({
142
142
  source: [
143
143
  {
@@ -152,23 +152,16 @@ test('multiline - preserve', () => {
152
152
  source: '...',
153
153
  tokens: seedTokens({
154
154
  postDelimiter: ' ',
155
- description: 'number',
155
+ description: 'number)} function type',
156
156
  }),
157
157
  },
158
158
  {
159
159
  number: 3,
160
160
  source: '...',
161
- tokens: seedTokens({
162
- description: ')} function type',
163
- }),
164
- },
165
- {
166
- number: 4,
167
- source: '...',
168
161
  tokens: seedTokens(),
169
162
  },
170
163
  {
171
- number: 5,
164
+ number: 4,
172
165
  source: '...',
173
166
  tokens: seedTokens({
174
167
  end: '*/',
@@ -192,25 +185,18 @@ test('multiline - preserve', () => {
192
185
  number: 2,
193
186
  source: '...',
194
187
  tokens: seedTokens({
195
- type: ' number',
196
- }),
197
- },
198
- {
199
- number: 3,
200
- source: '...',
201
- tokens: seedTokens({
202
- type: ')}',
188
+ type: ' number)}',
203
189
  postType: ' ',
204
190
  description: 'function type',
205
191
  }),
206
192
  },
207
193
  {
208
- number: 4,
194
+ number: 3,
209
195
  source: '...',
210
196
  tokens: seedTokens(),
211
197
  },
212
198
  {
213
- number: 5,
199
+ number: 4,
214
200
  source: '...',
215
201
  tokens: seedTokens({
216
202
  end: '*/',
@@ -1,6 +1,14 @@
1
1
  import align from '../../src/transforms/align';
2
- import getParser from '../../src/parser/index';
3
- import getStringifier from '../../src/stringifier/index';
2
+ import getParser, { Parser } from '../../src/parser/index';
3
+ import getStringifier, { Stringifier } from '../../src/stringifier/index';
4
+
5
+ let parse: Parser;
6
+ let stringify: Stringifier;
7
+
8
+ beforeEach(() => {
9
+ parse = getParser();
10
+ stringify = getStringifier();
11
+ });
4
12
 
5
13
  test('multiline', () => {
6
14
  const source = `
@@ -23,18 +31,20 @@ test('multiline', () => {
23
31
  * @another-tag {another-type} another-name description line 1
24
32
  description line 2
25
33
  * description line 3
26
- */`;
34
+ */`.slice(1);
27
35
 
28
- const parsed = getParser()(source);
29
- const out = getStringifier()(align()(parsed[0]));
36
+ const parsed = parse(source);
37
+ const aligned = align()(parsed[0]);
38
+ const out = stringify(aligned);
30
39
 
31
- expect(out).toBe(expected.slice(1));
40
+ // console.log(inspect(aligned));
41
+ expect(out).toBe(expected);
32
42
  });
33
43
 
34
44
  test('one-liner', () => {
35
45
  const source = ` /** @tag {type} name description */`;
36
- const parsed = getParser()(source);
37
- const out = getStringifier()(align()(parsed[0]));
46
+ const parsed = parse(source);
47
+ const out = stringify(align()(parsed[0]));
38
48
 
39
49
  expect(out).toBe(source);
40
50
  });
@@ -43,8 +53,8 @@ test('same line open', () => {
43
53
  const source = `
44
54
  /** @tag {type} name description
45
55
  */`.slice(1);
46
- const parsed = getParser()(source);
47
- const out = getStringifier()(align()(parsed[0]));
56
+ const parsed = parse(source);
57
+ const out = stringify(align()(parsed[0]));
48
58
 
49
59
  expect(out).toBe(source);
50
60
  });
@@ -52,22 +62,76 @@ test('same line open', () => {
52
62
  test('same line close', () => {
53
63
  const source = `
54
64
  /**
65
+ * @tag {type} name description */`;
66
+
67
+ const expected = `
68
+ /**
55
69
  * @tag {type} name description */`.slice(1);
56
- const parsed = getParser()(source);
57
- const out = getStringifier()(align()(parsed[0]));
58
70
 
59
- expect(out).toBe(source);
71
+ const parsed = parse(source);
72
+ const aligned = align()(parsed[0]);
73
+ const out = stringify(aligned);
74
+
75
+ expect(out).toBe(expected);
60
76
  });
61
77
 
62
78
  test('spec source referencing', () => {
63
- const parsed = getParser()(`/** @tag {type} name Description */`);
79
+ const parsed = parse(`/** @tag {type} name Description */`);
64
80
  const block = align()(parsed[0]);
65
81
  expect(block.tags[0].source[0] === block.source[0]).toBe(true);
66
82
  });
67
83
 
68
84
  test('block source clonning', () => {
69
- const parsed = getParser()(`/** @tag {type} name Description */`);
85
+ const parsed = parse(`/** @tag {type} name Description */`);
70
86
  const block = align()(parsed[0]);
71
87
  parsed[0].source[0].tokens.description = 'test';
72
88
  expect(block.source[0].tokens.description).toBe('Description ');
73
89
  });
90
+
91
+ test('ignore right whitespace', () => {
92
+ const source = `
93
+ /**
94
+ * Description may go
95
+ * over multiple lines followed by @tags
96
+ * @param {string} name
97
+ * @param {any} value the value parameter
98
+ */`.slice(1);
99
+
100
+ const expected = `
101
+ /**
102
+ * Description may go
103
+ * over multiple lines followed by @tags
104
+ * @param {string} name
105
+ * @param {any} value the value parameter
106
+ */`.slice(1);
107
+
108
+ const parsed = parse(source);
109
+ const aligned = align()(parsed[0]);
110
+ const stringified = stringify(aligned);
111
+
112
+ expect(stringified).toEqual(expected);
113
+ });
114
+
115
+ test('collapse postDelimiter', () => {
116
+ const source = `
117
+ /**
118
+ * Description may go
119
+ * over multiple lines followed by @tags
120
+ * @param {string} name the name parameter
121
+ * @param {any} value the value parameter
122
+ */`.slice(1);
123
+
124
+ const expected = `
125
+ /**
126
+ * Description may go
127
+ * over multiple lines followed by @tags
128
+ * @param {string} name the name parameter
129
+ * @param {any} value the value parameter
130
+ */`.slice(1);
131
+
132
+ const parsed = parse(source);
133
+ const aligned = align()(parsed[0]);
134
+ const stringified = stringify(aligned);
135
+
136
+ expect(stringified).toEqual(expected);
137
+ });