Skip to content

Commit

Permalink
init
Browse files Browse the repository at this point in the history
  • Loading branch information
2betop committed Aug 13, 2015
1 parent 61f9687 commit ce6299f
Show file tree
Hide file tree
Showing 5 changed files with 370 additions and 0 deletions.
31 changes: 31 additions & 0 deletions index.js
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
};
208 changes: 208 additions & 0 deletions lookup.js
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);
}
24 changes: 24 additions & 0 deletions package.json
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"
}
52 changes: 52 additions & 0 deletions parser.js
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
};
}
55 changes: 55 additions & 0 deletions wrap.js
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);
}
}

0 comments on commit ce6299f

Please sign in to comment.