1 | (function () {
|
2 | |
3 |
|
4 |
|
5 |
|
6 | |
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 |
|
16 |
|
17 |
|
18 |
|
19 |
|
20 |
|
21 |
|
22 |
|
23 |
|
24 |
|
25 |
|
26 |
|
27 |
|
28 | |
29 |
|
30 |
|
31 |
|
32 |
|
33 | var errors = [],
|
34 | reference_blocks = [],
|
35 | processing_time = 0,
|
36 | regex = {
|
37 | regLevel: new RegExp('^([\\s\\-]+)'),
|
38 | invalidLine: new RegExp('^\\-\\-\\-|^\\.\\.\\.|^\\s*#.*|^\\s*$'),
|
39 | dashesString: new RegExp('^\\s*\\"([^\\"]*)\\"\\s*$'),
|
40 | quotesString: new RegExp("^\\s*\\'([^\\']*)\\'\\s*$"),
|
41 | float: new RegExp('^[+-]?[0-9]+\\.[0-9]+(e[+-]?[0-9]+(\\.[0-9]+)?)?$'),
|
42 | integer: new RegExp('^[+-]?[0-9]+$'),
|
43 | array: new RegExp('\\[\\s*(.*)\\s*\\]'),
|
44 | map: new RegExp('\\{\\s*(.*)\\s*\\}'),
|
45 | key_value: new RegExp('([a-z0-9_-][ a-z0-9_-]*):( .+)', 'i'),
|
46 | single_key_value: new RegExp('^([a-z0-9_-][ a-z0-9_-]*):( .+?)$', 'i'),
|
47 | key: new RegExp('([a-z0-9_-][ a-z0-9_-]+):( .+)?', 'i'),
|
48 | item: new RegExp('^-\\s+'),
|
49 | trim: new RegExp('^\\s+|\\s+$'),
|
50 | comment: new RegExp('([^\\\'\\"#]+([\\\'\\"][^\\\'\\"]*[\\\'\\"])*)*(#.*)?')
|
51 | };
|
52 |
|
53 | |
54 |
|
55 |
|
56 |
|
57 |
|
58 | function Block(lvl) {
|
59 | return {
|
60 |
|
61 | parent: null,
|
62 |
|
63 | length: 0,
|
64 |
|
65 | level: lvl,
|
66 |
|
67 | lines: [],
|
68 |
|
69 | children: [],
|
70 |
|
71 | addChild: function(obj) {
|
72 | this.children.push(obj);
|
73 | obj.parent = this;
|
74 | ++this.length;
|
75 | }
|
76 | }
|
77 | }
|
78 |
|
79 | function parser(str) {
|
80 | var regLevel = regex['regLevel'];
|
81 | var invalidLine = regex['invalidLine'];
|
82 | var lines = str.split('\n');
|
83 | var m;
|
84 | var level = 0,
|
85 | curLevel = 0;
|
86 |
|
87 | var blocks = [];
|
88 |
|
89 | var result = new Block(-1);
|
90 | var currentBlock = new Block(0);
|
91 | result.addChild(currentBlock);
|
92 | var levels = [];
|
93 | var line = '';
|
94 |
|
95 | blocks.push(currentBlock);
|
96 | levels.push(level);
|
97 |
|
98 | for (var i = 0, len = lines.length; i < len; ++i) {
|
99 | line = lines[i];
|
100 |
|
101 | if (line.match(invalidLine)) {
|
102 | continue
|
103 | }
|
104 |
|
105 | if ((m = regLevel.exec(line))) {
|
106 | level = m[1].length;
|
107 | } else { level = 0; }
|
108 |
|
109 | if (level > curLevel) {
|
110 | var oldBlock = currentBlock;
|
111 | currentBlock = new Block(level);
|
112 | oldBlock.addChild(currentBlock);
|
113 | blocks.push(currentBlock);
|
114 | levels.push(level);
|
115 | } else if (level < curLevel) {
|
116 | var added = false;
|
117 |
|
118 | var k = levels.length - 1;
|
119 | for (; k >= 0; --k) {
|
120 | if (levels[k] == level) {
|
121 | currentBlock = new Block(level);
|
122 | blocks.push(currentBlock);
|
123 | levels.push(level);
|
124 | if (blocks[k].parent != null) { blocks[k].parent.addChild(currentBlock); }
|
125 | added = true;
|
126 | break
|
127 | }
|
128 | }
|
129 |
|
130 | if (!added) {
|
131 | errors.push('Error: Invalid indentation at line ' + i + ': ' + line);
|
132 | return
|
133 | }
|
134 | }
|
135 |
|
136 | currentBlock.lines.push(line.replace(regex['trim'], ''));
|
137 | curLevel = level;
|
138 | }
|
139 |
|
140 | return result
|
141 | }
|
142 |
|
143 | function processValue(val) {
|
144 | val = val.replace(regex['trim'], '');
|
145 | var m = null;
|
146 |
|
147 | if (val == 'true') {
|
148 | return true
|
149 | } else if (val == 'false') {
|
150 | return false
|
151 | } else if (val == '.NaN') {
|
152 | return Number.NaN
|
153 | } else if (val == 'null') {
|
154 | return null
|
155 | } else if (val == '.inf') {
|
156 | return Number.POSITIVE_INFINITY
|
157 | } else if (val == '-.inf') {
|
158 | return Number.NEGATIVE_INFINITY
|
159 | } else if ((m = val.match(regex['dashesString']))) {
|
160 | return m[1]
|
161 | } else if ((m = val.match(regex['quotesString']))) {
|
162 | return m[1]
|
163 | } else if ((m = val.match(regex['float']))) {
|
164 | return parseFloat(m[0])
|
165 | } else if ((m = val.match(regex['integer']))) {
|
166 | return parseInt(m[0])
|
167 | } else if (!isNaN((m = Date.parse(val)))) {
|
168 | return new Date(m)
|
169 | } else if ((m = val.match(regex['single_key_value']))) {
|
170 | var res = {};
|
171 | res[m[1]] = processValue(m[2]);
|
172 | return res
|
173 | } else if ((m = val.match(regex['array']))) {
|
174 | var count = 0,
|
175 | c = ' ';
|
176 | var res = [];
|
177 | var content = '';
|
178 | var str = false;
|
179 | for (var j = 0, lenJ = m[1].length; j < lenJ; ++j) {
|
180 | c = m[1][j];
|
181 | if (c == "'" || c == '"') {
|
182 | if (str === false) {
|
183 | str = c;
|
184 | content += c;
|
185 | continue
|
186 | } else if ((c == "'" && str == "'") || (c == '"' && str == '"')) {
|
187 | str = false;
|
188 | content += c;
|
189 | continue
|
190 | }
|
191 | } else if (str === false && (c == '[' || c == '{')) {
|
192 | ++count;
|
193 | } else if (str === false && (c == ']' || c == '}')) {
|
194 | --count;
|
195 | } else if (str === false && count == 0 && c == ',') {
|
196 | res.push(processValue(content));
|
197 | content = '';
|
198 | continue
|
199 | }
|
200 |
|
201 | content += c;
|
202 | }
|
203 |
|
204 | if (content.length > 0) { res.push(processValue(content)); }
|
205 | return res
|
206 | } else if ((m = val.match(regex['map']))) {
|
207 | var count = 0,
|
208 | c = ' ';
|
209 | var res = [];
|
210 | var content = '';
|
211 | var str = false;
|
212 | for (var j = 0, lenJ = m[1].length; j < lenJ; ++j) {
|
213 | c = m[1][j];
|
214 | if (c == "'" || c == '"') {
|
215 | if (str === false) {
|
216 | str = c;
|
217 | content += c;
|
218 | continue
|
219 | } else if ((c == "'" && str == "'") || (c == '"' && str == '"')) {
|
220 | str = false;
|
221 | content += c;
|
222 | continue
|
223 | }
|
224 | } else if (str === false && (c == '[' || c == '{')) {
|
225 | ++count;
|
226 | } else if (str === false && (c == ']' || c == '}')) {
|
227 | --count;
|
228 | } else if (str === false && count == 0 && c == ',') {
|
229 | res.push(content);
|
230 | content = '';
|
231 | continue
|
232 | }
|
233 |
|
234 | content += c;
|
235 | }
|
236 |
|
237 | if (content.length > 0) { res.push(content); }
|
238 |
|
239 | var newRes = {};
|
240 | for (var j = 0, lenJ = res.length; j < lenJ; ++j) {
|
241 | if ((m = res[j].match(regex['key_value']))) {
|
242 | newRes[m[1]] = processValue(m[2]);
|
243 | }
|
244 | }
|
245 |
|
246 | return newRes
|
247 | } else { return val }
|
248 | }
|
249 |
|
250 | function processFoldedBlock(block) {
|
251 | var lines = block.lines;
|
252 | var children = block.children;
|
253 | var str = lines.join(' ');
|
254 | var chunks = [str];
|
255 | for (var i = 0, len = children.length; i < len; ++i) {
|
256 | chunks.push(processFoldedBlock(children[i]));
|
257 | }
|
258 | return chunks.join('\n')
|
259 | }
|
260 |
|
261 | function processLiteralBlock(block) {
|
262 | var lines = block.lines;
|
263 | var children = block.children;
|
264 | var str = lines.join('\n');
|
265 | for (var i = 0, len = children.length; i < len; ++i) {
|
266 | str += processLiteralBlock(children[i]);
|
267 | }
|
268 | return str
|
269 | }
|
270 |
|
271 | function processBlock(blocks) {
|
272 | var m = null;
|
273 | var res = {};
|
274 | var lines = null;
|
275 | var children = null;
|
276 | var currentObj = null;
|
277 |
|
278 | var level = -1;
|
279 |
|
280 | var processedBlocks = [];
|
281 |
|
282 | var isMap = true;
|
283 |
|
284 | for (var j = 0, lenJ = blocks.length; j < lenJ; ++j) {
|
285 | if (level != -1 && level != blocks[j].level) { continue }
|
286 |
|
287 | processedBlocks.push(j);
|
288 |
|
289 | level = blocks[j].level;
|
290 | lines = blocks[j].lines;
|
291 | children = blocks[j].children;
|
292 | currentObj = null;
|
293 |
|
294 | for (var i = 0, len = lines.length; i < len; ++i) {
|
295 | var line = lines[i];
|
296 |
|
297 | if ((m = line.match(regex['key']))) {
|
298 | var key = m[1];
|
299 |
|
300 | if (key[0] == '-') {
|
301 | key = key.replace(regex['item'], '');
|
302 | if (isMap) {
|
303 | isMap = false;
|
304 | if (typeof res.length === 'undefined') {
|
305 | res = [];
|
306 | }
|
307 | }
|
308 | if (currentObj != null) { res.push(currentObj); }
|
309 | currentObj = {};
|
310 | isMap = true;
|
311 | }
|
312 |
|
313 | if (typeof m[2] != 'undefined') {
|
314 | var value = m[2].replace(regex['trim'], '');
|
315 | if (value[0] == '&') {
|
316 | var nb = processBlock(children);
|
317 | if (currentObj != null) { currentObj[key] = nb; }
|
318 | else { res[key] = nb; }
|
319 | reference_blocks[value.substr(1)] = nb;
|
320 | } else if (value[0] == '|') {
|
321 | if (currentObj != null)
|
322 | { currentObj[key] = processLiteralBlock(children.shift()); }
|
323 | else { res[key] = processLiteralBlock(children.shift()); }
|
324 | } else if (value[0] == '*') {
|
325 | var v = value.substr(1);
|
326 | var no = {};
|
327 |
|
328 | if (typeof reference_blocks[v] == 'undefined') {
|
329 | errors.push("Reference '" + v + "' not found!");
|
330 | } else {
|
331 | for (var k in reference_blocks[v]) {
|
332 | no[k] = reference_blocks[v][k];
|
333 | }
|
334 |
|
335 | if (currentObj != null) { currentObj[key] = no; }
|
336 | else { res[key] = no; }
|
337 | }
|
338 | } else if (value[0] == '>') {
|
339 | if (currentObj != null)
|
340 | { currentObj[key] = processFoldedBlock(children.shift()); }
|
341 | else { res[key] = processFoldedBlock(children.shift()); }
|
342 | } else {
|
343 | if (currentObj != null) { currentObj[key] = processValue(value); }
|
344 | else { res[key] = processValue(value); }
|
345 | }
|
346 | } else {
|
347 | if (currentObj != null) { currentObj[key] = processBlock(children); }
|
348 | else { res[key] = processBlock(children); }
|
349 | }
|
350 | } else if (line.match(/^-\s*$/)) {
|
351 | if (isMap) {
|
352 | isMap = false;
|
353 | if (typeof res.length === 'undefined') {
|
354 | res = [];
|
355 | }
|
356 | }
|
357 | if (currentObj != null) { res.push(currentObj); }
|
358 | currentObj = {};
|
359 | isMap = true;
|
360 | continue
|
361 | } else if ((m = line.match(/^-\s*(.*)/))) {
|
362 | if (currentObj != null) { currentObj.push(processValue(m[1])); }
|
363 | else {
|
364 | if (isMap) {
|
365 | isMap = false;
|
366 | if (typeof res.length === 'undefined') {
|
367 | res = [];
|
368 | }
|
369 | }
|
370 | res.push(processValue(m[1]));
|
371 | }
|
372 | continue
|
373 | }
|
374 | }
|
375 |
|
376 | if (currentObj != null) {
|
377 | if (isMap) {
|
378 | isMap = false;
|
379 | if (typeof res.length === 'undefined') {
|
380 | res = [];
|
381 | }
|
382 | }
|
383 | res.push(currentObj);
|
384 | }
|
385 | }
|
386 |
|
387 | for (var j = processedBlocks.length - 1; j >= 0; --j) {
|
388 | blocks.splice.call(blocks, processedBlocks[j], 1);
|
389 | }
|
390 |
|
391 | return res
|
392 | }
|
393 |
|
394 | function semanticAnalysis(blocks) {
|
395 | var res = processBlock(blocks.children);
|
396 | return res
|
397 | }
|
398 |
|
399 | function preProcess(src) {
|
400 | var m;
|
401 | var lines = src.split('\n');
|
402 |
|
403 | var r = regex['comment'];
|
404 |
|
405 | for (var i in lines) {
|
406 | if ((m = lines[i].match(r))) {
|
407 | |
408 |
|
409 |
|
410 |
|
411 |
|
412 |
|
413 |
|
414 |
|
415 | if (typeof m[3] !== 'undefined') {
|
416 | lines[i] = m[0].substr(0, m[0].length - m[3].length);
|
417 | }
|
418 | }
|
419 | }
|
420 |
|
421 | return lines.join('\n')
|
422 | }
|
423 |
|
424 | function load(str) {
|
425 | errors = [];
|
426 | reference_blocks = [];
|
427 | processing_time = new Date().getTime();
|
428 | var pre = preProcess(str);
|
429 | var doc = parser(pre);
|
430 | var res = semanticAnalysis(doc);
|
431 | processing_time = new Date().getTime() - processing_time;
|
432 |
|
433 | return res
|
434 | }
|
435 |
|
436 | |
437 |
|
438 |
|
439 |
|
440 | var optionalByteOrderMark = '\\ufeff?';
|
441 | var pattern =
|
442 | '^(' +
|
443 | optionalByteOrderMark +
|
444 | '(= yaml =|---)' +
|
445 | '$([\\s\\S]*?)' +
|
446 | '(?:\\2|\\.\\.\\.)' +
|
447 | '$' +
|
448 | '' +
|
449 | '(?:\\n)?)';
|
450 |
|
451 |
|
452 | var regex$1 = new RegExp(pattern, 'm');
|
453 |
|
454 | function extractor(string) {
|
455 | string = string || '';
|
456 |
|
457 | var lines = string.split(/(\r?\n)/);
|
458 | if (lines[0] && /= yaml =|---/.test(lines[0])) {
|
459 | return parse(string)
|
460 | } else {
|
461 | return { attributes: {}, body: string }
|
462 | }
|
463 | }
|
464 |
|
465 | function parse(string) {
|
466 | var match = regex$1.exec(string);
|
467 |
|
468 | if (!match) {
|
469 | return {
|
470 | attributes: {},
|
471 | body: string
|
472 | }
|
473 | }
|
474 |
|
475 | var yaml = match[match.length - 1].replace(/^\s+|\s+$/g, '');
|
476 | var attributes = load(yaml) || {};
|
477 | var body = string.replace(match[0], '');
|
478 |
|
479 | return { attributes: attributes, body: body, frontmatter: yaml }
|
480 | }
|
481 |
|
482 | var install = function (hook, vm) {
|
483 |
|
484 | vm.config.frontMatter = {};
|
485 | vm.config.frontMatter.installed = true;
|
486 | vm.config.frontMatter.parseMarkdown = function (content) {
|
487 | var ref = extractor(content);
|
488 | var body = ref.body;
|
489 | return body;
|
490 | };
|
491 |
|
492 | hook.beforeEach(function (content) {
|
493 | var ref = extractor(content);
|
494 | var attributes = ref.attributes;
|
495 | var body = ref.body;
|
496 |
|
497 | vm.frontmatter = attributes;
|
498 |
|
499 | return body;
|
500 | });
|
501 | };
|
502 |
|
503 | $docsify.plugins = [].concat(install, $docsify.plugins);
|
504 |
|
505 | }());
|