UNPKG

nui-concat

Version:

Nui框架模块文件合并插件

281 lines (249 loc) 8.57 kB
'use strict'; var through = require('through2'); var path = require('path'); var fs = require('fs'); var replacePath = function(path){ // a\b\c => a/b/c path = path.replace(/\\/g, '/'); // a///b///c => a/b/c path = path.replace(/([^:])\/{2,}/g, '$1/'); // a/b...../c => a/b../c path = path.replace(/\.{2,}/g, '..'); // a/b../c => a/c // a/../c => c var replace = function(str){ if(/([\w]+\/?)(\.\.\/)/g.test(str)){ str = str.replace(/([\w]+\/?)(\.\.\/)/g, function(a, b, c){ if(a == b+c){ return '' } return a }) return replace(str) } return str } path = replace(path); // a/b./c => a/b/c // a/./c => a/c return path.replace(/([\w]+)\/?(\.\/)+/g, '$1/') } var isEmptyObject = function(obj){ var name; for(name in obj){ return false; } return true; } var inArray = function(str, arr){ var len = arr.length; var i=0; for(i; i<len; i++){ if(arr[i] == str){ return true } } return false } var unique = function(arr){ var newarr = []; var temp = {}; arr.forEach(function(val, i){ if(!temp[val]){ temp[val] = true newarr.push(val) } }) return newarr } module.exports = function(options){ options = options || {}; //路径别名 options.paths = options.paths || {}; //模块别名 options.alias = options.alias || {}; //忽略的模块名,模块不会追加到合并的文件中 options.ignore = options.ignore || ['util', 'template', 'component']; if(options.paths.base){ for(var i in options.paths){ var _path = options.paths[i]; if(i !== 'base' && !/^[A-Z]:/.test(_path)){ options.paths[i] = options.paths.base + _path; } } } return through.obj(function(file, enc, cb){ if(file.isNull()){ return cb(); } var dirname = path.dirname(file.path)+'/'; var content = file.contents.toString(); var matchs = content.match(/Nui.load\(['"][^'"]+['"]/g); var cacheModules = {}; var cacheStyles = {}; if(!matchs){ return cb(); } function Module(id, name, deps){ var mod = this; mod.id = id; mod.name = name; mod.deps = deps; mod.depmodules = {}; mod.filename = mod.id.substr(mod.id.lastIndexOf('/')+1); mod.uri = mod.id.replace(new RegExp(mod.filename+'$'), ''); } Module.prototype.load = function(){ var mod = this; if(!/_module_\d+/.test(mod.name)){ mod.url = mod.id + '.js'; try{ var buffer = fs.readFileSync(mod.url); var content = buffer.toString(); mod.content = content.replace(/Nui.define\((['"][^'"]+['"]\s*,)?/, "Nui.define('"+ mod.name +"',"); var arrs = mod.getdeps(); mod.deps = arrs[0]; mod.styles = arrs[1]; } catch(e){} } return mod.resolve() } Module.prototype.getdeps = function(){ var mod = this; var content = mod.content; var deps = []; var styles = []; var depsMatchs = content.match(/Nui.define\((['"][^'"]+['"]\s*,)?\s*\[([^\[\]]+)\]/); var requireMatchs = content.match(/(require|extands|imports)\(['"][^'"]+['"]/g); if(depsMatchs){ var match = depsMatchs[2].split(','); match.forEach(function(val, i){ val = val.replace(/^\s+|\s+/g, '').replace(/['"]/g, ''); if(!inArray(val, options.ignore)){ deps.push(val) } }) } if(requireMatchs){ requireMatchs.forEach(function(val, i){ if(/^(require|extands)/.test(val)){ val = val.replace(/(require|extands)|[\('"]/g, ''); if(!inArray(val, options.ignore)){ deps.push(val) } } else{ styles.push(val.replace(/(imports)|[\('"]/g, '')) } }) } return [unique(deps), unique(styles)] } Module.prototype.resolve = function(){ var mod = this; if(isEmptyObject(mod.depmodules)){ mod.deps.forEach(function(val, i){ var module = Module.getModule(val, [], mod.uri); mod.depmodules[val] = module.load() }) } return mod } Module.prototype.getContents = function(contents){ var mod = this; if(!contents){ contents = []; } contents.unshift(mod.content) if(mod.deps.length){ for(var i in mod.depmodules){ contents = mod.depmodules[i].getContents(contents) } } return contents } Module.prototype.loadstyles = function(styles){ var mod = this; if(!styles){ styles = []; } var arrs = []; if(mod.styles && mod.styles.length){ mod.styles.forEach(function(val){ arrs.push(Module.setId(val, mod.uri)[0]+'.css'); }) } styles = arrs.concat(styles); if(mod.deps.length){ for(var i in mod.depmodules){ styles = mod.depmodules[i].loadstyles(styles) } } return styles } Module.setPath = function(id){ var pathMatch = id.match(/\{([^\{\}]+)\}/); if(pathMatch){ var _path = options.paths[pathMatch[1]]; if(_path){ id = id.replace(pathMatch[0], _path).replace(/(\.(js|css))?(\?[\s\S]*)?$/g, ''); } } return id } Module.setId = function(id, uri){ var name = id.replace(/(\.(js|css))?(\?[\s\S]*)?$/g, ''); id = Module.setPath(options.alias[name] || name); if(!/^[A-Z]:/.test(id)){ id = uri + name; } return [replacePath(id), name] } Module.getModule = function(id, deps, uri){ var arr = Module.setId(id, uri); id = arr[0]; return cacheModules[id] || (cacheModules[id] = new Module(id, arr[1], deps)) } Module.id = 0; Module.load = function(id, callback){ var mod = Module.getModule('_module_'+Module.id++, [id], dirname); callback(mod.load()) } Module.getStyles = function(arr){ var arrs = []; arr.forEach(function(val){ try{ var buffer = fs.readFileSync(val); var content = buffer.toString(); arrs.push(content); } catch(e){} }) return arrs } matchs.forEach(function(val, i){ var id = matchs[i].replace(/Nui.load\(/, '').replace(/['"]/g, '').replace(/-debug|-min/g, ''); Module.load(id, function(mod){ var contents = unique(mod.getContents()).join(''); var styles = Module.getStyles(unique(mod.loadstyles())).join(''); var url; for(var i in mod.depmodules){ url = mod.depmodules[i].url; break; } if(url){ if(styles){ var path = url.replace(/\/([^\/]+)\.js$/, '/style/'); if(!fs.existsSync(path)){ fs.mkdirSync(path) } fs.writeFileSync(url.replace(/\/([^\/]+)\.js$/, '/style/$1-debug.css'), styles) } fs.writeFileSync(url.replace(/(\.js)$/, '-debug$1'), contents) } }) }) cb(); }) }