UNPKG

9.29 kBJavaScriptView Raw
1/*
2* iconfont fis3
3* 依赖具体的项目目录结构
4* 字体生成到modules/common/fonts目录下面
5* 对应的css直接插入到了页面中
6* 目前的目录结构
7* -src
8* -----|lego_modules
9* -----|modules
10* -----|pages
11* ----------|index
12* ---------------|main.js
13* ----------|test
14* ---------------|main.js
15* -----partials
16* -----index.html
17* -----test.html
18* -----fis-conf.js
19* -----package.json
20 */
21
22
23/*
24* 1. 分析html A 深层次依赖 js, tpl 等
25* 2. 分析js和tpl中的icon, 分析依据:
26* 1)html,tpl中有iconfont i-xxx类名
27* 2)js 中有addClass('i-xxx');
28* 3. 将icon生成css,插入到html文件中
29* 4. 根据项目所有的iconList,生成字体文件
30*
31*
32* html 按需加载依赖的icon
33 */
34'use strict';
35
36var path = require('path'),
37 fs = require('fs'),
38 _ = fis.util,
39 icon = require('./iconfont.js');
40
41var iconfontTag = new RegExp('<!--ICONFONT_PLACEHOLDER-->');
42
43/*
44* 递归计算文件依赖
45 */
46function getDeps(file, res) {
47 var ret = [],
48 deps = (res[file] || {}).deps || [],
49 subDeps;
50 for(var i=0;i<deps.length;i++) {
51 subDeps = (res[deps[i]] || {}).deps || [];
52 if(subDeps.length === 0) {
53 ret.push(deps[i]);
54 } else {
55 ret = ret.concat(getDeps(deps[i], res));
56 }
57 }
58 return ret;
59}
60
61
62
63// 获取fis config中的信息
64// fis3 获取css cdn和ttf cdn
65// useHash
66// 字体和css cdn前缀
67function getFis3ConfigInfo() {
68 var globMatches = fis.config.getMatches(),
69 globMatch,
70 globMatchStr,
71 settings = {},
72 properties;
73 // 根据配置的match获取cdn前缀
74 // 就近查找
75 for(var i = globMatches.length - 1; i > 0; i--) {
76 globMatch = globMatches[i];
77 globMatchStr = globMatch.pattern.toString();
78 // 有些正则传到glob里面有报错
79 if(~globMatchStr.indexOf('css') || ~globMatchStr.indexOf('::image') || ~globMatchStr.indexOf('ttf')) {
80 properties = globMatch.properties;
81 if(properties.domain) {
82 if(_.glob(globMatchStr, '*.css') && !settings.cssCdn) {
83 settings.cssCdn = properties.domain;
84 }
85 if(_.glob(globMatchStr, '.ttf') && !settings.ttfCdn) {
86 settings.ttfCdn = properties.domain;
87 }
88 }
89
90 if(properties.useHash) {
91 if(_.glob(globMatchStr, '*.css') && !settings.cssHash) {
92 settings.cssHash = properties.useHash;
93 }
94 if(_.glob(globMatchStr, '.ttf') && !settings.ttfHash) {
95 settings.ttfHash = properties.useHash;
96 }
97 }
98 }
99 }
100
101 return settings;
102}
103
104// 获取fis config中的信息
105// fis2 获取css cdn和ttf cdn
106// useHash
107// 字体和css cdn前缀
108function getFis2ConfigInfo() {
109 var settings = {};
110 var domains = fis.config.get('roadmap.domain');
111 for(var key in domains) {
112 if (domains.hasOwnProperty(key)) {
113 if(_.glob(key, '.css')) {
114 settings.cssCdn = domains[key];
115 }
116
117 if(_.glob(key, '.ttf')) {
118 settings.ttfCdn = domains[key];
119 }
120 }
121 }
122 settings.cssHash = true;
123 settings.ttfHash = true;
124 return settings;
125}
126
127// 数组去重
128function uniqList(arr) {
129 var ret = [],
130 tmpl = {},
131 item;
132 for(var k=0,len=arr.length; k<len; k++){
133 item = arr[k];
134 if(!tmpl[item]){
135 tmpl[item] = 1;
136 ret.push(item);
137 }
138 }
139 return ret;
140}
141
142
143/*
144* 匹配文本中的icon
145 */
146function getIconMatches (content, iconReg, cleanIconReg) {
147 var matches = content.match(iconReg);
148 if(matches){
149 for(var i=0; i<matches.length; i++){
150 matches[i] = matches[i].replace(cleanIconReg, '');
151 }
152 }
153 return matches || [];
154}
155
156
157
158module.exports = function (ret, conf, settings, opt) {
159
160 var files = ret.src,
161 res = ret.map.res,
162 sources = _.toArray(files);
163
164 var projectPath = fis.project.getProjectPath(),
165 iconPrefix = settings.classPrefix,
166 iconReg = new RegExp('icon-font\\\s' + iconPrefix + '([a-zA-Z0-9\\\-_]*)', 'mg'),
167 cleanIconReg = new RegExp('icon-font\\\s' + iconPrefix, 'g');
168 // iconReg = new RegExp('[\\\s\\\'\\\"]' + iconPrefix + '([a-zA-Z0-9\\\-_]*)', 'mg'),
169 // cleanIconReg = new RegExp('[\\\s\\\'\\\"]' + iconPrefix, 'g');
170
171
172 settings.output = settings.output + '/iconfont';
173 var fontOutPath = path.join(projectPath, sources[0].deploy.to);
174 settings.fontsOutput = path.join(fontOutPath, settings.output);
175
176 // 所有svg 的字体文件都生成了,实际上没有必要
177 // icon.genarateFonts(settings);
178
179 var ignoreLibList = settings.ignore || ['zepto', 'badjs', 'mod', 'bj-report', 'tools', 'db.js'];
180
181 /*
182 * 获取html所有依赖项中的icon
183 * js 匹配方式方式不同,参考index.js
184 */
185 function getHtmlDepsIcons(deps) {
186 var icons = [],
187 fileIcons,
188 content,
189 isLegoMod = false,
190 file,
191 fileInfo;
192 for(var i=0;i<deps.length;i++) {
193 file = deps[i];
194 fileInfo = ret.ids[file];
195 isLegoMod = /\d\.\d\.\d/.test(file);
196 // 过滤基础库
197 // 过滤这里可能过滤modules/common中的库
198 if(isLegoMod) {
199 var moduleName = file.replace(/\/\d\.\d\.\d(.*)/, '');
200 if(!ignoreLibList.indexOf(moduleName)) {
201 continue;
202 }
203 }
204 // 过滤css
205 if(~['.scss', '.css'].indexOf(fileInfo.ext)) {
206 continue;
207 }
208 // js and tpl files
209 content = fs.readFileSync(fileInfo.fullname).toString();
210 // js 和 tpl 的匹配方式不同
211 if(fileInfo.ext === '.js') {
212 var matches = content.match(/addClass\(\'([^\'\s]*\s)?i-([^\'\s]*)/mg);
213 if(matches){
214 // iconfont 无法覆盖
215 // 场景 html 标签上已经有 i-a
216 // 依赖的js中有addClass('i-b'),这里没法确保覆盖
217 matches.forEach(function(match, i) {
218 matches[i] = matches[i].replace(/addClass\(\'([^\'\s]*\s)?i-/, '');
219 });
220 fileIcons = matches;
221 }
222
223 } else if(fileInfo.ext === '.tpl') {
224 fileIcons = getIconMatches(content, iconReg, cleanIconReg);
225 }
226
227 if(fileIcons) {
228 icons = icons.concat(fileIcons);
229 }
230
231 }
232 return icons;
233 }
234 /*
235 * 先根据icon的顺序,生成content
236 * 所有的icon遍历出来后,根据icon查找svg,生成对应的字体问题。
237 * 确保顺序,否则content会错乱
238 */
239
240 // console.log(res);
241 var svgCnt = 0,
242 allIconList = []; // whole project icon list
243 _.map(files, function(subpath, file) {
244 var ext = _.ext(file.toString());
245 // src 目录下的 html文件
246 if(ext.ext === '.html' && ext.dirname === projectPath) {
247 var content = file.getContent();
248 var htmlIcons = getIconMatches(content, iconReg, cleanIconReg);
249 // entry js file
250 // html 入口文件,pages下同名目录下的main.js
251 var entry = 'pages/' + ext.filename + '/main.js';
252
253 // 入口文件依赖
254 var jsDeps = ((res[entry].extras || {}).async || []).concat(res[entry].deps || []);
255 var deepDeps = [];
256 // 文件的深层次依赖
257 for(var i=0;i<jsDeps.length;i++) {
258 deepDeps = deepDeps.concat(getDeps(jsDeps[i], res));
259 }
260 // 所有依赖
261 deepDeps = uniqList(jsDeps.concat(deepDeps));
262 // 依赖文件中包含的icon
263 var iconList = htmlIcons.concat(getHtmlDepsIcons(deepDeps));
264 var ttfPath = settings.output + '.ttf';
265 if(iconList.length > 0) {
266 var cssContent = icon.generateCss(settings, iconList, settings.pseClass, svgCnt);
267
268 svgCnt += iconList.length;
269
270 allIconList = allIconList.concat(iconList);
271
272 ttfPath = settings.ttfCdn + '/' + ttfPath;
273 cssContent = cssContent.replace(/\{\{\$path\}\}/mg, ttfPath);
274 if(iconfontTag.test(content)) {
275 content = content.replace(iconfontTag, '<style>\r\n' + cssContent + '\r\n</style>');
276 } else {
277 content = content.replace('</head>', '<style>\r\n' + cssContent + '\r\n</style>\r\n$&');
278 }
279
280 file.setContent(content);
281 }
282 }
283 });
284 /*
285 * 按需生成字体文件
286 */
287 icon.genarateFonts(settings, allIconList);
288};
\No newline at end of file