UNPKG

nyx_server

Version:

Node内容发布

236 lines (207 loc) 6.71 kB
/* global process */ "use strict"; var fs = require('fs'); var path = require('path'); var crypto = require('crypto'); var patterns = [ /<link[^\>]+href=['"]([^"']+)["']/gi, /<img[^\>]+src=['"]?([^"']+)["']?/gi, /url\(\s*([^\(\)]+)\s*\)/gi, /<script[^\>]+src=['"]([^"']+)["']/gi, /\(\s*src=['"]([^"']+)["']/gi ] function ResFetch(options){ this.filePaths = options.filePaths; //需要提取资源的文件完整路径 this.distPath = options.distPath || 'dist'; if(!/\/$/i.test(this.distPath)){ this.distPath += '/'; } if(typeof this.filePaths != 'undefined' && this.filePaths.length>0){ for(var i=0; i < this.filePaths.length; i++){ var filePath = this.filePaths[i]; var content = this.resloveFile(this.filePaths[i]); var finalPath = this.distPath + path.basename(filePath); mkdir(path.dirname(finalPath)); fs.writeFileSync(finalPath , content); } } } /** * 分析文件 * @filePath 需要分析的文件路径 * @ */ ResFetch.prototype.resloveFile = function(filePath){ var _self = this; var content = null; try{ content = fs.readFileSync(filePath); }catch(error){ return content; } if((!isHtml(filePath)) && (!isCss(filePath)) && (!isEjs(filePath))){ return content; } content = content.toString(); var basePath = path.dirname(filePath); for(var i=0 ; i<patterns.length; i++){ var regex = patterns[i]; content = content.replace(regex , function(match , url , offset, string){ if(!isRemoteResource(url)){ //如果是远程资源则不需要处理 var fullPath = reslovePath(basePath , url); var _content = _self.resloveFile(fullPath); if(_content == null){ return match; } var converPath = converFilePath(fullPath , _content); var finalPath = _self.distPath + converPath; mkdir(path.dirname(finalPath)); fs.writeFileSync(finalPath , _content); if(isCss(filePath)){ return match.replace(url , '../'+converPath); } return match.replace(url , converPath); }else{ return match; } }); } if(isHtml(filePath)){ content = this.requireReplace(basePath , content); } return content; } ResFetch.prototype.requireReplace = function(basePath , content){ var _self = this; var contentBlocks = content.match(/requirejs.config(?:\r|\n|\s|\(\s*{)*paths(?:\r|\n|\s)*:(?:\r|\n|\s)*{([^}]*)}/gi); //得到paths的内容 if(!contentBlocks){ return content; } for(var i=0 ; i<contentBlocks.length ; i++){ var block = contentBlocks[i]; var arr = block.match(/["']+[^"']*["']+[\s]*:[\s]*["']+([^"']*)["']+/gi); if(typeof arr !== 'undefined'){ for(var j=0 ; j<arr.length ; j++){ var c = arr[j] var m = /["']+[^"']*["']+[\s]*:[\s]*(["']+([^"']*)["'])+/gi.exec(c); var path1 = m[1]; //带引号的地址 var path2 = m[2]; //地址 if(isRemoteResource(path2)){ continue; } var fullPath = reslovePath(basePath , path2+'.js'); var _content = _self.resloveFile(fullPath); if(_content == null){ return content; } var converPath = converFilePath(fullPath , _content); var finalPath = _self.distPath + converPath; mkdir(path.dirname(finalPath)); fs.writeFileSync(finalPath , _content); content = content.replace(path1, '"'+path.dirname(converPath)+ '/' +path.basename(converPath,'.js')+'"'); } } } return content; } function converFilePath(filePath , content){ var options = { algorithm: 'md5', length: 8 }; var hash = md5(content, options.algorithm, 'hex'); var suffix = hash.slice(0, options.length); var extname = path.extname(filePath); var fname = ''; if(extname == '.css'){ fname = 'styles/'+ path.basename(filePath , extname)+'_'+ suffix + extname; }else if(extname == '.js'){ fname = 'scripts/'+ path.basename(filePath , extname)+'_'+ suffix + extname; }else{ fname = 'images/'+ path.basename(filePath , extname)+'_'+ suffix + extname; } return fname; } /** * 解析文件路径 * @param basePath 文件根路径 * @param filePath 文件路径 * @return 完整文件路径 */ function reslovePath(basePath , filePath){ if(!/\/$/i.test(basePath)){ basePath += "/"; } return basePath+filePath } function md5(content, algorithm, encoding) { var hash = crypto.createHash(algorithm); hash.update(content); return hash.digest(encoding); } /** * 判断是否是网络资源 */ function isRemoteResource(url){ if(!/^http:\/\//i.test(url)){ return false } return true; } /** * 判断是否是css资源文件 * @param url 文件路径 */ function isCss(url){ if(path.extname(url) == '.css'){ return true } return false; } /** * 判断是否是js文件 * @param url 文件 */ function isJs(url){ if(path.extname(url) == '.js'){ return true; } return false; } function isHtml(url){ if(path.extname(url) == '.html' || path.extname(url) == '.htm'){ return true; } return false; } function isEjs(url){ if(path.extname(url) == '.ejs'){ return true; } return false; } var pathSeparatorRe = /[\/\\]/g; /** * 递归创建目录 * @param dirpath 目录路径 * @param mode 读取模式 默认0777 * @return */ function mkdir(dirpath, mode) { if (mode == null) { mode = parseInt('0777', 8) & (~process.umask()); } dirpath.split(pathSeparatorRe).reduce(function(parts, part) { parts += part + '/'; var subpath = path.resolve(parts); if (!fs.existsSync(subpath)) { try { fs.mkdirSync(subpath, mode); } catch(e) { throw new Error('Unable to create directory "' + subpath + '" (Error code: ' + e.code + ').', e); } } return parts; }.bind(this), ''); }; module.exports = ResFetch;