1 | "use strict";
|
2 |
|
3 | const path = require('path');
|
4 | const os = require('os');
|
5 | const fs = require('fs');
|
6 | const jsmart = require('jsmart');
|
7 | const logger = require('jdf-log');
|
8 | const escapeStringRegexp = require('escape-string-regexp');
|
9 | const stripJsonComments = require('strip-json-comments');
|
10 |
|
11 |
|
12 | const jdfUtils = require('jdf-utils');
|
13 | const $ = jdfUtils.base;
|
14 | const f = jdfUtils.file;
|
15 | const jdf = require('./jdf');
|
16 | const Vm = require("./vm");
|
17 | const VFS = require('./VFS/VirtualFileSystem');
|
18 | const widgetParser = require('./buildWidget');
|
19 | const pluginCore = require('./pluginCore')
|
20 |
|
21 | let buildHTML = module.exports = {};
|
22 |
|
23 |
|
24 |
|
25 |
|
26 |
|
27 |
|
28 |
|
29 | buildHTML.init = function () {
|
30 | buildHTML.VFS = VFS;
|
31 | logger.profile('parse widget');
|
32 | return VFS.go()
|
33 | .then(() => {
|
34 | return VFS.travel((vfile, done) => {
|
35 |
|
36 | if (!$.is.html(vfile.originPath)) {
|
37 | return;
|
38 | }
|
39 |
|
40 | logger.verbose(`reset vfile.targetContent to be vfile.originContent: ${vfile.originPath}`);
|
41 |
|
42 | vfile.targetContent = vfile.originContent;
|
43 |
|
44 | logger.verbose(`parse widget tag in html, generate widgetInfo object collection.`)
|
45 | let widgets = widgetParser.parseWidget(vfile.originContent);
|
46 | widgets.forEach(widgetInfo => {
|
47 | widgetInfo.pagename = path.basename(vfile.originPath);
|
48 | });
|
49 |
|
50 | logger.verbose(`foreach widgetInfo`);
|
51 |
|
52 | let jsMap = new Map();
|
53 | let cssMap = new Map();
|
54 | widgets.forEach(widgetInfo => {
|
55 | logger.verbose(`parse widget: ${widgetInfo.name}`);
|
56 | let widgetVfiles = VFS.queryDir(widgetInfo.dirname);
|
57 | widgetVfiles.forEach(widgetVfile => {
|
58 |
|
59 |
|
60 |
|
61 | let oPath = widgetVfile.originPath;
|
62 | let oBasename = path.basename(oPath);
|
63 | let dirname = path.dirname(oPath);
|
64 | let widgetNameReg = new RegExp(escapeStringRegexp(widgetInfo.name) + '\.\\w+$');
|
65 | if (path.relative(dirname, widgetInfo.dirname)
|
66 | || !widgetNameReg.test(oBasename)) {
|
67 |
|
68 |
|
69 | return;
|
70 | }
|
71 |
|
72 | let wPath = widgetVfile.targetPath;
|
73 | let existMap = {jsMap: jsMap, cssMap: cssMap};
|
74 |
|
75 | if (widgetInfo.buildTag.vm && $.is.vm(wPath)) {
|
76 | logger.verbose(`insert vm into HTML: ${widgetVfile.originPath}`);
|
77 | buildHTML.insertVM(widgetInfo, vfile, widgetVfile, existMap);
|
78 | }
|
79 | else if (widgetInfo.buildTag.tpl && $.is.tpl(wPath)) {
|
80 |
|
81 | logger.verbose(`insert vm into HTML: ${widgetVfile.originPath}`);
|
82 | buildHTML.insertVM(widgetInfo, vfile, widgetVfile, existMap);
|
83 | }
|
84 | else if (widgetInfo.buildTag.smarty && $.is.smarty(wPath)){
|
85 | logger.verbose(`insert smarty into HTML: ${widgetVfile.originPath}`);
|
86 | buildHTML.insertSmarty(widgetInfo, vfile, widgetVfile);
|
87 | }
|
88 | else if (widgetInfo.buildTag.css && $.is.css(wPath)){
|
89 | if (cssMap.has(widgetInfo.name)) {
|
90 | logger.verbose(`have inserted widget ${widgetInfo.name}'s css <link> in html`);
|
91 | } else {
|
92 | logger.verbose(`insert <link> tag into HTML: ${widgetVfile.originPath}`);
|
93 | buildHTML.insertCSS(vfile, widgetVfile);
|
94 | cssMap.set(widgetInfo.name, true);
|
95 | }
|
96 | }
|
97 | else if (widgetInfo.buildTag.js && $.is.js(wPath)){
|
98 | if (jsMap.has(widgetInfo.name)) {
|
99 | logger.verbose(`have inserted widget ${widgetInfo.name}'s js <script> in html`);
|
100 | } else {
|
101 | logger.verbose(`insert <script> tag into HTML: ${widgetVfile.originPath}`);
|
102 | buildHTML.insertJS(vfile, widgetVfile, jdf.config.build.jsPlace);
|
103 | jsMap.set(widgetInfo.name, true);
|
104 | }
|
105 | }
|
106 | });
|
107 | });
|
108 |
|
109 | widgets.forEach(widgetInfo => {
|
110 | vfile.targetContent = vfile.targetContent.replace(widgetInfo.text, os.EOL);
|
111 | })
|
112 | });
|
113 | }).then(() => {
|
114 | logger.profile('parse widget');
|
115 | }).catch(err => {
|
116 | logger.error(err);
|
117 | });
|
118 |
|
119 | }
|
120 |
|
121 |
|
122 |
|
123 |
|
124 |
|
125 |
|
126 |
|
127 |
|
128 | buildHTML.insertVM = function (widgetInfo, htmlVfile, vmVfile, existMap) {
|
129 | logger.verbose(widgetInfo.name, '->insertVM');
|
130 | widgetInfo.type = 'vm';
|
131 |
|
132 | let replaceStr = '';
|
133 |
|
134 | let tpl = vmVfile.targetContent;
|
135 |
|
136 |
|
137 | tpl = pluginCore.excuteBeforeTplRender(tpl, widgetInfo);
|
138 |
|
139 | let vmdata = widgetParser.getWidgetData(widgetInfo);
|
140 |
|
141 | if (!tpl) {
|
142 | replaceStr = '';
|
143 | } else {
|
144 | try {
|
145 | let result = Vm.render(tpl, {
|
146 | dataObj: vmdata,
|
147 | dirname: widgetInfo.dirname,
|
148 | existMap: existMap,
|
149 | htmlDir: path.dirname(htmlVfile.originPath)
|
150 | });
|
151 | replaceStr = os.EOL + result;
|
152 | logger.verbose(`have vm content and render success`);
|
153 | } catch (err) {
|
154 | logger.error('velocityjs compile failed.');
|
155 | logger.error(err);
|
156 | }
|
157 | }
|
158 |
|
159 |
|
160 | if (replaceStr === '') {
|
161 | logger.verbose(`vm parsed, and result to empty string`);
|
162 | }
|
163 |
|
164 |
|
165 | replaceStr = pluginCore.excuteBeforeTplInsert(replaceStr, widgetInfo);
|
166 |
|
167 |
|
168 |
|
169 |
|
170 | replaceStr = `${os.EOL}<!-- widget ${widgetInfo.name} begin -->`
|
171 | + `${replaceStr}`
|
172 | + `${os.EOL}<!-- widget ${widgetInfo.name} end -->`;
|
173 | htmlVfile.targetContent = htmlVfile.targetContent.replace(widgetInfo.text, replaceStr);
|
174 | }
|
175 |
|
176 | buildHTML.insertSmarty = function (widgetInfo, htmlVfile, smVfile) {
|
177 | widgetInfo.type = 'smarty';
|
178 |
|
179 | let smdata = widgetParser.getWidgetData(widgetInfo);
|
180 |
|
181 | let tpl = smVfile.targetContent;
|
182 |
|
183 |
|
184 | tpl = pluginCore.excuteBeforeTplRender(tpl, widgetInfo);
|
185 |
|
186 | let smartyCompiled = new jSmart(tpl);
|
187 |
|
188 | let replaceStr = '';
|
189 | if(smartyCompiled){
|
190 | replaceStr = smartyCompiled.fetch(smdata);
|
191 | }
|
192 |
|
193 |
|
194 | replaceStr = pluginCore.excuteBeforeTplInsert(replaceStr, widgetInfo);
|
195 |
|
196 |
|
197 |
|
198 |
|
199 |
|
200 | replaceStr = `${os.EOL}<!-- widget ${widgetInfo.name} begin -->`
|
201 | + `${replaceStr}`
|
202 | + `${os.EOL}<!-- widget ${widgetInfo.name} end -->`;
|
203 | htmlVfile.targetContent = htmlVfile.targetContent.replace(widgetInfo.text, replaceStr);
|
204 | }
|
205 |
|
206 |
|
207 |
|
208 |
|
209 |
|
210 |
|
211 |
|
212 |
|
213 | buildHTML.insertJS = function (htmlVfile, jsVfile, place) {
|
214 | let insertFn;
|
215 | if (place !== 'insertBody') {
|
216 | insertFn = $.placeholder.insertHead;
|
217 | } else {
|
218 | insertFn = $.placeholder.insertBody;
|
219 | }
|
220 |
|
221 | let htmlFileDir = path.dirname(htmlVfile.originPath);
|
222 |
|
223 | let scriptPath = path.join(path.dirname(jsVfile.originPath), path.basename(jsVfile.targetPath));
|
224 | scriptPath = path.relative(htmlFileDir, scriptPath);
|
225 | scriptPath = f.pathFormat(scriptPath);
|
226 |
|
227 | if (!htmlVfile.targetContent) {
|
228 | htmlVfile.targetContent = htmlVfile.originContent;
|
229 | }
|
230 | htmlVfile.targetContent = insertFn(htmlVfile.targetContent, $.placeholder.jsLink(scriptPath));
|
231 | }
|
232 |
|
233 |
|
234 |
|
235 |
|
236 |
|
237 |
|
238 |
|
239 | buildHTML.insertCSS = function (htmlVfile, cssVfile) {
|
240 | let insertFn = $.placeholder.insertHead;
|
241 |
|
242 | let htmlFileDir = path.dirname(htmlVfile.originPath);
|
243 |
|
244 | let linkPath = path.join(path.dirname(cssVfile.originPath), path.basename(cssVfile.targetPath));
|
245 | linkPath = path.relative(htmlFileDir, linkPath);
|
246 | linkPath = f.pathFormat(linkPath);
|
247 |
|
248 | if (!htmlVfile.targetContent) {
|
249 | htmlVfile.targetContent = htmlVfile.originContent;
|
250 | }
|
251 | htmlVfile.targetContent = insertFn(htmlVfile.targetContent, $.placeholder.cssLink(linkPath));
|
252 | }
|