-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathlookup.js
150 lines (126 loc) · 4.02 KB
/
lookup.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
143
144
145
146
147
148
149
/**
* 查找依赖
* @author jerojiang
*
* 默认最新 require('zepto') -> require('zepto/x.x.x/zepto')
* 指定版本号 require('zepto@1.2.3') -> require('zepto/1.2.3')
* modules 目录覆盖 require('zepto') -> require('modules/zepto')
*/
var _ = fis.util,
fs = _.fs,
compare = require('compare-version');
module.exports = function(id, opts) {
var ignore = opts.ignore,
ret;
if (typeof ignore === 'string') {
ignore = [opts.ignore];
} else {
ignore = opts.ignore || [];
}
if (ignore.indexOf(id) > -1) {
fis.log.debug('lego: ignore module %s', id);
return null;
}
opts.paths.every(function(item) {
if (item.type === 'lego') {
ret = getLegoModule(item.location, id);
} else {
ret = getModule(item.location, id);
}
return !ret;
});
return ret || null;
};
/**
* 从 modules 目录获取模块
* @param {String} root 目录
* @param {String} id 就是 require('zepto') 中的 zepto
*/
function getModule(root, id) {
var mod = fis.project.getProjectPath(root);
// 不处理多级目录
// 快速判断
if (id.indexOf('\/') !== -1
|| (!getListAll(root)[id + '.js'] && !getListAll(root)[id])
) {
return null;
}
if (_.isFile(_(mod, id + '.js'))) {
fis.log.debug('lego: get %s from <modules>', id);
return fis.uri(_(root, id + '.js'));
} else if (_.isFile(_(mod, id, id + '.js'))) {
fis.log.debug('lego: get %s from <modules>', id + '/' + id);
return fis.uri(_(root, id, id + '.js'));
}
return null;
}
/**
* 从 lego_modules 下获取模块
* @param {String} root 目录
* @param {String} id 就是 require('zepto') 中的 zepto
*/
function getLegoModule(root, id) {
var ver, versions,
lego = fis.project.getProjectPath(root),
match = id.match(/^\/?([^@\/]+)(@([^\/]*))?(\/(.*)+)?$/);
pkgName = match && match[1] || '',
ver = match && match[3] || '',
subFile = match && match[5] || '';
// 做一次快速判断
if (!pkgName || !getListAll(root)[pkgName]) {
return null;
}
fis.log.debug('lego: get %s from <lego_modules>', id);
if (!_.isDir(_(lego, pkgName))) {
return fis.log.error('lego: 找不到 lego 组件 %s 的目录', id);
}
if (!ver) { // 默认最新
versions = fs.readdirSync(_(lego, pkgName)) || [];
if (versions.length > 1) {
versions = versions.sort(function(prev, cur) {
return compare(prev, cur) <= 0;
});
}
ver = versions[0];
}
if (!_.isDir(_(lego, pkgName, ver))) {
return fis.log.error('lego: 找不到 lego 组件 %s 的对应的版本', id, ver);
}
if (!subFile) {
try {
subFile = require(_(lego, pkgName, ver, 'package.json'))
.lego.main.replace(/\.js$/, '');
} catch (ex) {
// 如果不存在 package.json
fis.log.info('lego: 组件 %s 没有 package.json', id);
}
// main
// zepto/x.x.x/zepto.js 同名文件
// zepto/x.x.x/index.js index 文件
[subFile, pkgName, 'index'].every(function(item) {
subFile = item;
return !item || !_.isFile(_(lego, pkgName, ver, item + '.js'));
});
}
if (!_.isFile(_(lego, pkgName, ver, subFile + '.js'))) {
return fis.log.error('lego: 找不到 lego 组件 %s 的对应的文件', id, subFile);
}
return fis.uri(_(root, pkgName, ver, subFile + '.js'));
}
/**
* 每一个文件都会经过lookup,防止频繁的判断文件是否存在,先列出一级目录,以备快速判断
*/
var _listAll = {};
function getListAll(root) {
var path;
if (!_listAll[root]) {
_listAll[root] = {};
path = fis.project.getProjectPath(root);
if (_.isDir(path)) {
fs.readdirSync(path).forEach(function(item) {
_listAll[root][item] = true;
});
}
}
return _listAll[root];
};