-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpage.js
142 lines (121 loc) · 3.16 KB
/
page.js
1
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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
const regLayout = /<!-- #layout \b(\w+)\b -->\n([\s\S]*)/;
const regMixin = /<!-- #mixin \b(\w+)\b -->\n([\s\S]*)/;
const regPage0 = /<!-- #page -->\n([\s\S]*)/;
const regPage = /<!-- #page \b(\w+)\b -->\n([\s\S]*)/;
const regPage2 = /<!-- #page \b(\w+)\b \b(\w+)\b -->\n([\s\S]*)/;
const regPageContent = /<!-- #content \b(\w+)\b -->\n?([\s\S]*)/;
const regPageContentNonGreedy = /<!-- #content \b\w+\b -->\n?[\s\S]*?(?=<!-- #content|$)/g;
const regPageContentRest = /([\s\S]*?)(?=<!-- #content|$)/;
const regPageContentRestOptionalNl = /([\s\S]*?)(?=\n?<!-- #content|$)/;
function jener(defs) {
let layouts = {},
mixins = {},
ctx = {
layouts,
mixins
},
res = [];
let pages = [];
for (let i = 0; i < defs.length; i += 2) {
let filename = defs[i],
content = defs[i + 1];
let match;
if (match = content.match(regPage)) {
pages.push(filename);
pages.push(page(match[2], match[1]));
} else if (match = content.match(regPage0)) {
pages.push(filename);
pages.push(page(match[1]));
} else if (match = content.match(regPage2)) {
pages.push(filename);
pages.push(page(match[3], match[1], match[2]));
} else if (match = content.match(regLayout)) {
layouts[match[1]] = layout(match[2]);
} else if (match = content.match(regMixin)) {
mixins[match[1]] = mixin(match[2]);
}
}
for (let i = 0; i < pages.length; i += 2) {
res.push(pages[i], genFromPage(ctx, pages[i + 1]));
}
return res;
}
function genFromPage(ctx, fsPage) {
let res = {
res: ``,
replace: {}
};
fsPage.forEach(f => {
f(ctx, res);
});
return res.res;
}
function layout(layout) {
let res = [];
let prematch = layout.match(regPageContentRest);
res.push(fappend(prematch[1]));
let matchs = layout.match(regPageContentNonGreedy);
matchs.forEach(match => {
let [_, name, text] = match.match(regPageContent);
res.push(fcontent(name));
res.push(fappend(text));
});
return res;
}
function mixin(mixin) {
return mixin;
}
function page(page, layout, replace) {
if (!layout) {
return [fappend(page)];
}
let innerMatch;
let res = [];
if (replace) {
let match = page.match(regPageContentRestOptionalNl);
res.push(freplace(replace, match[1]));
}
let matchs = page.match(regPageContentNonGreedy);
if (matchs) {
matchs.forEach(match => {
let [_, name, body] = match.match(regPageContent);
res.push(freplace(name, body));
});
}
res.push(flayout(layout));
return res;
}
function freplace(content, body) {
return (ctx, res) => {
res.replace[content] = body;
};
}
function fappend(body) {
return (ctx, res) => {
let {
mixins
} = ctx;
for (let mixin in mixins) {
let regexStr = `<!-- #include ${mixin} -->\n?`;
body = body.replace(new RegExp(regexStr), mixins[mixin]);
}
res.res += body;
};
}
function flayout(layout) {
return (ctx, res) => {
let {
layouts
} = ctx;
layout = layouts[layout];
layout.forEach(f => {
f(ctx, res);
});
};
}
function fcontent(name) {
return (ctx, res) => {
fappend(res.replace[name])(ctx, res);
};
}
module.exports = jener;