diff --git a/ChangeLog b/ChangeLog index b9ef49ae..75387793 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,10 +1,71 @@ -2013.02.13, v0.8.1 +2014.03.03, v0.8.2 + +fix: +- (style) .loading: spinner size +- (server) createRedirect: add sslPort +- (server) http -> procol +- (server) start: http -> HTTP +- (dom) promptDeleteSelected: pCurrentFile -> current +- (rest) onDelete: func(null, body) -> func +- (rest) onStat: add var +- (cloudcmd) change index path +- (server) start: url -> URL +- (server) start: SSLPort -> sslPort +- (server) start: Port -> port +- (dom) getCurrentDirPath: "," -> ";" +- (dom) renameCurrent: rm dir listing from Storage +- (client) loadDir: do not change dir after fail load +- (cloudcmd) route: add name +- (style) .files height: 95% -> 85% +- (dom) setCurrent: set id of li to +- (client) ajaxLoad: do not save path to history if content not load +- (path) #js-path -> .js-path: 2 pathes on a page + +feature: +- (package) rm pty.js +- (view) rm spinner from doBefore, add to view +- (package) add pty.js +- (package) minify: v0.2.5 -> 0.2.6 +- (client) initModules doBefore: add filepicker +- (menu) DOM.Images -> Images, "From Cloud" -> "From FilePicker" +- (index) change favicon +- (favicon) add +- (ext) .ico: vnd.microsoft.icon -> x-icon +- (index) hide .path-icon when no js +- (style) .loading top: 1px -> 2px +- (storage) get: ret -> this +- (favicon) optimize img +- (cloudcmd) optimize image +- (deleteSelected) rm param notSet +- (fs) add fs folder +- (style) height < 800px: .fm height: 74% +- (style) set bigger font for width < 600px +- (style)if height < 800px: .fm height 85% +- (css) html: change height +- (style) show only part of name is to long +- (index) add style for no js: hide keys, show one panel +- (style) .cmd-button: height: 30px +- (polyfill) rm localStorage +- (refactor) .js-left -> [data=js-left] +- (rest) add onFSPut +- (style) change .fm height to 75% on small screen heights +- (style) change name color on small screens +- (style) rm duplicate .fm-header +- (edit) add save on F2 +- (storage) change to async +- (storage) add +- (dom) add storage +- (listeners) change touchend +- (key) setCurrentByLatter: add numbers + + +2014.02.13, v0.8.1 fix: - (commander) changeUIDToName: doesn't work on win -2013.02.13, v0.8.0 +2014.02.13, v0.8.0 fix: - (test) template diff --git a/HELP.md b/HELP.md index 65a997f8..485150d6 100644 --- a/HELP.md +++ b/HELP.md @@ -1,15 +1,17 @@ -Cloud Commander v0.8.1 [![NPM version][NPMIMGURL]][NPMURL] [![Dependency Status][DependencyStatusIMGURL]][DependencyStatusURL] [![Build Status][BuildStatusIMGURL]][BuildStatusURL] +Cloud Commander v0.8.2 [![NPM version][NPMIMGURL]][NPMURL] [![Dependency Status][DependencyStatusIMGURL]][DependencyStatusURL] [![Build Status][BuildStatusIMGURL]][BuildStatusURL] [![License][LicenseIMGURL]][LicenseURL] [![Flattr][FlattrIMGURL]][FlattrURL] =============== ###[Main][MainURL] [Blog][BlogURL] Live(![IO][IO_LIVE_IMG] [IO][IOURL], ![JitSu][JitSu_LIVE_IMG] [JitSu][JitSuURL], ![Heroku][Heroku_LIVE_IMG] [Heroku][HerokuURL]) -[NPMIMGURL]: https://badge.fury.io/js/cloudcmd.png -[BuildStatusIMGURL]: https://secure.travis-ci.org/coderaiser/cloudcmd.png?branch=master +[NPMIMGURL]: https://img.shields.io/npm/v/cloudcmd.svg +[BuildStatusIMGURL]: https://api.travis-ci.org/coderaiser/cloudcmd.png?branch=dev [DependencyStatusIMGURL]: https://gemnasium.com/coderaiser/cloudcmd.png -[FlattrIMGURL]: https://api.flattr.com/button/flattr-badge-large.png -[NPM_INFO_IMG]: https://nodei.co/npm/cloudcmd.png +[FlattrIMGURL]: https://img.shields.io/badge/flattr-donate-317BF9.svg +[LicenseIMGURL]: https://img.shields.io/badge/license-MIT-317BF9.svg +[NPM_INFO_IMG]: http://nodei.co/npm/cloudcmd.png [NPMURL]: https://npmjs.org/package/cloudcmd "npm" -[BuildStatusURL]: http://travis-ci.org/coderaiser/cloudcmd "Build Status" +[BuildStatusURL]: https://travis-ci.org/coderaiser/cloudcmd "Build Status" [DependencyStatusURL]: https://gemnasium.com/coderaiser/cloudcmd "Dependency Status" [FlattrURL]: https://flattr.com/submit/auto?user_id=coderaiser&url=github.com/coderaiser/cloudcmd&title=cloudcmd&language=&tags=github&category=software "flattr" +[LicenseURL]: https://tldrlegal.com/license/mit-license "MIT License" [MainURL]: http://cloudcmd.io "Main" [BlogURL]: http://blog.cloudcmd.io "Blog" [IOURL]: http://io.cloudcmd.io "IO" @@ -19,53 +21,32 @@ Cloud Commander v0.8.1 [![NPM version][NPMIMGURL]][NPMURL] [![Dependency Status] [JitSu_LIVE_IMG]: http://status-ok.cloudcmd.io/host/cloudcmd.jit.su/fs?json "JitSu" [HEROKU_LIVE_IMG]: http://status-ok.cloudcmd.io/host/cloudcmd.herokuapp.com/fs?json "Heroku" -**Cloud Commander** - cloud file manager with console and editor. +**Cloud Commander** - cloud file manager with console and editor. Will help you: **create**, **edit**, **move** and **delete files** and **folders** in your favorite browser from any computer. File manager has two parts: +- **client** (with nice and simple interface) +- **server** (based on Node.js). ![Cloud Commander](/img/logo/cloudcmd.png "Cloud Commander") -[![Flattr][FlattrIMGURL]][FlattrURL] - Benefits --------------- -- Open Source. +- Open Source (**MIT License**). - Has 2 classic ortodox panels. - Works on Windows, Linux and Mac OS. - Could be used local or remotly. - Has nice console and editor. - Wrote on JavaScript/Node.js. +- Works in browser. Install --------------- -[![NPM_INFO][NPM_INFO_IMG]][NPMURL] -Installing **Cloud Commander** is very simple. -All you need is +The installation of file manager is very simple. -- install [node.js](http://nodejs.org/ "node.js") -- [download](https://github.com/coderaiser/cloudcmd/archive/master.zip) -and unpack or just clone repository from github: +- install [node.js](http://nodejs.org/ "node.js") if you still have not. +- install ```cloudcmd``` via ```npm``` with one simple command. -``` -git clone git://github.com/coderaiser/cloudcmd.git -cd cloudcmd -npm install -node cloudcmd -``` -or install in npm: - -``` -npm install cloudcmd -g -cloudcmd -``` - -Additional modules ---------------- -**Cloud Commander** could work without any modules installed. -But for console, minification, file system operations etc, recommended -install additional modules with next commnad (type in **Cloud Commander**'s directory): - - npm install +![NPM_INFO][NPM_INFO_IMG] Hot keys --------------- @@ -77,7 +58,7 @@ Hot keys - **F5** - copy - **F6** - rename/move - **F7** - new dir -- **F7** + **shift** = new file +- **F7** + **shift** - new file - **F8, Delete** - remove current file - **F9** - menu - **F10** - config @@ -97,7 +78,8 @@ Hot keys - **Home** - to begin of list - **End** - to end of list - **Shift + Delete** - remove without prompt -- **Insert** - select current file +- **Space** - select current file (and show size of directory) +- **Insert** - select current file (and move to next) - **Shift + F10** - context menu - **~** - console - **Ctrl + Click** - open file on new tab @@ -340,6 +322,7 @@ Additional modules list To extend capabilities of file manager next modules used: - [Ace] [AceURL] +- [Minify] [MinifyURL] - [FancyBox] [FancyBoxURL] - [jQuery-contextMenu] [jQuery-contextMenuURL] - [jq-console] [jq-consoleURL] @@ -351,6 +334,7 @@ To extend capabilities of file manager next modules used: - [fs-extra] [fs-extraURL] [AceURL]: http://ace.ajax.org/ "Ace" +[MinifyURL]: http://coderaiser.github.io/minify "Minify" [FancyBoxURL]: //github.com/fancyapps/fancyBox "FancyBox" [jQuery-contextMenuURL]: //github.com/medialize/jQuery-contextMenu "jQuery-contextMenu" [jq-consoleURL]: //github.com/replit/jq-console "jq-console" @@ -379,6 +363,7 @@ so to get it you should type a couple more commands: Version history --------------- +- *2014.03.03*, **[v0.8.2](//github.com/cloudcmd/archive/raw/master/cloudcmd-v0.8.2.zip)** - *2014.02.13*, **[v0.8.1](//github.com/cloudcmd/archive/raw/master/cloudcmd-v0.8.1.zip)** - *2014.02.13*, **[v0.8.0](//github.com/cloudcmd/archive/raw/master/cloudcmd-v0.8.0.zip)** - *2013.12.09*, **[v0.7.0](//github.com/cloudcmd/archive/raw/master/cloudcmd-v0.7.0.zip)** @@ -398,10 +383,6 @@ Version history - *2012.07.11*, **[v0.1.1](//github.com/cloudcmd/archive/raw/master/cloudcmd-v0.1.1.zip)** - *2012.07.09*, **[v0.1.0](//github.com/cloudcmd/archive/raw/master/cloudcmd-v0.1.0.zip)** -License ---------------- -MIT [license](LICENSE "license"). - Special Thanks --------------- diff --git a/README.md b/README.md index f80dde0f..75660e5b 100644 --- a/README.md +++ b/README.md @@ -1,15 +1,17 @@ -Cloud Commander v0.8.1 [![NPM version][NPMIMGURL]][NPMURL] [![Dependency Status][DependencyStatusIMGURL]][DependencyStatusURL] [![Build Status][BuildStatusIMGURL]][BuildStatusURL] +Cloud Commander v0.8.2 [![NPM version][NPMIMGURL]][NPMURL] [![Dependency Status][DependencyStatusIMGURL]][DependencyStatusURL] [![Build Status][BuildStatusIMGURL]][BuildStatusURL] [![License][LicenseIMGURL]][LicenseURL] [![Flattr][FlattrIMGURL]][FlattrURL] =============== ###[Main][MainURL] [Blog][BlogURL] Live(![IO][IO_LIVE_IMG] [IO][IOURL], ![JitSu][JitSu_LIVE_IMG] [JitSu][JitSuURL], ![Heroku][Heroku_LIVE_IMG] [Heroku][HerokuURL]) -[NPMIMGURL]: https://badge.fury.io/js/cloudcmd.png -[BuildStatusIMGURL]: https://secure.travis-ci.org/coderaiser/cloudcmd.png?branch=master +[NPMIMGURL]: https://img.shields.io/npm/v/cloudcmd.svg +[BuildStatusIMGURL]: https://api.travis-ci.org/coderaiser/cloudcmd.png?branch=dev [DependencyStatusIMGURL]: https://gemnasium.com/coderaiser/cloudcmd.png -[FlattrIMGURL]: http://api.flattr.com/button/flattr-badge-large.png -[NPM_INFO_IMG]: https://nodei.co/npm/cloudcmd.png?downloads=true&&stars +[FlattrIMGURL]: https://img.shields.io/badge/flattr-donate-317BF9.svg +[LicenseIMGURL]: https://img.shields.io/badge/license-MIT-317BF9.svg +[NPM_INFO_IMG]: https://nodei.co/npm/cloudcmd.png [NPMURL]: https://npmjs.org/package/cloudcmd "npm" -[BuildStatusURL]: http://travis-ci.org/coderaiser/cloudcmd "Build Status" +[BuildStatusURL]: https://travis-ci.org/coderaiser/cloudcmd "Build Status" [DependencyStatusURL]: https://gemnasium.com/coderaiser/cloudcmd "Dependency Status" [FlattrURL]: https://flattr.com/submit/auto?user_id=coderaiser&url=github.com/coderaiser/cloudcmd&title=cloudcmd&language=&tags=github&category=software "flattr" +[LicenseURL]: https://tldrlegal.com/license/mit-license "MIT License" [MainURL]: http://cloudcmd.io "Main" [BlogURL]: http://blog.cloudcmd.io "Blog" [IOURL]: http://io.cloudcmd.io "IO" @@ -21,6 +23,4 @@ Cloud Commander v0.8.1 [![NPM version][NPMIMGURL]][NPMURL] [![Dependency Status] **Cloud Commander** - cloud file manager with console and editor. -![Cloud Commander](/img/logo/cloudcmd.png "Cloud Commander") - -[![Flattr][FlattrIMGURL]][FlattrURL] +![Cloud Commander](http://cloudcmd.io/img/logo/cloudcmd.png "Cloud Commander") diff --git a/cloudcmd.js b/cloudcmd.js index 15fc1fb3..cd2260fb 100644 --- a/cloudcmd.js +++ b/cloudcmd.js @@ -22,16 +22,17 @@ Minify = main.minify, Config = main.config, - INDEX_PATH = HTMLDIR + 'index.html', CONFIG_PATH = JSONDIR + 'config.json', - KEY = DIR + 'ssl/ssl.key', + KEY = DIR + 'ssl/ssl.key', CERT = DIR + 'ssl/ssl.crt', - FILE_TMPL = HTMLDIR + 'file.html', - PANEL_TMPL = HTMLDIR + 'panel.html', - PATH_TMPL = HTMLDIR + 'path.html', - LINK_TMPL = HTMLDIR + 'link.html', + HTML_FS_DIR = HTMLDIR + 'fs/', + INDEX_PATH = HTML_FS_DIR + 'index.html', + FILE_TMPL = HTML_FS_DIR + 'file.html', + PANEL_TMPL = HTML_FS_DIR + 'panel.html', + PATH_TMPL = HTML_FS_DIR + 'path.html', + LINK_TMPL = HTML_FS_DIR + 'link.html', FileTemplate, PanelTemplate, PathTemplate, LinkTemplate, @@ -83,29 +84,29 @@ }); return data; - } /** * init and process of appcache if it allowed in config */ function appCacheProcessing() { - var lFONT_REMOTE = '//themes.googleusercontent.com/static/fonts/droidsansmono/v4/ns-m2xQYezAtqh7ai59hJUYuTAAIFFn5GTWtryCmBQ4.woff', - lFONT_LOCAL = './font/DroidSansMono.woff', - lJQUERY_REMOTE = '//ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js', - lJQUERY_LOCAL = './lib/client/jquery.js', - lFiles = [{}, {}]; + var FONT_REMOTE = '//themes.googleusercontent.com/static/fonts/droidsansmono/v4/ns-m2xQYezAtqh7ai59hJUYuTAAIFFn5GTWtryCmBQ4.woff', + FONT_LOCAL = './font/DroidSansMono.woff', + JQUERY_REMOTE = '//ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js', + JQUERY_LOCAL = './lib/client/jquery.js', + files = [{}, {}]; - lFiles[0][lFONT_REMOTE] = lFONT_LOCAL; - lFiles[1][lJQUERY_REMOTE] = lJQUERY_LOCAL; + files[0][FONT_REMOTE] = FONT_LOCAL; + files[1][JQUERY_REMOTE] = JQUERY_LOCAL; - AppCache.addFiles(lFiles); + AppCache.addFiles(files); AppCache.createManifest(); } function init() { - var lServerDir, lArg, lParams, lFiles; + var serverDir, params, filesList, isContain, argvFirst, + argv = process.argv; if (update) update.get(); @@ -115,80 +116,80 @@ * (usually /) to it. * argv[1] - is always script name */ - lServerDir = path.dirname(process.argv[1]) + '/'; + serverDir = path.dirname(argv[1]) + '/'; - if (DIR !== lServerDir) { + if (DIR !== serverDir) { Util.log('current dir: ' + DIR); - process.chdir(lServerDir); + process.chdir(serverDir); } - Util.log('server dir: ' + lServerDir); + Util.log('server dir: ' + serverDir); /* if command line parameter testing resolved * setting config to testing, so server * not created, just init and * all logs writed to screen */ - lArg = process.argv; - lArg = lArg[lArg.length - 1]; + argvFirst = argv[argv.length - 1]; + isContain = Util.isContainStr(argvFirst, 'test'); - if ( lArg === 'test' || lArg === 'test\r') { - Util.log(process.argv); + if (isContain) { + Util.log(argv); Config.server = false; } if (Config.logs) { Util.log('log param setted up in config.json\n' + 'from now all logs will be writed to log.txt'); + writeLogsToFile(); } - lParams = { + params = { appcache : appCacheProcessing, rest : main.rest, route : route - }, + }; - lFiles = [FILE_TMPL, PANEL_TMPL, PATH_TMPL, LINK_TMPL]; + filesList = [FILE_TMPL, PANEL_TMPL, PATH_TMPL, LINK_TMPL]; if (Config.ssl) - lFiles.push(KEY, CERT); + filesList.push(KEY, CERT); - files.read(lFiles, 'utf-8', function(pErrors, pFiles) { - if (pErrors) - Util.log(pErrors); + files.read(filesList, 'utf-8', function(errors, files) { + if (errors) + Util.log(errors); else { - FileTemplate = pFiles[FILE_TMPL]; - PanelTemplate = pFiles[PANEL_TMPL]; - PathTemplate = pFiles[PATH_TMPL]; - LinkTemplate = pFiles[LINK_TMPL]; + FileTemplate = files[FILE_TMPL]; + PanelTemplate = files[PANEL_TMPL]; + PathTemplate = files[PATH_TMPL]; + LinkTemplate = files[LINK_TMPL]; if (Config.ssl) - lParams.ssl = { - key : pFiles[KEY], - cert : pFiles[CERT] + params.ssl = { + key : files[KEY], + cert : files[CERT] }; - server.start(lParams); + server.start(params); } }); } function readConfig(callback) { fs.readFile(CONFIG_PATH, 'utf8', function(error, data) { - var msg, status, readed; + var status, json, msg; if (error) - status = 'error'; + status = 'error'; else { - status = 'ok'; - readed = Util.parseJSON(data); - - main.config = Config = readed; + status = 'ok'; + json = Util.parseJSON(data); + main.config = Config = json; } - - msg = CloudFunc.formatMsg('read', 'config', status); - Util.log(msg); + msg = CloudFunc.formatMsg('read', 'config', status); + + Util.log(msg); Util.exec(callback); }); } @@ -197,7 +198,7 @@ * routing of server queries */ function route(request, response, callback) { - var ret, name, params, isAuth, isFS; + var ret, name, params, isAuth, isFS, query; if (request && response) { ret = true; @@ -216,9 +217,20 @@ params.name = main.HTMLDIR + name + '.html'; main.sendFile(params); - } else if (isFS) - sendContent(params); - else { + } else if (isFS) { + query = main.getQuery(params.request), + sendContent(name, query, function(name, error, data, isFile) { + if (error) + main.sendError(params, error); + else if (isFile) { + params.name = name; + main.sendFile(params); + } else { + params.name = name; + main.sendResponse(params, data, true); + } + }); + } else { ret = false; Util.exec(callback); } @@ -227,74 +239,59 @@ return ret; } - function sendContent(pParams) { - var p, lRet = main.checkParams(pParams); + function sendContent(name, query, callback) { + name = Util.removeStrOneTime(name, CloudFunc.FS) || main.SLASH; - if (lRet) { - p = pParams; - p.name = Util.removeStrOneTime(p.name, CloudFunc.FS) || main.SLASH; + fs.stat(name, function(error, stat) { + var func = Util.retExec(callback, name); - fs.stat(p.name, function(error, stat) { - if (error) - main.sendError(pParams, error); - else - if (stat.isDirectory()) - processContent(pParams); - else - main.sendFile(pParams); - }); - } - - return lRet; - } - - function processContent(params) { - var p = params, - ret = main.checkParams(params); - - if (ret) - main.commander.getDirContent(p.name, function(error, json) { - var query, isJSON; - - if (error) - main.sendError(params, error); + if (error) + func(error); + else + if (!stat.isDirectory()) + func(error, null, true); else { - query = main.getQuery(p.request); - isJSON = Util.isContainStr(query, 'json'); - - if (!isJSON) - readIndex(json, params); - else { - p.data = Util.stringifyJSON(json); - p.name +='.json'; - main.sendResponse(params, null, true); - } + processContent(name, query, callback); } - }); + }); } - function readIndex(pJSON, params) { - var p = params; - + function processContent(name, query, callback) { + main.commander.getDirContent(name, function(error, json) { + var data, name, + isJSON = Util.isContainStr(query, 'json'); + + if (!isJSON && !error) + readIndex(json, Util.retExec(callback, INDEX_PATH)); + else { + if (!error) { + data = Util.stringifyJSON(json); + name +='.json'; + } + + Util.exec(callback, name, error, data); + } + }); + } + + function readIndex(json, callback) { Util.ifExec(!Minify, function(params) { var name = params && params.name; fs.readFile(name || INDEX_PATH, 'utf8', function(error, template) { - var panel, + var panel, data, config = main.config, minify = config.minify; - if (error) - main.sendError(p, error); - else { - p.name = INDEX_PATH, - panel = CloudFunc.buildFromJSON(pJSON, FileTemplate, PathTemplate, LinkTemplate), - - main.sendResponse(p, indexProcessing({ + if (!error) { + panel = CloudFunc.buildFromJSON(json, FileTemplate, PathTemplate, LinkTemplate), + data = indexProcessing({ panel : panel, data : template, - }), true); + }); } + + Util.exec(callback, error, data); }); }, function(callback) { Minify.optimize(INDEX_PATH, { diff --git a/css/style.css b/css/style.css index 360049e1..70296b12 100644 --- a/css/style.css +++ b/css/style.css @@ -22,11 +22,12 @@ } html { - height: 100%; + height: 94%; } body { height: 95%; + width: 100%; font:16px "Droid Sans Mono"; background-color:white; } @@ -85,12 +86,13 @@ body { } .loading { - position : relative; - top : 1px; - display : inline-block; - width : 15px; - height : 14.8px; - background : url(/img/spinner.gif); + position : relative; + top : 2px; + display : inline-block; + width : 16px; + height : 16px; + background : url(/img/spinner.gif); + vertical-align : top; } .refresh-icon { @@ -103,6 +105,7 @@ body { .cmd-button { width: 5%; + height: 30px; margin: 20px 2px 0 2px; color: #222; background-color: white; @@ -164,7 +167,8 @@ body { } .fm { height: 85%; - margin: 26px 26px 0 26px; + width: 97%; + margin: 26px auto 0 auto; } .fm-header { font-weight: bold; @@ -188,9 +192,8 @@ body { } .panel { width: 46%; - height: 90%; - padding: 20px; - margin: 0; + height: 97%; + padding: 1%; border: 1.5px solid; border-color: rgb(49, 123, 249); border-color: rgba(49, 123, 249, .40); @@ -264,7 +267,22 @@ a:hover, a:active { * друг-под-другом */ /* responsive design */ + +@media only screen and (max-height: 800px) { + .fm { + height: 74%; + } + + .files { + height: 85%; + } + +} + @media only screen and (max-width: 600px) { + .panel { + font-size: 26px; + } /* текущий файл под курсором */ .current-file { background-color: rgb(49, 123, 249); @@ -272,25 +290,18 @@ a:hover, a:active { color:white; } /* делаем иконки под курсом белыми*/ - .current-file > .mini-icon{ + .current-file a { color:white; } - .current-file > .text-file::before { + .current-file .text-file::before { color:white; } - .fm-header { - display:none; - } - /* меняем иконки на шрифтовые*/ .mini-icon { color : rgb(246, 224, 124); color : rgba(246, 224, 124, 0.56); font : 16px 'Fontello'; - width : 6%; - margin-left : 10px; - float : left; background-image: none; } @@ -300,8 +311,8 @@ a:hover, a:active { .name { float: none; - width: 100%; - font-size: 18px; + width: 90%; + display: inline-block; } .directory::before { @@ -315,9 +326,9 @@ a:hover, a:active { .text-file { background-image:none; } - + /* убираем заголовок*/ - .fm_header { + .fm-header { display:none; } @@ -341,7 +352,7 @@ a:hover, a:active { @media only screen and (max-width: 1155px) { .panel { - width:94%; + width:97%; } /* если правая панель не помещаеться - прячем её */ .panel-right, .cmd-button#f5, .cmd-button#f6 { diff --git a/favicon.ico b/favicon.ico new file mode 100644 index 00000000..a283c7ee Binary files /dev/null and b/favicon.ico differ diff --git a/html/file.html b/html/fs/file.html similarity index 100% rename from html/file.html rename to html/fs/file.html diff --git a/html/index.html b/html/fs/index.html similarity index 68% rename from html/index.html rename to html/fs/index.html index 9455e5d7..48034731 100644 --- a/html/index.html +++ b/html/fs/index.html @@ -7,27 +7,55 @@ - + {{ title }} + +
{{ fm }}
- - - - - - - - - - - - + + + + + + + + + + + +