├── .gitignore ├── .npmignore ├── README.md ├── package.json ├── lib ├── cssUpgrade.js ├── util.js ├── jsUpgrade.js └── tplUpgrade.js └── upgrade.js /.gitignore: -------------------------------------------------------------------------------- 1 | /.idea 2 | node_modules/ 3 | 4 | .DS_Store 5 | *.db 6 | *.bak 7 | *.tmp 8 | *.cmd 9 | ~* 10 | 11 | upload.py -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | /.idea 2 | /.settings 3 | /.project 4 | /.gitignore 5 | /node_modules 6 | /test 7 | /.tmp 8 | 9 | 10 | .DS_Store 11 | 12 | *.db 13 | *.bak 14 | *.tmp 15 | ~* 16 | 17 | upload.py -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | fis-command-upgrade 2 | =================== 3 | 4 | This tool can help you upgrade your project from FIS-1.x to FIS-2.x. 5 | 6 | fis upgrade --namespace photo 7 | 8 | help 9 | ---- 10 | 11 | Usage: upgrade [options] 12 | Options: 13 | 14 | -h, --help output usage information 15 | --namespace namespace 16 | --ld smarty left delimiter 17 | --rd smarty right delimiter 18 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "fis-command-upgrade", 3 | "version": "0.0.6", 4 | "description": "This tool can help you upgrade your project from FIS-1.x to FIS-2.x.", 5 | "main": "upgrade.js", 6 | "repository": { 7 | "type": "git", 8 | "url": "https://github.com/xiangshouding/fis-command-upgrade.git" 9 | }, 10 | "keywords": [ 11 | "fis", 12 | "upgrade" 13 | ], 14 | "dependencies": { 15 | "xmlreader": "~0.2.3" 16 | }, 17 | "author": "fis", 18 | "license": "MIT", 19 | "readmeFilename": "README.md", 20 | "gitHead": "55ba08280eec9d836c587457476430e5d5176578" 21 | } 22 | -------------------------------------------------------------------------------- /lib/cssUpgrade.js: -------------------------------------------------------------------------------- 1 | /* 2 | * fis 3 | * http://fis.baidu.com/ 4 | */ 5 | 6 | 'use strict'; 7 | 8 | var pth = require('path'), 9 | fs = require('fs'), 10 | util = require('./util.js'); 11 | 12 | exports.update = function(content, namespace, filepath, root, jsconf) { 13 | 14 | function parseImport(content, namespace, filepath, root) { 15 | var reg = /(?:\/\*[^*]*\*+(?:[^\/*][^*]*\*+)*\/)|(?:\/\/[^\n\r\f]*)|@import\s+url\s*\(\s*([^\n\r\}\{\)]*?)\s*\)\s*\;/g; 16 | return content.replace(reg, function (m , v) { 17 | if(v){ 18 | if(v.indexOf('?__inline') !== -1){ 19 | return m; 20 | } 21 | var tmp = v; 22 | var group = ''; 23 | 24 | var info = fis.util.stringQuote(v); 25 | v = info.rest.trim(); 26 | 27 | if(v.indexOf(':') !== -1){ 28 | group = v.split(':'); 29 | if(group[0] == 'common' || group[1].indexOf('.') == -1){ 30 | var tmp = group[1].split('/'); 31 | v = 'static/common/ui/' + group[1] + '/' + tmp[tmp.length-1] + '.css'; 32 | if(getSuffix(root + '/' + v)){ 33 | v = v.replace('.css', '.less'); 34 | } 35 | v = util.getStandardPath('common:' + v, namespace, jsconf); 36 | return '/*@require ' + v + '*/'; 37 | }else if(group[0] == 'macro'){ 38 | return ''; 39 | } 40 | }else{ 41 | if(v.substr(0, 1) == '.'){ 42 | v = pth.normalize(pth.dirname(filepath) + '/' + v); 43 | v = v.replace(/[\/\\]+/g, '/'); 44 | v = v.replace(root + '/', ''); 45 | }else{ 46 | if(v.substr(0, 1) !== '/'){ 47 | group = v.split('/'); 48 | v = 'static/' + namespace + '/ui/' + v + '/' + group[group.length-1] + '.css'; 49 | }else{ 50 | v = v.substring(1); 51 | } 52 | } 53 | var suffix = '.css'; 54 | if(getSuffix(root + '/' + v)){ 55 | suffix = '.less'; 56 | v = v.replace('.css', '.less'); 57 | } 58 | group = v.split('/'); 59 | if(group[group.length-2] == pth.basename(v, suffix)){ 60 | return '/*@require ' + util.getStandardPath(namespace + ':' + v, namespace, jsconf) + '*/'; 61 | }else{ 62 | v = util.getStandardPath(v, namespace, jsconf); 63 | return m.replace(tmp, '\'/' + v +'?__inline\''); 64 | } 65 | } 66 | } 67 | return m; 68 | }); 69 | return content; 70 | }; 71 | 72 | /** 73 | * csssprite 功能替换 74 | * @param content 75 | * @returns {XML|string|void} 76 | */ 77 | function replaceCssSprite(content){ 78 | content = content.replace(/\?M=x/ig,'?__sprite'); 79 | content = content.replace(/\?M=y/ig,'?__sprite'); 80 | return content.replace(/\?M=z/ig,'?__sprite'); 81 | }; 82 | 83 | content = parseImport(content, namespace, filepath, root); 84 | content = replaceCssSprite(content); 85 | return content; 86 | } 87 | 88 | 89 | 90 | function getSuffix(path){ 91 | if(!fs.existsSync(path)){ 92 | path = path.replace('.css', '.less'); 93 | if(fs.existsSync(path)){ 94 | return true; 95 | } 96 | return false; 97 | } 98 | var content = fis.util.read(path); 99 | return util.detMarco(content); 100 | } -------------------------------------------------------------------------------- /lib/util.js: -------------------------------------------------------------------------------- 1 | /* 2 | * fis 3 | * http://web.baidu.com/ 4 | */ 5 | 6 | 'use strict'; 7 | 8 | var util = module.exports = {}; 9 | 10 | util.detContext = function(content){ 11 | var reg = /(\bF\.context)(?:\([^)]*\))/g; 12 | if(reg.test(content)){ 13 | return true; 14 | } 15 | return false; 16 | } 17 | 18 | util.detMarco = function(content){ 19 | var reg = /\{[^}]+{/; 20 | if(reg.test(content)){ 21 | return true; 22 | } 23 | if(/@mixin/.test(content)){ 24 | return true; 25 | } 26 | if(/@var/.test(content)){ 27 | return true; 28 | } 29 | if(/@fis/.test(content)){ 30 | return true; 31 | } 32 | return false; 33 | } 34 | 35 | util.detWidgetExtends = function(content, ld, rd){ 36 | var reg = new RegExp(ld + 'widget(?:\\s+|' + rd + ')(?:[\\s\\S]*?)' + ld + '\/widget\\s*' + rd); 37 | if(reg.test(content)){ 38 | reg = /\bextends\s*=\s*("(?:[^\\"]|\\[\s\S])+"|'(?:[^\\']|\\[\s\S])+')\s*/; 39 | if(reg.test(content)){ 40 | return true; 41 | } 42 | } 43 | reg = new RegExp(ld + 'widget_block'); 44 | if(reg.test(content)){ 45 | return true; 46 | } 47 | return false; 48 | } 49 | 50 | util.trim = function(str, charlist) { 51 | var whitespace, l = 0, 52 | i = 0; 53 | str += ''; 54 | 55 | if (!charlist) { 56 | // default list 57 | whitespace = " \n\r\t\f\x0b\xa0\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u200b\u2028\u2029\u3000"; 58 | } else { 59 | // preg_quote custom list 60 | charlist += ''; 61 | whitespace = charlist.replace(/([\[\]\(\)\.\?\/\*\{\}\+\$\^\:])/g, '$1'); 62 | } 63 | 64 | l = str.length; 65 | for (i = 0; i < l; i++) { 66 | if (whitespace.indexOf(str.charAt(i)) === -1) { 67 | str = str.substring(i); 68 | break; 69 | } 70 | } 71 | 72 | l = str.length; 73 | for (i = l - 1; i >= 0; i--) { 74 | if (whitespace.indexOf(str.charAt(i)) === -1) { 75 | str = str.substring(0, i + 1); 76 | break; 77 | } 78 | } 79 | 80 | return whitespace.indexOf(str.charAt(0)) === -1 ? str : ''; 81 | } 82 | 83 | 84 | function inArray (needle, haystack, argStrict) { 85 | var key = '', 86 | strict = !! argStrict; 87 | if (strict) { 88 | for (key in haystack) { 89 | if (haystack[key] === needle) { 90 | return true; 91 | } 92 | } 93 | } else { 94 | for (key in haystack) { 95 | if (haystack[key] == needle) { 96 | return true; 97 | } 98 | } 99 | } 100 | return false; 101 | } 102 | 103 | /** 104 | * 去掉模块名那一层 common:static/common/ui/a/a.js => common:static/ui/a/a.js 105 | * @param v 106 | * @param namespace 107 | * @returns {string} 108 | */ 109 | util.removeModuleName = function(v, namespace){ 110 | if (typeof(v) === "undefined") return ''; 111 | var pathSplit = []; 112 | if(v.indexOf(':') !== -1) { 113 | var group = v.split(':'); 114 | var tpmnamespace = util.trim(group[0]); 115 | pathSplit = group[1].split('/'); 116 | if(pathSplit[1] == tpmnamespace){ 117 | pathSplit.splice(1, 1); 118 | v = tpmnamespace + ':' + pathSplit.join('/'); 119 | return v; 120 | } 121 | }else{ 122 | pathSplit = v.split('/'); 123 | if(pathSplit[1] == namespace || pathSplit[1] == 'common'){ 124 | pathSplit.splice(1, 1); 125 | v = pathSplit.join('/'); 126 | return v; 127 | } 128 | } 129 | return v; 130 | } 131 | 132 | /** 133 | * 将common:static/ui/a/a.js 组件化放到widget下 common:widget/ui/a/a.js 134 | * common:static/lib/tangram/base.js => common:widget/lib/tangram/base.js 135 | * @param v 136 | * @param namespace 137 | */ 138 | function moveUiToWidget(v){ 139 | if (typeof(v) === "undefined") return ''; 140 | var tpmnamespace = ''; 141 | var pathSplit = []; 142 | if(v.indexOf(':') !== -1){ 143 | var group = v.split(':'); 144 | tpmnamespace = util.trim(group[0]); 145 | pathSplit = group[1].split('/'); 146 | }else{ 147 | pathSplit = v.split('/'); 148 | } 149 | if(pathSplit[0] == 'static' && inArray(pathSplit[1], ['ui', 'lib'])){ 150 | pathSplit.splice(0, 1, 'widget'); 151 | v = tpmnamespace ? tpmnamespace + ':' + pathSplit.join('/') : pathSplit.join('/'); 152 | } 153 | return v; 154 | } 155 | 156 | 157 | util.getStandardPath = function(v, namespace, changePathJs){ 158 | if (typeof(v) === "undefined") return ''; 159 | var testflag = false; 160 | if(v.substr(0,4) =='test'){ 161 | v = v.substr(5); 162 | testflag = true; 163 | } 164 | v = util.removeModuleName(v, namespace); 165 | if(testflag){ 166 | v = 'test/' + v; 167 | } 168 | if(changePathJs){ 169 | var pathChange = require(changePathJs); 170 | if(typeof pathChange.modifyPath === "function"){ 171 | v = pathChange.modifyPath(v); 172 | } 173 | }else{ 174 | v = moveUiToWidget(v); 175 | } 176 | return v; 177 | } -------------------------------------------------------------------------------- /lib/jsUpgrade.js: -------------------------------------------------------------------------------- 1 | /* 2 | * fis 3 | * http://fis.baidu.com/ 4 | */ 5 | 6 | 'use strict'; 7 | 8 | var util = require('./util.js'), 9 | pth = require('path'); 10 | 11 | exports.update = function(content, namespace, filepath, root,jsconf) { 12 | var libs = [ 13 | 'tangram', 14 | 'fis', 15 | 'magic', 16 | 'gmu', 17 | ]; 18 | var filepath = filepath, 19 | root = root; 20 | 21 | function inArray (needle, haystack, argStrict) { 22 | var key = '', 23 | strict = !! argStrict; 24 | if (strict) { 25 | for (key in haystack) { 26 | if (haystack[key] === needle) { 27 | return true; 28 | } 29 | } 30 | } else { 31 | for (key in haystack) { 32 | if (haystack[key] == needle) { 33 | return true; 34 | } 35 | } 36 | } 37 | return false; 38 | } 39 | 40 | function getPathId(v, namespace) { 41 | var group = ''; 42 | //没有: 43 | if(v.indexOf(':') == -1) { 44 | if(v.indexOf('.js') == -1){ 45 | group = v.split('/'); 46 | v = namespace + ':widget/' + namespace + '/ui/' + v + '/' + group[group.length-1] + '.js'; 47 | }else if(v.indexOf('.') == 0){ 48 | v = pth.normalize(pth.dirname(filepath) + '/' + v); 49 | v = v.replace(/[\/\\]+/g, '/'); 50 | v = v.replace(root + '/', ''); 51 | v = namespace + ':' + v; 52 | }else if(v.indexOf('.js') != -1 && v.indexOf('static') == 0){ 53 | v = namespace + ':' + v; 54 | }else if(v.indexOf('.js') != -1 && v.indexOf('/static') == 0){ 55 | v = namespace + ':' + v.substring(1); 56 | } 57 | }else if( v.indexOf(':') !== -1){ 58 | group = v.split(':'); 59 | if (group[1].indexOf('.js') == -1) { 60 | var tpmnamespace = util.trim(group[0]); 61 | if(tpmnamespace == namespace || tpmnamespace == 'common'){ 62 | var grouptmp = group[1].split('/'); 63 | v = tpmnamespace + ":widget/" + tpmnamespace + '/ui/' + group[1] + '/' + grouptmp[grouptmp.length-1] + '.js'; 64 | }else if (inArray(tpmnamespace, libs)) { 65 | if(group[1] == '' && tpmnamespace == 'magic'){ 66 | v = 'common:widget/lib/magic/magic.js'; 67 | }else{ 68 | var grouptmp = group[1].split('/'); 69 | v = 'common:widget/lib/' + tpmnamespace + '/' + group[1] + '/' + grouptmp[grouptmp.length-1] + '.js'; 70 | } 71 | } 72 | } 73 | } 74 | v = util.getStandardPath(v, namespace, jsconf); 75 | return v; 76 | } 77 | 78 | function parseExports(content){ 79 | var reg = /(\bexports\b)([^=]*)|(\bmodule.exports\b\s*=)/g 80 | content = content.replace(reg, function(m, v, fn){ 81 | if(v && v.indexOf('e') == 0){ 82 | return 'module.exports' + fn; 83 | } 84 | return m; 85 | }); 86 | return content; 87 | } 88 | 89 | //对require添加namespace,注意私有处理 90 | function parseRequire(content, namespace) { 91 | var reg = /\brequire\s*\(\s*("(?:[^\\"]|\\[\s\S])+"|'(?:[^\\']|\\[\s\S])+')\s*\)/g; 92 | content = content.replace(reg, function(m, value){ 93 | if(value){ 94 | var info = fis.util.stringQuote(value); 95 | value = info.rest.trim(); 96 | value = getPathId(value, namespace); 97 | m = 'require(' + info.quote + value + info.quote + ')'; 98 | } 99 | return m; 100 | }); 101 | return content; 102 | } 103 | 104 | /** 105 | * F.use -> require.async 106 | **/ 107 | function parseUse(content, namespace) { 108 | var reg = /(?:\/\*[^*]*\*+(?:[^\/*][^*]*\*+)*\/)|(?:\/\/[^\n\r\f]*)|F.use\s*\(\s*("(?:[^\\"]|\\[\s\S])+"|'(?:[^\\']|\\[\s\S])+'|(?:\[[^\[\]]+?\]))\s*/g; 109 | return content.replace(reg, function (m , value) { 110 | if (value) { 111 | var hasBrackets = false; 112 | var values = []; 113 | value = value.trim().replace(/(^\[|\]$)/g, function(m, v) { 114 | if (v) { 115 | hasBrackets = true; 116 | } 117 | return ''; 118 | }); 119 | values = value.split(/\s*,\s*/); 120 | values = values.map(function(v) { 121 | var info = fis.util.stringQuote(v); 122 | v = info.rest.trim(); 123 | v = getPathId(v, namespace); 124 | return info.quote + v + info.quote; 125 | }); 126 | if (hasBrackets) { 127 | m = 'require.async([' + values.join(', ') + ']'; 128 | } else { 129 | m = 'require.async(' + values.join(', '); 130 | } 131 | } 132 | return m; 133 | }); 134 | return content; 135 | } 136 | 137 | function parseTemplate(content){ 138 | var reg = /\bF.template/g; 139 | content = content.replace(reg, function (m , value) { 140 | return '__inline' 141 | }); 142 | return content; 143 | } 144 | 145 | function parseUri(content) { 146 | var reg = /\bF.uri/g; 147 | content = content.replace(reg, function(m, value){ 148 | return '__uri'; 149 | }); 150 | return content; 151 | } 152 | 153 | function parseInline(content){ 154 | var reg = /(?:\/\*[^*]*\*+(?:[^\/*][^*]*\*+)*\/)|(?:\/\/[^\n\r\f]*)|F.inline\s*\(\s*("(?:[^\\"]|\\[\s\S])+"|'(?:[^\\']|\\[\s\S])+'|(?:\[[^\[\]]+?\]))\s*/g; 155 | return content.replace(reg, function (m , value) { 156 | if(value){ 157 | var hasBrackets = false; 158 | var values = []; 159 | value = value.trim().replace(/(^\[|\]$)/g, function(m, v) { 160 | if (v) { 161 | hasBrackets = true; 162 | } 163 | return ''; 164 | }); 165 | values = value.split(/\s*,\s*/); 166 | values = values.map(function(v) { 167 | var info = fis.util.stringQuote(v); 168 | v = info.rest.trim(); 169 | return '__inline(' + info.quote + v + info.quote +')'; 170 | }); 171 | value = values.join(';'); 172 | return value.substr(0, value.length-1); 173 | } 174 | return m; 175 | }); 176 | } 177 | 178 | function parseFcontent(content){ 179 | var reg = /(\bF\.context)(?:\([^)]*\))/g; 180 | content = content.replace(reg, function (m , value) { 181 | if(m.indexOf(',') !== -1){ 182 | m = m.replace('F.context', 'define'); 183 | }else{ 184 | m = m.replace('F.context', 'require'); 185 | } 186 | return m; 187 | }); 188 | return content; 189 | } 190 | 191 | content = parseRequire(content, namespace); 192 | content = parseUse(content, namespace); 193 | content = parseUri(content); 194 | content = parseInline(content); 195 | content = parseTemplate(content); 196 | var widgetReg = new RegExp("\/widget\/" + namespace + "\/.*\\.js$"); 197 | var uiReg = new RegExp("\/static\/" + namespace + "\/ui\/.*\\.js$"); 198 | //ui widget目录下才做此处理 199 | if(widgetReg.test(filepath) || uiReg.test(filepath)){ 200 | content = parseExports(content); 201 | } 202 | 203 | return content; 204 | } 205 | 206 | -------------------------------------------------------------------------------- /lib/tplUpgrade.js: -------------------------------------------------------------------------------- 1 | /* 2 | * fis 3 | * http://fis.baidu.com/ 4 | */ 5 | 6 | 'use strict'; 7 | 8 | var pth = require('path'), 9 | util = require('./util.js'); 10 | 11 | exports.update = function(content, namespace, ld, rd, filepath, root, jsconf) { 12 | content = replaceWidget(content, namespace, ld, rd); 13 | content = replaceExtends(content, ld, rd, filepath, root, namespace) 14 | content = replaceInclude(content, namespace, ld, rd, filepath, root) 15 | // content = replaceHTML(content, ld, rd); 16 | content = replaceScript(content, ld, rd); 17 | return content; 18 | } 19 | /** 20 | * {widget name="menu" $a='a'} => {widget name="module:widget/menu/menu.tpl" $a='a'} 21 | * {widget name="common:menu"} => {widget name="common:widget/menu/menu.tpl"} 22 | * {widget name="menu"} => 23 | * {widget name="menu" $a='a' inline="false"} => {widget name="module:widget/menu/menu.tpl" $a='a'} 24 | * {widget name="menu" inline="true"} => 25 | * */ 26 | function replaceWidget(content, namespace, ld, rd){ 27 | var l_ld = pregQuote(ld); 28 | var l_rd = pregQuote(rd); 29 | var reg = new RegExp('(?:'+l_ld+'\\s*\\bwidget\\b([\\s\\S]*?)'+l_rd+'|'+l_ld+'\\s*\\/widget\\s*'+l_rd+')', 'g'); 30 | content = content.replace(reg, function(m, value) { 31 | var path = ''; 32 | var nameReg = /\bname\s*=\s*("(?:[^\\"]|\\[\s\S])+"|'(?:[^\\']|\\[\s\S])+')\s*/; 33 | var pathReg = /\bpath\s*=\s*("(?:[^\\"]|\\[\s\S])+"|'(?:[^\\']|\\[\s\S])+')\s*/; 34 | // var inlineReg = /\binline\s*=\s*[\\'"]\s*(false|true)\s*[\\'"]/; 35 | if (value) { 36 | if (!nameReg.test(value)) { 37 | if(pathReg.test(value)){ 38 | value = value.replace(pathReg, function (m1, v) { 39 | var info = fis.util.stringQuote(v); 40 | v = info.rest.trim(); 41 | if (v && v.indexOf(':') === -1) { 42 | v = namespace+':'+v; 43 | m1 = 'name=' + info.quote + util.removeModuleName(v, namespace) + info.quote + ' '; 44 | } 45 | return m1; 46 | }); 47 | m = ld + 'widget ' + util.trim(value) + rd; 48 | }else{ 49 | m = ''; 50 | } 51 | } else { 52 | value = value.replace(nameReg, function (m1, v) { 53 | var info = fis.util.stringQuote(v); 54 | v = info.rest.trim(); 55 | if (v && v.indexOf(':') === -1 && v.indexOf('.tpl') === -1) { 56 | v = getWidgetPath(namespace, v); 57 | path = v ; 58 | v = namespace+':'+v; 59 | m1 = 'name=' + info.quote + util.removeModuleName(v, namespace) + info.quote + ' '; 60 | }else{ 61 | var group = v.split(':'); 62 | if(group[1].indexOf('.tpl') == -1){ 63 | v = getWidgetPath(group[0], group[1]); 64 | path = v; 65 | m1 = 'name=' + info.quote + group[0] + ':' + util.removeModuleName(v, namespace) + info.quote + ' '; 66 | } 67 | } 68 | return m1; 69 | }); 70 | m = ld + 'widget ' + util.trim(value) + rd; 71 | } 72 | } else { 73 | m = ''; 74 | } 75 | return m; 76 | }); 77 | return content; 78 | } 79 | 80 | function getWidgetPath(namespace, path){ 81 | var basename = path; 82 | if(path.indexOf('/')){ 83 | var group = path.split('/'); 84 | basename = group[group.length-1]; 85 | } 86 | return 'widget/' + path + '/' + basename + '.tpl'; 87 | } 88 | 89 | /** 90 | * {extends file="page/common/layout.tpl"} => {extends file="common/page/layout.tpl"} 91 | * */ 92 | function replaceExtends(content, ld, rd, filepath, root, namespace){ 93 | var l_ld = pregQuote(ld); 94 | var l_rd = pregQuote(rd); 95 | var rd_0 = pregQuote(rd.substr(0, 1), '/'); 96 | //右边界剩下字符的正则转义 97 | var rd_1 = pregQuote(rd.substr(1), '/'); 98 | var reg = new RegExp(l_ld + 'extends\\s+((?:[^' + l_rd + ']|' + rd_0 + '(?!' + rd_1 + '))*?)' + l_rd, 'g'); 99 | var regfile = /\bfile\s*=\s*("(?:[^\\"]|\\[\s\S])+"|'(?:[^\\']|\\[\s\S])+')\s*/; 100 | content = content.replace(reg, function(m, value) { 101 | var v1 = value.replace(regfile, function (m1, v) { 102 | if(v.indexOf(':') !== -1){ 103 | return util.removeModuleName(m1, namespace); 104 | } 105 | v = v.substring(1, v.length-1); 106 | if(v.substr(0, 1) == '.'){ 107 | v = pth.normalize(pth.dirname(filepath) + '/' + v); 108 | v = v.replace(/[\/\\]+/g, '/'); 109 | v = v.replace(root + '/', ''); 110 | } 111 | var group = v.split('/'); 112 | if(group[1] == 'common'){ 113 | return 'file=\'common/' + util.removeModuleName(v, namespace) + '\''; 114 | } 115 | return 'file=\'' + namespace + '/'+ util.removeModuleName(v, namespace) + '\''; 116 | }); 117 | return m.replace(value, v1); 118 | }); 119 | return content; 120 | } 121 | 122 | /** 123 | * {include file="page/home/a.tpl"} => {include file="home/page/a.tpl"} 124 | * {include file="./a.tpl"} => {include file="home/page/a.tpl"} 125 | * {include file="./a.tpl" inline="true"} => 126 | * */ 127 | function replaceInclude(content, namespace, ld, rd, filepath, root){ 128 | var l_ld = pregQuote(ld); 129 | var l_rd = pregQuote(rd); 130 | var rd_0 = pregQuote(rd.substr(0, 1), '/'); 131 | //右边界剩下字符的正则转义 132 | var rd_1 = pregQuote(rd.substr(1), '/'); 133 | var reg = new RegExp(l_ld + 'include\\s+((?:[^' + l_rd + ']|' + rd_0 + '(?!' + rd_1 + '))*?)' + l_rd, 'g'); 134 | var regfile = /\bfile\s*=\s*("(?:[^\\"]|\\[\s\S])+"|'(?:[^\\']|\\[\s\S])+')\s*/; 135 | var reginline = /\binline\s*=\s*("(?:[^\\"]|\\[\s\S])+"|'(?:[^\\']|\\[\s\S])+'|\b)\s*/; 136 | content = content.replace(reg, function(m, value) { 137 | //先判断是否有inline 138 | var inline = false; 139 | var path = ''; 140 | var v1 = value.replace(reginline, function(m1, v){ 141 | v = v.substring(1, v.length-1); 142 | inline = (v == 'true' || v == '1' || m1 == 'inline'); 143 | }); 144 | v1 = value.replace(regfile, function (m1, v) { 145 | // if(v.indexOf(':') != -1){ 146 | // return util.removeModuleName(m1, namespace); 147 | // } 148 | v = v.substring(1, v.length-1); 149 | if(v.substr(0, 1) == '.'){ 150 | v = pth.normalize(pth.dirname(filepath) + '/' + v); 151 | v = v.replace(/[\/\\]+/g, '/'); 152 | v = v.replace(root + '/', ''); 153 | } 154 | v = util.removeModuleName(v, namespace); 155 | if(!inline){ 156 | var group = v.split('/'); 157 | if(group[1] == 'common'){ 158 | return 'file=\'common/' + v + '\''; 159 | } 160 | return 'file=\'' + namespace + '/' + v + '\''; 161 | } 162 | path = v; 163 | }); 164 | if(!inline){ 165 | return m.replace(value, v1); 166 | } 167 | return ''; 168 | }); 169 | return content; 170 | } 171 | 172 | /** 173 | * ---> {html} 174 | * 175 | * @param content 176 | * @param ld 177 | * @param rd 178 | * @returns {XML} 179 | */ 180 | function replaceHTML(content, ld, rd){ 181 | var reg = /|\s*)>|(\<\/html\>)||\s*>)|(\<\/body>)||\s*>)|(\<\/head\>)/g; 182 | content = content.replace(reg, function(m, v1, v2, v3, v4, v5, v6){ 183 | if(v1){ 184 | m = ld + 'html' + v1 + rd; 185 | }else if(m.substring(0,5) === ']*\>)([\s\S]*?)(\<\/script\s*\>)/g; 209 | var srcreg = /^(\]*?src\s*=\s*)("[^"]+"|[^\s>]+)([^>]*\>)$/i; 210 | var requirereg = /\brequire.async/; 211 | content = content.replace(reg, function(m, v1, v2, v3){ 212 | if(srcreg.test(v1)){ 213 | return m; 214 | } 215 | if(requirereg.test(v2)){ 216 | return ld + 'script' +rd + v2 + ld + '/script' +rd; 217 | } 218 | return m; 219 | }); 220 | return content; 221 | } 222 | 223 | function pregQuote (str, delimiter) { 224 | // http://kevin.vanzonneveld.net 225 | return (str + '').replace(new RegExp('[.\\\\+*?\\[\\^\\]$(){}=!<>|:\\' + (delimiter || '') + '-]', 'g'), '\\$&'); 226 | } 227 | -------------------------------------------------------------------------------- /upgrade.js: -------------------------------------------------------------------------------- 1 | /* 2 | * fis 3 | * http://fis.baidu.com/ 4 | */ 5 | 6 | 'use strict'; 7 | 8 | var fs = require('fs'), 9 | pth = require('path'), 10 | xmlreader = require('xmlreader'), 11 | js = require('./lib/jsUpgrade.js'), 12 | css = require('./lib/cssUpgrade.js'), 13 | tpl = require('./lib/tplUpgrade.js'), 14 | util = require('./lib/util.js'), 15 | jsconf ='', 16 | _exists = fs.existsSync || pth.existsSync; 17 | 18 | exports.name = 'upgrade'; 19 | exports.desc = 'Upgrade 1.0 - 2.0'; 20 | exports.register = function(commander) { 21 | var namespace, ld, rd, 22 | model = 0; 23 | 24 | commander 25 | .option('--namespace ', 'namespace', String, 'common') 26 | .option('--ld ', 'smarty left delimiter', String, '{%') 27 | .option('--rd ', 'smarty right delimiter', String, '%}') 28 | .option('-j --jsconf ', 'change the filepath', String, '') 29 | .action(function(options) { 30 | var root = fis.util.realpath(process.cwd()); 31 | if(options.jsconf){ 32 | if(fis.util.realpath(options.jsconf)){ 33 | jsconf = fis.util.realpath(options.jsconf) 34 | console.log('Setting UI processing path to the file path is' + jsconf); 35 | }else{ 36 | console.log('The jsconf does not exist!'); 37 | return; 38 | } 39 | } 40 | rd = options.rd; 41 | ld = options.ld; 42 | //判断是不是一个正规模块 43 | var xmlpath = root + '/config/fis-config.xml'; 44 | var rootSplit = root.split('/'); 45 | rootSplit.splice(rootSplit.length - 1, 1, rootSplit[rootSplit.length - 1] + '_2.0'); 46 | var projectRoot = rootSplit.join('/'); 47 | if(_exists(xmlpath)){ 48 | xmlreader.read(fis.util.read(xmlpath), function(errors, res){ 49 | if(null !== errors ){ 50 | console.log(errors) 51 | return; 52 | } 53 | if(res.project.attributes()['modulename']){ 54 | namespace = res.project.attributes().modulename; 55 | }else{ 56 | console.log('There has no modulename!'); 57 | return; 58 | } 59 | if(res.project['smarty']){ 60 | if(res.project.smarty.attributes()['left_delimiter']){ 61 | ld = res.project.smarty.attributes().left_delimiter; 62 | } 63 | if(res.project.smarty.attributes()['right_delimiter']){ 64 | rd = res.project.smarty.attributes().right_delimiter; 65 | } 66 | } 67 | }) 68 | }else{ 69 | console.log('No configuration file, Please check the catalog is correct!'); 70 | return; 71 | } 72 | console.log('The namespace : ' + namespace); 73 | console.log('The smarty left delimiter : ' +ld); 74 | console.log('The smarty right delimiter : ' +rd); 75 | console.log('Upgrade process starts.'); 76 | var macro = new Array(); 77 | var widget = new Array(); 78 | var jsContext = new Array(); 79 | process.stdout.write('loading'); 80 | fis.util.find(root).forEach(function(filepath) { 81 | process.stdout.write('.'); 82 | if(/.*\.(tpl|js|html|css)$/.test(filepath)){ 83 | var content = fis.util.read(filepath); 84 | content = js.update(content, namespace,filepath, root, jsconf); 85 | filepath = filepath.replace(/[\/\\]+/g, '/'); 86 | content = css.update(content, namespace, filepath, root, jsconf); 87 | if(/\.tpl$/.test(filepath)){ 88 | content = tpl.update(content, namespace, ld, rd, filepath, root, jsconf); 89 | } 90 | filepath = projectRoot + '/' + util.getStandardPath(filepath.replace(root + '/', ''), namespace,jsconf); 91 | fis.util.write(filepath, content); 92 | 93 | if(/\.tpl$/.test(filepath) && util.detWidgetExtends(content, ld, rd)){ 94 | widget.push(filepath); 95 | } 96 | if(/\.css$/.test(filepath) && util.detMarco(content)){ 97 | fs.renameSync(filepath, filepath.replace(/\.css/, '.less')); 98 | macro.push(filepath); 99 | } 100 | if(util.detContext(content)){ 101 | jsContext.push(filepath); 102 | } 103 | // console.log('Upgrade ' + filepath +' successfully!'); 104 | }else{ 105 | if(pth.basename(filepath) == 'fis-config.xml'){ 106 | return; 107 | } 108 | fis.util.copy(filepath, projectRoot + '/' + util.getStandardPath(filepath.replace(root + '/', ''), namespace, jsconf)); 109 | } 110 | }); 111 | // if(fis.util.isDir(root + "/test")){ 112 | // fis.util.find(root + "/test").forEach(function(filepath) { 113 | // var content = fis.util.read(filepath); 114 | // filepath = filepath.replace(/[\/\\]+/g, '/'); 115 | // filepath = projectRoot + '/test/' + util.getStandardPath(filepath.replace(root + '/test/', ''), namespace, jsconf); 116 | // fis.util.write(filepath, content); 117 | // }); 118 | // } 119 | // if(fis.util.isDir(root + "/plugin")){ 120 | // fis.util.find(root + "/plugin").forEach(function(filepath) { 121 | // var content = fis.util.read(filepath); 122 | // filepath = filepath.replace(/[\/\\]+/g, '/'); 123 | // filepath = filepath.replace(root, projectRoot); 124 | // fis.util.write(filepath, content); 125 | // }); 126 | // } 127 | // fis.util.find(root + "/config", /.*\.(conf)$/).forEach(function(filepath) { 128 | // var content = fis.util.read(filepath); 129 | // filepath = filepath.replace(/[\/\\]+/g, '/'); 130 | // filepath = projectRoot + '/' + util.getStandardPath(filepath.replace(root + '/', ''), namespace, jsconf); 131 | // fis.util.write(filepath, content); 132 | // }); 133 | var config = 'fis.config.merge({\n' 134 | + ' namespace : \'' + namespace +'\',\n' 135 | + '});'; 136 | var configPath = projectRoot + '/fis-conf.js'; 137 | fis.util.write(configPath, config); 138 | if(macro.length >0 || widget.length > 0 && jsContext.length > 0){ 139 | fis.util.write(projectRoot + '/detect.html', createHTML(macro, widget,jsContext)); 140 | } 141 | console.log('\nUpgrade process ends!'); 142 | }); 143 | }; 144 | 145 | function createHTML(macro, widget, jsContext){ 146 | var html = '' 147 | + '' 148 | + ' ' 149 | + ' ' 150 | + ' FIS 2.0 detect' 151 | + ' ' 152 | + ' ' 157 | + ' '; 158 | var tr = ''; 159 | 160 | if(jsContext.length > 0){ 161 | for(var i = 0; i < jsContext.length; i++){ 162 | tr += ''; 163 | if(i == 0){ 164 | tr += '此文件中使用了F.context,2.0不支持此功能,请替换为其他数据中心.' 165 | } 166 | tr += ' ' + jsContext[i]+ '' 167 | + ''; 168 | } 169 | } 170 | 171 | if(macro.length > 0){ 172 | for(var i = 0; i < macro.length; i++){ 173 | tr += ''; 174 | if(i == 0){ 175 | tr += '此文件中使用了Macro,请替换为Less语法,文件后缀已修改为less,同时请修改跨模块引用此文件的引用方式.' 176 | } 177 | tr += ' ' + macro[i]+ '' 178 | + ''; 179 | } 180 | } 181 | 182 | if(widget.length > 0){ 183 | for(var i = 0; i < widget.length; i++){ 184 | tr += ''; 185 | if(i == 0){ 186 | tr += '此文件中使用了widget继承,请替换此功能.' 187 | } 188 | tr += ' ' + widget[i]+ '' 189 | + ''; 190 | } 191 | } 192 | 193 | html += '' 194 | + '
' 195 | + '' 196 | + '' 197 | + tr 198 | + '
检测功能文件路径
' 199 | + '
' 200 | + '' 201 | return html; 202 | } --------------------------------------------------------------------------------