comment-parser 1.1.1 → 1.1.5

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/CHANGELOG.md CHANGED
@@ -1,3 +1,20 @@
1
+ # v1.1.5
2
+ - drop unused variables
3
+ - add .editorconfig
4
+
5
+ # v1.1.4
6
+ - `bugfix` fix unsynced lib/
7
+
8
+ # v1.1.3
9
+ - export primitive type on the top level: Markers, Block, Spec, Line, Tokens, Problem
10
+
11
+ # v1.1.2
12
+ - `bugfix` Allow to build nested tags from `name.subname` even if `name` wasn't d
13
+ - `bugfix` Preserve indentation when extracting comments
14
+
15
+ # v1.1.1
16
+ - add helpers for rewiring Spec.source <-> Spec.tags.source
17
+
1
18
  # v1.1.0
2
19
  - split tokenizers into separate modules
3
20
  - allow multiline {type} definitions - issue #109
@@ -5,9 +22,6 @@
5
22
  - allow using "=" in quoted [name=default] defaults – issue #112
6
23
  - add tokenizers usage example - issue #111
7
24
 
8
- # v1.1.1
9
- - add helpers for rewiring Spec.source <-> Spec.tags.source
10
-
11
25
  # v1.0.0
12
26
  - complete rewrite in TS with more flexible API
13
27
 
package/browser/index.js CHANGED
@@ -62,13 +62,12 @@ var CommentParser = (function (exports) {
62
62
  return fence;
63
63
  }
64
64
 
65
- var Markers;
66
65
  (function (Markers) {
67
66
  Markers["start"] = "/**";
68
67
  Markers["nostart"] = "/***";
69
68
  Markers["delim"] = "*";
70
69
  Markers["end"] = "*/";
71
- })(Markers || (Markers = {}));
70
+ })(exports.Markers || (exports.Markers = {}));
72
71
 
73
72
  function getParser$1({ startLine = 0, } = {}) {
74
73
  let block = null;
@@ -78,29 +77,29 @@ var CommentParser = (function (exports) {
78
77
  const tokens = seedTokens();
79
78
  [tokens.start, rest] = splitSpace(rest);
80
79
  if (block === null &&
81
- rest.startsWith(Markers.start) &&
82
- !rest.startsWith(Markers.nostart)) {
80
+ rest.startsWith(exports.Markers.start) &&
81
+ !rest.startsWith(exports.Markers.nostart)) {
83
82
  block = [];
84
- tokens.delimiter = rest.slice(0, Markers.start.length);
85
- rest = rest.slice(Markers.start.length);
83
+ tokens.delimiter = rest.slice(0, exports.Markers.start.length);
84
+ rest = rest.slice(exports.Markers.start.length);
86
85
  [tokens.postDelimiter, rest] = splitSpace(rest);
87
86
  }
88
87
  if (block === null) {
89
88
  num++;
90
89
  return null;
91
90
  }
92
- const isClosed = rest.trimRight().endsWith(Markers.end);
91
+ const isClosed = rest.trimRight().endsWith(exports.Markers.end);
93
92
  if (tokens.delimiter === '' &&
94
- rest.startsWith(Markers.delim) &&
95
- !rest.startsWith(Markers.end)) {
96
- tokens.delimiter = Markers.delim;
97
- rest = rest.slice(Markers.delim.length);
93
+ rest.startsWith(exports.Markers.delim) &&
94
+ !rest.startsWith(exports.Markers.end)) {
95
+ tokens.delimiter = exports.Markers.delim;
96
+ rest = rest.slice(exports.Markers.delim.length);
98
97
  [tokens.postDelimiter, rest] = splitSpace(rest);
99
98
  }
100
99
  if (isClosed) {
101
100
  const trimmed = rest.trimRight();
102
- tokens.end = rest.slice(trimmed.length - Markers.end.length);
103
- rest = trimmed.slice(0, -Markers.end.length);
101
+ tokens.end = rest.slice(trimmed.length - exports.Markers.end.length);
102
+ rest = trimmed.slice(0, -exports.Markers.end.length);
104
103
  }
105
104
  tokens.description = rest;
106
105
  block.push({ number: num, source, tokens });
@@ -200,7 +199,7 @@ var CommentParser = (function (exports) {
200
199
  tokens.type = tokens.postDelimiter.slice(offset) + type;
201
200
  tokens.postDelimiter = tokens.postDelimiter.slice(0, offset);
202
201
  }
203
- [tokens.postType, tokens.description] = splitSpace(tokens.description.slice(tokens.type.length));
202
+ [tokens.postType, tokens.description] = splitSpace(tokens.description.slice(type.length));
204
203
  parts.push(tokens.type);
205
204
  }
206
205
  parts[0] = parts[0].slice(1);
@@ -343,13 +342,13 @@ var CommentParser = (function (exports) {
343
342
  return '';
344
343
  // skip the opening line with no description
345
344
  if (lines[0].tokens.description === '' &&
346
- lines[0].tokens.delimiter === Markers.start)
345
+ lines[0].tokens.delimiter === exports.Markers.start)
347
346
  lines = lines.slice(1);
348
347
  // skip the closing line with no description
349
348
  const lastLine = lines[lines.length - 1];
350
349
  if (lastLine !== undefined &&
351
350
  lastLine.tokens.description === '' &&
352
- lastLine.tokens.end.endsWith(Markers.end))
351
+ lastLine.tokens.end.endsWith(exports.Markers.end))
353
352
  lines = lines.slice(0, -1);
354
353
  // description starts at the last line of type definition
355
354
  lines = lines.slice(lines.reduce(lineNo, 0));
@@ -425,19 +424,11 @@ var CommentParser = (function (exports) {
425
424
  name: 0,
426
425
  };
427
426
  const getWidth = (w, { tokens: t }) => ({
428
- start: t.delimiter === Markers.start ? t.start.length : w.start,
427
+ start: t.delimiter === exports.Markers.start ? t.start.length : w.start,
429
428
  tag: Math.max(w.tag, t.tag.length),
430
429
  type: Math.max(w.type, t.type.length),
431
430
  name: Math.max(w.name, t.name.length),
432
431
  });
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
432
  const space = (len) => ''.padStart(len, ' ');
442
433
  function align() {
443
434
  let intoTags = false;
@@ -451,26 +442,53 @@ var CommentParser = (function (exports) {
451
442
  tokens.type === '' &&
452
443
  tokens.description === '';
453
444
  // dangling '*/'
454
- if (tokens.end === Markers.end && isEmpty) {
445
+ if (tokens.end === exports.Markers.end && isEmpty) {
455
446
  tokens.start = space(w.start + 1);
456
447
  return Object.assign(Object.assign({}, line), { tokens });
457
448
  }
458
449
  switch (tokens.delimiter) {
459
- case Markers.start:
450
+ case exports.Markers.start:
460
451
  tokens.start = space(w.start);
461
452
  break;
462
- case Markers.delim:
453
+ case exports.Markers.delim:
463
454
  tokens.start = space(w.start + 1);
464
455
  break;
465
456
  default:
466
- tokens.start = space(w.start + 3);
467
457
  tokens.delimiter = '';
458
+ tokens.start = space(w.start + 2); // compensate delimiter
468
459
  }
469
- if (intoTags) {
460
+ if (!intoTags) {
461
+ tokens.postDelimiter = tokens.description === '' ? '' : ' ';
462
+ return Object.assign(Object.assign({}, line), { tokens });
463
+ }
464
+ const nothingAfter = {
465
+ delim: false,
466
+ tag: false,
467
+ type: false,
468
+ name: false,
469
+ };
470
+ if (tokens.description === '') {
471
+ nothingAfter.name = true;
472
+ tokens.postName = '';
473
+ if (tokens.name === '') {
474
+ nothingAfter.type = true;
475
+ tokens.postType = '';
476
+ if (tokens.type === '') {
477
+ nothingAfter.tag = true;
478
+ tokens.postTag = '';
479
+ if (tokens.tag === '') {
480
+ nothingAfter.delim = true;
481
+ }
482
+ }
483
+ }
484
+ }
485
+ tokens.postDelimiter = nothingAfter.delim ? '' : ' ';
486
+ if (!nothingAfter.tag)
470
487
  tokens.postTag = space(w.tag - tokens.tag.length + 1);
488
+ if (!nothingAfter.type)
471
489
  tokens.postType = space(w.type - tokens.type.length + 1);
490
+ if (!nothingAfter.name)
472
491
  tokens.postName = space(w.name - tokens.name.length + 1);
473
- }
474
492
  return Object.assign(Object.assign({}, line), { tokens });
475
493
  }
476
494
  return (_a) => {
package/es6/index.d.ts CHANGED
@@ -6,8 +6,9 @@ import typeTokenizer from './parser/tokenizers/type';
6
6
  import alignTransform from './transforms/align';
7
7
  import indentTransform from './transforms/indent';
8
8
  import { flow as flowTransform } from './transforms/index';
9
+ export * from './primitives';
9
10
  export declare function parse(source: string, options?: Partial<ParserOptions>): import("./primitives").Block[];
10
- export declare const stringify: (block: import("./primitives").Block) => string;
11
+ export declare const stringify: import("./stringifier").Stringifier;
11
12
  export { default as inspect } from './stringifier/inspect';
12
13
  export declare const transforms: {
13
14
  flow: typeof flowTransform;
package/es6/index.js CHANGED
@@ -7,6 +7,7 @@ import getStringifier from './stringifier/index';
7
7
  import alignTransform from './transforms/align';
8
8
  import indentTransform from './transforms/indent';
9
9
  import { flow as flowTransform } from './transforms/index';
10
+ export * from './primitives';
10
11
  export function parse(source, options = {}) {
11
12
  return getParser(options)(source);
12
13
  }
@@ -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) => {
@@ -1,3 +1,3 @@
1
1
  import { Block } from '../primitives';
2
- export declare type Transform = (Block: any) => Block;
2
+ export declare type Transform = (Block: Block) => Block;
3
3
  export declare function flow(...transforms: Transform[]): Transform;
package/lib/index.d.ts CHANGED
@@ -6,8 +6,9 @@ import typeTokenizer from './parser/tokenizers/type';
6
6
  import alignTransform from './transforms/align';
7
7
  import indentTransform from './transforms/indent';
8
8
  import { flow as flowTransform } from './transforms/index';
9
+ export * from './primitives';
9
10
  export declare function parse(source: string, options?: Partial<ParserOptions>): import("./primitives").Block[];
10
- export declare const stringify: (block: import("./primitives").Block) => string;
11
+ export declare const stringify: import("./stringifier").Stringifier;
11
12
  export { default as inspect } from './stringifier/inspect';
12
13
  export declare const transforms: {
13
14
  flow: typeof flowTransform;
package/lib/index.js CHANGED
@@ -1,4 +1,14 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
5
+ }) : (function(o, m, k, k2) {
6
+ if (k2 === undefined) k2 = k;
7
+ o[k2] = m[k];
8
+ }));
9
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
10
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
11
+ };
2
12
  Object.defineProperty(exports, "__esModule", { value: true });
3
13
  exports.tokenizers = exports.transforms = exports.inspect = exports.stringify = exports.parse = void 0;
4
14
  const index_1 = require("./parser/index");
@@ -10,6 +20,7 @@ const index_2 = require("./stringifier/index");
10
20
  const align_1 = require("./transforms/align");
11
21
  const indent_1 = require("./transforms/indent");
12
22
  const index_3 = require("./transforms/index");
23
+ __exportStar(require("./primitives"), exports);
13
24
  function parse(source, options = {}) {
14
25
  return index_1.default(options)(source);
15
26
  }
@@ -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) => {
@@ -1,3 +1,3 @@
1
1
  import { Block } from '../primitives';
2
- export declare type Transform = (Block: any) => Block;
2
+ export declare type Transform = (Block: Block) => Block;
3
3
  export declare function flow(...transforms: Transform[]): Transform;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "comment-parser",
3
- "version": "1.1.1",
3
+ "version": "1.1.5",
4
4
  "description": "Generic JSDoc-like comment parser",
5
5
  "main": "lib/index.js",
6
6
  "types": "lib/index.d.ts",
@@ -20,10 +20,11 @@
20
20
  "node": ">= 10.0.0"
21
21
  },
22
22
  "scripts": {
23
- "build": "rimraf lib es6 browser; tsc -p tsconfig.es6.json && tsc -p tsconfig.node.json && rollup -o browser/index.js -f iife --context window -n CommentParser es6/index.js",
23
+ "build": "rimraf lib es6 browser; tsc -p tsconfig.json && tsc -p tsconfig.node.json && rollup -o browser/index.js -f iife --context window -n CommentParser es6/index.js",
24
24
  "format": "prettier --write src/ tests/",
25
25
  "pretest": "rimraf coverage; npm run build",
26
- "test": "prettier --check src/ tests/ && jest --verbose"
26
+ "test": "prettier --check src/ tests/ && jest --verbose",
27
+ "preversion": "npm run build"
27
28
  },
28
29
  "repository": {
29
30
  "type": "git",
package/src/index.ts CHANGED
@@ -8,6 +8,8 @@ import alignTransform from './transforms/align';
8
8
  import indentTransform from './transforms/indent';
9
9
  import { flow as flowTransform } from './transforms/index';
10
10
 
11
+ export * from './primitives';
12
+
11
13
  export function parse(source: string, options: Partial<ParserOptions> = {}) {
12
14
  return getParser(options)(source);
13
15
  }
@@ -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 });
@@ -1,5 +1,5 @@
1
1
  import { Spec, Line } from '../../primitives';
2
- import { splitSpace, isSpace, seedBlock } from '../../util';
2
+ import { splitSpace, isSpace } from '../../util';
3
3
  import { Tokenizer } from './index';
4
4
 
5
5
  const isQuoted = (s: string) => s && s.startsWith('"') && s.endsWith('"');
@@ -1,4 +1,4 @@
1
- import { Spec, Line, Tokens } from '../../primitives';
1
+ import { Spec, Tokens } from '../../primitives';
2
2
  import { splitSpace } from '../../util';
3
3
  import { Tokenizer } from './index';
4
4
 
@@ -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
  }
@@ -1,5 +1,5 @@
1
- import { Block, Line, Tokens } from '../primitives';
2
- import { seedTokens, isSpace } from '../util';
1
+ import { Block, Tokens } from '../primitives';
2
+ import { isSpace } from '../util';
3
3
 
4
4
  interface Width {
5
5
  line: number;
@@ -1,5 +1,5 @@
1
1
  import { Transform } from './index';
2
- import { Markers, Tokens, Block, Line } from '../primitives';
2
+ import { Markers, Block, Line } from '../primitives';
3
3
  import { rewireSource } from '../util';
4
4
 
5
5
  interface Width {
@@ -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
  }
@@ -9,7 +9,7 @@ const push = (offset: number) => {
9
9
  };
10
10
 
11
11
  export default function indent(pos: number): Transform {
12
- let shift: (string) => string;
12
+ let shift: (string: string) => string;
13
13
  const pad = (start: string) => {
14
14
  if (shift === undefined) {
15
15
  const offset = pos - start.length;
@@ -1,6 +1,6 @@
1
1
  import { Block } from '../primitives';
2
2
 
3
- export type Transform = (Block) => Block;
3
+ export type Transform = (Block: Block) => Block;
4
4
 
5
5
  export function flow(...transforms: Transform[]): Transform {
6
6
  return (block: Block): Block =>
@@ -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
+ });
@@ -9,4 +9,4 @@
9
9
  },
10
10
  "include": ["src"],
11
11
  "exclude": ["node_modules"]
12
- }
12
+ }
@@ -9,4 +9,4 @@
9
9
  },
10
10
  "include": ["src"],
11
11
  "exclude": ["node_modules"]
12
- }
12
+ }