UNPKG

gulp-build-html

Version:

Used to process html files to automatically concat css and js files, and meanwhile update html references.

345 lines (289 loc) 9.31 kB
var path = require("path"), fs = require("fs"), utils = require("wzh.node-utils"), lib = require("./lib"); var logger = lib.logger; var prefix = utils.string.randomString("@FileContent@_"); /** * @constructor * 构建块 */ var BuildBlock = function(){ var /* 构建类型。js:脚本;css:样式 */ type, /* 目标文件名称 */ targetFileName, /** * 要构建的文件路径或正文列表 * 正文统一含有前缀[prefix] * @type {String[]} */ referencedFilePathsOrContents = [], /* 声明了该构建块的html文件路径 */ containingHtmlFilePath, /* 构建块的开始索引,亦即第一个字符在html中的索引位置 */ beginIndex, /* 构建块的结束索引,亦即最后一个字符在html中的索引位置 */ endIndex, /* 构建选项 */ buildOptions = {}; /** * 获取构件类型 * @return {String} */ this.getType = function(){ return null == type? type: String(type).toLowerCase(); }; /** * 设置构建类型 * @param {String} v 构建类型。js:脚本;css:样式 * @returns {String} */ this.setType = function(v){ type = v; return this; }; /** * 获取要构建的目标文件名称 * @param {Boolean} [ifResolvePath=false] 是否将解析路径(相对于“声明了该构建块的html文件路径”) * @returns {String} */ this.getTargetFileName = function(ifResolvePath){ if(arguments.length < 1) ifResolvePath = false; if(null == containingHtmlFilePath || null == targetFileName) return ""; return !ifResolvePath? targetFileName: path.resolve(path.dirname(containingHtmlFilePath), targetFileName); }; /** * 获取要构建的目标文件名称对应的HTML引用代码 * @returns {String} */ this.getTargetFileReferringHtml = function(){ if(utils.string.isEmptyString(targetFileName, true)) return ""; var _type = this.getType(); if(utils.string.isEmptyString(_type, true)){ logger.warn("Empty file type to generate html reference for file: {}", targetFileName); return ""; } switch(_type){ case "js": return '<script data-auto-generated-by = "gulp-build-html" type = "text/javascript" src = "' + targetFileName + '"></script>'; case "css": return '<link data-auto-generated-by = "gulp-build-html" rel = "stylesheet" href = "' + targetFileName + '" />'; default: logger.error("Unknown file type: {} to generate html reference for file: {}", _type, targetFileName); return ""; } }; /** * 获取要构建的目标正文对应的HTML引用代码 * @param {String} content 正文 * @returns {String} */ this.getTargetContentReferringHtml = function(content){ var _type = this.getType(); if(utils.string.isEmptyString(_type, true)){ logger.warn("Empty file type to generate html reference"); return ""; } switch(_type){ case "js": return '<script data-auto-generated-by = "gulp-build-html" type = "text/javascript">' + content + '</script>'; case "css": return '<style data-auto-generated-by = "gulp-build-html">' + content + '</style>'; default: logger.error("Unknown file type: {} to generate html reference", _type); return ""; } }; /** * 设置要构建的目标文件名称 * @param {String} v 要构建的目标文件名称 * @returns {BuildBlock} */ this.setTargetFileName = function(v){ targetFileName = v; return this; }; /** * 获取要构建的文件路径或正文列表。 * @param {Boolean} [ifResolvePath=false] 是否将解析路径(相对于“声明了该构建块的html文件路径”) * @returns {String[]} */ this.getReferencedFilePathsOrContents = function(ifResolvePath){ if(arguments.length < 1) ifResolvePath = false; var dir = path.dirname(containingHtmlFilePath); return !ifResolvePath? referencedFilePathsOrContents: referencedFilePathsOrContents.map(function(p){ if(p.startsWith(prefix)) return p; return path.resolve(dir, p); }); }; /** * 设置要构建的文件路径或正文列表。如果是正文,则需要在调用该方法前统一添加prefix前缀 * @param {String[]} v 要构建的文件路径列表 * @returns {BuildBlock} */ this.setReferencedFilePaths = function(v){ referencedFilePathsOrContents = v; return this; }; /** * 添加要构建的文件路径或正文至列表中。如果是正文,则需要在调用该方法前统一添加prefix前缀 * @param {String} p 要构建的文件路径或文件正文 * @param {Boolean} [isInlineContentRatherThanFilePath=false] 是否为文件正文。true:文件路径;false:文件正文 * @returns {BuildBlock} */ this.addReference = function(p, isInlineContentRatherThanFilePath){ if(arguments.length < 2) isInlineContentRatherThanFilePath = false; if(isInlineContentRatherThanFilePath) p = prefix + p; referencedFilePathsOrContents = referencedFilePathsOrContents || []; if(referencedFilePathsOrContents.indexOf(p) === -1) referencedFilePathsOrContents.push(p); return this; }; /** * 获取声明了该构建块的html文件路径 * @returns {String} */ this.getContainingHtmlFilePath = function(){ return containingHtmlFilePath; }; /** * 设置声明了该构建块的html文件路径 * @param {String} v 声明了该构建块的html文件路径 * @returns {BuildBlock} */ this.setContainingHtmlFilePath = function(v){ containingHtmlFilePath = v; return this; }; /** * 获取构建块的开始索引 * @returns {Number} */ this.getBeginIndex = function(){ return beginIndex; }; /** * 设置构建块的开始索引 * @param {String} v 构建块的开始索引 * @returns {BuildBlock} */ this.setBeginIndex = function(v){ beginIndex = v; return this; }; /** * 获取构建块的结束索引 * @returns {Number} */ this.getEndIndex = function(){ return endIndex; }; /** * 设置构建块的结束索引。亦即构建块最后一个字符所在的索引 * @param {String} v 构建块的结束索引。亦即构建块最后一个字符所在的索引 * @returns {BuildBlock} */ this.setEndIndex = function(v){ endIndex = v; return this; }; /** * 获取构建选项集合 * @returns {Object} */ this.getBuildOptions = function(){ var ops = {}; for(var p in buildOptions) ops[p] = buildOptions[p]; return ops; }; /** * 获取特定的构建选项 * @param {String} name 选项key * returns {String|null} */ this.getBuildOption = function(name){ return name in buildOptions? buildOptions[name]: null; }; /** * 设置构建选项 * @param {String} name 选项key * @param {String} value 选项取值 * @returns {BuildBlock} */ this.setBuildOption = function(name, value){ buildOptions[name] = value; return this; }; /** * 设置构建选项集合 * @param {Object} ops 构建选项集合 * @returns {BuildBlock} */ this.setBuildOptions = function(ops){ if(null != ops && typeof ops === "object") for(var p in ops) buildOptions[p] = ops[p]; return this; }; /** * 根据既有的引用拼合内容 * @param {String[]} [filePathsOrContents] 引用列表。如果为空,则使用自身已经存在的引用 * @param {String} referringFileFolderAbsolutePath 最终引用资源的文件所在目录的绝对路径 * @returns {string} */ this.concatReferenceContent = function(filePathsOrContents, referringFileFolderAbsolutePath){ var concatContent = ""; filePathsOrContents = filePathsOrContents || this.getReferencedFilePathsOrContents(true); for(var i = 0; i < filePathsOrContents.length; i++){ var p = filePathsOrContents[i]; var content = ""; if(BuildBlock.isReferenceContent(p)){/* 文件正文 */ content = BuildBlock.getReference(p); }else{/* 文件路径 */ try{ content = fs.readFileSync(p, 'utf8'); }catch(e){ logger.error("Error occurred while reading content from file: {}. {}", p, e); console.error(e); continue; } /* 对于CSS文件中的资源引用,需要调整引用路径,保证合并后资源可以正常饮用得到 */ if("css" === this.getType()) content = lib.updateReferenceAsRelativeTo(content, p, referringFileFolderAbsolutePath); } concatContent += "\r\n" + "/* [gul-build-html] merged from: " + path.relative(referringFileFolderAbsolutePath, p) + " */" + "\r\n" + content; } return concatContent; }; }; /** * 判断给定的内容时否是正文,而非路径 * @param {String} tar 要判断的字符串 * @returns {boolean} */ BuildBlock.isReferenceContent = function(tar){ return tar.startsWith(prefix); }; /** * 根据给定的字符串获取引用的正文或引用的路径 * @param {String} src 源字符串 * @returns {String} */ BuildBlock.getReference = function(src){ if(!BuildBlock.isReferenceContent(src)) return src; return src.substring(prefix.length); }; module.exports = BuildBlock;