UNPKG

6.96 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, tpl, js 文件中的icon
25* 2. 生成字体文件
26* 3. 生成css文件,
27* 4. 所有项目根目录下的html以inline或者link方式引入样式
28*
29* 每个html文件都引入了项目下的所有icon相关的样式,非按需加载方式
30* cdn 编译
31 */
32'use strict';
33
34var path = require('path'),
35 fs = require('fs'),
36 _ = fis.util,
37 icon = require('./iconfont.js');
38
39var iconfontTag = new RegExp('<!--ICONFONT_PLACEHOLDER-->');
40
41var fisVersion = fis.version.split('.')[0],
42 isFis3 = fisVersion === 3;
43
44// 数组去重
45function uniqList(arr) {
46 var ret = [],
47 tmpl = {},
48 item;
49 for(var k=0,len=arr.length; k<len; k++){
50 item = arr[k];
51 if(!tmpl[item]){
52 tmpl[item] = 1;
53 ret.push(item);
54 }
55 }
56 return ret;
57}
58
59/*
60* 匹配文本中的icon
61 */
62function getIconMatches (content, iconReg, cleanIconReg) {
63 var matches = content.match(iconReg);
64 if(matches){
65 for(var i=0; i<matches.length; i++){
66 matches[i] = matches[i].replace(cleanIconReg, '');
67 }
68 }
69 return matches || [];
70}
71
72
73// ret.pkg生成虚拟文件,产出由fis本身处理
74module.exports = function (ret, conf, settings, opt) {
75
76 var files = ret.src,
77 res = ret.map.res;
78
79 var projectPath = fis.project.getProjectPath(),
80 iconPrefix = settings.classPrefix || 'i-',
81 iconReg = new RegExp('icon-font\\\s' + iconPrefix + '([a-zA-Z0-9\\\-_]*)', 'mg'),
82 cleanIconReg = new RegExp('icon-font\\\s' + iconPrefix, 'g');
83
84 // svg在插件目录下,安装插件时,就installsvg
85 // var defaultSvgPath = path.join(path.dirname(__dirname), 'svgs');
86 var configSvgPath = settings.svgPath ? path.join(projectPath, settings.svgPath) : '';
87
88 settings._svgPath = configSvgPath;
89
90
91 if(!fs.existsSync(configSvgPath)) {
92 fis.log.error('目录 --' + configSvgPath + '-- 不存在, 请配置正确的 fis-postpackager-iconfont 插件的 "svgPath" 属性');
93 }
94
95
96 var ignoreLibList = settings.ignore || ['zepto', 'badjs', 'mod', 'bj-report', 'tools', 'db'];
97
98 var pages = [],
99 ext,
100 content,
101 eachFileIconList = [],
102 allIconList = [];
103 // whole project icon list
104 _.map(files, function(subpath, file) {
105 ext = _.ext(file.toString());
106 content = file.getContent();
107 // src 目录下的 html文件
108 // ~['.html', '.js', '.tpl']
109 // if(~['.html', '.tpl'].indexOf(ext.ext)) {
110 if(file.isHtmlLike || ext.ext === '.tpl') {
111 // html, tpl, vm
112 eachFileIconList = getIconMatches(content, iconReg, cleanIconReg);
113 if(eachFileIconList.length > 0) {
114 allIconList = allIconList.concat(eachFileIconList);
115 }
116
117 // 需要添加css的页面
118 // 项目根目录下面的html文件,认定为是业务页面,需要添加字体文件
119 if(ext.dirname === projectPath ) {
120 pages.push(file);
121 }
122 } else if(file.isJsLike && ~~ignoreLibList.indexOf(ext.filename)) {
123 // 基础库忽略查找
124 // js 中iconfont查找方式不同 addClass('i-xxx');
125 var matches = content.match(/addClass\([\'\"]([^\'\"\s]*\s)?i-([^\'\"\s]*)/mg);
126 if(matches){
127 // iconfont 无法覆盖
128 // 场景 html 标签上已经有 i-a
129 // 依赖的js中有addClass('i-b'),这里没法确保覆盖
130 matches.forEach(function(match, i) {
131 matches[i] = matches[i].replace(/addClass\([\'\"]([^\'\"\s]*\s)?i-/, '');
132 });
133 allIconList = allIconList.concat(matches);
134 }
135
136 }
137 });
138
139
140
141 /*
142 * 整个项目中的icon
143 * font和css中的content都是根据这个数组生成出来的,
144 * 数组里面即便有多余的icon(实际不是icon),也能确保css和font对应上
145 * css中的content和font中svg对应的key值都是用数据的index生成的,是一致的。
146 */
147 allIconList = uniqList(allIconList);
148
149 if(isFis3) {
150 fis.emit('iconfont:allIcons', allIconList);
151 }
152
153 /*
154 * 按需生成字体文件
155 */
156 // var fontsFile = icon.genarateFonts(settings, allIconList);
157
158 var fontObj = icon.genarateFonts(settings, allIconList),
159 outFontsContent = fontObj.content;
160
161 settings._fontCdn = {};
162 // 这种pkg的处理方式有兼容问题,fis2中getUrl没有返回domain
163
164 for(var type in outFontsContent){
165 if(outFontsContent.hasOwnProperty(type)) {
166 var fontPkg = fis.file(projectPath, fontObj.subpath + '.' + type);
167 fontPkg.setContent(outFontsContent[type]);
168 if(!isFis3 && opt.dest === 'dev') {
169 // dev 模式下 useHash = false
170 fontPkg.useHash = false;
171 }
172 ret.pkg[fontPkg.subpath] = fontPkg;
173 // getUrl 参数为了兼容fis2
174 settings._fontCdn[type] = fontPkg.getUrl(fontPkg.useHash, fontPkg.useDomain);
175 }
176 }
177
178 var cssContent = icon.generateCss(settings, allIconList);
179
180 var cssFileHash = 'font.css';
181
182 cssFileHash = path.join(settings.output, cssFileHash);
183
184 // 这种方式 fis2有问题,dev模式下,useHash 都是true,导致 getUrl有问题
185 var cssFile = fis.file(projectPath, cssFileHash);
186 cssFile.setContent(cssContent);
187 if(!isFis3 && opt.dest === 'dev') {
188 // dev 模式下 useHash = false
189 cssFile.useHash = false;
190 }
191 ret.pkg[cssFile.subpath] = cssFile;
192
193 // 外链方式引入
194 var inlineCss = '<link rel="stylesheet" type="text/css" href="' + cssFile.getUrl(cssFile.useHash, cssFile.useDomain) + '" />\r\n';
195
196 if(settings.cssInline) {
197 // inline 方式引入
198 inlineCss = '<style>\r\n' + cssContent + '\r\n</style>';
199 }
200
201
202 /*
203 * 页面页面引入css
204 */
205 pages.forEach(function(page) {
206 var content = page.getContent();
207 if(iconfontTag.test(content)) {
208 content = content.replace(iconfontTag, inlineCss);
209 } else {
210 content = content.replace('</head>', '\t' + inlineCss + '$&');
211 }
212 page.setContent(content);
213 });
214};