-
Notifications
You must be signed in to change notification settings - Fork 18
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
370 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
var path = require('path'); | ||
var lookup = require('./lookup.js'); | ||
var wrapJs = require('./wrap.js'); | ||
var parseJs = require('./parser.js'); | ||
|
||
// 程序入口 | ||
var entry = module.exports = function(fis, opts) { | ||
lookup.init(fis, opts); | ||
|
||
fis.on('lookup:file', lookup); | ||
fis.on('standard:js', parseJs); | ||
fis.on('compile:postprocessor', function(file) { | ||
wrapJs(file, opts); | ||
}); | ||
}; | ||
|
||
entry.defaultOptions = { | ||
|
||
// 是否前置依赖,如果是 mod.js 千万别配置成 true | ||
// 给那种自己实现 loader 的用户使用的。 | ||
forwardDeclaration: false, | ||
|
||
// 当前置依赖启动的时候才有效,用来控制是否把内建的 `require`, `exports`, `module` 从第二个参数中去掉。 | ||
skipBuiltinModules: true, | ||
|
||
// 用来查找无后缀资源的 | ||
extList: ['.js', '.coffee', '.jsx', '.es6'], | ||
|
||
// 设置包裹时,内容缩进的空格数。 | ||
tab: 2 | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,208 @@ | ||
var path = require('path'); | ||
var inited = false; | ||
var root, baseUrl, pkgs, paths, opts; | ||
|
||
// 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 ret; | ||
} | ||
|
||
// 判读是否为 fis id 格式的路径 | ||
function isFISID(filepath) { | ||
var nsConnector = fis.media().get('namespaceConnector', ':'); | ||
return !!~filepath.indexOf(nsConnector); | ||
} | ||
|
||
// 当 require 没有指定后缀时,用来根据后缀查找模块定义。 | ||
function findResource(name, path, extList) { | ||
var info = fis.uri(name, path); | ||
|
||
for (var i = 0, len = extList.length; i < len && !info.file; i++) { | ||
info = fis.uri(name + extList[i], path); | ||
} | ||
|
||
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) { | ||
return findResource(info.rest, baseUrl, opts.extList); | ||
} | ||
} | ||
|
||
// 在 Paths 中查找 | ||
function tryPathsLookUp(info, file, opts) { | ||
var id = info.rest; | ||
var test; | ||
|
||
if (/^([^\/]+)(?:\/(.*))?$/.test(id)) { | ||
var prefix = RegExp.$1; | ||
var subpath = RegExp.$2; | ||
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); | ||
} | ||
} | ||
} | ||
|
||
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.dirname, 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'); | ||
if (!/\.[^\.]+$/.test(info.id)) { | ||
info.id += '.js'; | ||
} | ||
info.moduleId = info.id.replace(/\.[^\.]+$/, ''); | ||
} else { | ||
return findResource(subpath || pkg.main || 'main', pkg.folder, opts.extList); | ||
} | ||
} | ||
} | ||
} | ||
|
||
module.exports = function(info, file, silent) { | ||
if (!inited) { | ||
throw new Error('Please make sure init is called before this.'); | ||
} | ||
|
||
[ | ||
tryNoExtLookUp, | ||
tryFisIdLookUp, | ||
tryPathsLookUp, | ||
tryPackagesLookUp, | ||
tryFolderLookUp, | ||
tryBaseUrlLookUp | ||
].every(function(finder) { | ||
|
||
var ret = finder(info, file, opts); | ||
|
||
if (ret && ret.file) { | ||
info.id = ret.file.getId(); | ||
info.file = ret.file; | ||
return false; | ||
} | ||
|
||
return true; | ||
}); | ||
|
||
// if (!silent && (!info.file || !info.moduleId)) { | ||
// fis.log.warn('Can\'t find resource %s', info.rest.red); | ||
// } | ||
|
||
return info; | ||
} | ||
|
||
/** | ||
* 初始化 lookup | ||
*/ | ||
module.exports.init = function(fis, conf) { | ||
inited = true; | ||
opts = conf; | ||
root = fis.project.getProjectPath(); | ||
baseUrl = path.join(root, opts.baseUrl || '.'); | ||
pkgs = {}; | ||
paths = {}; | ||
|
||
// normalize packages. | ||
// 规整,方便后续查找 | ||
opts.packages = opts.packages && opts.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; | ||
return item; | ||
}); | ||
|
||
// 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); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
{ | ||
"name": "fis3-hook-commonJs", | ||
"version": "0.0.1", | ||
"description": "fis3 commonJs module", | ||
"main": "index.js", | ||
"scripts": { | ||
"test": "echo \"Error: no test specified\" && exit 1" | ||
}, | ||
"repository": { | ||
"type": "git", | ||
"url": "https://github.com/fex-team/fis3-hook-commonJs.git" | ||
}, | ||
"keywords": [ | ||
"fis3", | ||
"commonJs", | ||
"module" | ||
], | ||
"author": "fis", | ||
"license": "BSD", | ||
"bugs": { | ||
"url": "https://github.com/fex-team/fis3-hook-commonJs/issues" | ||
}, | ||
"homepage": "https://github.com/fex-team/fis3-hook-commonJs" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
var lang = fis.compile.lang; | ||
var rRequire = /"(?:[^\\"\r\n\f]|\\[\s\S])*"|'(?:[^\\'\n\r\f]|\\[\s\S])*'|(\/\/[^\r\n\f]+|\/\*[\s\S]+?(?:\*\/|$))|\b(require\.async|require)\s*\(\s*("(?:[^\\"\r\n\f]|\\[\s\S])*"|'(?:[^\\'\n\r\f]|\\[\s\S])*'|\[[\s\S]*?\])\s*/g; | ||
|
||
module.exports = function(info) { | ||
var content = info.content; | ||
var file = info.file; | ||
|
||
info.content = content.replace(rRequire, function(m, comment, type, params) { | ||
if (type) { | ||
switch (type) { | ||
case 'require.async': | ||
var info = parseParams(params); | ||
|
||
m = 'require.async([' + info.params.map(function(v) { | ||
var type = lang.jsAsync; | ||
return type.ld + v + type.rd; | ||
}).join(',') + ']'; | ||
break; | ||
|
||
case 'require': | ||
var info = parseParams(params); | ||
var async = info.hasBrackets; | ||
|
||
m = 'require(' + (async ? '[' : '') + info.params.map(function(v) { | ||
var type = lang[async ? 'jsAsync' : 'jsRequire']; | ||
return type.ld + v + type.rd; | ||
}).join(',') + (async ? ']' : ''); | ||
break; | ||
} | ||
} | ||
|
||
return m; | ||
}); | ||
} | ||
|
||
function parseParams(value) { | ||
var hasBrackets = false; | ||
var params = []; | ||
|
||
value = value.trim().replace(/(^\[|\]$)/g, function(m, v) { | ||
if (v) { | ||
hasBrackets = true; | ||
} | ||
return ''; | ||
}); | ||
params = value.split(/\s*,\s*/); | ||
|
||
return { | ||
params: params, | ||
hasBrackets: hasBrackets | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
var rDefine = /('.*?'|".*?"|[^\\]\/\/[^\r\n\f]*|\/\*[\s\S]*?\*\/)|((?:^|[^\.])\bdefine\s*\()/ig; | ||
|
||
function hasDefine(content) { | ||
var matched = false; | ||
|
||
rDefine.lastIndex = 0; // reset RegExp | ||
while(!matched && rDefine.test(content)) { | ||
matched = !!RegExp.$2; | ||
} | ||
|
||
return matched; | ||
} | ||
|
||
module.exports = function(file, opts) { | ||
// 不是 js 文件不处理。 | ||
if (!file.isJsLike || file.isPartial) { | ||
return; | ||
} | ||
|
||
var content = file.getContent(); | ||
var force = file.wrap === true || file.wrap === 'amd'; | ||
|
||
if (force || file.isMod && !hasDefine(content)) { | ||
var deps = ''; | ||
if (opts.forwardDeclaration) { | ||
var reqs = opts.skipBuiltinModules ? [] : ['\'require\'', '\'exports\'', '\'module\'']; | ||
|
||
file.requires.forEach(function(id) { | ||
var dep = fis.uri(id, file.dirname); | ||
|
||
if (dep.file) { | ||
if (dep.file.isJsLike) { | ||
reqs.push('\'' + (dep.file.moduleId || dep.file.id) + '\''); | ||
} | ||
} else { | ||
/(\..+)$/.test(id) ? (~opts.extList.indexOf(RegExp.$1) ? reqs.push('\'' + id.replace(/\.js$/i, '') + '\'') : '') : reqs.push('\'' + id + '\''); | ||
} | ||
}); | ||
|
||
deps = ' [' + reqs.join(', ') + '],'; | ||
} | ||
|
||
if (opts.tab) { | ||
content = fis.util.pad(' ', opts.tab) + content.split(/\n|\r\n|\r/g).join('\n' + fis.util.pad(' ', opts.tab)); | ||
} | ||
|
||
content = 'define(\'' + (file.moduleId || file.id) + '\',' + deps + ' function(require, exports, module) {\n\n' + content + '\n\n});\n'; | ||
|
||
if (file.moduleId !== file.id) { | ||
file.extras.moduleId = file.moduleId; | ||
} | ||
|
||
file.setContent(content); | ||
} | ||
} |