UNPKG

4.15 kBJavaScriptView Raw
1/**
2 * @fileOverview FeLoader - KISSY模块依赖关系解析器.
3 *
4 * @author zhuofeng.ls@tmall.com dafeng.xdf@taobao.com
5 *
6 */
7var debug = require('debug')('clam:dependParser');
8var config = require('./config.js');
9var assetsConfig = require('./assetsConfig.js').config;
10var path = require('path');
11var _ = require('underscore');
12
13var gconfig = config.get('gconfig');
14
15var hasLoadMod = {};
16
17/**
18 * config merge
19 */
20if(assetsConfig !={}){
21 if(gconfig){
22 gconfig['modules'] = _.extend(gconfig['modules'], assetsConfig['modules']);
23 gconfig['packages'] = _.extend(gconfig['packages'], assetsConfig['packages']);
24 }else {
25 gconfig = assetsConfig;
26 }
27}
28
29var modules = gconfig.modules,
30 packages = gconfig.packages;
31
32function getPackage(mod) {
33 if (!mod) return;
34
35 var pkg, max = 0, l;
36 for (var prop in packages) {
37 if (mod.indexOf(prop) === 0) {
38 l = prop.length;
39
40 // 贪婪式匹配
41 if (l > max) {
42 pkg = packages[prop];
43 pkg.name = prop; // 补充name字段
44
45 max = l;
46 }
47 }
48 }
49
50 // kissy的默认包的情况
51 if (!pkg) {
52 pkg = packages['default'];
53 pkg.name = 'default';
54 }
55
56 return pkg;
57}
58
59function recurse(mods, obj) {
60 var len;
61 if (!mods || !(len = mods.length))
62 return;
63
64 !obj && (obj = {});
65 for (var i = 0, mod, cfg; i < len; i++) {
66
67 mod = mods[i];
68
69 cfg = modules[mod] || {};
70
71 //recurse(cfg['requires'], obj);
72
73 var pkg = getPackage(mod),
74 path = cfg['path'];
75
76 if (pkg['ignorePackageNameInUri']) {
77 if (!path) {
78 path = mod.replace(pkg.name + '/', '') + (/\S*.(css|js)/g.test(mod) ? '' : '.js') ;
79 }
80 } else {
81 if (!path) {
82 path = mod + (/\S*.(css|js)/g.test(mod) ? '' : '.js');
83 }
84 }
85
86 obj[mod] = {
87 path: path, // TODO 1.需修正无path情况;2.修正basePath+path
88 pkg: pkg,
89 baseURI: pkg.path,
90 fullPath: pkg.path + path
91 }
92 }
93
94 return obj;
95}
96
97// 提取最长公共子串(Longest Common Substring)
98function getLCString(aStr, bStr) {
99 var len = aStr.length < bStr.length ? aStr.length : bStr.length,
100 max = -1;
101
102 for (var i = 0; i < len; i++) {
103 if (aStr.charAt(i) == bStr.charAt(i) && i - max == 1) {
104 max = i;
105 } else {
106 break;
107 }
108 }
109 return aStr.substring(0, max + 1);
110}
111
112// 生成Combo urls | 这行内容适合提取到配置文件中
113var comboPrefix = '??', comboSep = ',', maxUrlLength = 1024, maxFileNum = 20;
114function getComboUrls(obj) {
115 var lCString = '', paths = [], path;
116
117 for (var k in obj) {
118 if (obj.hasOwnProperty(k) && !(k in hasLoadMod)) {
119 paths.push(path = obj[k].fullPath);
120
121 if (lCString) {
122 lCString = getLCString(path, lCString);
123 } else {
124 lCString = path;
125 }
126 hasLoadMod[k] = true;
127 }
128 }
129
130 var num, start = 0, url, comboUrls = [], baseURI = paths.length > 1 ? lCString + comboPrefix : lCString;
131
132 while (start < paths.length) {
133 num = maxFileNum;
134 do {
135 url = baseURI + paths.slice(start, num).join(comboSep).replace(new RegExp(lCString,'g'), ''); // TODO 时间戳...
136 } while ((url.length > maxUrlLength) && (num--));
137 comboUrls.push(url);
138 start = num;
139 }
140
141 return comboUrls;
142}
143
144var parser = {
145 getComboUrls: function (content) {
146 var mods = this.getMods(content), len = mods.length;
147
148 if (!len)
149 return '';
150
151 var obj = recurse(mods); // 利用对象的KV特征自动去重
152 return getComboUrls(obj);
153 },
154
155 getMods: function (content) {
156 if (!content)
157 return [];
158 return content instanceof Array ?
159 content:
160 content.split(',');
161
162 },
163
164 clear: function() {
165 hasLoadMod = {}; // 页面刷新时需要清楚记录的模块
166 }
167};
168
169exports.parser = parser;