UNPKG

rollup-plugin-dk

Version:

Seamless migration from es5 to es6 for `dk-fe` project

219 lines (184 loc) 6.95 kB
'use strict'; function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; } var fs = _interopDefault(require('fs')); var path = _interopDefault(require('path')); var R = _interopDefault(require('ramda')); /* eslint-disable */ var transform = function (tmpl) { function unescape(code) { return code.replace(/\\('|\\)/g, "$1").replace(/[\r\t\n]/g, " "); } var c = { func : /{{#\s*([\w$]+)\s*(\([^)]*\)|)\s*}}([\s\S]*?){{#}}/g, evaluate: /\{\{([\s\S]+?(\}?)+)\}\}/g, interpolate: /\{\{=([\s\S]+?)\}\}/g, conditional: /\{\{\?(\?)?\s*([\s\S]*?)\s*\}\}/g, transclude: /\{\{\-(\-)?\s*([\s\S]*?)\s*\}\}/g, iterate: /\{\{~\s*(?:\}\}|([\s\S]+?)\s*\:\s*([\w$]+)\s*(?:\:\s*([\w$]+))?\s*\}\})/g, }; var cse = { start: "'+(", end: ")+'" }, sid = 0, indv; // 只替换{{#func()}}{{#}}里面的内容 tmpl = tmpl.replace(c.func, function(m, def, args, str) { // 转译特殊字符,在html拼接的时候出现语法错误 str = str.replace(/('|\\)/g, '\\$1'); // 干掉所有空白符, 通过连字符解决,保持文件格式 //str = str.replace(/(^|\r|\n)\t* +| +\t*(\r|\n|$)/g,"") //.replace(/\r|\n|\t/g,"") // 拼接方法名 str = "function " + def + (args || "()") + " {var out='" + str; // 替换各种标志符 str = str .replace(c.interpolate, function(m, code) { return cse.start + unescape(code) + cse.end; }) .replace(c.conditional, function(m, elsecase, code) { return elsecase ? (code ? "';}else if(" + unescape(code) + ") {out+='" : "';}else {out+='") : (code ? "';if(" + unescape(code) + ") {out+='" : "';}out+='"); }) .replace(c.transclude, function(m, elsecase, code) { function formatCode() { if (!/\)$/.test(code)) { // {{-page}}, 无argsBody code = code + '('; } else if (/\(\s*\)$/.test(code)) { // {{-bem(page)()}}, 有body, 但是最后一个是空括号 code = code.substr(0, code.length - 1); } else { // {{-bem(page)(1)}}, 有body, 也有内容 code = code.substr(0, code.length - 1) + ','; } return code; } return elsecase ? "';return out;})(), (function() {var out='';out+='": (code ? "';out+=" + unescape(formatCode()) + "(function() {var out=''; out+='" : "';return out;})());out+='"); }) .replace(c.iterate, function(m, iterate, vname, iname) { if (!iterate) return "';} } out+='"; sid+=1; indv=iname || "i"+sid; iterate=unescape(iterate); return "';var arr"+sid+"="+iterate+";if(arr"+sid+") {var "+vname+","+indv+"=-1,l"+sid+"=arr"+sid+".length-1;while("+indv+"<l"+sid+") {" +vname+"=arr"+sid+"["+indv+"+=1];out+='"; }) .replace(c.evaluate, function(m, code) { // 因为此处是js, 所以需要将特殊字符转回来 return "';" + unescape(code) + "out+='"; }) .replace(/(\s|;|\}|^|\{)out\+='';/g, "$1").replace(/\+''/g, ""); // 拼接方法结尾 str = str + "';return out;}"; // 把所有字符串链接起来, 并且保持行数不变 str = str.replace(/(\r|\n|\r\n)/g, '\\\n'); return str; }); return tmpl; }; const includesReg = /include\s*\(\[([^\]]+)\]\)\s*;?/; // 同时包含 exported注释 和 函数声明时,才认为需要 export const exportedReg = /\/\*\s+(?:public|exported)\s+([$\w]+)\s+\*\//; const declareReg = /(?:^function\s+([$\w]+)|^var\s+([$\w]+))/; function nonNullFilter (item) { return !!item } function readFile (filepath) { // css 不解析 if (filepath.match(/\.css$/)) return null // 转译模板 return transform(fs.readFileSync(filepath, 'utf8')) } function isEs6Code (cnt) { return !!cnt.match(/import.*?from/) || !!cnt.match(/export.*?\{[^}]+\}/) } function hasInclude (cnt) { return includesReg.test(cnt) } function needParse (cnt) { // es6 module无需解析 // 但是es6 module 和 include 混用时要解析 if (isEs6Code(cnt) && !hasInclude(cnt)) { return false } return true } function parseDeclared (m) { // function | var return m.match(declareReg)[1] || m.match(declareReg)[2] } function parseIncludes (dir, cnt) { const match = cnt.match(includesReg); if (!match) return [] return match[1].split(',').map(line => { if (!line.trim()) { return } return line.match(/\s*['"]([^'"]+)['"]\s*/)[1] }).filter(nonNullFilter).map(filepath => path.normalize(dir + filepath)) } function parseExports (cnt) { if (!cnt || !needParse(cnt)) return null let exports = R.compose( R.uniq, R.map(exported => exportedReg.exec(exported)[1]), R.match(new RegExp(exportedReg, 'g')) )(cnt); if (exports.length) return exports // 没有exported 函数时,将所有的函数都暴露 let fnMatchs = cnt.match(new RegExp(declareReg, 'mg')); if (!fnMatchs) return null return fnMatchs.map(parseDeclared) } function removeIncludes (cnt) { return cnt.replace(/include\(\[[\s\S]+?\]\)\s*;\s*/, '') } function generateImports (dir, cnt, paths) { let importCache = []; return paths.map(filepath => { let fromCnt = readFile(filepath); let imports = parseExports(fromCnt); if (!imports) return null let declaredFns = R.compose( R.map(parseDeclared), R.match(new RegExp(declareReg, 'mg')) )(cnt); imports = R.compose( // 排除已经import的函数 R.reject(importFn => R.contains(importFn, importCache)), // 排除本文件声明过的函数 R.reject(importFn => R.contains(importFn, declaredFns)) )(imports); importCache = R.concat(importCache, imports); return `import { ${R.join(',', imports)} } from '${filepath}';` }).filter(nonNullFilter).join('\n') } function generateExports (fns) { if (!fns) return '' return `export {\n ${fns.join(',\n ')}\n}` } function getCurrDir (path$$1) { return path$$1.replace(/(.*\/)(.*)/, '$1') } var index = function () { return { name: 'dk', load (id) { let cnt = readFile(id); if (!needParse(cnt)) { return cnt } let currDir = getCurrDir(id); let includePaths = R.compose( R.reject(R.equals(id)), R.uniq, parseIncludes )(currDir, cnt); let exportedFns = parseExports(cnt); let code = `${generateImports(currDir, cnt, includePaths)}\n${removeIncludes(cnt)}\n${generateExports(exportedFns)}\n`; return code } } }; module.exports = index; //# sourceMappingURL=rollup-plugin-dk.cjs.js.map