From ca4c24a6e72545f7a91808e920748c09254c4ddd Mon Sep 17 00:00:00 2001 From: coderaiser Date: Thu, 14 Jun 2012 09:42:58 +0000 Subject: [PATCH] lib-scripts moved to lib folder --- lib/cloudfunc.js | 513 +++++++++++++++++++++++++++++++++++++++++++++++ lib/minify.js | 240 ++++++++++++++++++++++ 2 files changed, 753 insertions(+) create mode 100644 lib/cloudfunc.js create mode 100644 lib/minify.js diff --git a/lib/cloudfunc.js b/lib/cloudfunc.js new file mode 100644 index 00000000..e245bba2 --- /dev/null +++ b/lib/cloudfunc.js @@ -0,0 +1,513 @@ +/* Модуль, содержащий функции, которые будут работать + * и на клиенте и на сервере + * + * Привала названий: + * varName - имя функции + * lVarName - имя локальной переменной + * pVarName - имя параметра + * fVarName - имя функции созданной внутри функции + * VARNAME - имя константы + * + * Типы переменных: + * varNameS - строка + * varNameN - число + * varNameO - обьект + * varNameM - массив + */ + +var CloudFunc={ + /* Путь с которым мы сейчас работаем */ + Path :'', + /* КОНСТАНТЫ (общие для клиента и сервера)*/ + /* название программы */ + NAME :'Cloud Commander', + /* если в ссылке будет эта строка - + * в браузере js отключен + */ + NOJS : '/no-js', + FS : '/c/f/s', + /* название css-класа кнопки обновления файловой структуры*/ + REFRESHICON : 'refresh-icon', + /* id панелей с файлами */ + LEFTPANEL : 'left', + RIGHTPANEL : 'right', + /* name of direcotory with libs */ + LIBDIR :'./lib' +}; + +/* + * Функция убирает последний слеш, + * если он - последний символ строки + */ +CloudFunc.removeLastSlash = function(pPath){ + if(typeof pPath==='string') + return (pPath.lastIndexOf('/')===pPath.length-1)? + pPath.substr(pPath, pPath.length-1):pPath; + else return pPath; +}; +/* + * Функция меняет код символа пробела на пробел + * в переданной строке + * @pPath - строка + */ +CloudFunc.replaceSpaces = function(pPath){ + if(pPath.indexOf('%20')>0){ + do{ + pPath=pPath.replace('%20',' '); + }while(pPath.indexOf('%20')>0); + } + return pPath; +}; + +/* Функция возвращает заголовок веб страницы */ +CloudFunc.setTitle = function(){ + + return CloudFunc.Path===''?CloudFunc.NAME: + CloudFunc.Path + + ' - ' + + CloudFunc.NAME; +}; +/* Функция переводит права из цыфрового вида в символьный + * @pPerm_s - строка с правами доступа + * к файлу в 8-миричной системе + */ +CloudFunc.convertPermissionsToSymbolic= function(pPerm_s){ + /* + S_IRUSR 0000400 protection: readable by owner + S_IWUSR 0000200 writable by owner + S_IXUSR 0000100 executable by owner + S_IRGRP 0000040 readable by group + S_IWGRP 0000020 writable by group + S_IXGRP 0000010 executable by group + S_IROTH 0000004 readable by all + S_IWOTH 0000002 writable by all + S_IXOTH 0000001 executable by all + */ + if(pPerm_s===undefined) return; + + /* тип файла */ + var lType=pPerm_s.charAt(0); + + switch (lType-0) { + case 1: /* обычный файл */ + lType='-'; + break; + case 2: /* байт-ориентированное (символьное) устройство*/ + lType='c'; + break; + case 4: /* каталог */ + lType='d'; + break; + default: + lType='-'; + } + + /* оставляем последние 3 символа*/ + pPerm_s=pPerm_s.length>5?pPerm_s.substr(3):pPerm_s.substr(2); + + /* Рекомендации гугла советуют вместо string[3] + * использовать string.charAt(3) + */ +/* + http://google-styleguide.googlecode.com/svn/trunk/javascriptguide.xml?showone=Standards_features#Standards_features + + Always preferred over non-standards featuresFor + maximum portability and compatibility, always + prefer standards features over non-standards + features (e.g., string.charAt(3) over string[3] + and element access with DOM functions instead + of using an application-specific shorthand). +*/ + /* Переводим в двоичную систему */ + var lOwner=(pPerm_s[0]-0).toString(2); + var lGroup=(pPerm_s[1]-0).toString(2); + var lAll =(pPerm_s[2]-0).toString(2); + /* + console.log(lOwner+' '+lGroup+' '+lAll); + */ + /* переводим в символьную систему*/ + var lPermissions=//lType+' '+ + (lOwner[0]-0>0?'r':'-')+ + (lOwner[1]-0>0?'w':'-')+ + (lOwner[2]-0>0?'x':'-')+ + ' ' + + (lGroup[0]-0>0?'r':'-')+ + (lGroup[1]-0>0?'w':'-')+ + (lGroup[2]-0>0?'x':'-')+ + ' ' + + (lAll[0]-0>0?'r':'-')+ + (lAll[1]-0>0?'w':'-')+ + (lAll[2]-0>0?'x':'-'); + /* + console.log(lPermissions); + */ + return lPermissions; +} + +/* Функция конвертирует права доступа к файлам из символьного вида + * в цыфровой + */ +CloudFunc.convertPermissionsToNumberic= function(pPerm_s){ + /* если передана правильная строка, конвертированная + * функциец convertPermissionsToSymbolic + */ + if(!pPerm_s || pPerm_s.length!==11)return pPerm_s; + + var lOwner= (pPerm_s[0]==='r'?4:0) + + (pPerm_s[1]==='w'?2:0) + + (pPerm_s[2]==='x'?1:0); + var lGroup= (pPerm_s[4]==='r'?4:0) + + (pPerm_s[5]==='w'?2:0) + + (pPerm_s[6]==='x'?1:0); + var lAll = (pPerm_s[8]==='r'?4:0) + + (pPerm_s[9]==='w'?2:0) + + (pPerm_s[10]==='x'?1:0); + /* добавляем 2 цыфры до 5 */ + return '00'+lOwner+lGroup+lAll; +} +/* Функция получает короткие размеры + * конвертируя байт в килобайты, мегабойты, + * гигайбайты и терабайты + * @pSize - размер в байтах + */ +CloudFunc.getShortedSize=function(pSize){ + /* Константі размеров, что используются + * внутри функции + */ + var l1BMAX=1024; + var l1KBMAX=1048576; + var l1MBMAX=1073741824; + var l1GBMAX=1099511627776; + var l1TBMAX=1125899906842624; + + var lShorted; + + if(pSize2){ + if(folders[0].lastIndexOf('/')===folders[0].length) + LPrevDir=folders[1]; + else LPrevDir=folders[2]; + }else LPrevDir='/'; + */ + /* ################################### */ + + /* Формируем ссылки на каждый каталог в пути */ + var lHref=''; + var lHrefEnd=''; + + var lHtmlPath; + /* путь в ссылке, который говорит + * что js отключен + */ + var lNoJS_s=CloudFunc.NOJS; + var lFS_s=CloudFunc.FS; + /* корневой каталог */ + lHtmlPath=lHref+lFS_s+lNoJS_s+lTitle+'"/"'+_l+'/'+lHrefEnd; + for(i=folders.length-1;i>0;i--) + { + var lUrl=folders[i]; + var lShortName=lUrl.replace(lUrl.substr(lUrl,lUrl.lastIndexOf('/')+1),''); + if(i!=1) + { + lHtmlPath+=lHref+lFS_s+lNoJS_s+lUrl+lTitle+lUrl+_l+lShortName+lHrefEnd+'/'; + } + else + lHtmlPath+=lShortName+'/'; + } + /* *** */ + return lHtmlPath; +} + +/* + * Функция ищет в имени файла расширение + * и если находит возвращает true + * @pName - получает имя файла + * @pExt - расширение + */ +CloudFunc.checkExtension=function(pName,pExt) +{ + /* если длина имени больше + * длинны расширения - + * имеет смысл продолжать + */ + if(pName.length>pExt.length){ + var lLength=pName.length; /* длина имени*/ + var lExtNum=pName.lastIndexOf(pExt);/* последнее вхождение расширения*/ + var lExtSub=lLength-lExtNum; /* длина расширения*/ + /* если pExt - расширение pName */ + if(lExtSub===pExt.length) + return true; + else + return false; + } + else return false; +} + +/* + * Функция формирует заголовки столбиков + * @pFileTableTitles - массив названий столбиков + */ +CloudFunc._getFileTableHeader=function(pFileTableTitles) +{ + var lHeader='
  • '; + lHeader+=''; + for(var i=0;i'+ + lStr+ + ''; + } + lHeader+='
  • '; + + return lHeader; +} + +/* + * Функция строит таблицу файлв из JSON-информации о файлах + * @pJSON - информация о файлах + * @pKeyBinded - если клавиши назначены, выделяем верхний файл + * [{path:'путь',size:'dir'}, + * {name:'имя',size:'размер',mode:'права доступа'}] + */ +CloudFunc.buildFromJSON=function(pJSON,pKeyBinded) +{ + var files; + /* + * если пропарсить стандартными + * функциями нельзя - + * пробуем eval, + */ + /* + * Если мы на клиенте и нет JSON - + * через eval парсим. + * Если-же мы на сервере, + * или на клиенте всё есть + * парсим стандарным методом + */ + + /* По скольку мы прописали заголовок application/json + * нет необходимости его конвертировать, + * но она есть, если мы вытягиваем данные из + * localStorage + */ + /* + if(typeof pJSON==='string'){ + if(window && !window.JSON){ + try{ + files=eval('('+pJSON+')'); + }catch(err){ + console.log(err); + } + } + else files=JSON.parse(pJSON); + }else + */ + files=pJSON; + /* сохраняем путь каталога в котором мы сейчас находимся*/ + var lPath=files[0].path; + + /* сохраняем путь */ + CloudFunc.Path=lPath; + + /* + * Строим путь каталога в котором мы находимся + * со всеми подкаталогами + */ + var lHtmlPath=CloudFunc._getDirPath(lPath); + + /* Убираем последний слэш + * с пути для кнопки обновить страницу + * если он есть + */ + var lRefreshPath=CloudFunc.removeLastSlash(lPath); + + /* путь в ссылке, который говорит + * что js отключен + */ + var lNoJS_s=CloudFunc.NOJS; + var lFS_s=CloudFunc.FS; + + var lFileTable='
  • '+ + ''+ + ''+ + '' + + ''+ + ''+ + ''+lHtmlPath+''+ + '
  • '; + + var fileTableTitles=['name','size','owner','mode']; + lFileTable+=CloudFunc._getFileTableHeader(fileTableTitles); + /* Если мы не в корне */ + if(lPath!=='/'){ + /* ссылка на верхний каталог*/ + var lDotDot; + /* убираем последний слеш и каталог в котором мы сейчас находимся*/ + lDotDot=lPath.substr(lPath,lPath.lastIndexOf('/')); + lDotDot=lDotDot.substr(lDotDot,lDotDot.lastIndexOf('/')); + /* Если предыдущий каталог корневой */ + if(lDotDot==='')lDotDot='/'; + + /* Сохраняем путь к каталогу верхнего уровня*/ + lFileTable += '
  • '+ + '' + + '' + + '' + + ''+".." + + '' + + '<dir>'+ + '.' + + '' + + '
  • '; + } + var lLength=files.length; + + for(var i=1;i'; + lFileTable +=''; + lFileTable +='' + + '16? + ' title="'+files[i].name+'">' + + files[i].name.substr( + files[i].name,16)+ + '..':'>'+files[i].name) + + "" + + ''; + /* если папка - не выводим размер */ + lFileTable +='' + + (files[i].size==='dir'? + '<dir>': + /* если это файл - получаем + * короткий размер + */ + CloudFunc.getShortedSize( + files[i].size)); + lFileTable +='' + + '' + + (!files[i].uid?'root':files[i].uid) + + '' + + '' + + /* конвертируем названия разрешений + * из числового формата в буквенный + * при этом корневой каталог не трогаем + * по скольку в нём и так всё уже + * установлено еще на сервере + */ + (//lPath==='/'?files[i].mode: + CloudFunc.convertPermissionsToSymbolic(files[i].mode)) + + ''; + lFileTable +=''; + } + + /* если клавиши назначены и + * мы в корневом каталоге и + * верхний файл еще не выделен - + * выделяем верхний файл + */ + if(pKeyBinded && lPath==='/'&& + lFileTable.indexOf('
  • ')<0){ + lFileTable=lFileTable.replace('
  • ','
  • '); + } + + + + return lFileTable; +} + +/* + * Если мы на стороне сервера - + * прописываем экспортируемые функции + */ +try{ + if(exports){ + /* экспортируемые функции */ + exports.checkExtension = CloudFunc.checkExtension; + exports.buildFromJSON = CloudFunc.buildFromJSON; + exports.replaceSpaces = CloudFunc.replaceSpaces; + exports.setTitle = CloudFunc.setTitle; + exports.convertPermissions = CloudFunc.convertPermissions; + exports.getUserUIDsAndNames = CloudFunc.getUserUIDsAndNames; + + /* константы*/ + exports.Name = CloudFunc.NAME; + exports.NOJS = CloudFunc.NOJS; + exports.FS =CloudFunc.FS; + + console.log('cloudfunc.js loaded...'); + } +}catch(err){ + /* если мы на клиенте */ +} \ No newline at end of file diff --git a/lib/minify.js b/lib/minify.js new file mode 100644 index 00000000..550d2232 --- /dev/null +++ b/lib/minify.js @@ -0,0 +1,240 @@ +/* Модуль сжатия js-скриптов и css*/ + +/* функция сжимает js-скрипты + * и сохраняет их с именем .min.js + */ + +var fs = require('fs'); + +exports.jsScripts=function jsScripts(){ + 'use strict'; + + /* подключаем модуль uglify-js + * если его нет - дальнейшая + * работа функции не имеет смысла + */ + try{ + var jsp = require("uglify-js").parser; + var pro = require("uglify-js").uglify; + }catch(error){ + 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'); + return false; + } + /* Константы */ + var CLIENT_JS='client.js'; + var CLOUDFUNC_JS='lib/cloudfunc.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,dataReaded_f)); + + return true; +}; + +/* функция сжимает css-стили + * и сохраняет их с именем .min.css + */ +exports.cssStyles=function cssStyles(){ + 'use strict'; + + /* connecting cleanCSS, + * if we can't find it - + * return false + */ + var cleanCSS; + try{ + cleanCSS = require('clean-css'); + }catch(error){ + 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'); + return false; + } + + /* Константы */ + 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 && lResetCssDone)? + 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)); + + return true; +}; + +/* функция сжимает 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)); + + return true; +}; + + + +/* Функция создаёт асинхроную версию + * для чтения файла + * @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...')); + }; +}