From 42e1741c34afbd977fb67b7ef1fecc5e08d0b5e5 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Wed, 13 Jun 2012 11:08:05 +0000 Subject: [PATCH] css and html optimizing --- .gitignore | 1 + all.min.css | 1 + index.html | 6 +- index.min.html | 1 + minify.js | 261 ++++++++++++++++++++++++++++++++++++------------- reset.min.css | 1 + server.js | 46 +++++++-- style.min.css | 1 + 8 files changed, 238 insertions(+), 80 deletions(-) create mode 100644 all.min.css create mode 100644 index.min.html create mode 100644 reset.min.css create mode 100644 style.min.css diff --git a/.gitignore b/.gitignore index ab433e16..43a7a45e 100644 --- a/.gitignore +++ b/.gitignore @@ -9,6 +9,7 @@ node_modules #cloudfoundry info files cloudcmd.manifest.yml cloudcmddemo.manifest.yml +demo-cloudcmd.manifest.yml #herocu info file Procfile diff --git a/all.min.css b/all.min.css new file mode 100644 index 00000000..c30ed57e --- /dev/null +++ b/all.min.css @@ -0,0 +1 @@ +@font-face{font-family:'FoundationIconsGeneralEnclosed';src:url('//dl.dropbox.com/u/78163899/mnemonia/fonts/foundation-icons-general-enclosed.woff') format('woff');font-weight:400;font-style:normal}@font-face{font-family:'Octicons Regular';font-style:normal;font-weight:400;src:local('Octicons Regular'),url('//dl.dropbox.com/u/78163899/mnemonia/fonts/octicons-regular-webfont.woff') format('woff')}@font-face{font-family:'Droid Sans Mono';font-style:normal;font-weight:400;src:local('Droid Sans Mono'),local('DroidSansMono'),url('http://themes.googleusercontent.com/static/fonts/droidsansmono/v4/ns-m2xQYezAtqh7ai59hJUYuTAAIFFn5GTWtryCmBQ4.woff') format('woff')}body{font:16px "Droid Sans Mono"}.menu{font:16px 'Octicons Regular';margin-bottom:0}.path_icon{font-family:'FoundationIconsGeneralEnclosed';font-size:30px;color:#46A4C3;text-shadow:black 0 2px 1px;width:15px;height:15px;display:inline-block;position:relative;top:3px;left:-4px}.path_icon:hover{cursor:pointer}.path_icon:active{text-shadow:black 0 0 1px;position:relative;top:4px}.icon{font-family:'Octicons Regular';font-size:16px;width:16px;height:16px;display:inline-block;margin-left:.5%}.error::before{content:'\f026';cursor:default;color:#de2929;position:relative;top:-3px}.loading{background:url(images/spinner.gif);position:relative;top:1px}.error:hover{color:rgba(222,41,41,.81)}.refresh-icon{background:url(images/panel_refresh.png) no-repeat}.refresh-icon:active{background:url(images/panel_refresh.png) 0 -15px no-repeat}.clear-cache{background:url(images/console_clear.png) -4px -4px no-repeat;margin-right:6px;margin-left:7px}.clear-cache:active{top:5px}.settings:before{content:'k'}.links{color:red}.mini-icon{float:left;height:16px;left:-5px;margin-left:6px;position:relative;top:2px;width:16px}.directory{background-image:url('images/dir.png');background-repeat:no-repeat;background-position:0 0}.text-file{background-image:url('images/txt.png');background-repeat:no-repeat;background-position:0 0}#fm{height:90%;overflow-y:scroll}.fm_header{font-weight:700}#path{margin-left:1.5%}#left{float:left;width:90%}.current-file{border:2px solid rgba(49,123,249,.40)}.selected-file{background-color:rgba(49,123,249,.40);color:#fff}#right{float:right}.panel{display:table;width:50%}#keyspanel{text-align:center}.name{float:left;width:37%}.size{float:left;width:16%;text-align:right;margin-right:27px}.owner{}.mode{float:right;width:25%}ul,li{list-style-type:none}button{width:10%}a{text-decoration:none}a:hover,a:active{cursor:pointer;outline:0;color:#06e}a:focus{outline:thin dotted}@media only screen and (max-width: 600px){#left{ width:90%!important}.panel >li{margin:10px}#right{display:none}.current-file{background-color:rgba(49,123,249,.40);color:#fff}.current-file>.mini-icon{color:#fff}.current-file>.text-file::before{color:#fff}.mini-icon{font:60px 'Octicons Regular';width:40%;height:0;margin-left:0;float:right;position:relative;top:-17px;color:rgba(246,224,124,.56)}.directory::before{content:'\f216'}.text-file::before{color:rgba(26,224,124,.56);content:'\f211'}.text-file{background-image:none}.fm_header{display:none}.mode,.size,.owner{display:table;float:none;width:0;text-align:left}.name::before{content:'name:';font-weight:700;font-size:13px}.mode::before{content:'mode:';font-weight:700;font-size:13px}.size::before{content:'size:';font-weight:700;font-size:13px}.owner::before{content:'owner:';font-weight:700;font-size:13px}.name{float:none;width:100%;font-size:18px}}@media only screen and (min-width: 601px) and (max-width: 767px){#left{ width:90%!important}#right{display:none}}@media only screen and (min-width:767px) and (max-width: 1060px){#left{ width:90%!important}#right{display:none}}html{font-size:100%;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;font-family:sans-serif;color:#222}body{margin:0;font-size:1em;line-height:1.4}::selection{text-shadow:none;opacity:0}a{text-decoration:none;color:#00e}a:visited{color:#551a8b}a:hover{color:#06e}a:focus{outline:thin dotted}a:hover,a:active{outline:0}ul{margin:1em 0;padding:0 0 0 40px}.chromeframe{margin:.2em 0;background:#ccc;color:#000;padding:.2em 0}.ir{display:block;border:0;text-indent:-999em;overflow:hidden;background-color:transparent;background-repeat:no-repeat;text-align:left;direction:ltr;*line-height:0}.ir br{display:none}.hidden{display:none!important;visibility:hidden}.visuallyhidden{border:0;clip:rect(0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.visuallyhidden.focusable:active,.visuallyhidden.focusable:focus{clip:auto;height:auto;margin:0;overflow:visible;position:static;width:auto}.invisible{visibility:hidden}.clearfix:before,.clearfix:after{content:"";display:table}.clearfix:after{clear:both}.clearfix{*zoom:1}@media print{*{ background:transparent!important;color:#000!important;box-shadow:none!important;text-shadow:none!important;filter:none!important;-ms-filter:none!important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}@page{margin:.5cm}} \ No newline at end of file diff --git a/index.html b/index.html index f4b0c2e5..7f978f4a 100644 --- a/index.html +++ b/index.html @@ -5,11 +5,7 @@ Cloud Commander - - +
\ No newline at end of file diff --git a/minify.js b/minify.js index c1f8c145..84c5d910 100644 --- a/minify.js +++ b/minify.js @@ -3,6 +3,9 @@ /* функция сжимает js-скрипты * и сохраняет их с именем .min.js */ + +var fs = require('fs'); + exports.jsScripts=function jsScripts(){ 'use strict'; @@ -14,78 +17,56 @@ exports.jsScripts=function jsScripts(){ var jsp = require("uglify-js").parser; var pro = require("uglify-js").uglify; }catch(error){ - console.log('ERROR. error loading uglify-js\n' + + console.log('can\'n load uglify-js\n' + 'to use js-minification you need to install uglify-js\n' + 'npm install uglify-js\n' + - 'https://github.com/mishoo/UglifyJS\n' + - error); + 'https://github.com/mishoo/UglifyJS'); return false; } - - var fs = require('fs'); - /* Константы */ var CLIENT_JS='client.js'; var CLOUDFUNC_JS='cloudfunc.js'; - - console.log('reading file ' + CLIENT_JS+'...'); - fs.readFile(CLIENT_JS,fileReaded(CLIENT_JS)); + + var dataReaded_f=function(pFileName, pData){ + console.log('file ' + pFileName + ' readed'); + + /*********************************/ + /* сжимаем код через uglify-js */ + var uglify_js=function(pDdata){ + var orig_code = pDdata.toString(); + var ast = jsp.parse(orig_code); // parse code and get the initial AST + ast = pro.ast_mangle(ast); // get a new AST with mangled names + ast = pro.ast_squeeze(ast); // get an AST with compression optimizations + var result_code = pro.gen_code(ast); // compressed code here + return result_code; + }; + /*********************************/ + var final_code=uglify_js(pData); + + var minFileName=pFileName.replace('.js','.min.js'); + /* если мы сжимаем client.js - + * меняем строку cloudfunc.js на + * cloudfunc.min.js и выводим сообщение + * если другой файл - ничего не деалем + */ + (pFileName===CLIENT_JS)? + console.log('file name of ' + + CLOUDFUNC_JS + + ' in ' + + CLIENT_JS + + ' changed. size:', + (final_code=final_code.replace(CLOUDFUNC_JS, + CLOUDFUNC_JS.replace('.js', + '.min.js'))).length): + ''; + /* записываем сжатый js-скрипт*/ + fs.writeFile(minFileName, final_code, fileWrited(minFileName)); + }; + console.log('reading file ' + CLIENT_JS+'...'); + fs.readFile(CLIENT_JS,fileReaded(CLIENT_JS,dataReaded_f)); console.log('reading file ' + CLOUDFUNC_JS+'...'); - fs.readFile(CLOUDFUNC_JS,fileReaded(CLOUDFUNC_JS)); - - /* Функция создаёт асинхроную версию - * для чтения файла - * @pFileName - имя считываемого файла - */ - function fileReaded(pFileName){ - return function(error,data){ - /* функция в которую мы попадаем, - * если данные считались - */ - var dataReaded=function(){ - console.log('file ' + pFileName + ' readed'); - - /*********************************/ - /* сжимаем код через uglify-js */ - var uglify_js=function(pDdata){ - var orig_code = pDdata.toString(); - var ast = jsp.parse(orig_code); // parse code and get the initial AST - ast = pro.ast_mangle(ast); // get a new AST with mangled names - ast = pro.ast_squeeze(ast); // get an AST with compression optimizations - var result_code = pro.gen_code(ast); // compressed code here - return result_code; - }; - /*********************************/ - var final_code=uglify_js(data); - - var minFileName=pFileName.replace('.js','.min.js'); - /* если мы сжимаем client.js - - * меняем строку cloudfunc.js на - * cloudfunc.min.js и выводим сообщение - * если другой файл - ничего не деалем - */ - (pFileName===CLIENT_JS)? - console.log('file name of ' + - CLOUDFUNC_JS + - ' in ' + - CLIENT_JS + - ' changed. size:', - (final_code=final_code.replace(CLOUDFUNC_JS, - CLOUDFUNC_JS.replace('.js', - '.min.js'))).length): - ''; - var fileWrited=function(error){ - console.log(error?error:('file '+minFileName+' writed...')); - }; - - /* записываем сжатый js-скрипт*/ - fs.writeFile(minFileName, final_code, fileWrited); - }; - - error?console.log(error):dataReaded(); - }; - } + fs.readFile(CLOUDFUNC_JS,fileReaded(CLOUDFUNC_JS,dataReaded_f)); }; /* функция сжимает css-стили @@ -102,14 +83,156 @@ exports.cssStyles=function cssStyles(){ try{ cleanCSS = require('clean-css'); }catch(error){ - console.log('ERROR. error loading clean-css \n' + + console.log('can\'n load clean-css \n' + 'to use css-minification you need to install clean-css \n' + 'npm install clean-css\n' + - 'https://github.com/GoalSmashers/clean-css\n' + - error); + 'https://github.com/GoalSmashers/clean-css'); return false; } - var source = "a{font-weight:bold;font-color:red}"; - var minimized = cleanCSS.process(source); -}; \ No newline at end of file + /* Константы */ + var STYLE_CSS='style.css'; + var RESET_CSS='reset.css'; + + var lAllStyle=''; + var lResetCssDone=false; + var lStyleCssDone=false; + var dataReaded_f=function(pFileName, pData){ + console.log('file ' + pFileName + ' readed'); + /*********************************/ + /* сжимаем код через clean-css */ + var clean_css=function(pData){ + /* Сохраняем весь стиль в одну переменную*/ + return cleanCSS.process(pData); + }; + /*********************************/ + var final_code=clean_css(pData); + + lAllStyle+=final_code; + + var minFileName=pFileName.replace('.css','.min.css'); + + if(pFileName===STYLE_CSS)lStyleCssDone=true; + if(pFileName===RESET_CSS)lResetCssDone=true; + /* if all files writed we + * save all minimized css + * to one file all.min.css + */ + (lStyleCssDone && lStyleCssDone)? + fs.writeFile('all.min.css', lAllStyle, fileWrited('all.min.css')):''; + + /* записываем сжатый css файл*/ + fs.writeFile(minFileName, final_code, fileWrited(minFileName)); + }; + + console.log('reading file ' + STYLE_CSS+'...'); + fs.readFile(STYLE_CSS,fileReaded(STYLE_CSS,dataReaded_f)); + + console.log('reading file ' + RESET_CSS+'...'); + fs.readFile(RESET_CSS,fileReaded(RESET_CSS,dataReaded_f)); + /* + var source = "a{font-weight:bold;font-color:red}"; + var minimized = cleanCSS.process(source); + */ +}; + +/* функция сжимает css-стили + * и сохраняет их с именем .min.css + */ +exports.html=function(){ + 'use strict'; + + /* connecting cleanCSS, + * if we can't find it - + * return false + */ + var htmlMinifier; + try{ + htmlMinifier = require('html-minifier'); + }catch(error){ + console.log('can\'n load html-minifier \n' + + 'to use html-minification you need to install html-minifier\n' + + 'npm install html-minifier\n' + + 'https://github.com/kangax/html-minifier'); + return false; + } + + /* Константы */ + var INDEX_HTML='index.html'; + + var dataReaded_f=function(pFileName, pData){ + console.log('file ' + pFileName + ' readed'); + /*********************************/ + /* сжимаем код через clean-css */ + var html_minify=function(pData){ + /* Сохраняем весь стиль в одну переменную*/ + + var lOptions={ + removeComments: true, + removeCommentsFromCDATA: true, + removeCDATASectionsFromCDATA: true, + collapseWhitespace: true, + collapseBooleanAttributes: true, + removeAttributeQuotes: true, + removeRedundantAttributes: true, + useShortDoctype: true, + removeEmptyAttributes: true, + /* оставляем, поскольку у нас + * в элемент fm генерируеться + * таблица файлов + */ + removeEmptyElements: false, + removeOptionalTags: true, + removeScriptTypeAttributes: true, + removeStyleLinkTypeAttributes: true + }; + + + return htmlMinifier.minify(pData,lOptions); + }; + /*********************************/ + var final_code=html_minify(pData); + + var minFileName=pFileName.replace('.html','.min.html'); + + /* записываем сжатый html файл*/ + fs.writeFile(minFileName, final_code, fileWrited(minFileName)); + }; + + console.log('reading file ' + INDEX_HTML+'...'); + fs.readFile(INDEX_HTML,fileReaded(INDEX_HTML,dataReaded_f)); +}; + + + +/* Функция создаёт асинхроную версию + * для чтения файла + * @pFileName - имя считываемого файла + */ +function fileReaded(pFileName,pCompressFunc){ + "use strict"; + return function(pError,pData){ + /* функция в которую мы попадаем, + * если данные считались + * + * если ошибка - показываем её + * иначе если переданная функция - + * функция запускаем её + */ + pError?console.log(pError): + ((pCompressFunc && typeof pCompressFunc==="function")? + pCompressFunc(pFileName,pData.toString()):''); + }; +} + +/* + * Функция вызываеться после записи файла + * и выводит ошибку или сообщает, + * что файл успешно записан + */ +function fileWrited(pFileName){ + "use strict"; + return function(error){ + console.log(error?error:('file '+pFileName+' writed...')); + }; +} diff --git a/reset.min.css b/reset.min.css new file mode 100644 index 00000000..4d8d6ca9 --- /dev/null +++ b/reset.min.css @@ -0,0 +1 @@ +html{font-size:100%;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;font-family:sans-serif;color:#222}body{margin:0;font-size:1em;line-height:1.4}::selection{text-shadow:none;opacity:0}a{text-decoration:none;color:#00e}a:visited{color:#551a8b}a:hover{color:#06e}a:focus{outline:thin dotted}a:hover,a:active{outline:0}ul{margin:1em 0;padding:0 0 0 40px}.chromeframe{margin:.2em 0;background:#ccc;color:#000;padding:.2em 0}.ir{display:block;border:0;text-indent:-999em;overflow:hidden;background-color:transparent;background-repeat:no-repeat;text-align:left;direction:ltr;*line-height:0}.ir br{display:none}.hidden{display:none!important;visibility:hidden}.visuallyhidden{border:0;clip:rect(0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.visuallyhidden.focusable:active,.visuallyhidden.focusable:focus{clip:auto;height:auto;margin:0;overflow:visible;position:static;width:auto}.invisible{visibility:hidden}.clearfix:before,.clearfix:after{content:"";display:table}.clearfix:after{clear:both}.clearfix{*zoom:1}@media print{*{ background:transparent!important;color:#000!important;box-shadow:none!important;text-shadow:none!important;filter:none!important;-ms-filter:none!important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}@page{margin:.5cm}} \ No newline at end of file diff --git a/server.js b/server.js index 1308333b..79979226 100644 --- a/server.js +++ b/server.js @@ -104,8 +104,9 @@ CloudServer.Cache={ */ CloudServer.Minify={ /* приватный переключатель минимизации */ - _styleAllowed :true, - _jsAllowed :true, + _styleAllowed :true, + _jsAllowed :true, + _htmlAllowed :true, /* функция разрешает или запрещает * минимизировать стили */ @@ -120,7 +121,7 @@ CloudServer.Minify={ this._jsAllowed=pAllowed; }), - scripts : function(){ + jsScripts : function(){ if(this._jsAllowed){ var lMinify = require('./minify'); var lResult_b=lMinify.jsScripts(); @@ -130,6 +131,28 @@ CloudServer.Minify={ this.done=(lResult_b===undefined?true:false); } }, + + cssStyles : function(){ + if(this._styleAllowed){ + var lMinify = require('./minify'); + var lResult_b=lMinify.cssStyles(); + /* if we get false, files wasn't minified + * error ocured + */ + this.done=(lResult_b===undefined?true:false); + } + }, + + html : function(){ + if(this._htmlAllowed){ + var lMinify = require('./minify'); + var lResult_b=lMinify.html(); + /* if we get false, files wasn't minified + * error ocured + */ + this.done=(lResult_b===undefined?true:false); + } + }, /* свойство показывающее случилась ли ошибка*/ done: false }; @@ -155,7 +178,9 @@ CloudServer.init=(function(){ CloudServer.Cache.setAllowed(true); CloudServer.Minify.setJSAllowed(true); /* Если нужно минимизируем скрипты */ - CloudServer.Minify.scripts(); + CloudServer.Minify.jsScripts(); + CloudServer.Minify.cssStyles(); + CloudServer.Minify.html(); }); @@ -422,6 +447,12 @@ CloudServer._readDir=function (pError, pFiles) /* если javascript отключен вылылаем html-код * и прописываем соответствующие заголовки */ + + /* если установлено сжатие + * меняем название html-файла и + * загружаем сжатый html-файл в дальнейшем + */ + CloudServer.INDEX=(CloudServer.Minify.done?'index.min.html':CloudServer.INDEX); if(CloudServer.NoJS){ var lPanel=CloudFunc.buildFromJSON(lJSON); lList='