comment-parser 0.3.2 → 0.5.0
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/.eslintignore +1 -0
- package/.eslintrc +11 -0
- package/.travis.yml +2 -4
- package/CHANGELOG.md +9 -0
- package/README.md +24 -5
- package/index.js +31 -34
- package/package.json +11 -6
- package/parser.js +180 -246
- package/parsers.js +100 -0
- package/tests/custom-parsers.spec.js +90 -99
- package/tests/files.spec.js +45 -46
- package/tests/fixtures/sample.js +15 -15
- package/tests/parse.js +18 -0
- package/tests/parse.spec.js +787 -534
- package/.jshintrc +0 -11
- package/.npmignore +0 -15
package/parser.js
CHANGED
|
@@ -1,131 +1,43 @@
|
|
|
1
1
|
|
|
2
|
-
var
|
|
3
|
-
|
|
4
|
-
var
|
|
5
|
-
var
|
|
2
|
+
var PARSERS = require('./parsers')
|
|
3
|
+
|
|
4
|
+
var MARKER_START = '/**'
|
|
5
|
+
var MARKER_START_SKIP = '/***'
|
|
6
|
+
var MARKER_END = '*/'
|
|
6
7
|
|
|
7
8
|
/* ------- util functions ------- */
|
|
8
9
|
|
|
9
|
-
function merge(/* ...objects */) {
|
|
10
|
-
var k, obj
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
for (k in obj) { if (obj.hasOwnProperty(k)) {
|
|
14
|
-
res[k] = obj[k];
|
|
15
|
-
}}
|
|
16
|
-
}
|
|
17
|
-
return res;
|
|
18
|
-
}
|
|
10
|
+
function merge (/* ...objects */) {
|
|
11
|
+
var k, obj
|
|
12
|
+
var res = {}
|
|
13
|
+
var objs = Array.prototype.slice.call(arguments)
|
|
19
14
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
15
|
+
for (var i = 0, l = objs.length; i < l; i++) {
|
|
16
|
+
obj = objs[i]
|
|
17
|
+
for (k in obj) {
|
|
18
|
+
if (obj.hasOwnProperty(k)) {
|
|
19
|
+
res[k] = obj[k]
|
|
20
|
+
}
|
|
21
|
+
}
|
|
27
22
|
}
|
|
28
|
-
return
|
|
23
|
+
return res
|
|
29
24
|
}
|
|
30
25
|
|
|
31
|
-
function
|
|
32
|
-
var
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
} while (++i < str.length);
|
|
36
|
-
return i;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
/* ------- default parsers ------- */
|
|
40
|
-
|
|
41
|
-
var PARSERS = {};
|
|
42
|
-
|
|
43
|
-
PARSERS.parse_tag = function parse_tag(str) {
|
|
44
|
-
var result = str.match(/^\s*@(\S+)/);
|
|
45
|
-
|
|
46
|
-
if (!result) { throw new Error('Invalid `@tag`, missing @ symbol'); }
|
|
47
|
-
|
|
48
|
-
return {
|
|
49
|
-
source : result[0],
|
|
50
|
-
data : {tag: result[1]}
|
|
51
|
-
};
|
|
52
|
-
};
|
|
53
|
-
|
|
54
|
-
PARSERS.parse_type = function parse_type(str, data) {
|
|
55
|
-
if (data.errors && data.errors.length) { return null; }
|
|
56
|
-
|
|
57
|
-
var pos = skipws(str);
|
|
58
|
-
var res = '';
|
|
59
|
-
var curlies = 0;
|
|
60
|
-
|
|
61
|
-
if (str[pos] !== '{') { return null; }
|
|
62
|
-
|
|
63
|
-
while (pos < str.length) {
|
|
64
|
-
curlies += (str[pos] === '{' ? 1 : (str[pos] === '}' ? -1 : 0));
|
|
65
|
-
res += str[pos];
|
|
66
|
-
pos ++;
|
|
67
|
-
if (curlies === 0) { break; }
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
if (curlies !== 0) { throw new Error('Invalid `{type}`, unpaired curlies'); }
|
|
71
|
-
|
|
72
|
-
return {
|
|
73
|
-
source : str.slice(0, pos),
|
|
74
|
-
data : {type: res.slice(1, -1)}
|
|
75
|
-
};
|
|
76
|
-
};
|
|
77
|
-
|
|
78
|
-
PARSERS.parse_name = function parse_name(str, data) {
|
|
79
|
-
if (data.errors && data.errors.length) { return null; }
|
|
80
|
-
|
|
81
|
-
var pos = skipws(str);
|
|
82
|
-
var name = '';
|
|
83
|
-
var brackets = 0;
|
|
84
|
-
|
|
85
|
-
while (pos < str.length) {
|
|
86
|
-
brackets += (str[pos] === '[' ? 1 : (str[pos] === ']' ? -1 : 0));
|
|
87
|
-
name += str[pos];
|
|
88
|
-
pos ++;
|
|
89
|
-
if (brackets === 0 && /\s/.test(str[pos])) { break; }
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
if (brackets !== 0) { throw new Error('Invalid `name`, unpaired brackets'); }
|
|
93
|
-
|
|
94
|
-
var res = {name: name, optional: false};
|
|
95
|
-
|
|
96
|
-
if (name[0] === '[' && name[name.length - 1] === ']') {
|
|
97
|
-
res.optional = true;
|
|
98
|
-
name = name.slice(1, -1);
|
|
26
|
+
function find (list, filter) {
|
|
27
|
+
var k
|
|
28
|
+
var i = list.length
|
|
29
|
+
var matchs = true
|
|
99
30
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
31
|
+
while (i--) {
|
|
32
|
+
for (k in filter) {
|
|
33
|
+
if (filter.hasOwnProperty(k)) {
|
|
34
|
+
matchs = (filter[k] === list[i][k]) && matchs
|
|
35
|
+
}
|
|
104
36
|
}
|
|
37
|
+
if (matchs) { return list[i] }
|
|
105
38
|
}
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
return {
|
|
110
|
-
source : str.slice(0, pos),
|
|
111
|
-
data : res
|
|
112
|
-
};
|
|
113
|
-
};
|
|
114
|
-
|
|
115
|
-
PARSERS.parse_description = function parse_description(str, data) {
|
|
116
|
-
if (data.errors && data.errors.length) { return null; }
|
|
117
|
-
|
|
118
|
-
var result = str.match(/^\s+((.|\s)+)?/);
|
|
119
|
-
|
|
120
|
-
if (result) {
|
|
121
|
-
return {
|
|
122
|
-
source : result[0],
|
|
123
|
-
data : {description: result[1] === undefined ? '' : result[1]}
|
|
124
|
-
};
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
return null;
|
|
128
|
-
};
|
|
39
|
+
return null
|
|
40
|
+
}
|
|
129
41
|
|
|
130
42
|
/* ------- parsing ------- */
|
|
131
43
|
|
|
@@ -135,216 +47,238 @@ PARSERS.parse_description = function parse_description(str, data) {
|
|
|
135
47
|
* @param {Array[function]} parsers Array of parsers to be applied to the source
|
|
136
48
|
* @returns {object} parsed tag node
|
|
137
49
|
*/
|
|
138
|
-
function parse_tag(str, parsers) {
|
|
139
|
-
if (typeof str !== 'string' || str[0] !== '@') { return null
|
|
50
|
+
function parse_tag (str, parsers) {
|
|
51
|
+
if (typeof str !== 'string' || str[0] !== '@') { return null }
|
|
140
52
|
|
|
141
|
-
var data = parsers.reduce(function(state, parser) {
|
|
142
|
-
var result
|
|
53
|
+
var data = parsers.reduce(function (state, parser) {
|
|
54
|
+
var result
|
|
143
55
|
|
|
144
56
|
try {
|
|
145
|
-
result = parser(state.source, merge({}, state.data))
|
|
57
|
+
result = parser(state.source, merge({}, state.data))
|
|
146
58
|
} catch (err) {
|
|
147
59
|
state.data.errors = (state.data.errors || [])
|
|
148
|
-
.concat(parser.name + ': ' + err.message)
|
|
60
|
+
.concat(parser.name + ': ' + err.message)
|
|
149
61
|
}
|
|
150
62
|
|
|
151
63
|
if (result) {
|
|
152
|
-
state.source = state.source.slice(result.source.length)
|
|
153
|
-
state.data
|
|
64
|
+
state.source = state.source.slice(result.source.length)
|
|
65
|
+
state.data = merge(state.data, result.data)
|
|
154
66
|
}
|
|
155
67
|
|
|
156
|
-
return state
|
|
68
|
+
return state
|
|
157
69
|
}, {
|
|
158
|
-
source
|
|
159
|
-
data
|
|
160
|
-
}).data
|
|
70
|
+
source: str,
|
|
71
|
+
data: {}
|
|
72
|
+
}).data
|
|
161
73
|
|
|
162
|
-
data.optional
|
|
163
|
-
data.type
|
|
164
|
-
data.name
|
|
165
|
-
data.description = data.description === undefined ? '' : data.description
|
|
74
|
+
data.optional = !!data.optional
|
|
75
|
+
data.type = data.type === undefined ? '' : data.type
|
|
76
|
+
data.name = data.name === undefined ? '' : data.name
|
|
77
|
+
data.description = data.description === undefined ? '' : data.description
|
|
166
78
|
|
|
167
|
-
return data
|
|
79
|
+
return data
|
|
168
80
|
}
|
|
169
81
|
|
|
170
82
|
/**
|
|
171
83
|
* Parses comment block (array of String lines)
|
|
172
84
|
*/
|
|
173
|
-
function parse_block(source, opts) {
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
}
|
|
85
|
+
function parse_block (source, opts) {
|
|
86
|
+
var trim = opts.trim
|
|
87
|
+
? function trim (s) { return s.trim() }
|
|
88
|
+
: function trim (s) { return s }
|
|
178
89
|
|
|
179
90
|
var source_str = source
|
|
180
|
-
|
|
181
|
-
|
|
91
|
+
.map(function (line) { return trim(line.source) })
|
|
92
|
+
.join('\n')
|
|
182
93
|
|
|
183
|
-
source_str = trim(source_str)
|
|
94
|
+
source_str = trim(source_str)
|
|
184
95
|
|
|
185
|
-
var start = source[0].number
|
|
96
|
+
var start = source[0].number
|
|
186
97
|
|
|
187
98
|
// merge source lines into tags
|
|
188
99
|
// we assume tag starts with "@"
|
|
189
100
|
source = source
|
|
190
|
-
.reduce(function(tags, line) {
|
|
191
|
-
line.source = trim(line.source)
|
|
101
|
+
.reduce(function (tags, line) {
|
|
102
|
+
line.source = trim(line.source)
|
|
192
103
|
|
|
193
|
-
if (line.source.match(/^\s*@(\w+)/)) {
|
|
194
|
-
tags.push({source: [line.source], line: line.number})
|
|
104
|
+
if (line.source.match(/^\s*@(\w+)/)) {
|
|
105
|
+
tags.push({source: [line.source], line: line.number})
|
|
195
106
|
} else {
|
|
196
|
-
var tag = tags[tags.length - 1]
|
|
197
|
-
|
|
107
|
+
var tag = tags[tags.length - 1]
|
|
108
|
+
if (opts.join !== undefined && opts.join !== false && opts.join !== 0 &&
|
|
109
|
+
!line.startWithStar && tag.source.length > 0) {
|
|
110
|
+
var source
|
|
111
|
+
if (typeof opts.join === 'string') {
|
|
112
|
+
source = opts.join + line.source.replace(/^\s+/, '')
|
|
113
|
+
} else if (typeof opts.join === 'number') {
|
|
114
|
+
source = line.source
|
|
115
|
+
} else {
|
|
116
|
+
source = ' ' + line.source.replace(/^\s+/, '')
|
|
117
|
+
}
|
|
118
|
+
tag.source[tag.source.length - 1] += source
|
|
119
|
+
} else {
|
|
120
|
+
tag.source.push(line.source)
|
|
121
|
+
}
|
|
198
122
|
}
|
|
199
123
|
|
|
200
|
-
return tags
|
|
124
|
+
return tags
|
|
201
125
|
}, [{source: []}])
|
|
202
|
-
.map(function(tag) {
|
|
203
|
-
tag.source = trim(tag.source.join('\n'))
|
|
204
|
-
return tag
|
|
205
|
-
})
|
|
126
|
+
.map(function (tag) {
|
|
127
|
+
tag.source = trim(tag.source.join('\n'))
|
|
128
|
+
return tag
|
|
129
|
+
})
|
|
206
130
|
|
|
207
131
|
// Block description
|
|
208
|
-
var description = source.shift()
|
|
132
|
+
var description = source.shift()
|
|
209
133
|
|
|
210
134
|
// skip if no descriptions and no tags
|
|
211
|
-
if (description.source === '' && source.length === 0) {
|
|
212
|
-
return null
|
|
135
|
+
if (description.source === '' && source.length === 0) {
|
|
136
|
+
return null
|
|
213
137
|
}
|
|
214
138
|
|
|
215
|
-
var tags = source.reduce(function(tags, tag) {
|
|
216
|
-
var tag_node = parse_tag(tag.source, opts.parsers)
|
|
139
|
+
var tags = source.reduce(function (tags, tag) {
|
|
140
|
+
var tag_node = parse_tag(tag.source, opts.parsers)
|
|
217
141
|
|
|
218
|
-
if (!tag_node) { return tags
|
|
142
|
+
if (!tag_node) { return tags }
|
|
219
143
|
|
|
220
|
-
tag_node.line
|
|
221
|
-
tag_node.source = tag.source
|
|
144
|
+
tag_node.line = tag.line
|
|
145
|
+
tag_node.source = tag.source
|
|
222
146
|
|
|
223
147
|
if (opts.dotted_names && tag_node.name.indexOf('.') !== -1) {
|
|
224
|
-
var parent_name
|
|
225
|
-
var parent_tag
|
|
226
|
-
var parent_tags = tags
|
|
227
|
-
var parts = tag_node.name.split('.')
|
|
148
|
+
var parent_name
|
|
149
|
+
var parent_tag
|
|
150
|
+
var parent_tags = tags
|
|
151
|
+
var parts = tag_node.name.split('.')
|
|
228
152
|
|
|
229
153
|
while (parts.length > 1) {
|
|
230
|
-
parent_name = parts.shift()
|
|
231
|
-
parent_tag
|
|
232
|
-
tag
|
|
233
|
-
name
|
|
234
|
-
})
|
|
154
|
+
parent_name = parts.shift()
|
|
155
|
+
parent_tag = find(parent_tags, {
|
|
156
|
+
tag: tag_node.tag,
|
|
157
|
+
name: parent_name
|
|
158
|
+
})
|
|
235
159
|
|
|
236
160
|
if (!parent_tag) {
|
|
237
161
|
parent_tag = {
|
|
238
|
-
tag
|
|
239
|
-
line
|
|
240
|
-
name
|
|
241
|
-
type
|
|
242
|
-
description
|
|
243
|
-
}
|
|
244
|
-
parent_tags.push(parent_tag)
|
|
162
|
+
tag: tag_node.tag,
|
|
163
|
+
line: Number(tag_node.line),
|
|
164
|
+
name: parent_name,
|
|
165
|
+
type: '',
|
|
166
|
+
description: ''
|
|
167
|
+
}
|
|
168
|
+
parent_tags.push(parent_tag)
|
|
245
169
|
}
|
|
246
170
|
|
|
247
|
-
parent_tag.tags = parent_tag.tags || []
|
|
248
|
-
parent_tags = parent_tag.tags
|
|
171
|
+
parent_tag.tags = parent_tag.tags || []
|
|
172
|
+
parent_tags = parent_tag.tags
|
|
249
173
|
}
|
|
250
174
|
|
|
251
|
-
tag_node.name = parts[0]
|
|
252
|
-
parent_tags.push(tag_node)
|
|
253
|
-
return tags
|
|
175
|
+
tag_node.name = parts[0]
|
|
176
|
+
parent_tags.push(tag_node)
|
|
177
|
+
return tags
|
|
254
178
|
}
|
|
255
179
|
|
|
256
|
-
return tags.concat(tag_node)
|
|
257
|
-
}, [])
|
|
258
|
-
|
|
180
|
+
return tags.concat(tag_node)
|
|
181
|
+
}, [])
|
|
182
|
+
|
|
259
183
|
return {
|
|
260
|
-
tags
|
|
261
|
-
line
|
|
262
|
-
description
|
|
263
|
-
source
|
|
264
|
-
}
|
|
184
|
+
tags: tags,
|
|
185
|
+
line: start,
|
|
186
|
+
description: description.source,
|
|
187
|
+
source: source_str
|
|
188
|
+
}
|
|
265
189
|
}
|
|
266
190
|
|
|
267
191
|
/**
|
|
268
192
|
* Produces `extract` function with internal state initialized
|
|
269
193
|
*/
|
|
270
|
-
function mkextract(opts) {
|
|
271
|
-
var chunk = null
|
|
272
|
-
var
|
|
194
|
+
function mkextract (opts) {
|
|
195
|
+
var chunk = null
|
|
196
|
+
var indent = 0
|
|
197
|
+
var number = 0
|
|
273
198
|
|
|
274
199
|
opts = merge({}, {
|
|
275
|
-
trim
|
|
276
|
-
dotted_names
|
|
277
|
-
parsers
|
|
200
|
+
trim: true,
|
|
201
|
+
dotted_names: false,
|
|
202
|
+
parsers: [
|
|
278
203
|
PARSERS.parse_tag,
|
|
279
204
|
PARSERS.parse_type,
|
|
280
205
|
PARSERS.parse_name,
|
|
281
206
|
PARSERS.parse_description
|
|
282
207
|
]
|
|
283
|
-
}, opts || {})
|
|
208
|
+
}, opts || {})
|
|
284
209
|
|
|
285
210
|
/**
|
|
286
|
-
*
|
|
287
|
-
*
|
|
211
|
+
* Read lines until they make a block
|
|
212
|
+
* Return parsed block once fullfilled or null otherwise
|
|
288
213
|
*/
|
|
289
|
-
return function extract(line) {
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
214
|
+
return function extract (line) {
|
|
215
|
+
var result = null
|
|
216
|
+
var startPos = line.indexOf(MARKER_START)
|
|
217
|
+
var endPos = line.indexOf(MARKER_END)
|
|
218
|
+
|
|
219
|
+
// if open marker detected and it's not skip one
|
|
220
|
+
if (startPos !== -1 && line.indexOf(MARKER_START_SKIP) !== startPos) {
|
|
221
|
+
chunk = []
|
|
222
|
+
indent = startPos + MARKER_START.length
|
|
297
223
|
}
|
|
298
224
|
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
225
|
+
// if we are on middle of comment block
|
|
226
|
+
if (chunk) {
|
|
227
|
+
var lineStart = indent
|
|
228
|
+
var startWithStar = false
|
|
229
|
+
|
|
230
|
+
// figure out if we slice from opening marker pos
|
|
231
|
+
// or line start is shifted to the left
|
|
232
|
+
var nonSpaceChar = line.match(/\S/)
|
|
233
|
+
|
|
234
|
+
// skip for the first line starting with /** (fresh chunk)
|
|
235
|
+
// it always has the right indentation
|
|
236
|
+
if (chunk.length > 0 && nonSpaceChar) {
|
|
237
|
+
if (nonSpaceChar[0] === '*') {
|
|
238
|
+
lineStart = nonSpaceChar.index + 2
|
|
239
|
+
startWithStar = true
|
|
240
|
+
} else if (nonSpaceChar.index < indent) {
|
|
241
|
+
lineStart = nonSpaceChar.index
|
|
242
|
+
}
|
|
243
|
+
}
|
|
307
244
|
|
|
308
|
-
|
|
309
|
-
// then append
|
|
310
|
-
if (chunk && line.match(RE_COMMENT_LINE)) {
|
|
245
|
+
// slice the line until end or until closing marker start
|
|
311
246
|
chunk.push({
|
|
312
|
-
number: number
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
247
|
+
number: number,
|
|
248
|
+
startWithStar: startWithStar,
|
|
249
|
+
source: line.slice(lineStart, endPos === -1 ? line.length : endPos)
|
|
250
|
+
})
|
|
251
|
+
|
|
252
|
+
// finalize block if end marker detected
|
|
253
|
+
if (endPos !== -1) {
|
|
254
|
+
result = parse_block(chunk, opts)
|
|
255
|
+
chunk = null
|
|
256
|
+
indent = 0
|
|
257
|
+
}
|
|
323
258
|
}
|
|
324
259
|
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
};
|
|
260
|
+
number += 1
|
|
261
|
+
return result
|
|
262
|
+
}
|
|
329
263
|
}
|
|
330
264
|
|
|
331
265
|
/* ------- Public API ------- */
|
|
332
266
|
|
|
333
|
-
module.exports = function parse(source, opts) {
|
|
334
|
-
var block
|
|
335
|
-
var blocks
|
|
336
|
-
var extract = mkextract(opts)
|
|
337
|
-
var lines
|
|
267
|
+
module.exports = function parse (source, opts) {
|
|
268
|
+
var block
|
|
269
|
+
var blocks = []
|
|
270
|
+
var extract = mkextract(opts)
|
|
271
|
+
var lines = source.split(/\n/)
|
|
338
272
|
|
|
339
|
-
|
|
340
|
-
block = extract(lines.shift())
|
|
273
|
+
for (var i = 0, l = lines.length; i < l; i++) {
|
|
274
|
+
block = extract(lines.shift())
|
|
341
275
|
if (block) {
|
|
342
|
-
blocks.push(block)
|
|
276
|
+
blocks.push(block)
|
|
343
277
|
}
|
|
344
278
|
}
|
|
345
279
|
|
|
346
|
-
return blocks
|
|
347
|
-
}
|
|
280
|
+
return blocks
|
|
281
|
+
}
|
|
348
282
|
|
|
349
|
-
module.exports.PARSERS = PARSERS
|
|
350
|
-
module.exports.mkextract = mkextract
|
|
283
|
+
module.exports.PARSERS = PARSERS
|
|
284
|
+
module.exports.mkextract = mkextract
|
package/parsers.js
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
function skipws (str) {
|
|
2
|
+
var i = 0
|
|
3
|
+
do {
|
|
4
|
+
if (str[i] !== ' ') { return i }
|
|
5
|
+
} while (++i < str.length)
|
|
6
|
+
return i
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/* ------- default parsers ------- */
|
|
10
|
+
|
|
11
|
+
var PARSERS = {}
|
|
12
|
+
|
|
13
|
+
PARSERS.parse_tag = function parse_tag (str) {
|
|
14
|
+
var result = str.match(/^\s*@(\S+)/)
|
|
15
|
+
|
|
16
|
+
if (!result) { throw new Error('Invalid `@tag`, missing @ symbol') }
|
|
17
|
+
|
|
18
|
+
return {
|
|
19
|
+
source: result[0],
|
|
20
|
+
data: {tag: result[1]}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
PARSERS.parse_type = function parse_type (str, data) {
|
|
25
|
+
if (data.errors && data.errors.length) { return null }
|
|
26
|
+
|
|
27
|
+
var pos = skipws(str)
|
|
28
|
+
var res = ''
|
|
29
|
+
var curlies = 0
|
|
30
|
+
|
|
31
|
+
if (str[pos] !== '{') { return null }
|
|
32
|
+
|
|
33
|
+
while (pos < str.length) {
|
|
34
|
+
curlies += (str[pos] === '{' ? 1 : (str[pos] === '}' ? -1 : 0))
|
|
35
|
+
res += str[pos]
|
|
36
|
+
pos++
|
|
37
|
+
if (curlies === 0) { break }
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
if (curlies !== 0) { throw new Error('Invalid `{type}`, unpaired curlies') }
|
|
41
|
+
|
|
42
|
+
return {
|
|
43
|
+
source: str.slice(0, pos),
|
|
44
|
+
data: {type: res.slice(1, -1)}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
PARSERS.parse_name = function parse_name (str, data) {
|
|
49
|
+
if (data.errors && data.errors.length) { return null }
|
|
50
|
+
|
|
51
|
+
var pos = skipws(str)
|
|
52
|
+
var name = ''
|
|
53
|
+
var brackets = 0
|
|
54
|
+
|
|
55
|
+
while (pos < str.length) {
|
|
56
|
+
brackets += (str[pos] === '[' ? 1 : (str[pos] === ']' ? -1 : 0))
|
|
57
|
+
name += str[pos]
|
|
58
|
+
pos++
|
|
59
|
+
if (brackets === 0 && /\s/.test(str[pos])) { break }
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
if (brackets !== 0) { throw new Error('Invalid `name`, unpaired brackets') }
|
|
63
|
+
|
|
64
|
+
var res = {name: name, optional: false}
|
|
65
|
+
|
|
66
|
+
if (name[0] === '[' && name[name.length - 1] === ']') {
|
|
67
|
+
res.optional = true
|
|
68
|
+
name = name.slice(1, -1)
|
|
69
|
+
|
|
70
|
+
if (name.indexOf('=') !== -1) {
|
|
71
|
+
var parts = name.split('=')
|
|
72
|
+
name = parts[0]
|
|
73
|
+
res.default = parts[1].replace(/^(["'])(.+)(\1)$/, '$2')
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
res.name = name
|
|
78
|
+
|
|
79
|
+
return {
|
|
80
|
+
source: str.slice(0, pos),
|
|
81
|
+
data: res
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
PARSERS.parse_description = function parse_description (str, data) {
|
|
86
|
+
if (data.errors && data.errors.length) { return null }
|
|
87
|
+
|
|
88
|
+
var result = str.match(/^\s+((.|\s)+)?/)
|
|
89
|
+
|
|
90
|
+
if (result) {
|
|
91
|
+
return {
|
|
92
|
+
source: result[0],
|
|
93
|
+
data: {description: result[1] === undefined ? '' : result[1]}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
return null
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
module.exports = PARSERS
|