Skip to content

Commit dbb9278

Browse files
committedFeb 19, 2017
feat(front-matter): add front matter[WIP]
1 parent 754f92c commit dbb9278

File tree

4 files changed

+556
-23
lines changed

4 files changed

+556
-23
lines changed
 

‎build/build.js

+20-23
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ var build = function (opts) {
99
rollup
1010
.rollup({
1111
entry: 'src/' + opts.entry,
12-
plugins: [buble()].concat(opts.plugins || [])
12+
plugins: [buble(), commonjs(), nodeResolve()].concat(opts.plugins || [])
1313
})
1414
.then(function (bundle) {
1515
var dest = 'lib/' + (opts.output || opts.entry)
@@ -28,38 +28,35 @@ var build = function (opts) {
2828

2929
build({
3030
entry: 'core/index.js',
31-
output: 'docsify.js',
32-
plugins: [commonjs(), nodeResolve()]
31+
output: 'docsify.js'
3332
})
3433

35-
build({
36-
entry: 'plugins/search/index.js',
37-
output: 'plugins/search.js',
38-
moduleName: 'D.Search'
39-
})
34+
var plugins = [
35+
{ name: 'search', entry: 'search/index.js', moduleName: 'Search' },
36+
{ name: 'ga', entry: 'ga.js', moduleName: 'GA' }
37+
// { name: 'front-matter', entry: 'front-matter/index.js', moduleName: 'FrontMatter' }
38+
]
4039

41-
build({
42-
entry: 'plugins/ga.js',
43-
output: 'plugins/ga.js',
44-
moduleName: 'D.GA'
40+
plugins.forEach(item => {
41+
build({
42+
entry: 'plugins/' + item.entry,
43+
output: 'plugins/' + item.name + '.js',
44+
moduleName: 'D.' + item.moduleName
45+
})
4546
})
4647

4748
if (isProd) {
4849
build({
4950
entry: 'core/index.js',
5051
output: 'docsify.min.js',
51-
plugins: [commonjs(), nodeResolve(), uglify()]
52-
})
53-
build({
54-
entry: 'plugins/search/index.js',
55-
output: 'plugins/search.min.js',
56-
moduleName: 'D.Search',
5752
plugins: [uglify()]
5853
})
59-
build({
60-
entry: 'plugins/ga.js',
61-
output: 'plugins/ga.min.js',
62-
moduleName: 'D.GA',
63-
plugins: [uglify()]
54+
plugins.forEach(item => {
55+
build({
56+
entry: 'plugins/' + item.entry,
57+
output: 'plugins/' + item.name + '.min.js',
58+
moduleName: 'D.' + item.moduleName,
59+
plugins: [uglify()]
60+
})
6461
})
6562
}

‎src/plugins/front-matter/index.js

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import parser from './parser'
2+
3+
const install = function (hook, vm) {
4+
hook.beforeEach(content => {
5+
const { attributes, body } = parser(content)
6+
7+
Docsify.util.merge(vm.config, attributes.config)
8+
9+
return body
10+
})
11+
}
12+
13+
window.$docsify.plugins = [].concat(install, window.$docsify.plugins)

‎src/plugins/front-matter/parser.js

+54
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/**
2+
* Fork https://github.com/egoist/docute/blob/master/src/utils/front-matter.js
3+
*/
4+
/* eslint-disable */
5+
import parser from './yaml'
6+
7+
var optionalByteOrderMark = '\\ufeff?'
8+
var pattern = '^(' +
9+
optionalByteOrderMark +
10+
'(= yaml =|---)' +
11+
'$([\\s\\S]*?)' +
12+
'(?:\\2|\\.\\.\\.)' +
13+
'$' +
14+
'' +
15+
'(?:\\n)?)'
16+
// NOTE: If this pattern uses the 'g' flag the `regex` variable definition will
17+
// need to be moved down into the functions that use it.
18+
var regex = new RegExp(pattern, 'm')
19+
20+
function extractor (string) {
21+
string = string || ''
22+
23+
var lines = string.split(/(\r?\n)/)
24+
if (lines[0] && /= yaml =|---/.test(lines[0])) {
25+
return parse(string)
26+
} else {
27+
return { attributes: {}, body: string }
28+
}
29+
}
30+
31+
function parse (string) {
32+
var match = regex.exec(string)
33+
34+
if (!match) {
35+
return {
36+
attributes: {},
37+
body: string
38+
}
39+
}
40+
41+
var yaml = match[match.length - 1].replace(/^\s+|\s+$/g, '')
42+
var attributes = parser(yaml) || {}
43+
var body = string.replace(match[0], '')
44+
45+
return { attributes: attributes, body: body, frontmatter: yaml }
46+
}
47+
48+
function test (string) {
49+
string = string || ''
50+
51+
return regex.test(string)
52+
}
53+
54+
export default extractor

‎src/plugins/front-matter/yaml.js

+469
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,469 @@
1+
/**
2+
* Fork https://github.com/egoist/docute/blob/master/src/utils/yaml.js
3+
*/
4+
/* eslint-disable */
5+
/*
6+
YAML parser for Javascript
7+
Author: Diogo Costa
8+
This program is released under the MIT License as follows:
9+
Copyright (c) 2011 Diogo Costa (costa.h4evr@gmail.com)
10+
Permission is hereby granted, free of charge, to any person obtaining a copy
11+
of this software and associated documentation files (the "Software"), to deal
12+
in the Software without restriction, including without limitation the rights
13+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14+
copies of the Software, and to permit persons to whom the Software is
15+
furnished to do so, subject to the following conditions:
16+
The above copyright notice and this permission notice shall be included in
17+
all copies or substantial portions of the Software.
18+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24+
THE SOFTWARE.
25+
*/
26+
27+
/**
28+
* @name YAML
29+
* @namespace
30+
*/
31+
32+
33+
var errors = [],
34+
reference_blocks = [],
35+
processing_time = 0,
36+
regex =
37+
{
38+
"regLevel" : new RegExp("^([\\s\\-]+)"),
39+
"invalidLine" : new RegExp("^\\-\\-\\-|^\\.\\.\\.|^\\s*#.*|^\\s*$"),
40+
"dashesString" : new RegExp("^\\s*\\\"([^\\\"]*)\\\"\\s*$"),
41+
"quotesString" : new RegExp("^\\s*\\\'([^\\\']*)\\\'\\s*$"),
42+
"float" : new RegExp("^[+-]?[0-9]+\\.[0-9]+(e[+-]?[0-9]+(\\.[0-9]+)?)?$"),
43+
"integer" : new RegExp("^[+-]?[0-9]+$"),
44+
"array" : new RegExp("\\[\\s*(.*)\\s*\\]"),
45+
"map" : new RegExp("\\{\\s*(.*)\\s*\\}"),
46+
"key_value" : new RegExp("([a-z0-9_-][ a-z0-9_-]*):( .+)", "i"),
47+
"single_key_value" : new RegExp("^([a-z0-9_-][ a-z0-9_-]*):( .+?)$", "i"),
48+
"key" : new RegExp("([a-z0-9_-][ a-z0-9_-]+):( .+)?", "i"),
49+
"item" : new RegExp("^-\\s+"),
50+
"trim" : new RegExp("^\\s+|\\s+$"),
51+
"comment" : new RegExp("([^\\\'\\\"#]+([\\\'\\\"][^\\\'\\\"]*[\\\'\\\"])*)*(#.*)?")
52+
};
53+
54+
/**
55+
* @class A block of lines of a given level.
56+
* @param {int} lvl The block's level.
57+
* @private
58+
*/
59+
function Block(lvl) {
60+
return {
61+
/* The block's parent */
62+
parent: null,
63+
/* Number of children */
64+
length: 0,
65+
/* Block's level */
66+
level: lvl,
67+
/* Lines of code to process */
68+
lines: [],
69+
/* Blocks with greater level */
70+
children : [],
71+
/* Add a block to the children collection */
72+
addChild : function(obj) {
73+
this.children.push(obj);
74+
obj.parent = this;
75+
++this.length;
76+
}
77+
};
78+
}
79+
80+
// function to create an XMLHttpClient in a cross-browser manner
81+
function createXMLHTTPRequest() {
82+
var xmlhttp;
83+
84+
try {
85+
// Mozilla / Safari / IE7
86+
xmlhttp = new XMLHttpRequest();
87+
} catch (e) {
88+
// IE
89+
var XMLHTTP_IDS = new Array('MSXML2.XMLHTTP.5.0',
90+
'MSXML2.XMLHTTP.4.0',
91+
'MSXML2.XMLHTTP.3.0',
92+
'MSXML2.XMLHTTP',
93+
'Microsoft.XMLHTTP' );
94+
var success = false;
95+
for (var i=0;i < XMLHTTP_IDS.length && !success; i++) {
96+
try {
97+
xmlhttp = new ActiveXObject(XMLHTTP_IDS[i]);
98+
success = true;
99+
} catch (e) {}
100+
}
101+
if (!success) {
102+
throw new Error('Unable to create XMLHttpRequest.');
103+
}
104+
}
105+
106+
return xmlhttp;
107+
}
108+
109+
function parser(str) {
110+
var regLevel = regex["regLevel"];
111+
var invalidLine = regex["invalidLine"];
112+
var lines = str.split("\n");
113+
var m;
114+
var level = 0, curLevel = 0;
115+
116+
var blocks = [];
117+
118+
var result = new Block(-1);
119+
var currentBlock = new Block(0);
120+
result.addChild(currentBlock);
121+
var levels = [];
122+
var line = "";
123+
124+
blocks.push(currentBlock);
125+
levels.push(level);
126+
127+
for(var i = 0, len = lines.length; i < len; ++i) {
128+
line = lines[i];
129+
130+
if(line.match(invalidLine)) {
131+
continue;
132+
}
133+
134+
if(m = regLevel.exec(line)) {
135+
level = m[1].length;
136+
} else
137+
level = 0;
138+
139+
if(level > curLevel) {
140+
var oldBlock = currentBlock;
141+
currentBlock = new Block(level);
142+
oldBlock.addChild(currentBlock);
143+
blocks.push(currentBlock);
144+
levels.push(level);
145+
} else if(level < curLevel) {
146+
var added = false;
147+
148+
var k = levels.length - 1;
149+
for(; k >= 0; --k) {
150+
if(levels[k] == level) {
151+
currentBlock = new Block(level);
152+
blocks.push(currentBlock);
153+
levels.push(level);
154+
if(blocks[k].parent!= null)
155+
blocks[k].parent.addChild(currentBlock);
156+
added = true;
157+
break;
158+
}
159+
}
160+
161+
if(!added) {
162+
errors.push("Error: Invalid indentation at line " + i + ": " + line);
163+
return;
164+
}
165+
}
166+
167+
currentBlock.lines.push(line.replace(regex["trim"], ""));
168+
curLevel = level;
169+
}
170+
171+
return result;
172+
}
173+
174+
function processValue(val) {
175+
val = val.replace(regex["trim"], "");
176+
var m = null;
177+
178+
if(val == 'true') {
179+
return true;
180+
} else if(val == 'false') {
181+
return false;
182+
} else if(val == '.NaN') {
183+
return Number.NaN;
184+
} else if(val == 'null') {
185+
return null;
186+
} else if(val == '.inf') {
187+
return Number.POSITIVE_INFINITY;
188+
} else if(val == '-.inf') {
189+
return Number.NEGATIVE_INFINITY;
190+
} else if(m = val.match(regex["dashesString"])) {
191+
return m[1];
192+
} else if(m = val.match(regex["quotesString"])) {
193+
return m[1];
194+
} else if(m = val.match(regex["float"])) {
195+
return parseFloat(m[0]);
196+
} else if(m = val.match(regex["integer"])) {
197+
return parseInt(m[0]);
198+
} else if( !isNaN(m = Date.parse(val))) {
199+
return new Date(m);
200+
} else if(m = val.match(regex["single_key_value"])) {
201+
var res = {};
202+
res[m[1]] = processValue(m[2]);
203+
return res;
204+
} else if(m = val.match(regex["array"])){
205+
var count = 0, c = ' ';
206+
var res = [];
207+
var content = "";
208+
var str = false;
209+
for(var j = 0, lenJ = m[1].length; j < lenJ; ++j) {
210+
c = m[1][j];
211+
if(c == '\'' || c == '"') {
212+
if(str === false) {
213+
str = c;
214+
content += c;
215+
continue;
216+
} else if((c == '\'' && str == '\'') || (c == '"' && str == '"')) {
217+
str = false;
218+
content += c;
219+
continue;
220+
}
221+
} else if(str === false && (c == '[' || c == '{')) {
222+
++count;
223+
} else if(str === false && (c == ']' || c == '}')) {
224+
--count;
225+
} else if(str === false && count == 0 && c == ',') {
226+
res.push(processValue(content));
227+
content = "";
228+
continue;
229+
}
230+
231+
content += c;
232+
}
233+
234+
if(content.length > 0)
235+
res.push(processValue(content));
236+
return res;
237+
} else if(m = val.match(regex["map"])){
238+
var count = 0, c = ' ';
239+
var res = [];
240+
var content = "";
241+
var str = false;
242+
for(var j = 0, lenJ = m[1].length; j < lenJ; ++j) {
243+
c = m[1][j];
244+
if(c == '\'' || c == '"') {
245+
if(str === false) {
246+
str = c;
247+
content += c;
248+
continue;
249+
} else if((c == '\'' && str == '\'') || (c == '"' && str == '"')) {
250+
str = false;
251+
content += c;
252+
continue;
253+
}
254+
} else if(str === false && (c == '[' || c == '{')) {
255+
++count;
256+
} else if(str === false && (c == ']' || c == '}')) {
257+
--count;
258+
} else if(str === false && count == 0 && c == ',') {
259+
res.push(content);
260+
content = "";
261+
continue;
262+
}
263+
264+
content += c;
265+
}
266+
267+
if(content.length > 0)
268+
res.push(content);
269+
270+
var newRes = {};
271+
for(var j = 0, lenJ = res.length; j < lenJ; ++j) {
272+
if(m = res[j].match(regex["key_value"])) {
273+
newRes[m[1]] = processValue(m[2]);
274+
}
275+
}
276+
277+
return newRes;
278+
} else
279+
return val;
280+
}
281+
282+
function processFoldedBlock(block) {
283+
var lines = block.lines;
284+
var children = block.children;
285+
var str = lines.join(" ");
286+
var chunks = [str];
287+
for(var i = 0, len = children.length; i < len; ++i) {
288+
chunks.push(processFoldedBlock(children[i]));
289+
}
290+
return chunks.join("\n");
291+
}
292+
293+
function processLiteralBlock(block) {
294+
var lines = block.lines;
295+
var children = block.children;
296+
var str = lines.join("\n");
297+
for(var i = 0, len = children.length; i < len; ++i) {
298+
str += processLiteralBlock(children[i]);
299+
}
300+
return str;
301+
}
302+
303+
function processBlock(blocks) {
304+
var m = null;
305+
var res = {};
306+
var lines = null;
307+
var children = null;
308+
var currentObj = null;
309+
310+
var level = -1;
311+
312+
var processedBlocks = [];
313+
314+
var isMap = true;
315+
316+
for(var j = 0, lenJ = blocks.length; j < lenJ; ++j) {
317+
318+
if(level != -1 && level != blocks[j].level)
319+
continue;
320+
321+
processedBlocks.push(j);
322+
323+
level = blocks[j].level;
324+
lines = blocks[j].lines;
325+
children = blocks[j].children;
326+
currentObj = null;
327+
328+
for(var i = 0, len = lines.length; i < len; ++i) {
329+
var line = lines[i];
330+
331+
if(m = line.match(regex["key"])) {
332+
var key = m[1];
333+
334+
if(key[0] == '-') {
335+
key = key.replace(regex["item"], "");
336+
if (isMap) {
337+
isMap = false;
338+
if (typeof(res.length) === "undefined") {
339+
res = [];
340+
}
341+
}
342+
if(currentObj != null) res.push(currentObj);
343+
currentObj = {};
344+
isMap = true;
345+
}
346+
347+
if(typeof m[2] != "undefined") {
348+
var value = m[2].replace(regex["trim"], "");
349+
if(value[0] == '&') {
350+
var nb = processBlock(children);
351+
if(currentObj != null) currentObj[key] = nb;
352+
else res[key] = nb;
353+
reference_blocks[value.substr(1)] = nb;
354+
} else if(value[0] == '|') {
355+
if(currentObj != null) currentObj[key] = processLiteralBlock(children.shift());
356+
else res[key] = processLiteralBlock(children.shift());
357+
} else if(value[0] == '*') {
358+
var v = value.substr(1);
359+
var no = {};
360+
361+
if(typeof reference_blocks[v] == "undefined") {
362+
errors.push("Reference '" + v + "' not found!");
363+
} else {
364+
for(var k in reference_blocks[v]) {
365+
no[k] = reference_blocks[v][k];
366+
}
367+
368+
if(currentObj != null) currentObj[key] = no;
369+
else res[key] = no;
370+
}
371+
} else if(value[0] == '>') {
372+
if(currentObj != null) currentObj[key] = processFoldedBlock(children.shift());
373+
else res[key] = processFoldedBlock(children.shift());
374+
} else {
375+
if(currentObj != null) currentObj[key] = processValue(value);
376+
else res[key] = processValue(value);
377+
}
378+
} else {
379+
if(currentObj != null) currentObj[key] = processBlock(children);
380+
else res[key] = processBlock(children);
381+
}
382+
} else if(line.match(/^-\s*$/)) {
383+
if (isMap) {
384+
isMap = false;
385+
if (typeof(res.length) === "undefined") {
386+
res = [];
387+
}
388+
}
389+
if(currentObj != null) res.push(currentObj);
390+
currentObj = {};
391+
isMap = true;
392+
continue;
393+
} else if(m = line.match(/^-\s*(.*)/)) {
394+
if(currentObj != null)
395+
currentObj.push(processValue(m[1]));
396+
else {
397+
if (isMap) {
398+
isMap = false;
399+
if (typeof(res.length) === "undefined") {
400+
res = [];
401+
}
402+
}
403+
res.push(processValue(m[1]));
404+
}
405+
continue;
406+
}
407+
}
408+
409+
if(currentObj != null) {
410+
if (isMap) {
411+
isMap = false;
412+
if (typeof(res.length) === "undefined") {
413+
res = [];
414+
}
415+
}
416+
res.push(currentObj);
417+
}
418+
}
419+
420+
for(var j = processedBlocks.length - 1; j >= 0; --j) {
421+
blocks.splice.call(blocks, processedBlocks[j], 1);
422+
}
423+
424+
return res;
425+
}
426+
427+
function semanticAnalysis(blocks) {
428+
var res = processBlock(blocks.children);
429+
return res;
430+
}
431+
432+
function preProcess(src) {
433+
var m;
434+
var lines = src.split("\n");
435+
436+
var r = regex["comment"];
437+
438+
for(var i in lines) {
439+
if(m = lines[i].match(r)) {
440+
/* var cmt = "";
441+
if(typeof m[3] != "undefined")
442+
lines[i] = m[1];
443+
else if(typeof m[3] != "undefined")
444+
lines[i] = m[3];
445+
else
446+
lines[i] = "";
447+
*/
448+
if(typeof m[3] !== "undefined") {
449+
lines[i] = m[0].substr(0, m[0].length - m[3].length);
450+
}
451+
}
452+
}
453+
454+
return lines.join("\n");
455+
}
456+
457+
function load(str) {
458+
errors = [];
459+
reference_blocks = [];
460+
processing_time = (new Date()).getTime();
461+
var pre = preProcess(str)
462+
var doc = parser(pre);
463+
var res = semanticAnalysis(doc);
464+
processing_time = (new Date()).getTime() - processing_time;
465+
466+
return res;
467+
}
468+
469+
export default load

0 commit comments

Comments
 (0)
Please sign in to comment.