mya-hook-commonjs
Version:
mya commonJs module
306 lines (244 loc) • 7.58 kB
JavaScript
var path = require('path');
var inited = false;
var root, baseUrl, pkgs, paths, opts;
var moitJsExtension;
function getJsExtensionMoited() {
if (typeof moitJsExtension === 'undefined') {
var testFile = fis.file(fis.project.getProjectPath() + '/test.js');
// console.log(testFile);
moitJsExtension = testFile.id !== testFile.moduleId;
}
return moitJsExtension;
}
// find package base on folder name
// 根据目录位置查找是否属于某个 package 配置
function findPkgByFolder(folder, list) {
var ret = null;
if (list && list.length) {
list.every(function(item) {
if (item.folder === folder || path.resolve(baseUrl, item.folder) === folder) {
ret = item;
return false;
}
return true;
});
}
return ret;
}
// 判读是否为 fis id 格式的路径
function isFISID(filepath) {
var nsConnector = fis.media().get('namespaceConnector', ':');
return !!~filepath.indexOf(nsConnector);
}
// 当 require 没有指定后缀时,用来根据后缀查找模块定义。
function findResource(name, filepath, extList) {
if (name === '') {
return null;
}
var candidates = [name, path.join(name, 'index')];
var baseName = path.basename(name);
if (baseName && baseName !== '.' && baseName !== '..') {
candidates.push(path.join(name, baseName));
}
var info = null;
candidates.every(function(candidate) {
info = fis.uri(candidate, filepath);
for (var i = 0, len = extList.length; i < len && !info.file; i++) {
info = fis.uri(candidate + extList[i], filepath);
}
if (info && info.file) {
return false;
}
return true;
});
return info;
}
// -------------------
// 各种查找
// -------------------
// 无后缀查找
function tryNoExtLookUp(info, file, opts) {
// 支持没有指定后缀的 require 查找。
return findResource(info.rest, file ? file.dirname : fis.project.getProjectPath(), opts.extList);
}
// fis id 查找
function tryFisIdLookUp(info, file, opts) {
// 如果是 fis id 路径且属于当前 namespace,也同样做一次查找,从根目录查起
var nsConnector = fis.media().get('namespaceConnector', ':');
var idx = info.rest.indexOf(nsConnector);
if (~idx) {
info.isFisId = true;
var ns = info.rest.substring(0, idx);
var subpath = info.rest.substring(idx + 1);
if (ns === fis.media().get('namespace')) {
return findResource(subpath, root, opts.extList);
}
}
}
// 基于 BaseUrl 查找
function tryBaseUrlLookUp(info, file, opts) {
if (root !== baseUrl && info.rest) {
var ret = findResource(info.rest, baseUrl, opts.extList);
if (ret && ret.file && info.rest[0] === '.') {
fis.log.warn('Should use `%s` instead of `%s` in [`%s`] since `BaseUrl` should not be used in relative path resolving.', ret.file.subpath, info.rest, file.subpath);
}
return ret;
}
}
// 基于 Root 查找
function tryRootLookUp(info, file, opts) {
if (info.rest && info.rest[0] === '.') {
return;
}
return findResource(info.rest, root, opts.extList);
}
// 在 Paths 中查找
function tryPathsLookUp(info, file, opts) {
var id = info.rest;
var test;
if (/^([^\/]+)(?:\/(.*))?$/.test(id)) {
var parts = id.split('/');
var idx = parts.length;
while (idx > 0) {
var prefix = parts.slice(0, idx).join('/');
var subpath = parts.slice(idx).join('/');
var dirs;
if ((dirs = paths[prefix])) {
for (var i = 0, len = dirs.length;
(!test || !test.file) && i < len; i++) {
test = subpath ? findResource(subpath, path.join(baseUrl, dirs[i]), opts.extList) : findResource(dirs[i], baseUrl, opts.extList);
}
}
idx--;
}
}
return test;
}
function tryFolderLookUp(info, file, opts) {
var id = info.rest;
if (id === '.' || opts.packages) {
// 真麻烦,还得去查找当前目录是不是 match 一个 packages。
// 如果是,得找到 main 的设置。
var folderName = id[0] === '/' ? path.join(baseUrl, id) : path.join(file ? file.dirname : baseUrl, id);
var pkg = findPkgByFolder(folderName, opts.packages);
if (pkg) {
return findResource(pkg.main || 'main', pkg.folder, opts.extList);
}
}
}
// 在 Pacakges 里面查找
function tryPackagesLookUp(info, file, opts) {
var id = info.rest;
if (/^([^\/]+)(?:\/(.*))?$/.test(id)) {
var prefix = RegExp.$1;
var subpath = RegExp.$2;
var pkg = pkgs[prefix];
if (pkg) {
if (pkg.isFISID) {
info.isFISID = true;
info.id = path.join(pkg.folder, subpath || pkg.main || 'main').replace(/\\/g, '/');
if (!/\.[^\.]+$/.test(info.id)) {
info.id += '.js';
}
info.moduleId = info.id.replace(/\.[^\.]+$/, '');
} else {
return findResource(subpath || pkg.main || 'main', pkg.folder, opts.extList);
}
}
}
}
var lookup = module.exports = function(info, file, silent) {
if (!inited) {
throw new Error('Please make sure init is called before this.');
}
var originPath = info.rest;
var lookupList = lookup.lookupList || [];
lookupList.every(function(finder) {
if (info.file) {
return false;
}
var ret = finder(info, file, opts);
if (ret && ret.file) {
info.id = ret.file.getId();
info.file = ret.file;
return false;
} else if (ret === false) {
return false;
}
return true;
});
// if (!silent && (!info.file || !info.moduleId)) {
// fis.log.warn('Can\'t find resource %s', info.rest.red);
// }
//
// 跨模块引用 js
if (info.isFISID && !info.file && (/\.js$/.test(info.rest) || !/\.\w+$/.test(info.rest))) {
info.id = info.id || info.rest;
var mod = getJsExtensionMoited();
// 只有在省略后缀的模式下才启用。
if (mod && !/^(https?\:)?\/\//.test(info.id)) {
info.moduleId = info.id.replace(/\.js$/, '');
info.id = info.moduleId + '.js';
}
}
return info;
}
lookup.lookupList = [
tryFisIdLookUp,
tryPathsLookUp,
tryPackagesLookUp,
tryFolderLookUp,
tryNoExtLookUp,
tryBaseUrlLookUp,
tryRootLookUp
];
lookup.tryFisIdLookUp = tryFisIdLookUp;
lookup.tryPathsLookUp = tryPathsLookUp;
lookup.tryPackagesLookUp = tryPackagesLookUp;
lookup.tryFolderLookUp = tryFolderLookUp;
lookup.tryNoExtLookUp = tryNoExtLookUp;
lookup.tryBaseUrlLookUp = tryBaseUrlLookUp;
lookup.tryRootLookUp = tryRootLookUp;
lookup.findResource = findResource;
/**
* 初始化 lookup
*/
lookup.init = function(fis, conf) {
inited = true;
opts = conf;
root = fis.project.getProjectPath();
baseUrl = path.join(root, opts.baseUrl || '.');
pkgs = {};
paths = {};
// normalize packages.
// 规整,方便后续查找
function normalizePackage(parent) {
parent.packages = parent.packages && parent.packages.map(function (item) {
if (typeof item === 'string') {
item = {
name: item
};
}
var folder = item.location || item.name;
item.isFISID = isFISID(folder);
item.folder = item.isFISID ? folder : path.join(baseUrl, item.location || item.name);
pkgs[item.name] = item;
if (item.packages) {
normalizePackage(item)
}
return item;
});
}
normalizePackage(opts)
// normalize paths.
// 规整,方便后续查找
opts.paths && (function(obj) {
Object.keys(obj).forEach(function(key) {
var val = obj[key];
if (!Array.isArray(val)) {
val = [val];
}
paths[key] = val;
});
})(opts.paths);
}