comment-parser 1.0.0 → 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.
Files changed (106) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/README.md +26 -19
  3. package/browser/index.js +331 -272
  4. package/es6/index.d.ts +21 -4
  5. package/es6/index.js +21 -5
  6. package/es6/parser/block-parser.d.ts +18 -2
  7. package/es6/parser/block-parser.js +12 -12
  8. package/es6/parser/index.d.ts +4 -4
  9. package/es6/parser/index.js +25 -26
  10. package/es6/parser/source-parser.js +13 -15
  11. package/es6/parser/spec-parser.d.ts +1 -6
  12. package/es6/parser/spec-parser.js +4 -151
  13. package/es6/parser/tokenizers/description.d.ts +19 -0
  14. package/es6/parser/tokenizers/description.js +46 -0
  15. package/es6/parser/tokenizers/index.d.ts +7 -0
  16. package/es6/parser/tokenizers/index.js +1 -0
  17. package/es6/parser/tokenizers/name.d.ts +6 -0
  18. package/es6/parser/tokenizers/name.js +91 -0
  19. package/es6/parser/tokenizers/tag.d.ts +6 -0
  20. package/es6/parser/tokenizers/tag.js +24 -0
  21. package/es6/parser/tokenizers/type.d.ts +27 -0
  22. package/es6/parser/tokenizers/type.js +67 -0
  23. package/es6/stringifier/index.d.ts +2 -1
  24. package/es6/stringifier/index.js +1 -6
  25. package/es6/stringifier/inspect.d.ts +2 -0
  26. package/es6/stringifier/inspect.js +41 -0
  27. package/es6/transforms/align.js +48 -43
  28. package/es6/transforms/indent.js +11 -22
  29. package/es6/transforms/index.d.ts +0 -2
  30. package/es6/transforms/index.js +2 -10
  31. package/es6/util.d.ts +11 -0
  32. package/es6/util.js +25 -25
  33. package/jest.config.js +12 -11
  34. package/lib/index.d.ts +21 -4
  35. package/lib/index.js +24 -6
  36. package/lib/parser/block-parser.d.ts +18 -2
  37. package/lib/parser/block-parser.js +12 -12
  38. package/lib/parser/index.d.ts +4 -4
  39. package/lib/parser/index.js +26 -27
  40. package/lib/parser/source-parser.js +14 -16
  41. package/lib/parser/spec-parser.d.ts +1 -6
  42. package/lib/parser/spec-parser.js +4 -156
  43. package/lib/parser/tokenizers/description.d.ts +19 -0
  44. package/lib/parser/tokenizers/description.js +51 -0
  45. package/lib/parser/tokenizers/index.d.ts +7 -0
  46. package/lib/parser/tokenizers/index.js +2 -0
  47. package/lib/parser/tokenizers/name.d.ts +6 -0
  48. package/lib/parser/tokenizers/name.js +94 -0
  49. package/lib/parser/tokenizers/tag.d.ts +6 -0
  50. package/lib/parser/tokenizers/tag.js +27 -0
  51. package/lib/parser/tokenizers/type.d.ts +27 -0
  52. package/lib/parser/tokenizers/type.js +70 -0
  53. package/lib/stringifier/index.d.ts +2 -1
  54. package/lib/stringifier/index.js +1 -6
  55. package/lib/stringifier/inspect.d.ts +2 -0
  56. package/lib/stringifier/inspect.js +44 -0
  57. package/lib/transforms/align.js +50 -45
  58. package/lib/transforms/indent.js +12 -23
  59. package/lib/transforms/index.d.ts +0 -2
  60. package/lib/transforms/index.js +3 -13
  61. package/lib/util.d.ts +11 -0
  62. package/lib/util.js +27 -26
  63. package/migrate-1.0.md +7 -7
  64. package/package.json +1 -1
  65. package/src/index.ts +20 -2
  66. package/src/parser/block-parser.ts +19 -1
  67. package/src/parser/index.ts +22 -21
  68. package/src/parser/source-parser.ts +2 -2
  69. package/src/parser/spec-parser.ts +2 -170
  70. package/src/parser/tokenizers/description.ts +75 -0
  71. package/src/parser/tokenizers/index.ts +8 -0
  72. package/src/parser/tokenizers/name.ts +112 -0
  73. package/src/parser/tokenizers/tag.ts +30 -0
  74. package/src/parser/tokenizers/type.ts +92 -0
  75. package/src/stringifier/index.ts +3 -1
  76. package/src/stringifier/inspect.ts +64 -0
  77. package/src/transforms/align.ts +37 -12
  78. package/src/transforms/index.ts +0 -3
  79. package/src/util.ts +20 -0
  80. package/tests/e2e/examples.js +39 -2
  81. package/tests/e2e/examples.spec.js +4 -2
  82. package/tests/e2e/issue-109.spec.js +49 -0
  83. package/tests/e2e/issue-112.spec.js +20 -0
  84. package/tests/e2e/issue-113.spec.js +23 -0
  85. package/tests/e2e/issue-119.spec.js +29 -0
  86. package/tests/e2e/issue-120.spec.js +29 -0
  87. package/tests/e2e/issue-121.spec.js +102 -0
  88. package/tests/e2e/transforms.spec.js +5 -2
  89. package/tests/unit/inspect.spec.ts +36 -0
  90. package/tests/unit/{spacer.spec.ts → spacer-description-joiner.spec.ts} +6 -6
  91. package/tests/unit/spec-description-tokenizer.spec.ts +100 -7
  92. package/tests/unit/spec-name-tokenizer.spec.ts +113 -1
  93. package/tests/unit/spec-parser.spec.ts +6 -9
  94. package/tests/unit/spec-tag-tokenizer.spec.ts +1 -1
  95. package/tests/unit/spec-type-tokenizer.spec.ts +121 -1
  96. package/tests/unit/stringifier.spec.ts +0 -1
  97. package/tests/unit/transforms-align.spec.ts +80 -16
  98. package/tests/unit/util-rewire.spec.ts +107 -0
  99. package/tests/unit/util.spec.ts +0 -48
  100. package/tsconfig.es6.json +1 -1
  101. package/tsconfig.node.json +1 -1
  102. package/es6/parser/spacer.d.ts +0 -3
  103. package/es6/parser/spacer.js +0 -37
  104. package/lib/parser/spacer.d.ts +0 -3
  105. package/lib/parser/spacer.js +0 -40
  106. package/src/parser/spacer.ts +0 -45
@@ -1,10 +1,10 @@
1
- import { Tokenizer } from './spec-parser';
2
1
  import { Block } from '../primitives';
3
- import { Spacer } from './spacer';
2
+ import { Tokenizer } from './tokenizers/index';
4
3
  export interface Options {
5
4
  startLine: number;
6
5
  fence: string;
7
- spacing: 'compact' | 'preserve' | Spacer;
6
+ spacing: 'compact' | 'preserve';
8
7
  tokenizers: Tokenizer[];
9
8
  }
10
- 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;
@@ -1,42 +1,41 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- var source_parser_1 = require("./source-parser");
4
- var block_parser_1 = require("./block-parser");
5
- var spec_parser_1 = require("./spec-parser");
6
- var spacer_1 = require("./spacer");
7
- var util_1 = require("../util");
8
- function getParser(_a) {
9
- var _b = _a === void 0 ? {} : _a, _c = _b.startLine, startLine = _c === void 0 ? 0 : _c, _d = _b.fence, fence = _d === void 0 ? '```' : _d, _e = _b.spacing, spacing = _e === void 0 ? 'compact' : _e, _f = _b.tokenizers, tokenizers = _f === void 0 ? [
10
- spec_parser_1.tagTokenizer(),
11
- spec_parser_1.typeTokenizer(),
12
- spec_parser_1.nameTokenizer(),
13
- spec_parser_1.descriptionTokenizer(spacer_1.default(spacing)),
14
- ] : _f;
3
+ const util_1 = require("../util");
4
+ const block_parser_1 = require("./block-parser");
5
+ const source_parser_1 = require("./source-parser");
6
+ const spec_parser_1 = require("./spec-parser");
7
+ const tag_1 = require("./tokenizers/tag");
8
+ const type_1 = require("./tokenizers/type");
9
+ const name_1 = require("./tokenizers/name");
10
+ const description_1 = require("./tokenizers/description");
11
+ function getParser({ startLine = 0, fence = '```', spacing = 'compact', tokenizers = [
12
+ tag_1.default(),
13
+ type_1.default(spacing),
14
+ name_1.default(),
15
+ description_1.default(spacing),
16
+ ], } = {}) {
15
17
  if (startLine < 0 || startLine % 1 > 0)
16
18
  throw new Error('Invalid startLine');
17
- var parseSource = source_parser_1.default({ startLine: startLine });
18
- var parseBlock = block_parser_1.default({ fence: fence });
19
- var parseSpec = spec_parser_1.default({ tokenizers: tokenizers });
20
- var join = spacer_1.default(spacing);
21
- var notEmpty = function (line) {
22
- return line.tokens.description.trim() != '';
23
- };
19
+ const parseSource = source_parser_1.default({ startLine });
20
+ const parseBlock = block_parser_1.default({ fence });
21
+ const parseSpec = spec_parser_1.default({ tokenizers });
22
+ const joinDescription = description_1.getJoiner(spacing);
23
+ const notEmpty = (line) => line.tokens.description.trim() != '';
24
24
  return function (source) {
25
- var blocks = [];
26
- for (var _i = 0, _a = util_1.splitLines(source); _i < _a.length; _i++) {
27
- var line = _a[_i];
28
- var lines = parseSource(line);
25
+ const blocks = [];
26
+ for (const line of util_1.splitLines(source)) {
27
+ const lines = parseSource(line);
29
28
  if (lines === null)
30
29
  continue;
31
30
  if (lines.find(notEmpty) === undefined)
32
31
  continue;
33
- var sections = parseBlock(lines);
34
- var specs = sections.slice(1).map(parseSpec);
32
+ const sections = parseBlock(lines);
33
+ const specs = sections.slice(1).map(parseSpec);
35
34
  blocks.push({
36
- description: join(sections[0]),
35
+ description: joinDescription(sections[0]),
37
36
  tags: specs,
38
37
  source: lines,
39
- problems: specs.reduce(function (acc, spec) { return acc.concat(spec.problems); }, []),
38
+ problems: specs.reduce((acc, spec) => acc.concat(spec.problems), []),
40
39
  });
41
40
  }
42
41
  return blocks;
@@ -1,46 +1,44 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- var util_1 = require("../util");
4
- var primitives_1 = require("../primitives");
5
- function getParser(_a) {
6
- var _b = (_a === void 0 ? {} : _a).startLine, startLine = _b === void 0 ? 0 : _b;
7
- var block = null;
8
- var num = startLine;
3
+ const primitives_1 = require("../primitives");
4
+ const util_1 = require("../util");
5
+ function getParser({ startLine = 0, } = {}) {
6
+ let block = null;
7
+ let num = startLine;
9
8
  return function parseSource(source) {
10
- var _a, _b, _c;
11
- var rest = source;
12
- var tokens = util_1.seedTokens();
13
- _a = util_1.splitSpace(rest), tokens.start = _a[0], rest = _a[1];
9
+ let rest = source;
10
+ const tokens = util_1.seedTokens();
11
+ [tokens.start, rest] = util_1.splitSpace(rest);
14
12
  if (block === null &&
15
13
  rest.startsWith(primitives_1.Markers.start) &&
16
14
  !rest.startsWith(primitives_1.Markers.nostart)) {
17
15
  block = [];
18
16
  tokens.delimiter = rest.slice(0, primitives_1.Markers.start.length);
19
17
  rest = rest.slice(primitives_1.Markers.start.length);
20
- _b = util_1.splitSpace(rest), tokens.postDelimiter = _b[0], rest = _b[1];
18
+ [tokens.postDelimiter, rest] = util_1.splitSpace(rest);
21
19
  }
22
20
  if (block === null) {
23
21
  num++;
24
22
  return null;
25
23
  }
26
- var isClosed = rest.trimRight().endsWith(primitives_1.Markers.end);
24
+ const isClosed = rest.trimRight().endsWith(primitives_1.Markers.end);
27
25
  if (tokens.delimiter === '' &&
28
26
  rest.startsWith(primitives_1.Markers.delim) &&
29
27
  !rest.startsWith(primitives_1.Markers.end)) {
30
28
  tokens.delimiter = primitives_1.Markers.delim;
31
29
  rest = rest.slice(primitives_1.Markers.delim.length);
32
- _c = util_1.splitSpace(rest), tokens.postDelimiter = _c[0], rest = _c[1];
30
+ [tokens.postDelimiter, rest] = util_1.splitSpace(rest);
33
31
  }
34
32
  if (isClosed) {
35
- var trimmed = rest.trimRight();
33
+ const trimmed = rest.trimRight();
36
34
  tokens.end = rest.slice(trimmed.length - primitives_1.Markers.end.length);
37
35
  rest = trimmed.slice(0, -primitives_1.Markers.end.length);
38
36
  }
39
37
  tokens.description = rest;
40
- block.push({ number: num, source: source, tokens: tokens });
38
+ block.push({ number: num, source, tokens });
41
39
  num++;
42
40
  if (isClosed) {
43
- var result = block.slice();
41
+ const result = block.slice();
44
42
  block = null;
45
43
  return result;
46
44
  }
@@ -1,12 +1,7 @@
1
1
  import { Line, Spec } from '../primitives';
2
- import { Spacer } from './spacer';
2
+ import { Tokenizer } from './tokenizers/index';
3
3
  export declare type Parser = (source: Line[]) => Spec;
4
- export declare type Tokenizer = (spec: Spec) => Spec;
5
4
  export interface Options {
6
5
  tokenizers: Tokenizer[];
7
6
  }
8
7
  export default function getParser({ tokenizers }: Options): Parser;
9
- export declare function tagTokenizer(): Tokenizer;
10
- export declare function typeTokenizer(): Tokenizer;
11
- export declare function nameTokenizer(): Tokenizer;
12
- export declare function descriptionTokenizer(join: Spacer): Tokenizer;
@@ -1,14 +1,11 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.descriptionTokenizer = exports.nameTokenizer = exports.typeTokenizer = exports.tagTokenizer = void 0;
4
- var util_1 = require("../util");
5
- function getParser(_a) {
6
- var tokenizers = _a.tokenizers;
3
+ const util_1 = require("../util");
4
+ function getParser({ tokenizers }) {
7
5
  return function parseSpec(source) {
8
6
  var _a;
9
- var spec = util_1.seedSpec({ source: source });
10
- for (var _i = 0, tokenizers_1 = tokenizers; _i < tokenizers_1.length; _i++) {
11
- var tokenize = tokenizers_1[_i];
7
+ let spec = util_1.seedSpec({ source });
8
+ for (const tokenize of tokenizers) {
12
9
  spec = tokenize(spec);
13
10
  if ((_a = spec.problems[spec.problems.length - 1]) === null || _a === void 0 ? void 0 : _a.critical)
14
11
  break;
@@ -17,152 +14,3 @@ function getParser(_a) {
17
14
  };
18
15
  }
19
16
  exports.default = getParser;
20
- function tagTokenizer() {
21
- return function (spec) {
22
- var tokens = spec.source[0].tokens;
23
- var match = tokens.description.match(/\s*(@(\S+))(\s*)/);
24
- if (match === null) {
25
- spec.problems.push({
26
- code: 'spec:tag:prefix',
27
- message: 'tag should start with "@" symbol',
28
- line: spec.source[0].number,
29
- critical: true,
30
- });
31
- return spec;
32
- }
33
- tokens.tag = match[1];
34
- tokens.postTag = match[3];
35
- tokens.description = tokens.description.slice(match[0].length);
36
- spec.tag = match[2];
37
- return spec;
38
- };
39
- }
40
- exports.tagTokenizer = tagTokenizer;
41
- function typeTokenizer() {
42
- return function (spec) {
43
- var _a;
44
- var res = '';
45
- var curlies = 0;
46
- var tokens = spec.source[0].tokens;
47
- var source = tokens.description.trimLeft();
48
- if (source[0] !== '{')
49
- return spec;
50
- for (var _i = 0, source_1 = source; _i < source_1.length; _i++) {
51
- var ch = source_1[_i];
52
- if (ch === '{')
53
- curlies++;
54
- if (ch === '}')
55
- curlies--;
56
- res += ch;
57
- if (curlies === 0) {
58
- break;
59
- }
60
- }
61
- if (curlies !== 0) {
62
- spec.problems.push({
63
- code: 'spec:type:unpaired-curlies',
64
- message: 'unpaired curlies',
65
- line: spec.source[0].number,
66
- critical: true,
67
- });
68
- return spec;
69
- }
70
- spec.type = res.slice(1, -1);
71
- tokens.type = res;
72
- _a = util_1.splitSpace(source.slice(tokens.type.length)), tokens.postType = _a[0], tokens.description = _a[1];
73
- return spec;
74
- };
75
- }
76
- exports.typeTokenizer = typeTokenizer;
77
- function nameTokenizer() {
78
- return function (spec) {
79
- var _a, _b;
80
- var _c;
81
- var tokens = spec.source[0].tokens;
82
- var source = tokens.description.trimLeft();
83
- var quotedGroups = source.split('"');
84
- // if it starts with quoted group, assume it is a literal
85
- if (quotedGroups.length > 1 &&
86
- quotedGroups[0] === '' &&
87
- quotedGroups.length % 2 === 1) {
88
- spec.name = quotedGroups[1];
89
- tokens.name = "\"" + quotedGroups[1] + "\"";
90
- _a = util_1.splitSpace(source.slice(tokens.name.length)), tokens.postName = _a[0], tokens.description = _a[1];
91
- return spec;
92
- }
93
- var brackets = 0;
94
- var name = '';
95
- var optional = false;
96
- var defaultValue;
97
- // assume name is non-space string or anything wrapped into brackets
98
- for (var _i = 0, source_2 = source; _i < source_2.length; _i++) {
99
- var ch = source_2[_i];
100
- if (brackets === 0 && util_1.isSpace(ch))
101
- break;
102
- if (ch === '[')
103
- brackets++;
104
- if (ch === ']')
105
- brackets--;
106
- name += ch;
107
- }
108
- if (brackets !== 0) {
109
- spec.problems.push({
110
- code: 'spec:name:unpaired-brackets',
111
- message: 'unpaired brackets',
112
- line: spec.source[0].number,
113
- critical: true,
114
- });
115
- return spec;
116
- }
117
- var nameToken = name;
118
- if (name[0] === '[' && name[name.length - 1] === ']') {
119
- optional = true;
120
- name = name.slice(1, -1);
121
- var parts = name.split('=');
122
- name = parts[0].trim();
123
- defaultValue = (_c = parts[1]) === null || _c === void 0 ? void 0 : _c.trim();
124
- if (name === '') {
125
- spec.problems.push({
126
- code: 'spec:name:empty-name',
127
- message: 'empty name',
128
- line: spec.source[0].number,
129
- critical: true,
130
- });
131
- return spec;
132
- }
133
- if (parts.length > 2) {
134
- spec.problems.push({
135
- code: 'spec:name:invalid-default',
136
- message: 'invalid default value syntax',
137
- line: spec.source[0].number,
138
- critical: true,
139
- });
140
- return spec;
141
- }
142
- if (defaultValue === '') {
143
- spec.problems.push({
144
- code: 'spec:name:empty-default',
145
- message: 'empty default value',
146
- line: spec.source[0].number,
147
- critical: true,
148
- });
149
- return spec;
150
- }
151
- }
152
- spec.optional = optional;
153
- spec.name = name;
154
- tokens.name = nameToken;
155
- if (defaultValue !== undefined)
156
- spec.default = defaultValue;
157
- _b = util_1.splitSpace(source.slice(tokens.name.length)), tokens.postName = _b[0], tokens.description = _b[1];
158
- return spec;
159
- };
160
- }
161
- exports.nameTokenizer = nameTokenizer;
162
- function descriptionTokenizer(join) {
163
- return function (spec) {
164
- spec.description = join(spec.source);
165
- return spec;
166
- };
167
- }
168
- exports.descriptionTokenizer = descriptionTokenizer;
@@ -0,0 +1,19 @@
1
+ import { Line } from '../../primitives';
2
+ import { Tokenizer } from './index';
3
+ /**
4
+ * Walks over provided lines joining description token into a single string.
5
+ * */
6
+ export declare type Joiner = (lines: Line[]) => string;
7
+ /**
8
+ * Shortcut for standard Joiners
9
+ * compact - strip surrounding whitespace and concat lines using a single string
10
+ * preserve - preserves original whitespace and line breaks as is
11
+ */
12
+ export declare type Spacing = 'compact' | 'preserve' | Joiner;
13
+ /**
14
+ * Makes no changes to `spec.lines[].tokens` but joins them into `spec.description`
15
+ * following given spacing srtategy
16
+ * @param {Spacing} spacing tells how to handle the whitespace
17
+ */
18
+ export default function descriptionTokenizer(spacing?: Spacing): Tokenizer;
19
+ export declare function getJoiner(spacing: Spacing): Joiner;
@@ -0,0 +1,51 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getJoiner = void 0;
4
+ const primitives_1 = require("../../primitives");
5
+ /**
6
+ * Makes no changes to `spec.lines[].tokens` but joins them into `spec.description`
7
+ * following given spacing srtategy
8
+ * @param {Spacing} spacing tells how to handle the whitespace
9
+ */
10
+ function descriptionTokenizer(spacing = 'compact') {
11
+ const join = getJoiner(spacing);
12
+ return (spec) => {
13
+ spec.description = join(spec.source);
14
+ return spec;
15
+ };
16
+ }
17
+ exports.default = descriptionTokenizer;
18
+ function getJoiner(spacing) {
19
+ if (spacing === 'compact')
20
+ return compactJoiner;
21
+ if (spacing === 'preserve')
22
+ return preserveJoiner;
23
+ return spacing;
24
+ }
25
+ exports.getJoiner = getJoiner;
26
+ function compactJoiner(lines) {
27
+ return lines
28
+ .map(({ tokens: { description } }) => description.trim())
29
+ .filter((description) => description !== '')
30
+ .join(' ');
31
+ }
32
+ const lineNo = (num, { tokens }, i) => tokens.type === '' ? num : i;
33
+ const getDescription = ({ tokens }) => (tokens.delimiter === '' ? tokens.start : tokens.postDelimiter.slice(1)) +
34
+ tokens.description;
35
+ function preserveJoiner(lines) {
36
+ if (lines.length === 0)
37
+ return '';
38
+ // skip the opening line with no description
39
+ if (lines[0].tokens.description === '' &&
40
+ lines[0].tokens.delimiter === primitives_1.Markers.start)
41
+ lines = lines.slice(1);
42
+ // skip the closing line with no description
43
+ const lastLine = lines[lines.length - 1];
44
+ if (lastLine !== undefined &&
45
+ lastLine.tokens.description === '' &&
46
+ lastLine.tokens.end.endsWith(primitives_1.Markers.end))
47
+ lines = lines.slice(0, -1);
48
+ // description starts at the last line of type definition
49
+ lines = lines.slice(lines.reduce(lineNo, 0));
50
+ return lines.map(getDescription).join('\n');
51
+ }
@@ -0,0 +1,7 @@
1
+ import { Spec } from '../../primitives';
2
+ /**
3
+ * Splits `spect.lines[].token.description` into other tokens,
4
+ * and populates the spec.{tag, name, type, description}. Invoked in a chaing
5
+ * with other tokens, operations listed above can be moved to separate tokenizers
6
+ */
7
+ export declare type Tokenizer = (spec: Spec) => Spec;
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,6 @@
1
+ import { Tokenizer } from './index';
2
+ /**
3
+ * Splits remaining `spec.lines[].tokens.description` into `name` and `descriptions` tokens,
4
+ * and populates the `spec.name`
5
+ */
6
+ export default function nameTokenizer(): Tokenizer;
@@ -0,0 +1,94 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const util_1 = require("../../util");
4
+ const isQuoted = (s) => s && s.startsWith('"') && s.endsWith('"');
5
+ /**
6
+ * Splits remaining `spec.lines[].tokens.description` into `name` and `descriptions` tokens,
7
+ * and populates the `spec.name`
8
+ */
9
+ function nameTokenizer() {
10
+ const typeEnd = (num, { tokens }, i) => tokens.type === '' ? num : i;
11
+ return (spec) => {
12
+ // look for the name in the line where {type} ends
13
+ const { tokens } = spec.source[spec.source.reduce(typeEnd, 0)];
14
+ const source = tokens.description.trimLeft();
15
+ const quotedGroups = source.split('"');
16
+ // if it starts with quoted group, assume it is a literal
17
+ if (quotedGroups.length > 1 &&
18
+ quotedGroups[0] === '' &&
19
+ quotedGroups.length % 2 === 1) {
20
+ spec.name = quotedGroups[1];
21
+ tokens.name = `"${quotedGroups[1]}"`;
22
+ [tokens.postName, tokens.description] = util_1.splitSpace(source.slice(tokens.name.length));
23
+ return spec;
24
+ }
25
+ let brackets = 0;
26
+ let name = '';
27
+ let optional = false;
28
+ let defaultValue;
29
+ // assume name is non-space string or anything wrapped into brackets
30
+ for (const ch of source) {
31
+ if (brackets === 0 && util_1.isSpace(ch))
32
+ break;
33
+ if (ch === '[')
34
+ brackets++;
35
+ if (ch === ']')
36
+ brackets--;
37
+ name += ch;
38
+ }
39
+ if (brackets !== 0) {
40
+ spec.problems.push({
41
+ code: 'spec:name:unpaired-brackets',
42
+ message: 'unpaired brackets',
43
+ line: spec.source[0].number,
44
+ critical: true,
45
+ });
46
+ return spec;
47
+ }
48
+ const nameToken = name;
49
+ if (name[0] === '[' && name[name.length - 1] === ']') {
50
+ optional = true;
51
+ name = name.slice(1, -1);
52
+ const parts = name.split('=');
53
+ name = parts[0].trim();
54
+ if (parts[1] !== undefined)
55
+ defaultValue = parts.slice(1).join('=').trim();
56
+ if (name === '') {
57
+ spec.problems.push({
58
+ code: 'spec:name:empty-name',
59
+ message: 'empty name',
60
+ line: spec.source[0].number,
61
+ critical: true,
62
+ });
63
+ return spec;
64
+ }
65
+ if (defaultValue === '') {
66
+ spec.problems.push({
67
+ code: 'spec:name:empty-default',
68
+ message: 'empty default value',
69
+ line: spec.source[0].number,
70
+ critical: true,
71
+ });
72
+ return spec;
73
+ }
74
+ // has "=" and is not a string, except for "=>"
75
+ if (!isQuoted(defaultValue) && /=(?!>)/.test(defaultValue)) {
76
+ spec.problems.push({
77
+ code: 'spec:name:invalid-default',
78
+ message: 'invalid default value syntax',
79
+ line: spec.source[0].number,
80
+ critical: true,
81
+ });
82
+ return spec;
83
+ }
84
+ }
85
+ spec.optional = optional;
86
+ spec.name = name;
87
+ tokens.name = nameToken;
88
+ if (defaultValue !== undefined)
89
+ spec.default = defaultValue;
90
+ [tokens.postName, tokens.description] = util_1.splitSpace(source.slice(tokens.name.length));
91
+ return spec;
92
+ };
93
+ }
94
+ exports.default = nameTokenizer;
@@ -0,0 +1,6 @@
1
+ import { Tokenizer } from './index';
2
+ /**
3
+ * Splits the `@prefix` from remaining `Spec.lines[].token.descrioption` into the `tag` token,
4
+ * and populates `spec.tag`
5
+ */
6
+ export default function tagTokenizer(): Tokenizer;
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ /**
4
+ * Splits the `@prefix` from remaining `Spec.lines[].token.descrioption` into the `tag` token,
5
+ * and populates `spec.tag`
6
+ */
7
+ function tagTokenizer() {
8
+ return (spec) => {
9
+ const { tokens } = spec.source[0];
10
+ const match = tokens.description.match(/\s*(@(\S+))(\s*)/);
11
+ if (match === null) {
12
+ spec.problems.push({
13
+ code: 'spec:tag:prefix',
14
+ message: 'tag should start with "@" symbol',
15
+ line: spec.source[0].number,
16
+ critical: true,
17
+ });
18
+ return spec;
19
+ }
20
+ tokens.tag = match[1];
21
+ tokens.postTag = match[3];
22
+ tokens.description = tokens.description.slice(match[0].length);
23
+ spec.tag = match[2];
24
+ return spec;
25
+ };
26
+ }
27
+ exports.default = tagTokenizer;
@@ -0,0 +1,27 @@
1
+ import { Tokenizer } from './index';
2
+ /**
3
+ * Joiner is a function taking collected type token string parts,
4
+ * and joining them together. In most of the cases this will be
5
+ * a single piece like {type-name}, but type may go over multipe line
6
+ * ```
7
+ * @tag {function(
8
+ * number,
9
+ * string
10
+ * )}
11
+ * ```
12
+ */
13
+ export declare type Joiner = (parts: string[]) => string;
14
+ /**
15
+ * Shortcut for standard Joiners
16
+ * compact - trim surrounding space, replace line breaks with a single space
17
+ * preserve - concat as is
18
+ */
19
+ export declare type Spacing = 'compact' | 'preserve' | Joiner;
20
+ /**
21
+ * Sets splits remaining `Spec.lines[].tokes.description` into `type` and `description`
22
+ * tokens and populates Spec.type`
23
+ *
24
+ * @param {Spacing} spacing tells how to deal with a whitespace
25
+ * for type values going over multiple lines
26
+ */
27
+ export default function typeTokenizer(spacing?: Spacing): Tokenizer;
@@ -0,0 +1,70 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const util_1 = require("../../util");
4
+ /**
5
+ * Sets splits remaining `Spec.lines[].tokes.description` into `type` and `description`
6
+ * tokens and populates Spec.type`
7
+ *
8
+ * @param {Spacing} spacing tells how to deal with a whitespace
9
+ * for type values going over multiple lines
10
+ */
11
+ function typeTokenizer(spacing = 'compact') {
12
+ const join = getJoiner(spacing);
13
+ return (spec) => {
14
+ let curlies = 0;
15
+ let lines = [];
16
+ for (const [i, { tokens }] of spec.source.entries()) {
17
+ let type = '';
18
+ if (i === 0 && tokens.description[0] !== '{')
19
+ return spec;
20
+ for (const ch of tokens.description) {
21
+ if (ch === '{')
22
+ curlies++;
23
+ if (ch === '}')
24
+ curlies--;
25
+ type += ch;
26
+ if (curlies === 0)
27
+ break;
28
+ }
29
+ lines.push([tokens, type]);
30
+ if (curlies === 0)
31
+ break;
32
+ }
33
+ if (curlies !== 0) {
34
+ spec.problems.push({
35
+ code: 'spec:type:unpaired-curlies',
36
+ message: 'unpaired curlies',
37
+ line: spec.source[0].number,
38
+ critical: true,
39
+ });
40
+ return spec;
41
+ }
42
+ const parts = [];
43
+ const offset = lines[0][0].postDelimiter.length;
44
+ for (const [i, [tokens, type]] of lines.entries()) {
45
+ if (type === '')
46
+ continue;
47
+ tokens.type = type;
48
+ if (i > 0) {
49
+ tokens.type = tokens.postDelimiter.slice(offset) + type;
50
+ tokens.postDelimiter = tokens.postDelimiter.slice(0, offset);
51
+ }
52
+ [tokens.postType, tokens.description] = util_1.splitSpace(tokens.description.slice(type.length));
53
+ parts.push(tokens.type);
54
+ }
55
+ parts[0] = parts[0].slice(1);
56
+ parts[parts.length - 1] = parts[parts.length - 1].slice(0, -1);
57
+ spec.type = join(parts);
58
+ return spec;
59
+ };
60
+ }
61
+ exports.default = typeTokenizer;
62
+ const trim = (x) => x.trim();
63
+ function getJoiner(spacing) {
64
+ if (spacing === 'compact')
65
+ return (t) => t.map(trim).join('');
66
+ else if (spacing === 'preserve')
67
+ return (t) => t.join('\n');
68
+ else
69
+ return spacing;
70
+ }
@@ -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;