/**
* 用来加载 fis 插件。通过它来加载插件,会优先从本地安装的 node_modules 目录里面找,然后才是 global
* 全局安装的 node_modules 里面找。
*
* @function require
* @param {String} paths... 去掉 fis 前缀的包名字,可以以多个参数传进来,多个参数会自动通过 `-` 符号连接起来。
* @memberOf fis
* @example
* // 查找顺序
* // local: fis3-parser-sass
* // local: fis-parser-sass
* // global: fis3-parser-sass
* // global: fis-parser-sass
* fis.require('parser-sass');
* @property {Array} prefixes 用来配置 fis.require 前缀的查找规则的。默认:['fis3', 'fis']。
* @property {Object} _cache 用来缓存模块加载,避免重复查找。
*/
var slice = [].slice;
var flag = false;
var path = require('path');
var fs = require('fs');
var _ = require('./util.js');
var isFile = _.isFile;
var readFileSync = fs.readFileSync;
var exports = module.exports = function() {
var name = slice.call(arguments, 0).join('-');
if (exports._cache.hasOwnProperty(name)) return exports._cache[name];
// 第一次调用的时候做兼容处理老的一些用法。
if (!flag) {
flag = true;
var global = fis.get('system.globalNPMFolder');
if (global) {
fis.log.warn('fis.set(\'system.globalNPMFolder\') is deprecated, please set fis.require.paths instead.');
exports.paths.push(global);
}
var local = fis.get('system.localNPMFolder');
if (local) {
fis.log.warn('fis.set(\'system.localNPMFolder\') is deprecated, please set fis.require.paths instead.');
exports.paths.unshift(local);
}
// 去重
exports.paths = exports.paths.filter(function(item, idx, arr) {
if (!/node_modules$/.test(item)) {
fis.log.warn('The path `%s` in fis.require.paths is not end with `node_modules`, and it will be skipped.', item);
return false;
}
return arr.indexOf(item) === idx;
});
if (!exports.paths.length) {
exports.paths = [path.join(path.dirname(__dirname), 'node_modules')];
}
}
var resolved = null;
var paths = gatherAvailableNodePaths(exports.paths);
var prefixes = exports.prefixes;
var names = prefixes.map(function(prefix) {
return prefix + '-' + name;
});
paths.every(function(dir) {
names.every(function(name) {
var ret = loadAsFileSync(path.join(dir, '/', name)) || loadAsDirectorySync(path.join(dir, '/', name));
if (ret) {
resolved = ret;
}
return !resolved;
});
return !resolved;
});
if (!resolved) {
// 特殊处理 fis-parser-less
if (name === 'parser-less') {
names = ['fis-parser-less'];
}
fis.log.error('unable to load plugin [%s]', names.join('] or ['));
}
fis.log.debug('Resolved module %s to %s', name, resolved);
return exports._cache[name] = require(resolved);
};
exports.paths = [];
exports._cache = {};
exports.prefixes = ['fis3', 'fis'];
exports.extensions = ['.js'];
function gatherAvailableNodePaths(paths) {
paths = paths.concat();
var start = paths.pop();
var node_modules = paths.concat();
var prefix = '/';
if (/^([A-Za-z]:)/.test(start)) {
prefix = '';
} else if (/^\\\\/.test(start)) {
prefix = '\\\\';
}
var splitRe = process.platform === 'win32' ? /[\/\\]/ : /\/+/;
// ensure that `start` is an absolute path at this point,
// resolving againt the process' current working directory
start = path.resolve(start);
var parts = start.split(splitRe);
var dirs = [];
for (var i = parts.length - 1; i >= 0; i--) {
if (parts[i] === 'node_modules') continue;
dirs = dirs.concat(
prefix + path.join(
path.join.apply(path, parts.slice(0, i + 1)),
'node_modules'
)
);
}
if (process.platform === 'win32') {
dirs[dirs.length - 1] = dirs[dirs.length - 1].replace(":", ":\\");
}
return node_modules.concat(dirs);
}
function loadAsFileSync(x) {
if (isFile(x)) {
return x;
}
var extensions = exports.extensions;
for (var i = 0; i < extensions.length; i++) {
var file = x + extensions[i];
if (isFile(file)) {
return file;
}
}
}
function loadAsDirectorySync(x) {
var pkgfile = path.join(x, '/package.json');
if (isFile(pkgfile)) {
var body = readFileSync(pkgfile, 'utf8');
try {
var pkg = JSON.parse(body);
if (pkg.main) {
var m = loadAsFileSync(path.resolve(x, pkg.main));
if (m) return m;
var n = loadAsDirectorySync(path.resolve(x, pkg.main));
if (n) return n;
}
} catch (err) {}
}
return loadAsFileSync(path.join(x, '/index'));
}
Namespaces
- fis
- cache
- cli
- compile
- lang
- config
- emitter
- file
- log
- project
- uri
- util
- applyMatches
- base64
- camelcase
- clone
- copy
- del
- download
- escapeReg
- escapeShellArg
- escapeShellCmd
- exist
- ext
- filter
- find
- getMimeType
- glob
- install
- isAbsolute
- isDir
- isEmpty
- isFile
- isImageFile
- isTextFile
- isUtf8
- isWin
- map
- md5
- merge
- mkdir
- mtime
- nohup
- pad
- parseUrl
- pathinfo
- pipe
- query
- read
- readBuffer
- readJson
- realpath
- realpathSafe
- stringQuote
- toEncoding
- touch
- upload
- write