From 09226499885e7808ef4eb25b5a4b8f612bb929fa Mon Sep 17 00:00:00 2001 From: coderaiser Date: Mon, 15 Apr 2019 12:04:41 +0300 Subject: [PATCH 0001/1728] fix(heroku) app: add "}" (#236) --- app.json | 1 + 1 file changed, 1 insertion(+) diff --git a/app.json b/app.json index 9072f44d..dbcdfac7 100644 --- a/app.json +++ b/app.json @@ -163,3 +163,4 @@ "required": false } } +} From 768d4bbab8bd148dd736f9d10697db15ca66cf26 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Mon, 15 Apr 2019 12:11:38 +0300 Subject: [PATCH 0002/1728] feature(package) stylelint v10.0.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e985efd9..a0caf097 100644 --- a/package.json +++ b/package.json @@ -190,7 +190,7 @@ "serviceworker-webpack-plugin": "^1.0.1", "smalltalk": "^3.3.0", "style-loader": "^0.23.0", - "stylelint": "^9.0.0", + "stylelint": "^10.0.0", "stylelint-config-standard": "^18.0.0", "supermenu": "^2.1.2", "supertape": "^1.0.3", From 372395575c38b67e97473dc616ab09c58b53f2ce Mon Sep 17 00:00:00 2001 From: coderaiser Date: Mon, 15 Apr 2019 15:10:20 +0300 Subject: [PATCH 0003/1728] feature(edit-names) add bulk rename (#231) --- HELP.md | 2 +- client/modules/edit-names.js | 22 ++++++++++++++++++---- package.json | 1 + 3 files changed, 20 insertions(+), 5 deletions(-) diff --git a/HELP.md b/HELP.md index dbb652cc..825414ff 100644 --- a/HELP.md +++ b/HELP.md @@ -188,7 +188,7 @@ Hot keys | `Ctrl + R` | refresh | `Ctrl + D` | clear local storage | `Ctrl + A` | select all files in a panel -| `Ctrl + M` | rename selected files in editor +| `Ctrl + M` | [rename selected files](https://github.com/coderaiser/cloudcmd/releases/tag/v12.0.0) in editor | `Shift + Ctrl + M` | rename selected files in vim mode of editor | `Ctrl + U` | swap panels | `Ctrl + F3` | sort by name diff --git a/client/modules/edit-names.js b/client/modules/edit-names.js index 5a23ec6d..9f5d4ee3 100644 --- a/client/modules/edit-names.js +++ b/client/modules/edit-names.js @@ -7,6 +7,8 @@ CloudCmd.EditNames = exports; const currify = require('currify/legacy'); const exec = require('execon'); const supermenu = require('supermenu'); +const smalltalk = require('smalltalk'); +const multiRename = require('multi-rename'); const reject = Promise.reject.bind(Promise); @@ -66,10 +68,22 @@ function keyListener(event) { const ctrlMeta = ctrl || meta; const {Key} = CloudCmd; - if (!ctrlMeta || event.keyCode !== Key.S) - return; + if (ctrlMeta && event.keyCode === Key.S) + EditNames.hide(); - EditNames.hide(); + else if (ctrlMeta && event.keyCode === Key.P) + smalltalk + .prompt(TITLE, 'Apply pattern:', '[n][e]', {cancel: false}) + .then(applyPattern); + + event.preventDefault(); +} + +function applyPattern(pattern) { + const newNames = multiRename(pattern, getActiveNames()); + const editor = CloudCmd.Edit.getEditor(); + + editor.setValue(newNames.join('\n')); } function getActiveNames() { @@ -162,7 +176,7 @@ function setMenu(event) { const menuData = { 'Save Ctrl+S' : () => { - editor.save(); + applyNames(); EditNames.hide(); }, 'Go To Line Ctrl+G' : () => { diff --git a/package.json b/package.json index a0caf097..1b26867e 100644 --- a/package.json +++ b/package.json @@ -176,6 +176,7 @@ "mkdirp": "^0.5.1", "mock-require": "^3.0.1", "morgan": "^1.6.1", + "multi-rename": "^1.0.0", "nodemon": "^1.9.1", "nyc": "^13.0.1", "optimize-css-assets-webpack-plugin": "^5.0.0", From d94d448ee4503efa9ec60092480ffff61407ddba Mon Sep 17 00:00:00 2001 From: coderaiser Date: Mon, 15 Apr 2019 15:37:38 +0300 Subject: [PATCH 0004/1728] chore(package) v12.1.0 --- ChangeLog | 10 ++++++++++ HELP.md | 3 ++- README.md | 2 +- package.json | 2 +- 4 files changed, 14 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index 055a6db6..7e99e99a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2019.04.15, v12.1.0 + +fix: +- (heroku) app: add "}" (#236) + +feature: +- (edit-names) add bulk rename (#231) +- (package) stylelint v10.0.0 + + 2019.04.04, v12.0.2 fix: diff --git a/HELP.md b/HELP.md index 825414ff..5540f599 100644 --- a/HELP.md +++ b/HELP.md @@ -1,4 +1,4 @@ -# Cloud Commander v12.0.2 +# Cloud Commander v12.1.0 ### [Main][MainURL] [Blog][BlogURL] Live(![Heroku][Heroku_LIVE_IMG] [Heroku][HerokuURL], ![Now][NOW_LIVE_IMG] [Now][NowURL]) @@ -815,6 +815,7 @@ There are a lot of ways to be involved in `Cloud Commander` development: Version history --------------- +- *2019.04.15*, **[v12.1.0](//github.com/coderaiser/cloudcmd/releases/tag/v12.1.0)** - *2019.04.04*, **[v12.0.2](//github.com/coderaiser/cloudcmd/releases/tag/v12.0.2)** - *2019.04.04*, **[v12.0.1](//github.com/coderaiser/cloudcmd/releases/tag/v12.0.1)** - *2019.04.01*, **[v12.0.0](//github.com/coderaiser/cloudcmd/releases/tag/v12.0.0)** diff --git a/README.md b/README.md index d9bbfde4..f559b9c0 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Cloud Commander v12.0.2 [![Build Status][BuildStatusIMGURL]][BuildStatusURL] [![Now status][BuildAppveyorIMGURL]][BuildAppveyorURL] [![Codacy][CodacyIMG]][CodacyURL] [![Gitter][GitterIMGURL]][GitterURL] [![OpenCollective](https://opencollective.com/cloudcmd/backers/badge.svg)](#backers) [![OpenCollective](https://opencollective.com/cloudcmd/sponsors/badge.svg)](#sponsors) +# Cloud Commander v12.1.0 [![Build Status][BuildStatusIMGURL]][BuildStatusURL] [![Now status][BuildAppveyorIMGURL]][BuildAppveyorURL] [![Codacy][CodacyIMG]][CodacyURL] [![Gitter][GitterIMGURL]][GitterURL] [![OpenCollective](https://opencollective.com/cloudcmd/backers/badge.svg)](#backers) [![OpenCollective](https://opencollective.com/cloudcmd/sponsors/badge.svg)](#sponsors) ### [Main][MainURL] [Blog][BlogURL] Live([Heroku][HerokuURL], [Now][NowURL]) diff --git a/package.json b/package.json index 1b26867e..962d6e55 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "cloudcmd", - "version": "12.0.2", + "version": "12.1.0", "author": "coderaiser (https://github.com/coderaiser)", "description": "File manager for the web with console and editor", "homepage": "http://cloudcmd.io", From 1cfb58d92280877ea139aa210e3a0470f14eb9cd Mon Sep 17 00:00:00 2001 From: coderaiser Date: Wed, 17 Apr 2019 11:18:36 +0300 Subject: [PATCH 0005/1728] feature(package) nyc v14.0.0 --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 962d6e55..211a0c47 100644 --- a/package.json +++ b/package.json @@ -40,7 +40,7 @@ }, "nyc": { "exclude": [ - "**.*.spec.js", + "**/*.spec.js", "test" ] }, @@ -178,7 +178,7 @@ "morgan": "^1.6.1", "multi-rename": "^1.0.0", "nodemon": "^1.9.1", - "nyc": "^13.0.1", + "nyc": "^14.0.0", "optimize-css-assets-webpack-plugin": "^5.0.0", "philip": "^2.0.0", "place": "^1.1.4", From 2c6449b14d1f73cafdb51000c0c5163e40a6c915 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Wed, 24 Apr 2019 14:03:58 +0300 Subject: [PATCH 0006/1728] chore(travis) node: v12 --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index bd8ec269..e05069a7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,6 @@ language: node_js node_js: - - 11 + - 12 - 10 - 8 From 0e39ecaa7712ccac75b4c97c124f491ff469dd0b Mon Sep 17 00:00:00 2001 From: coderaiser Date: Wed, 24 Apr 2019 15:38:18 +0300 Subject: [PATCH 0007/1728] feature(package) putout v4.23.0 --- .putout.json | 6 +++--- package.json | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.putout.json b/.putout.json index 9a634682..598adc33 100644 --- a/.putout.json +++ b/.putout.json @@ -1,5 +1,8 @@ { "match": { + "server": { + "remove-process-exit": true + }, "server/(server|exit).js": { "remove-process-exit": false, "remove-console": false @@ -12,9 +15,6 @@ }, "test/common/cloudfunc.js": { "remove-console": false - }, - "server": { - "remove-process-exit": true } } } diff --git a/package.json b/package.json index 211a0c47..1be97fb5 100644 --- a/package.json +++ b/package.json @@ -182,7 +182,7 @@ "optimize-css-assets-webpack-plugin": "^5.0.0", "philip": "^2.0.0", "place": "^1.1.4", - "putout": "^4.0.0", + "putout": "^4.23.0", "readjson": "^1.1.3", "request": "^2.76.0", "rimraf": "^2.5.4", From d1af83e2587ddb62f879b5dac278f2c9fdb76ca9 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Tue, 30 Apr 2019 19:44:49 +0300 Subject: [PATCH 0008/1728] feature(cloudcmd) avoid service worker reoload scripts in dev mode --- .webpack/js.js | 5 +++-- client/cloudcmd.js | 5 +++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/.webpack/js.js b/.webpack/js.js index e2e7ba23..7fd45044 100644 --- a/.webpack/js.js +++ b/.webpack/js.js @@ -15,7 +15,8 @@ const dirModules = './client/modules'; const modules = './modules'; const {env} = process; -const isDev = env.NODE_ENV === 'development'; +const {NODE_ENV} = env; +const isDev = NODE_ENV === 'development'; const rootDir = join(__dirname, '..'); const dist = resolve(rootDir, 'dist'); @@ -50,7 +51,7 @@ const rules = clean([ const plugins = [ new EnvironmentPlugin({ - NODE_ENV: 'production', + NODE_ENV, }), new ServiceWorkerWebpackPlugin({ diff --git a/client/cloudcmd.js b/client/cloudcmd.js index 32d54c4b..49a81d50 100644 --- a/client/cloudcmd.js +++ b/client/cloudcmd.js @@ -9,6 +9,8 @@ const {promisify} = require('es6-promisify'); const wraptile = require('wraptile/legacy'); const load = require('load.js'); +const isDev = process.env.NODE_ENV === 'development'; + const { registerSW, listenSW, @@ -49,6 +51,9 @@ function getPrefix(prefix) { } const onUpdateFound = wraptile(async (config) => { + if (isDev) + return; + const {DOM} = window; const prefix = getPrefix(config.prefix); const js = promisify(load.js); From 9db56a7fd745df1a530db8e4e86a3c0596c11907 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Wed, 1 May 2019 13:02:06 +0300 Subject: [PATCH 0009/1728] test(terminal) node v12 support --- test/server/terminal.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/server/terminal.js b/test/server/terminal.js index de1b607d..e734c85b 100644 --- a/test/server/terminal.js +++ b/test/server/terminal.js @@ -69,7 +69,9 @@ test('cloudcmd: terminal: enabled: no string', (t) => { const msg = 'cloudcmd --terminal: Cannot find module \'hello\''; - t.ok(log.calledWith(msg), 'should call exit'); + const [arg] = log.args[0]; + + t.ok(arg.includes(msg), 'should call with msg'); t.end(); }); From 4ad101dca16a993bf9fe4cc0065e9312e3bf18e0 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Wed, 1 May 2019 18:20:14 +0300 Subject: [PATCH 0010/1728] feature(config) speed up load: series -> parallel --- client/modules/config.js | 36 +++++++++++++++--------------------- 1 file changed, 15 insertions(+), 21 deletions(-) diff --git a/client/modules/config.js b/client/modules/config.js index d5cd86e1..4579b198 100644 --- a/client/modules/config.js +++ b/client/modules/config.js @@ -5,7 +5,6 @@ require('../../css/config.css'); const rendy = require('rendy/legacy'); -const exec = require('execon'); const currify = require('currify/legacy'); const wraptile = require('wraptile/legacy'); const squad = require('squad/legacy'); @@ -43,7 +42,10 @@ const addChange = currify((fn, input) => { const Config = {}; -let Loading = true; +let Template; + +const getFile = promisify(Files.get); +const loadCSS = promisify(load.css); module.exports.init = async () => { if (!CloudCmd.config('configDialog')) @@ -51,10 +53,16 @@ module.exports.init = async () => { showLoad(); - await CloudCmd.View(); - await loadSocket(); + const {prefix} = CloudCmd; + + [Template] = await Promise.all([ + getFile('config-tmpl'), + loadSocket(), + loadCSS(prefix + '/dist/config.css'), + CloudCmd.View(), + ]); + initSocket(); - Loading = false; }; const { @@ -63,7 +71,6 @@ const { } = CloudCmd; let Element; -let Template; function getHost() { const { @@ -125,23 +132,10 @@ function show() { if (!CloudCmd.config('configDialog')) return; - const {prefix} = CloudCmd; - const funcs = [ - exec.with(Files.get, 'config-tmpl'), - exec.with(load.css, prefix + '/dist/config.css'), - ]; - - if (Loading) - return; - - showLoad(); - exec.parallel(funcs, fillTemplate); + fillTemplate(); } -function fillTemplate(error, template) { - if (!Template) - Template = template; - +function fillTemplate() { Files.get('config', (error, config) => { if (error) return alert('Could not load config!'); From 370182e3aab089980e5858c09f6af4152e915251 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Sat, 4 May 2019 19:49:50 +0300 Subject: [PATCH 0011/1728] feature(package) eslint-plugin-node v9.0.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 1be97fb5..42813383 100644 --- a/package.json +++ b/package.json @@ -157,7 +157,7 @@ "es6-promise": "^4.0.5", "es6-promisify": "^6.0.0", "eslint": "^5.0.0", - "eslint-plugin-node": "^8.0.0", + "eslint-plugin-node": "^9.0.1", "eslint-plugin-putout": "^1.0.1", "extract-text-webpack-plugin": "^4.0.0-alpha.0", "fast-async": "^7.0.6", From 632abeef8726489168fbf4eecaae8f9e0d71a1ae Mon Sep 17 00:00:00 2001 From: coderaiser Date: Sat, 4 May 2019 20:37:25 +0300 Subject: [PATCH 0012/1728] feature(package) eslint v6.0.0-alpha --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 42813383..c38e15fd 100644 --- a/package.json +++ b/package.json @@ -156,7 +156,7 @@ "emitify": "^3.0.2", "es6-promise": "^4.0.5", "es6-promisify": "^6.0.0", - "eslint": "^5.0.0", + "eslint": "^6.0.0-alpha", "eslint-plugin-node": "^9.0.1", "eslint-plugin-putout": "^1.0.1", "extract-text-webpack-plugin": "^4.0.0-alpha.0", From cde38e3bb04a77be0a0f104cc01c0b898a7f8997 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Sat, 4 May 2019 21:22:58 +0300 Subject: [PATCH 0013/1728] fix(cloudcmd) different title --- client/client.js | 2 +- client/dom/buffer.js | 4 +--- client/dom/dialog.js | 14 ++++++++------ client/dom/index.js | 11 +++++------ client/dom/rest.js | 2 +- client/dom/select-by-pattern.js | 3 +-- client/dom/upload-files.js | 4 +--- client/key/vim/index.js | 4 +--- client/modules/config.js | 7 +++---- client/modules/edit-file.js | 8 +++----- client/modules/edit-names.js | 11 ++++------- client/modules/konsole.js | 5 ++--- client/modules/markdown.js | 5 +---- client/modules/menu.js | 3 +-- client/modules/operation/index.js | 19 ++++++++----------- client/modules/operation/set-listeners.js | 12 ++++-------- client/modules/terminal.js | 6 ++---- 17 files changed, 47 insertions(+), 73 deletions(-) diff --git a/client/client.js b/client/client.js index eddcfa6a..8823df4f 100644 --- a/client/client.js +++ b/client/client.js @@ -430,7 +430,7 @@ function CloudCmdProto(DOM) { } = Info; if (error) - return Dialog.alert(TITLE, error.responseText); + return Dialog.alert(error.responseText); const {childNodes} = panel; let i = childNodes.length; diff --git a/client/dom/buffer.js b/client/dom/buffer.js index 989c8788..a844384f 100644 --- a/client/dom/buffer.js +++ b/client/dom/buffer.js @@ -15,8 +15,6 @@ function BufferProto() { const CLASS = 'cut-file'; const COPY = 'copy'; const CUT = 'cut'; - const TITLE = 'Buffer'; - const Buffer = { cut : callIfEnabled.bind(null, cut), copy : callIfEnabled.bind(null, copy), @@ -25,7 +23,7 @@ function BufferProto() { }; function showMessage(msg) { - DOM.Dialog.alert(TITLE, msg); + DOM.Dialog.alert(msg); } function getNames() { diff --git a/client/dom/dialog.js b/client/dom/dialog.js index c2c9bfcd..157e6923 100644 --- a/client/dom/dialog.js +++ b/client/dom/dialog.js @@ -5,15 +5,17 @@ const { alert, prompt, confirm, + progress, }= require('smalltalk'); -module.exports = { - alert, - prompt, - confirm, -}; +const title = 'Cloud Commander'; -module.exports.alert.noFiles = (title) => { +module.exports.alert = (...a) => alert(title, ...a); +module.exports.prompt = (...a) => prompt(title, ...a); +module.exports.confirm = (...a) => confirm(title, ...a); +module.exports.progress = (...a) => progress(title, ...a); + +module.exports.alert.noFiles = () => { return alert(title, 'No files selected!', { cancel: false, }); diff --git a/client/dom/index.js b/client/dom/index.js index 900b1313..e7623e09 100644 --- a/client/dom/index.js +++ b/client/dom/index.js @@ -44,7 +44,6 @@ function CmdProto() { const Cmd = this; const SELECTED_FILE = 'selected-file'; - const TITLE = 'Cloud Commander'; const TabPanel = { 'js-left' : null, 'js-right' : null, @@ -97,7 +96,7 @@ function CmdProto() { const name = getName(); const cancel = false; - Dialog.prompt(TITLE, msg, name, {cancel}).then((name) => { + Dialog.prompt(msg, name, {cancel}).then((name) => { if (!name) return; @@ -342,7 +341,7 @@ function CmdProto() { }; if (Info.name === '..') { - Dialog.alert.noFiles(TITLE); + Dialog.alert.noFiles(); return callback(Error('No files selected!')); } @@ -756,11 +755,11 @@ function CmdProto() { const from = DOM.getCurrentName(current); if (from === '..') - return Dialog.alert.noFiles(TITLE); + return Dialog.alert.noFiles(); const cancel = false; - Dialog.prompt(TITLE, 'Rename', from, {cancel}).then((to) => { + Dialog.prompt('Rename', from, {cancel}).then((to) => { const isExist = !!DOM.getCurrentByName(to); const dirPath = DOM.getCurrentDirPath(); @@ -872,7 +871,7 @@ function CmdProto() { path, }); - Dialog.prompt(TITLE, msg, path, {cancel}) + Dialog.prompt(msg, path, {cancel}) .then(setPath) .then(CloudCmd.loadDir); }, diff --git a/client/dom/rest.js b/client/dom/rest.js index 7281c2cd..f6acd1b9 100644 --- a/client/dom/rest.js +++ b/client/dom/rest.js @@ -206,7 +206,7 @@ function RESTful() { Images.show.error(encoded); setTimeout(() => { - DOM.Dialog.alert(CloudCmd.TITLE, encoded); + DOM.Dialog.alert(encoded); }, 100); p.callback(Error(text)); diff --git a/client/dom/select-by-pattern.js b/client/dom/select-by-pattern.js index 74871fab..32f7ab7d 100644 --- a/client/dom/select-by-pattern.js +++ b/client/dom/select-by-pattern.js @@ -3,7 +3,6 @@ /* global DOM */ let SelectType = '*.*'; -const TITLE = 'Cloud Commander'; const {getRegExp} = require('../../common/util'); @@ -12,7 +11,7 @@ module.exports = (msg, files) => { const cancel = false; const {Dialog} = DOM; - Dialog.prompt(TITLE, allMsg, SelectType, {cancel}).then((type) => { + Dialog.prompt(allMsg, SelectType, {cancel}).then((type) => { SelectType = type; const regExp = getRegExp(type); diff --git a/client/dom/upload-files.js b/client/dom/upload-files.js index 9faddeaf..0b313311 100644 --- a/client/dom/upload-files.js +++ b/client/dom/upload-files.js @@ -12,8 +12,6 @@ const {alert} = require('./dialog'); const {FS} = require('../../common/cloudfunc'); -const {TITLE} = CloudCmd; - const onEnd = wraptile(_onEnd); const loadFile = wraptile(_loadFile); @@ -71,6 +69,6 @@ function _loadFile(dir, n, file, callback) { } function showError({message}) { - alert(TITLE, message); + alert(message); } diff --git a/client/key/vim/index.js b/client/key/vim/index.js index d8ad6629..7e66d37b 100644 --- a/client/key/vim/index.js +++ b/client/key/vim/index.js @@ -15,8 +15,6 @@ const { findPrevious, } = require('./find'); -const TITLE = 'Cloud Commander'; - const stopVisual = () => { visual(false); }; @@ -117,7 +115,7 @@ module.exports = (key, event) => { if (key === '/') { event.preventDefault(); - Dialog.prompt(TITLE, 'Find', '', {cancel: false}) + Dialog.prompt('Find', '', {cancel: false}) .then(find); return end(); diff --git a/client/modules/config.js b/client/modules/config.js index 4579b198..b22905dd 100644 --- a/client/modules/config.js +++ b/client/modules/config.js @@ -22,7 +22,6 @@ const {Dialog, setTitle} = DOM; const Name = 'Config'; CloudCmd[Name] = module.exports; -const alert = currify(Dialog.alert, Name); const loadSocket = promisify(DOM.loadSocket); @@ -116,12 +115,12 @@ function initSocket() { Config.save = saveHttp; }); - socket.on('err', alert); + socket.on('err', Dialog.alert); } function authCheck(socket) { socket.emit('auth', config('username'), config('password')); - socket.on('reject', wraptile(alert, 'Wrong credentials!')); + socket.on('reject', wraptile(Dialog.alert, 'Wrong credentials!')); } Config.save = saveHttp; @@ -138,7 +137,7 @@ function show() { function fillTemplate() { Files.get('config', (error, config) => { if (error) - return alert('Could not load config!'); + return Dialog.alert('Could not load config!'); const { editor, diff --git a/client/modules/edit-file.js b/client/modules/edit-file.js index 05207fa8..a91f901c 100644 --- a/client/modules/edit-file.js +++ b/client/modules/edit-file.js @@ -19,10 +19,8 @@ const { const {config} = CloudCmd; let Menu; - -const TITLE = 'Edit'; - let MSG_CHANGED; + const isLoading = fullstore(); const ConfigView = { @@ -111,7 +109,7 @@ function setListeners(editor) { function authCheck(spawn) { spawn.emit('auth', config('username'), config('password')); spawn.on('reject', () => { - Dialog.alert(TITLE, 'Wrong credentials!'); + Dialog.alert('Wrong credentials!'); }); } @@ -190,7 +188,7 @@ function isChanged() { return; const cancel = false; - Dialog.confirm(TITLE, MSG_CHANGED, {cancel}) + Dialog.confirm(MSG_CHANGED, {cancel}) .then(() => { editor.save(); }); diff --git a/client/modules/edit-names.js b/client/modules/edit-names.js index 9f5d4ee3..117cb49d 100644 --- a/client/modules/edit-names.js +++ b/client/modules/edit-names.js @@ -7,7 +7,6 @@ CloudCmd.EditNames = exports; const currify = require('currify/legacy'); const exec = require('execon'); const supermenu = require('supermenu'); -const smalltalk = require('smalltalk'); const multiRename = require('multi-rename'); const reject = Promise.reject.bind(Promise); @@ -15,8 +14,6 @@ const reject = Promise.reject.bind(Promise); const Info = DOM.CurrentInfo; const {Dialog} = DOM; -const TITLE = 'Edit Names'; -const alert = currify(Dialog.alert, TITLE); const refresh = currify(_refresh); const rename = currify(_rename); @@ -46,7 +43,7 @@ module.exports.show = (options) => { }; if (Info.name === '..' && names.length === 1) - return Dialog.alert.noFiles(TITLE); + return Dialog.alert.noFiles(); DOM.Events.addKey(keyListener); @@ -72,8 +69,8 @@ function keyListener(event) { EditNames.hide(); else if (ctrlMeta && event.keyCode === Key.P) - smalltalk - .prompt(TITLE, 'Apply pattern:', '[n][e]', {cancel: false}) + Dialog + .prompt('Apply pattern:', '[n][e]', {cancel: false}) .then(applyPattern); event.preventDefault(); @@ -217,7 +214,7 @@ function isChanged() { if (!editor.isChanged()) return; - Dialog.confirm(TITLE, msg, {cancel: false}) + Dialog.confirm(msg, {cancel: false}) .then(applyNames); } diff --git a/client/modules/konsole.js b/client/modules/konsole.js index 2eed9988..0683ef09 100644 --- a/client/modules/konsole.js +++ b/client/modules/konsole.js @@ -28,7 +28,6 @@ const {config} = CloudCmd; const cd = currify((fn, dir) => fn(`cd ${rmLastSlash(dir)}`)); const Name = 'Konsole'; -const TITLE = 'Console'; let Element; let Loaded; @@ -119,7 +118,7 @@ function authCheck(konsole) { konsole.emit('auth', config('username'), config('password')); konsole.on('reject', () => { - Dialog.alert(TITLE, 'Wrong credentials!'); + Dialog.alert('Wrong credentials!'); }); } @@ -149,7 +148,7 @@ const load = async () => { Util.timeEnd(Name + ' load'); if (error) - return Dialog.alert(TITLE, error.message, { + return Dialog.alert(error.message, { cancel: false, }); }; diff --git a/client/modules/markdown.js b/client/modules/markdown.js index c83c95c9..a25539df 100644 --- a/client/modules/markdown.js +++ b/client/modules/markdown.js @@ -7,8 +7,6 @@ const tryToCatch = require('try-to-catch/legacy'); CloudCmd.Markdown = exports; -const TITLE = 'Cloud Commander'; - const createElement = require('@cloudcmd/create-element'); const Images = require('../dom/images'); @@ -44,12 +42,11 @@ async function show(name, options = {}) { Images.hide(); if (error) - return alert(TITLE, error.message, { + return alert(error.message, { cancel: false, }); const className = 'help'; - const div = createElement('div', { className, innerHTML, diff --git a/client/modules/menu.js b/client/modules/menu.js index 8731f51d..ef1c6b67 100644 --- a/client/modules/menu.js +++ b/client/modules/menu.js @@ -24,8 +24,7 @@ const { } = DOM; const Info = DOM.CurrentInfo; -const TITLE = 'Cloud Commander'; -const alertNoFiles = wrap(Dialog.alert.noFiles)(TITLE); +const alertNoFiles = Dialog.alert.noFiles; const uploadTo = wrap(_uploadTo); let MenuShowedName; diff --git a/client/modules/operation/index.js b/client/modules/operation/index.js index 0f02c7e5..451ccd25 100644 --- a/client/modules/operation/index.js +++ b/client/modules/operation/index.js @@ -23,10 +23,7 @@ const removeQuery = (a) => a.replace(/\?.*/, ''); const Name = 'Operation'; CloudCmd[Name] = exports; -const { - TITLE, - config, -} = CloudCmd; +const {config} = CloudCmd; const {Dialog, Images} = DOM; const initOperations = wraptile(_initOperations); const authCheck = wraptile(_authCheck); @@ -55,7 +52,7 @@ const noFilesCheck = () => { const is = Boolean(!length); if (is) - return Dialog.alert.noFiles(TITLE); + return Dialog.alert.noFiles(); return is; }; @@ -88,7 +85,7 @@ function _authCheck(spawn, ok) { const alertDialog = wraptile(Dialog.alert); spawn.on('accept', accept(spawn)); - spawn.on('reject', alertDialog (TITLE, 'Wrong credentials!')); + spawn.on('reject', alertDialog ('Wrong credentials!')); spawn.emit('auth', config('username'), config('password')); } @@ -298,7 +295,7 @@ function promptDelete() { const cancel = false; - Dialog.confirm(TITLE, msg, {cancel}).then(() => { + Dialog.confirm(msg, {cancel}).then(() => { deleteSilent(files); }); } @@ -400,7 +397,7 @@ function _processFiles(options, data) { const str = `"${ name }" already exist. Overwrite?`; const cancel = false; - Dialog.confirm(TITLE, str, {cancel}).then(go); + Dialog.confirm(str, {cancel}).then(go); function go() { showLoad(); @@ -457,7 +454,7 @@ function twopack(operation, type) { checkEmpty('operation', operation); if (!names.length) - return Dialog.alert.noFiles(TITLE); + return Dialog.alert.noFiles(); switch(operation) { case 'extract': @@ -512,7 +509,7 @@ function message(msg, to, names) { const cancel = false; - return Dialog.prompt(TITLE, msg, to, {cancel}); + return Dialog.prompt(msg, to, {cancel}); } function load(callback) { @@ -521,7 +518,7 @@ function load(callback) { loadJS(file, (error) => { if (error) { - Dialog.alert(TITLE, error.message); + Dialog.alert(error.message); return exec(callback); } diff --git a/client/modules/operation/set-listeners.js b/client/modules/operation/set-listeners.js index d5538c2a..fa5f7cf1 100644 --- a/client/modules/operation/set-listeners.js +++ b/client/modules/operation/set-listeners.js @@ -3,8 +3,6 @@ /* global DOM */ /* global CloudCmd */ -const smalltalk = require('smalltalk'); - const { Dialog, Images, @@ -12,7 +10,6 @@ const { const forEachKey = require('for-each-key/legacy'); const wraptile = require('wraptile/legacy'); -const {TITLE} = CloudCmd; const format = require('./format'); @@ -34,7 +31,7 @@ module.exports = (options) => (emitter) => { const msg = `${operation} aborted`; lastError = true; - Dialog.alert(TITLE, msg, { + Dialog.alert(msg, { noCancel: true, }); }); @@ -43,8 +40,7 @@ module.exports = (options) => (emitter) => { const on = emitter.on.bind(emitter); const message = format(operation, from, to); - - const progress = smalltalk.progress(TITLE, message); + const progress = Dialog.progress(message); progress.catch(onAbort({ emitter, @@ -70,11 +66,11 @@ module.exports = (options) => (emitter) => { if (noContinue) { listeners.end(error); - Dialog.alert(TITLE, error); + Dialog.alert(error); return; } - Dialog.confirm(TITLE, error + '\n Continue?') + Dialog.confirm(error + '\n Continue?') .then(() => { emitter.continue(); }, () => { diff --git a/client/modules/terminal.js b/client/modules/terminal.js index 81a5ca89..ddb7cd37 100644 --- a/client/modules/terminal.js +++ b/client/modules/terminal.js @@ -14,8 +14,6 @@ const Images = require('../dom/images'); const loadParallel = promisify(load.parallel); -const TITLE = 'Terminal'; - const {Dialog} = DOM; const { Key, @@ -38,7 +36,7 @@ const loadAll = async () => { if (e) { const src = e.target.src.replace(window.location.href, ''); - return Dialog.alert(TITLE, `file ${src} could not be loaded`); + return Dialog.alert(`file ${src} could not be loaded`); } Loaded = true; @@ -103,7 +101,7 @@ function authCheck(spawn) { spawn.emit('auth', config('username'), config('password')); spawn.on('reject', () => { - Dialog.alert(TITLE, 'Wrong credentials!'); + Dialog.alert('Wrong credentials!'); }); } From f6dcdb72ec8c98aaa52ca9e4b6730273b9252168 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Sat, 4 May 2019 21:26:09 +0300 Subject: [PATCH 0014/1728] fix(operation) set-listeners: alert: noCancel -> cancel --- client/modules/operation/set-listeners.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/modules/operation/set-listeners.js b/client/modules/operation/set-listeners.js index fa5f7cf1..2abdc586 100644 --- a/client/modules/operation/set-listeners.js +++ b/client/modules/operation/set-listeners.js @@ -32,7 +32,7 @@ module.exports = (options) => (emitter) => { lastError = true; Dialog.alert(msg, { - noCancel: true, + cancel: false, }); }); From 08764690300be7745bbc8d532d38b0f83a542e4e Mon Sep 17 00:00:00 2001 From: coderaiser Date: Sun, 5 May 2019 18:44:55 +0300 Subject: [PATCH 0015/1728] feature(package) smalltalk v3.4.0 --- client/modules/operation/set-listeners.js | 3 +++ package.json | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/client/modules/operation/set-listeners.js b/client/modules/operation/set-listeners.js index 2abdc586..f3414772 100644 --- a/client/modules/operation/set-listeners.js +++ b/client/modules/operation/set-listeners.js @@ -56,6 +56,7 @@ module.exports = (options) => (emitter) => { end: () => { Images.hide(); forEachKey(removeListener, listeners); + progress.remove(); if (lastError || done) callback(); @@ -67,6 +68,7 @@ module.exports = (options) => (emitter) => { if (noContinue) { listeners.end(error); Dialog.alert(error); + progress.remove(); return; } @@ -75,6 +77,7 @@ module.exports = (options) => (emitter) => { emitter.continue(); }, () => { emitter.abort(); + progress.remove(); }); }, }; diff --git a/package.json b/package.json index c38e15fd..3a01765f 100644 --- a/package.json +++ b/package.json @@ -189,7 +189,7 @@ "scroll-into-view-if-needed": "^2.2.5", "serve-once": "^1.5.0", "serviceworker-webpack-plugin": "^1.0.1", - "smalltalk": "^3.3.0", + "smalltalk": "^3.4.0", "style-loader": "^0.23.0", "stylelint": "^10.0.0", "stylelint-config-standard": "^18.0.0", From 57142324ed2a0ede53154c4d810dc72e77bf3d1e Mon Sep 17 00:00:00 2001 From: coderaiser Date: Mon, 6 May 2019 12:07:40 +0300 Subject: [PATCH 0016/1728] feature(package) dword v11.0.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 3a01765f..aaa74af4 100644 --- a/package.json +++ b/package.json @@ -97,7 +97,7 @@ "currify": "^3.0.0", "deepmerge": "^3.0.0", "deepword": "^6.0.0", - "dword": "^10.0.0", + "dword": "^11.0.0", "edward": "^10.0.0", "execon": "^1.2.0", "express": "^4.13.0", From c8bbc2400b7723e23ea04d576ac357062b690d48 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Mon, 6 May 2019 12:13:27 +0300 Subject: [PATCH 0017/1728] feature(npmignore) add fixture.json --- .npmignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.npmignore b/.npmignore index 82f3ebf0..3c2c59aa 100644 --- a/.npmignore +++ b/.npmignore @@ -1,6 +1,6 @@ .* *.spec.js -*.fixture.js +*.fixture.js* manifest.yml Dockerfile* docker-compose.yml From 1f97fd27a01a6113b66cbe3fa415811b2ebabc16 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Mon, 6 May 2019 13:25:29 +0300 Subject: [PATCH 0018/1728] feature(package) edward v11.0.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index aaa74af4..a5ee40f3 100644 --- a/package.json +++ b/package.json @@ -98,7 +98,7 @@ "deepmerge": "^3.0.0", "deepword": "^6.0.0", "dword": "^11.0.0", - "edward": "^10.0.0", + "edward": "^11.0.0", "execon": "^1.2.0", "express": "^4.13.0", "files-io": "^3.0.0", From f60af287d3a6b14ba783fa9e763961add4b0f4e2 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Tue, 7 May 2019 18:03:26 +0300 Subject: [PATCH 0019/1728] feature(package) clean-css-loader v2.0.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a5ee40f3..cc715043 100644 --- a/package.json +++ b/package.json @@ -148,7 +148,7 @@ "auto-globals": "^1.7.0", "babel-loader": "^8.0.0", "babel-plugin-macros": "^2.2.1", - "clean-css-loader": "^1.0.1", + "clean-css-loader": "^2.0.0", "codegen.macro": "^3.0.0", "coveralls": "^3.0.0", "css-loader": "^2.0.1", From eb4f7c0d7cba6df68807005d49b085b4edbf5e68 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Sun, 5 May 2019 17:40:05 +0300 Subject: [PATCH 0020/1728] feature(user-menu) add (#221) --- .cloudcmd.menu.js | 25 +++ .webpack/css.js | 3 +- .webpack/js.js | 5 +- .yaspellerrc | 5 +- HELP.md | 53 ++++++- bin/cloudcmd.js | 3 + client/dom/index.js | 46 +++--- client/key/index.js | 3 + client/listeners/index.js | 9 +- client/modules/operation/set-listeners.js | 1 - client/modules/terminal-run.js | 146 ++++++++++++++++++ client/modules/terminal.js | 14 +- client/modules/user-menu/get-user-menu.js | 20 +++ .../modules/user-menu/get-user-menu.spec.js | 29 ++++ client/modules/user-menu/index.js | 112 ++++++++++++++ css/icons.css | 5 + css/user-menu.css | 14 ++ font/fontello.eot | Bin 12648 -> 13012 bytes font/fontello.json | 6 + font/fontello.svg | 4 +- font/fontello.ttf | Bin 12480 -> 12844 bytes font/fontello.woff | Bin 7876 -> 8048 bytes font/fontello.woff2 | Bin 6572 -> 6704 bytes html/index.html | 1 + json/config.json | 3 +- json/help.json | 4 +- json/modules.json | 4 +- man/cloudcmd.1 | 2 + package.json | 1 + server/cloudcmd.js | 2 + server/route.js | 8 + server/route.spec.js | 1 + server/user-menu.js | 53 +++++++ server/user-menu.spec.js | 21 +++ 34 files changed, 562 insertions(+), 41 deletions(-) create mode 100644 .cloudcmd.menu.js create mode 100644 client/modules/terminal-run.js create mode 100644 client/modules/user-menu/get-user-menu.js create mode 100644 client/modules/user-menu/get-user-menu.spec.js create mode 100644 client/modules/user-menu/index.js create mode 100644 css/user-menu.css create mode 100644 server/user-menu.js create mode 100644 server/user-menu.spec.js diff --git a/.cloudcmd.menu.js b/.cloudcmd.menu.js new file mode 100644 index 00000000..010b6615 --- /dev/null +++ b/.cloudcmd.menu.js @@ -0,0 +1,25 @@ +'use strict'; + +module.exports = { + 'F2 - Rename file': async ({DOM}) => { + await DOM.renameCurrent(); + }, + 'D - Build Dev': async ({CloudCmd}) => { + await CloudCmd.TerminalRun.show({ + command: 'npm run build:client:dev', + autoClose: false, + closeMessage: 'Press any button to close Terminal', + }); + + CloudCmd.refresh(); + }, + 'P - Build Prod': async ({CloudCmd}) => { + await CloudCmd.TerminalRun.show({ + command: 'npm run build:client', + autoClose: true, + }); + + CloudCmd.refresh(); + }, +}; + diff --git a/.webpack/css.js b/.webpack/css.js index f28fa100..2338b53d 100644 --- a/.webpack/css.js +++ b/.webpack/css.js @@ -21,6 +21,7 @@ const cssNames = [ 'view', 'config', 'terminal', + 'user-menu', ...getCSSList('columns'), ]; @@ -35,7 +36,7 @@ const plugins = clean([ const rules = [{ test: /\.css$/, - exclude: /css\/(nojs|view|config|terminal|columns.*)\.css/, + exclude: /css\/(nojs|view|config|terminal|user-menu|columns.*)\.css/, use: extractMain.extract([ 'css-loader', ]), diff --git a/.webpack/js.js b/.webpack/js.js index 7fd45044..e156fbd1 100644 --- a/.webpack/js.js +++ b/.webpack/js.js @@ -32,7 +32,6 @@ const babelDev = { babelrc: false, plugins: [ 'module:babel-plugin-macros', - '@babel/plugin-proposal-object-rest-spread', ], }; @@ -43,7 +42,7 @@ const rules = clean([ loader: 'babel-loader', }, isDev && { - test: /sw\.js$/, + test: /\.js$/, exclude: /node_modules/, loader: 'babel-loader', options: babelDev, @@ -90,7 +89,9 @@ module.exports = { [modules + '/operation']: `${dirModules}/operation/index.js`, [modules + '/konsole']: `${dirModules}/konsole.js`, [modules + '/terminal']: `${dirModules}/terminal.js`, + [modules + '/terminal-run']: `${dirModules}/terminal-run.js`, [modules + '/cloud']: `${dirModules}/cloud.js`, + [modules + '/user-menu']: `${dirModules}/user-menu/index.js`, [modules + '/polyfill']: `${dirModules}/polyfill.js`, }, output: { diff --git a/.yaspellerrc b/.yaspellerrc index c6a7ec3b..ad0eddc1 100644 --- a/.yaspellerrc +++ b/.yaspellerrc @@ -10,6 +10,7 @@ ".md" ], "dictionary":[ + "CloudCmd", "Dev", "Dropbox", "Deepword", @@ -27,12 +28,14 @@ "Zalitok", "WebSocket", "auth", + "binded", "cd", "cloudcmd", "coderaiser", "com", - "dev", "deepword", + "dev", + "destructuring", "dropbox", "dword", "edward", diff --git a/HELP.md b/HELP.md index 5540f599..2ec743a8 100644 --- a/HELP.md +++ b/HELP.md @@ -109,6 +109,7 @@ Cloud Commander supports the following command-line parameters: | `--dropbox` | enable dropbox integration | `--dropbox-token` | set dropbox token | `--log` | enable logging +| `--user-menu` | enable user menu | `--no-show-config` | do not show config values | `--no-server` | do not start server | `--no-auth` | disable authorization @@ -137,6 +138,7 @@ Cloud Commander supports the following command-line parameters: | `--no-dropbox` | disable dropbox integration | `--no-dropbox-token` | unset dropbox token | `--no-log` | disable logging +| `--no-user-menu` | disable user menu For options not specified by command-line parameters, Cloud Commander then reads configuration data from `~/.cloudcmd.json`. It uses port `8000` by default. @@ -162,7 +164,7 @@ Hot keys |Key |Operation |:----------------------|:-------------------------------------------- | `F1` | help -| `F2` | rename +| `F2` | rename or show `user menu` | `F3` | view, change directory | `Shift + F3` | view as markdown | `F4` | edit @@ -421,7 +423,8 @@ Here's a description of all options: "importListen" : false, // listen on config updates "dropbox" : false, // disable dropbox integration "dropboxToken" : "", // unset dropbox token - "log" : true // logging + "log" : true, // logging + "userMenu" : false // do not show user menu } ``` @@ -458,6 +461,52 @@ Some config options can be overridden with environment variables, such as: - `CLOUDCMD_IMPORT_TOKEN` - authorization token used to connect to export server - `CLOUDCMD_IMPORT_URL` - url of an import server - `CLOUDCMD_IMPORT_LISTEN`- enable listen on config updates from import server +- `CLOUDCMD_USER_MENU`- enable `user menu` + +### User Menu + +You can enable `user menu` with help of a flag `--user-menu` (consider that file rename using `F2` will be disabled). +When you press `F2` Cloud Commander will a file `.cloudcmd.menu.js` by walking up parent directories, if can't read it will try to read `~/.cloudcmd.menu.js`. +Let's consider example `user menu` works file: + +```js +module.exports = { + 'F2 - Rename file': async ({DOM}) => { + await DOM.renameCurrent(); + }, + 'D - Build Dev': async ({CloudCmd}) => { + await CloudCmd.TerminalRun.show({ + command: 'npm run build:client:dev', + autoClose: false, + closeMessage: 'Press any button to close Terminal', + }); + + CloudCmd.refresh(); + }, + 'P - Build Prod': async ({CloudCmd}) => { + await CloudCmd.TerminalRun.show({ + command: 'npm run build:client', + autoClose: true, + }); + + CloudCmd.refresh(); + }, +}; +``` + +You will have ability to run one of this 3 commands with help of double click, enter, or binded key (`F2`, `D` or `P` in this example). Also you can run commands in terminal, or execute any built-in function of `Cloud Commander` extended it's interface. + +#### User Menu API + +Here you can find `API` that can be used in **User Menu**. **DOM** and **CloudCmd** to main objects you receive in arguments list using destructuring. + +**DOM** contains all base functions of `Cloud Commander` (rename, remove, download etc); + +- `renameCurrent` - shows renames current file dialog, and does renaming. + +**CloudCmd** contains all modules (`Terminal`, `View`, `Edit`, `Config`, `Console` etc); + +- `TerminalRun` - module that shows `Terminal` with a `command` from options and closes terminal when everything is done. ### Distribute diff --git a/bin/cloudcmd.js b/bin/cloudcmd.js index 95da4136..1e4e3ac5 100755 --- a/bin/cloudcmd.js +++ b/bin/cloudcmd.js @@ -73,6 +73,7 @@ const args = require('minimist')(argv.slice(2), { 'import-listen', 'log', 'dropbox', + 'user-menu', ], default: { server : true, @@ -111,6 +112,7 @@ const args = require('minimist')(argv.slice(2), { 'one-file-panel': choose(env.bool('one_file_panel'), config('oneFilePanel')), 'confirm-copy': choose(env.bool('confirm_copy'), config('confirmCopy')), 'confirm-move': choose(env.bool('confirm_move'), config('confirmMove')), + 'user-menu': choose(env.bool('user_menu'), config('userMenu')), 'keys-panel': env.bool('keys_panel') || config('keysPanel'), 'import-token': env('import_token') || config('importToken'), 'export-token': env('export_token') || config('exportToken'), @@ -180,6 +182,7 @@ function main() { config('importToken', args['import-token']); config('importListen', args['import-listen']); config('importUrl', args['import-url']); + config('userMenu', args['user-menu']); config('dropbox', args['dropbox']); config('dropboxToken', args['dropbox-token'] || ''); diff --git a/client/dom/index.js b/client/dom/index.js index e7623e09..271b563d 100644 --- a/client/dom/index.js +++ b/client/dom/index.js @@ -5,6 +5,8 @@ const itype = require('itype/legacy'); const exec = require('execon'); const jonny = require('jonny/legacy'); +const tryToCatch = require('try-to-catch/legacy'); + const Util = require('../../common/util'); const Images = require('./images'); @@ -746,7 +748,7 @@ function CmdProto() { * * @currentFile */ - this.renameCurrent = (current) => { + this.renameCurrent = async (current) => { const {Dialog} = DOM; if (!DOM.isCurrentFile(current)) @@ -757,30 +759,30 @@ function CmdProto() { if (from === '..') return Dialog.alert.noFiles(); - const cancel = false; + const [e, to] = await tryToCatch(Dialog.prompt, 'Rename', from); - Dialog.prompt('Rename', from, {cancel}).then((to) => { - const isExist = !!DOM.getCurrentByName(to); - const dirPath = DOM.getCurrentDirPath(); - - if (from === to) + if (e) + return; + const isExist = !!DOM.getCurrentByName(to); + const dirPath = DOM.getCurrentDirPath(); + + if (from === to) + return; + + const files = { + from : dirPath + from, + to : dirPath + to, + }; + + RESTful.mv(files, (error) => { + if (error) return; - const files = { - from : dirPath + from, - to : dirPath + to, - }; + DOM.setCurrentName(to, current); + Storage.remove(dirPath); - RESTful.mv(files, (error) => { - if (error) - return; - - DOM.setCurrentName(to, current); - Storage.remove(dirPath); - - if (isExist) - CloudCmd.refresh(); - }); + if (isExist) + CloudCmd.refresh(); }); }; @@ -940,7 +942,7 @@ function CmdProto() { const info = DOM.CurrentInfo; const current = currentFile || DOM.getCurrentFile(); const files = current.parentElement; - const panel = files.parentElement; + const panel = files.parentElement || DOM.getPanel(); const panelPassive = DOM.getPanel({ active: false, diff --git a/client/key/index.js b/client/key/index.js index 6cb11e4d..627400a4 100644 --- a/client/key/index.js +++ b/client/key/index.js @@ -186,6 +186,9 @@ function KeyProto() { break; case Key.F2: + if (CloudCmd.config('userMenu')) + return CloudCmd.UserMenu.show(); + DOM.renameCurrent(current); break; diff --git a/client/listeners/index.js b/client/listeners/index.js index ffc4d8c5..2f8c6771 100644 --- a/client/listeners/index.js +++ b/client/listeners/index.js @@ -123,7 +123,7 @@ module.exports.initKeysPanel = () => { const clickFuncs = { 'f1' : CloudCmd.Help.show, - 'f2' : DOM.renameCurrent, + 'f2' : initF2, 'f3' : CloudCmd.View.show, 'f4' : CloudCmd.EditFile.show, 'f5' : operation('copy'), @@ -141,6 +141,13 @@ module.exports.initKeysPanel = () => { }); }; +function initF2() { + if (CloudCmd.config('userMenu')) + return CloudCmd.UserMenu.show(); + + return DOM.renameCurrent(); +} + const getPanel = (side) => { if (!itype.string(side)) return side; diff --git a/client/modules/operation/set-listeners.js b/client/modules/operation/set-listeners.js index f3414772..71d7b64e 100644 --- a/client/modules/operation/set-listeners.js +++ b/client/modules/operation/set-listeners.js @@ -1,7 +1,6 @@ 'use strict'; /* global DOM */ -/* global CloudCmd */ const { Dialog, diff --git a/client/modules/terminal-run.js b/client/modules/terminal-run.js new file mode 100644 index 00000000..02ce4f28 --- /dev/null +++ b/client/modules/terminal-run.js @@ -0,0 +1,146 @@ +'use strict'; + +/* global CloudCmd, gritty */ + +const {promisify} = require('es6-promisify'); +const tryToCatch = require('try-to-catch/legacy'); + +require('../../css/terminal.css'); + +const exec = require('execon'); +const load = require('load.js'); +const DOM = require('../dom'); +const Images = require('../dom/images'); + +const loadParallel = promisify(load.parallel); + +const {Dialog} = DOM; +const { + Key, + config, +} = CloudCmd; + +CloudCmd.TerminalRun = exports; + +let Loaded; +let Terminal; +let Socket; + +const loadAll = async () => { + const {prefix} = CloudCmd; + + const prefixGritty = getPrefix(); + const js = `${prefixGritty}/gritty.js`; + const css = `${prefix}/dist/terminal.css`; + + const [e] = await tryToCatch(loadParallel, [js, css]); + + if (e) { + const src = e.target.src.replace(window.location.href, ''); + return Dialog.alert(`file ${src} could not be loaded`); + } + + Loaded = true; +}; + +module.exports.init = async () => { + if (!config('terminal')) + return; + + Images.show.load('top'); + + await CloudCmd.View(); + await loadAll(); +}; + +module.exports.show = show; +module.exports.hide = hide; + +function hide () { + CloudCmd.View.hide(); +} + +function getPrefix() { + return CloudCmd.prefix + '/gritty'; +} + +function getPrefixSocket() { + return CloudCmd.prefixSocket + '/gritty'; +} + +function getEnv() { + return { + ACTIVE_DIR: DOM.getCurrentDirPath, + PASSIVE_DIR: DOM.getNotCurrentDirPath, + CURRENT_NAME: DOM.getCurrentName, + CURRENT_PATH: DOM.getCurrentPath, + }; +} + +function create(createOptions) { + const { + command, + autoClose, + closeMessage = 'Press any key to close Terminal...', + } = createOptions; + + const options = { + env: getEnv(), + prefix: getPrefixSocket(), + socketPath: CloudCmd.prefix, + fontFamily: 'Droid Sans Mono', + command, + autoRestart: false, + }; + + let commandExit = false; + + const {socket, terminal} = gritty(document.body, options); + + Socket = socket; + Terminal = terminal; + + Terminal.on('key', (char, {keyCode, shiftKey}) => { + if (commandExit) + hide(); + + if (shiftKey && keyCode === Key.ESC) { + hide(); + } + }); + + Socket.on('exit', () => { + if (autoClose) + return hide(); + + terminal.write(`\n${closeMessage}`); + commandExit = true; + }); + + Socket.on('connect', exec.with(authCheck, socket)); +} + +function authCheck(spawn) { + spawn.emit('auth', config('username'), config('password')); + + spawn.on('reject', () => { + Dialog.alert('Wrong credentials!'); + }); +} + +async function show(options = {}) { + if (!Loaded) + return; + + if (!config('terminal')) + return; + + await create(options); + + CloudCmd.View.show(Terminal.element, { + afterShow: () => { + Terminal.focus(); + }, + }); +} + diff --git a/client/modules/terminal.js b/client/modules/terminal.js index ddb7cd37..ee33f4ae 100644 --- a/client/modules/terminal.js +++ b/client/modules/terminal.js @@ -24,6 +24,7 @@ CloudCmd.Terminal = exports; let Loaded; let Terminal; +let Socket; const loadAll = async () => { const {prefix} = CloudCmd; @@ -84,17 +85,19 @@ function create() { socketPath: CloudCmd.prefix, fontFamily: 'Droid Sans Mono', }; + const {socket, terminal} = gritty(document.body, options); + Socket = socket; Terminal = terminal; - terminal.on('key', (char, {keyCode, shiftKey}) => { + Terminal.on('key', (char, {keyCode, shiftKey}) => { if (shiftKey && keyCode === Key.ESC) { hide(); } }); - socket.on('connect', exec.with(authCheck, socket)); + Socket.on('connect', exec.with(authCheck, socket)); } function authCheck(spawn) { @@ -105,7 +108,7 @@ function authCheck(spawn) { }); } -function show(callback) { +function show() { if (!Loaded) return; @@ -114,10 +117,7 @@ function show(callback) { CloudCmd.View.show(Terminal.element, { afterShow: () => { - if (Terminal) - Terminal.focus(); - - exec(callback); + Terminal.focus(); }, }); } diff --git a/client/modules/user-menu/get-user-menu.js b/client/modules/user-menu/get-user-menu.js new file mode 100644 index 00000000..4b3d8923 --- /dev/null +++ b/client/modules/user-menu/get-user-menu.js @@ -0,0 +1,20 @@ +'use strict'; + +const defaultUserMenu = { + 'F2 - Rename file': async ({DOM}) => { + DOM.renameCurrent(); + }, +}; + +module.exports = (menuFn) => { + if (!menuFn) + return defaultUserMenu; + + const module = {}; + const fn = Function('module', menuFn); + + fn(module); + + return module.exports; +}; + diff --git a/client/modules/user-menu/get-user-menu.spec.js b/client/modules/user-menu/get-user-menu.spec.js new file mode 100644 index 00000000..77ee4fea --- /dev/null +++ b/client/modules/user-menu/get-user-menu.spec.js @@ -0,0 +1,29 @@ +'use strict'; + +const test = require('supertape'); +const getUserMenu = require('./get-user-menu'); + +test('user-menu: getUserMenu', (t) => { + const menu = `module.exports = { + 'F2 - Rename file': ({DOM}) => { + const {element} = DOM.CurrentInfo; + DOM.renameCurrent(element); + } + }`; + + const result = getUserMenu(menu); + + const [key] = Object.keys(result); + + t.equal(key, 'F2 - Rename file', 'should equal'); + t.end(); +}); + +test('user-menu: getUserMenu: no args', (t) => { + const result = getUserMenu(); + const [key] = Object.keys(result); + + t.equal(key, 'F2 - Rename file', 'should equal'); + t.end(); +}); + diff --git a/client/modules/user-menu/index.js b/client/modules/user-menu/index.js new file mode 100644 index 00000000..78e1f5dc --- /dev/null +++ b/client/modules/user-menu/index.js @@ -0,0 +1,112 @@ +'use strict'; + +/* global CloudCmd, DOM */ + +require('../../../css/user-menu.css'); + +const currify = require('currify/legacy'); +const {promisify} = require('es6-promisify'); +const load = require('load.js'); +const createElement = require('@cloudcmd/create-element'); + +const Images = require('../../dom/images'); +const getUserMenu = require('./get-user-menu'); + +const loadCSS = promisify(load.css); + +const Name = 'UserMenu'; +CloudCmd[Name] = module.exports; + +const {Key} = CloudCmd; + +module.exports.init = async () => { + await Promise.all([ + loadCSS(`${CloudCmd.prefix}/dist/user-menu.css`), + CloudCmd.View(), + ]); +}; + +module.exports.show = show; +module.exports.hide = hide; + +const getKey = (a) => a.split(' - ')[0]; +const beginWith = (a) => (b) => !b.indexOf(a); + +const {CurrentInfo} = DOM; + +async function show() { + Images.show.load('top'); + + const {dirPath} = CurrentInfo; + const res = await fetch(`/api/v1/user-menu?dir=${dirPath}`); + const userMenu = getUserMenu(await res.text()); + const options = Object.keys(userMenu); + + const el = createElement('select', { + className: 'cloudcmd-user-menu', + innerHTML: fillTemplate(options), + size: 10, + }); + + const keys = options.map(getKey); + el.addEventListener('keydown', onKeyDown(keys, options, userMenu)); + el.addEventListener('dblclick', onDblClick(options, userMenu)); + + const afterShow = () => el.focus(); + const autoSize = true; + + Images.hide(); + + CloudCmd.View.show(el, { + autoSize, + afterShow, + }); +} + +function fillTemplate(options) { + const result = []; + + for (const option of options) { + result.push(``); + } + + return result.join(''); +} + +function hide() { + CloudCmd.View.hide(); +} + +const onDblClick = currify(async (options, userMenu, e) => { + const {value} = e.target; + await runUserMenu(value, options, userMenu); +}); + +const onKeyDown = currify(async (keys, options, userMenu, e) => { + const {keyCode} = e; + const key = e.key.toUpperCase(); + + let value; + + if (keyCode === Key.ENTER) + ({value} = e.target); + else if (keys.includes(key)) + value = options.find(beginWith(key)); + else + return; + + e.preventDefault(); + e.stopPropagation(); + + await runUserMenu(value, options, userMenu); +}); + +const runUserMenu = async (value, options, userMenu) => { + hide(); + + await userMenu[value]({ + DOM, + CloudCmd, + }); +}; + diff --git a/css/icons.css b/css/icons.css index 4f979db7..253b3593 100644 --- a/css/icons.css +++ b/css/icons.css @@ -132,3 +132,8 @@ font-family : 'Fontello'; content : '\e81b '; } + +.icon-user-menu::before { + font-family : 'Fontello'; + content : '\e81c '; +} diff --git a/css/user-menu.css b/css/user-menu.css new file mode 100644 index 00000000..37f07c14 --- /dev/null +++ b/css/user-menu.css @@ -0,0 +1,14 @@ +.cloudcmd-user-menu { + font-size: 16px; + font-family: 'Droid Sans Mono', 'Ubuntu Mono', 'Consolas', monospace; + width: 400px; +} + +.cloudcmd-user-menu:focus { + outline: 0; +} + +.cloudcmd-user-menu > option:checked { + box-shadow: 20px -20px 0 2px rgba(49, 123, 249) inset; +} + diff --git a/font/fontello.eot b/font/fontello.eot index 4274ddd2908829e0efc110032eaaa475d96df979..c886783f811e722665b18fb0c993c2d45f84d749 100644 GIT binary patch delta 809 zcmZWlO-vI(6n<}ZyZt3K5w?lKGNpxvP-5h#1gV0F9Q=tQlB$qc3KmLeVPiL@UhKid z5al4*n^EN8!HbEphJ$+YDkPfJ#H$CAg_9Q}5}>|mt06j@owwi5`)2l86UC%b>;MRN zEGZFrd1Ay^8hDtG1KRxT#*+@M7b9a;0(?brc z-dtp7Z4IO-<~O!uerHav_&vb1*l9HswxnTnS@ptQ#!=hLBY6d&^h>fNH+Z2DjzK?M zf;dD6dfjMup(5FpaVJU+WGJz58`4=gLIvTPjCAsa8)LC67teQBSEt9;(AHd6tJnig zEurqNh_AClJxn-M#XW>k=>CeH_xUSC8&-%utl&`9&_lWi2vl*W@M~Os?bGnToqgo$ z-ey^0KA*PNbHMSBM$N*Rrz)(E(<aW<}8c`T>OnN#Uy4_SX)W(D9e2 z`Ot9bHAW_u`G~>5kRxR{}sQ q>~JSyuPHaJVsGJH(>Wxo5ei0Fuh7H zD^Xy(`k#q`K?TTXP)I9C&+VExArike*mv02CJh@)rPUj`W<$G_EXmM+OF# zDGUr!t1?m(Q-sck0QJf{0OidxfC3!zSuOzi6+pg9Ms7((wprN!mq39zK!K8+{N%)h zt~4ND0ca?LO>SaE0iz3#CXnv~{`2|SHbz_be7(F>d(VS6s@&d(@$r4J|?4e-0WjDtuaWXPmOwLf=#%Qrw aUd4+Ms3uF*YV$HxW=3FuZ{Db;%mV;&(rBFk diff --git a/font/fontello.json b/font/fontello.json index 61c8d00e..354b93cc 100644 --- a/font/fontello.json +++ b/font/fontello.json @@ -174,6 +174,12 @@ "code": 59413, "src": "entypo" }, + { + "uid": "f805bb95d40c7ef2bc51b3d50d4f2e5c", + "css": "th-list", + "code": 59420, + "src": "fontawesome" + }, { "uid": "60617c8adc1e7eb3c444a5491dd13f57", "css": "attention-circled-1", diff --git a/font/fontello.svg b/font/fontello.svg index afc5a844..ac6e533b 100644 --- a/font/fontello.svg +++ b/font/fontello.svg @@ -1,7 +1,7 @@ -Copyright (C) 2018 by original authors @ fontello.com +Copyright (C) 2019 by original authors @ fontello.com @@ -61,6 +61,8 @@ + + \ No newline at end of file diff --git a/font/fontello.ttf b/font/fontello.ttf index 1065b0d3a9035ab21a8d53fd0533384405dae35c..57d3d33173116cfd592e11de175917715a215633 100644 GIT binary patch delta 790 zcmZWl%}W$v7=NCb+1b@yQ&4B1bavL+Ttp?zFE%YJ=+FmcCR=H^PP*&L&a6WYVVCw0 zgoFoWJVa=D=+L1cn&=Q6qH78T1^odDtM_P&-0gYYEu`LI-e-Ov&+mQbd8*o3KD+kJQ55q<)|D$qjsIbk)Un~C++V2JPsy5NR2Gi#f-M^wsMqf4i)8wqRkMC%)X zj>k*+QGDqP;{Y}|%NS`{0Hg?jyTI>$wNb64rUejSgm{4-a^xDEuXx(iNQ&roa2(bE z`!_&??X()*ll%}?<{FrH7cUFX_Gd+a;txK@`=J_wa0mwA0>q*Jc+`*HN)&moI9`Fg z4>{zyaSzf-I7|iMihy+Pxv|mMrSoUI%d0csX>2`MUnhFCrsha@SC8CzSgIu)DdS$k z$n;Q2&&r_^(TXLa4@)>wHuRFt0<<#jWPU}JUdRgmw{!1RX=iI!;bd9a>D}Y_N26xu z%u;362Zls>^@gOPf?}E#In9C!8+#NkOo}S8t+2kwgucH#&4-3duRVPIVZ6Hk8~FJg zoBx;Z7pwl%;?Lr=XOJHPa5BMmRGgKd&G9*BpL*0Et16TNKyioE3dE>$E%XYbZf(;U bB`~^UoBR!`wjVp`Yk%56_3Il`Gs*Kdc6ruAWK)vz~ zKzXwapa92wmJ2|B1(2_jky}!cZ5HD-Fn302<0*lbcvk!05uG z3FP|#`3iZ7xv6L7$|(SuIY0-VEyyn}sV+Uen}I>u2I%O-f}+%dr;gft7#IvJCjN+K z+%!3a(VkIy@)SmO%`OH;pb-oVEey@)=DXZ3;|+08@r--ew(ih+{`aPO0FAow7}@e2NcX1Wheho zD4ATKXw4o9woZ2QHbqWGMvKV@l(sQiY%W*!Vg#x=q++%Cp9(W0Fo-vEswwjT0O0#$ A2mk;8 diff --git a/font/fontello.woff b/font/fontello.woff index 9a4a595269b97a02fca49f8f7720d3023dc1f65f..fd4d9d12c41f37dd2611bcc2872deeab13cd143d 100644 GIT binary patch delta 6248 zcmX|FbyU?&w7r+^?oJ7>q%>SQ1f)Ysy1Sd7bV&4TS&S%m+y!kpxUFoz2}qAn+oBnFfK7 zZV$!6`z(FD7!Ywaf+I$N0d4*n$;Qpr8Nu~{K&Z(e5Vl)fO0t2ixhJ9)Lj$3~_&*TX zI{Dim(szhbIuMBZ5fUSKU}tS^g^2wS8a@OB$@F*H?GPjg1W^CigaH8-jC_=7J7+J1 zhB$`WxKB&C*s_Gxt3;9$V3DqG?$XZ5nv)4T&W4INQg+QFd#!kLM z)~L_R3C%*3gMX;8@H*KCi!SxeOqi|c8!Emm)hHXB38{Z(qJIo0pH4c`G(XGmNvy)* zKURZpesrv#?p@r~Vstcn0dQ8q3D|(_W{Hvl6?GuwCoA)@^~ae~oCu{{rSB2MKZU=r z;(T~ZG-MVB3g=~biuB^6!n`NV^6M#f>%vzi+kdY_dcYG=nQly9V#QibZPTVR7R~AJ zE}hcPxcUzLD^;i8WkTR-@Ydg()0FPV!*08uos}ETyQH|Uv#Lxr+kk5O+76wBwxst# zr<$_R2I2lW^?q5W}$)U5T_#w>zsR1VqMJkVpZ^Y8PirZ@2!#;iZp~2axz2IuQP?>PX?u`(| zj#e;*vckJeQtr)=ARJc~)5ZE1qrG!u>WwAW6`Kc7=6mu;zFQ0(aK*J+Icn~yJJrkuW4~n)+H%-EgYEVU& zvLZLp!Llx_C;EVvMaoNyL4a>doXl2_JE8cP)QSB%G`t)NCI8muDSWYmCKa z2aBMtU4T!An~wol^sgaDcfYh25^39o=7^(a>pwr`$6r@uqguv>p*n6|kLh)Lk8-l~ z93~aZZ!ZrY^96(8>M49n%ZtaQIz_Zni^`@_doM2b!Jm4>Q>Iz1yfFX3+)<(O!e_j* zBl{aMg=g>RxBpty#cR~eSr3NE;c|+wvThA!I?OBM(tZJs;vlSicgA1eAEA%FUObS% zFU<=&8l4Ld^m!yIFd%CI>B-*Y_&3%^{;bA$vcJ$9>cI|-u-@1A_JDv!MPXVtnVBLqI@5~vgIzjg{64#VaK)oxW0hAV-x9siZigA=>l@;+PSw-l^M_pf zG9omX?Of35Z9>F(oc}td-=A?u+x6guo}6IM>GGwH{r=1Zltp!7nL3k>Ytg{WA94Vb z74Fi~;u^Z~uh0QrBA$~Rt}G^%5o4%~lm!unxRg%8MXLpon>|`Ip{O)FYhb-hbF>E| zKgj|rfmNjS8%+k3-H7j>K5|J7Sc-~jbGEF3WkNCf{5B+x8%nu0@J4=${4(8zCJ+uH zt2w`!d!0@=5&vbKl!P7nS7d2;(p?S!a07Hg)UHP^ZuJC$w!9lBe_XpBOWZ@xiQ>oM z!YiTE8ACiNi?n?TUtoK-}7zNok#;4&_d4|IAm&;O*~}iES>vg;x0PD;>SSv@c-t z5sdk_iOEsDxK`l&tb%_UyY86Al?wt#M+KFN#eC&_Gg&L}sjR@bR??frFP<$ELFV_R zvDCxO0zxiR`~hm6Ga+m9==;F0kuyA&YR8V7y(ZaEE2$QcGaVZHp66X-_1QNHVmosc zXfl}^gTfZpe9B!r82j660cH%^_(Anbpp>JgvM6DhPWS5>nXc|b{Y&21ZWfg@(`-Y> zVj10!4;`IV>%z8V#&_hJm|Ygn-&--LHhORv#ASnC^KU zU=Cp)7&6RBw{)%I3COA4r8+57azIRJM$ z)O$mlqIV(B8W=0G0s#i~OBB-4(en(`Ekas{=iV?ioZ9b zuuiT1be&$}XIUrW{@`adIdpayTV!O=^m2wnUU1b;t-9g_R~>l0rDf|>dK`8fn&x?V z!iLxDvtRNY zE;D4hGJfG`{RVXT_YKSM%g+9zKS|$ec)VU|pxFzN(@?u%*fk+jQ)1pPm#695YS0gP z*sCeL);(#dD;)%B5^P9qFH6rk*QL?K3W-{NNSv3O77UZvd@~xV%K0{BPQEBbZO0n* zc`Dqai3UoUO0fE2EVmA4mhY#F&s~bCWHvYKg1r9Yt~}sWHqPw5A9tc3r0vNQvN_+T z2s~ko!>(b~UPfx^J;h*oq-*!O!lA7~nS;?$XEvLKU(h|b6aGuxj2?L`!n6S%z7xCg zc6UvP7$BLkU zAPKOpxF$0xsVRJEx%`ZMyNqXr}f1@4k8s#-p*c3B7i?gxU zN8*|=e%%?5u^gWwlFy%V_+#hi7I$%xN`$E(ktJr3Y|=sZrjO})&c;i;zozz1O2=|rXxL%;t`$G&a;jtsnrs_{jZNo~tiuf#g59grB#B+A`2_^IbIe z3Of0MLiUlG0Xac8QWYnwpRL6Uj5bc#%c2-jF7B}kkqGKHi`YWK3ZEjdM$Hm7#HyfH zE&f^;VWALjct_T0H?Z0<$(;V$>h7_X+LyL#=T5z{{VN=rm4vWY02$+HvyXX z*f?eK^fzR9n3qCaSZeX+`bq(rtwj+s4Ej5R!X(XhFnmlyOo`cLx&cs}wzA1BC&kjW zx2LUQy5dDtg}7Iu<`dkeN%e0^&7mh{hrAGib~zdd^c zYFy&d_+PK|uF`C-bbf3Pn zeCJUyOpb?meU<8B`AR$vqgsV2(mi@WM+6Rz%nyJ25f>uQ3IN{V3+vrdB=y+C)OmwV znLf8dje*t-4B@OMBdg!SBNA_5F1;5nf<9(0&o$bC*wcA=L8h;_Z(`(RX`)H(C$^a! zc66XsBli6%3FS5(O!`vyJo4Z6{%#V*Wf@Pj*%Z!ltR|Dz+JyEwwgsu>%21VRa`74q zPX7(FiyW_XlLX`+<=UwkCi|6z275NWA0;9ccxb|63rK<~EkaJ{b!Fn7n#^M>bSi7s zpin^#y%IzBhZBp$DrRQRNm5@|?%ymnUbSl?Ke}2oG<7MXqTQC+)l5Yx66z}Fu+1Mi z>)>!>(j=-b$FZsbck?H1N9m?@bfWv-b1L!GM%V1!Q~;t$|5$1Nyor}=J`^LSo^~JE zp*W#5qs|YZgHxXxu675gfV;yuPY-sK&6=93xJ9fk>rR&E>Er8<)!RO~??{L-uWY@M z;B#Pwa}T!U1Za`CnQBe1YR##fM|aajBxJ1%R_1ch1nte79?K!wUDzGb$jh_Dq=+s} zQ{X!202ZtTS~xsmQ>as}qzw!)X(~E2rGI9yzxK>=NEa6~xqs;+I7)8Oot;n4!eo8o zg4yTc2;U|vsE(O0Gsn-GtA;xidgKB3mjfa%aj7jVH{@?MXlx%T(qtZ>duAXy?Z!cV z+a5!Ir&ON(5N0sl6>YaWGtIa0u`=FZl%!lj!1GvA^5VzSXMQJ9!qQW*CVi4CTGNU8 z2i7@!c}2;~)F@%vnj-Y(D`fZ4TIP|=xS$AjRguk@sL^yL86wIsx#8dVU&jt~4v0}x zF0`;6u69n-G2br{p`+r_@wK^Tt-1wk$+ThLKGJ~Cf0SjsNBo!86u}#Dki#GH5i|1q z0Et_p+&9Oie2KC2VGR)$97sV&S=mY$W^oPmy*pNA(hh8&(g#VP>kZ`ZQ&g1Zpr|JD z>~7+BuD$KlH*o_e1GKxjuvlW2ZA^F76Qy8MIXa2LxUEfllA&+>zeU3hX0yv6j~m3) zU(-FU`p83`OAZbcl9OxwAaQ7)Lp7Rc05?VnR?V#H4_75qmW&4>t zn~7f$k6%YHzDlP#e!ruq=U8l?*+xZKhJxAA;FdZq`LjNu2qnF3M|~;75WaxRnU5bV zTSXzsu5zE;D1~FtyeBM;E!iIvlsmG|utE@Rt?Df&(;wMMII7aHjJ@O_=)@TWJpMGO z?EUtX{X|mTV%qH$3;#i7o|*Z6@s90#5{%bh`@wkM^5g7|XCdykLW8MzB=rCXrS`VL zxP$Htn)cK*5wVkR88`egW=fgxg>1~10yU3~eePB{C6 zn@WC6bFqOQjdjc-Zq1n&8}*O|;QYliq_RZPX_zOf&fZYvYVss}-CiPik#Hb-y7*P{ z-e9H(cK{qPnU>|h=sT4+f3_QB(5N$Id&Z^=PALChXU)pY478b=+$w+mC}>LAnq>-- zr*H|v-;SJq2A(FZaLw?LJVYoyOBI34(s3sLzve&tF^!xW9}OLpbAsld2BB6)CwKxC z46x{=1ye%-J=}i?>kfZ0eK>#kJt!P^S`yclgHHhq)4KkQ{u5= zsougwUn28nsB9t;5fR}ydCB4!X)D{SC`YTJ6TR>EJu?r&%pc76;X$*=ISAUz;kQ*o z?-BUHm@KJIBZ8gF`|}Q^Y~O%uO45i6NHv9IY7FM=@I7_xV9^o0tKCGSuV#qb`$%@% z2ytWOdX@i22KJxUkSjGXL#36pE@SL6ZwKoIQk6vrVI*CklQQgJXnQQ@*KJ&A0 zrvz=d_6%R`OxcX2>tV0+tJ#fLuGl?F;3KnFe~VNYsKPR5&@8U;bSaJ{6D{H3XW_r7 z#=tZlc+K@2MriYrV+%T*t0{BD&-_B{?ACM*ws^gs6O5C%yk1XR_J>IOpUr_aB`@UVocV}ue z&Z8KIBZ7qi(XfccdRgrr>FDGZZUoz)!}l8?&N~m&@7$m@3SyxiRDA^)tt&f+`&dSv-uGy=)#?RqiUeya4|zCrCWfiC>%mk0hWkdz3`q})I+w%w;Yl8BpJgnKcCg?% z(>A<6-jovS2k&+AX^E}pG@Z*nL|gQ22CdF8=+J~aJys*hKfL7={Moj{O%t$3w!GwW zs>|~gs~2C>K_aHynP!i6xLOQ-JM$;(uK2Vqw{+B`x5-P;BlQtfaBN8fN>ii@{vS%w Bw-x{Z delta 6019 zcmV-}7kudOKEyo~cTYw}009610017u01p5F001z+krY3FTw`rvZ~y=S*Z=?k%K!iZ z>aN}HV`Fx7AOHXYqyPW_6951JAO_X{0%mY$Z2$lQxBvhJkN^M+aEg(TS!ZE$Z~y=Z zNB{r;2mk;82mk;85NB+8W&i*PPyhfDg#Z8=stRfcL1<-RWB>pf*Z=?kG5`PoHWJTN zsAyyd03ZMW03-;X1kh-0ba(&&8!P|-08sz{0Ca0M|LJURV_^UQ8-M@+ z06YKy06budX6bEVcyIs!8@vDj03ZMW03ZQG3@L75ZDjxe8{7Z@0e1iZ0?o{w9w2aU zb94Xz9aI1S0P_F<0bzS}%e!!LWpDrh9!LNH0D1tEQ2|K-#FLu=Cx2!R`k%!R#T>*i z9VpBQk^=zx<_r4(c%1Fh*=++c6hqNFvFs$?vv{8pT#!FgOukYnyRi9WmJtC*fCOnU z5D83yiCwM1@W()nU+)fmf5N=)H*Wn*t9@PWchA)9b?fts&o+N?#w%~U``&^jE7ok- z^1&xxe6wTEfg>l*Tw)k~amN2x)-?QNHP+ic_16x+Fp5e|QSYy)L={c~g)>3nbWk`a z6qU5X*`cVvQ#el)P8NkTM&YzkICm6o019^jgkN32||bi1SddXAqy-~TgX^o0~Talf@xwWcFYhn z<5n&uv~@fk@Yunf)H8tFxG;+UVU|m^ ze5jHa7Zf=h(v1~Rs=;fA-hS+{x3B;3fc%xq|D-AVRSj>mU(rC5x%yR=%bMnTSk;*O z(3KCa9CC`ep?#{Rsr$sxe;>dOg>lXl`#Z9#5<=!}+KD##NSzFlp~kvS;LHUS2yGIH zGAgkdg4Qs;pD2V%3KjMd;ADz`EW;Q9kjIG(@^IMd3K_XvTIKPs?1C+AF#qJCN)gg% zNjn(jQhfkQMp%~>FPP!^{z`2X3@~$XDR5QbBTd~eo*awWf%|)(e{H&2HcGOKTiIm= zBbM$5rz;YSYnJZ$$>OSfbm?oOi_;^;YqC0a1XFIm9F2F3 zetBV)4qYMA?OV8k&(McRfas(^YGkCbSqB#f+*(Swi}ESra)ZiTD()=-g~24Q2~oy~ zqL6V-qSzW<(q)Fre?48bCAEAu)gF(A3uYl038p+e(v>yjbZRN2(eNVFL$#90%6Ukp za`jL;l^cM1vScW%Tr#|n#S4`hx`Cm~RPw~Fq&NFX)>X)RwW}?Ip2M?4Y>oW`%L?7R z8cxu-3Cr))?V-J4%L?x`EbEolQro6Yx;NAjhBL94{U5XTf9aY9!-;|g%i{LyR=0K4 zDkQ+_j-y57_9yH*eG=_Ykuq7|SnH-#qAft!-M)a%P4=S)Py+jjj4mOgO91DNEAVl` zfe)KTMh`~}g~z%emlu0ogleTOD;6YbP{}DN88^OEt5$00=v-H1DUr$ND)m}7NT$Kg zY`XxxevfuE#*H8Nm|6q^X5C87oVt;J^%>HSBz=DG+P>9CAA9y$*nnfF*SYj91^QQC(~0n6wD%hN zzKq_#oD7g5P#WRJzzRR3pb)77A_!K41nW1Q(?-S{e?3HD5>uoZ^b_pcjcXwhCQYf> zkU7XZ38$2g5zgs2p_~rKHl1_hyv~L33j7`u%>UO9HG1!!A`zJRopUB8CK?7IgKJmz z_ZB;IR?G;lA?E|xSOv8Z?qC}Iv>K??&`C`Tup^(tOR^F`v`Ut0 zE1`k|e+_0rx(Z6ZUMpd&>+svgwni1gF4q-T5I>p8wRX?i$;q|wZrXA&C8laE9=j)7 zfm#OM%~p6ujnvQB$IsA%VIDZm+?K#ar0_uy6hbYbL=fh2*#@u}XH~ z9_tmng9@{!?c=ARSUFSi`L_AHoxR@2uCr0ne~!MLMept>k2dzEacSDXMe+%%aMtu7 zg1b0zP2zY(;>r}Rpr%UN6j2FvtLWyk%*GMWJwq+vb_-aC7T8d!0IBp>`d2KkReP2e zyE{9wnN%`rdOa?gw1ee!aNaNjh!%juo;o zlna@mxGsPoD=bTj0wFLboTX&60U{pL(V0@Yl@1UJL=eUc?_t+9bq;qxRxWV`|R8Q%08ese~6b@ zWO~!N7L2wuhKa-;5;h7@o55W@fN)2pF(OIyK14XWDb`5gD0c7*2Te2rK-!|F9`NJN zd!a?1-+6_30YfFvaZlClsi z$Mg(*6p7gVk!T67L?Q<|j_UE0f0cdX=8hbK)=U=WShp?u-oYK*EXz_x_@GD3A>37NE@o0Ofoxf1j2W9u{K) z^VpIPq=gfR(YQi&WWIL50xV6<2tvnV_S5R0Xv%z5(S~e~s#18Ds;YhbW=!JeWeNUM zQ)>&TP!;3;ChzJtE|>*Z{xwuWZ`l7RF2ZV2eooz>u93*L)#0V1MYpnKOQcnbthvV=?X7MPk2d2{YizRYg6y7? z)AW(&_rX+diB#M%f8Dvv>MYS>m$fW^|JGt}Z=wJ_`R=LC{$!!FtQcL^IlZLVqjZ)w z?Adc-58bzD|0nDW-HIwOL#mCE3&p#IBFMnNXH6mH52A8L6-4LNkdXL-QyCr3b;N@b z3O$Uv1(3_nBb_O@aAEU=kBiWUrv2aCE5~K|z4v4}&i#m>f1GYZ%)2g}kVeo^i#UYG zWv~3+&*z8Qx47TFl@hI#v@!+aUIcCnb9_sWe4W7l}qX zm6sKKp$Fw^IeaoCA-W2eIbRu|Wt83Q`mtX>n=c&rvsgy+BDPcJky>;`_ba~fX&56$z&`FZ)Ob8pD4iJFaCBYELHAOClTZsY+g(Gn`9FIpLy3Qp+;_dNv zt1S|X#GLnf29lvJ`he;#pmB3@@S#2uV8yR z`ujWJBijSV?CTK0Pi4mr_)TA7Zcy~l%Z0vMzoeJv2I+m8}&{I-K zfg%%He@KT`f+LF^ET|(C%y0FSr z1c(Y*TW3au}GA_?{NL zsae|1fJ-xH4eu<1_H1O@=S-x!Z?W>+>!|1w;n$7Ca01`ZVft^n-8cPa_@;yWHy5yN zANxC82M_M@&c^+Kd<0EIGoVa}8U-^Se@ygcs-S8Dxy4Ogm~&4q2s+{!LTu;TH4o*y zg>PtSA*3bJ62TzUL&1RG=f(Sa0{9p7^46|!pq>n%mJN$fzFMx9F{em})78sV*>2B% z2VQ#S>gjjhIem(izGuG-(u;G` z;Q*URN4&^Uj&>Fz5&;fZ8^H~!M9A#+#Z_;EdJT1jA^U)>h*vXSozc1rk7CTw6nr($|MVI;0K7Z>;P`!Q8l{jbHciRfk9slk&yt)!6ZQuTR z9nN}RWTT8B{`HWa#*#uNhRorUf9G`p2FyXhBnO44Jb1?}J-oax!f^qGL1>6_7nwL( z3aJ}RV_shg#f%os=Ueca5qEFBh*Z*$<%=V3+;#MpS3a%kmbUdG(#a|r`mjx1TQ70m zzzaAcZWypv;g_76*XbR(h`oH?Z_cwF4mR|V-bS&by%otJ=wb8dfRJ`je-I#A1ME{n z`gAi|cMMs0V6i(G8e&5h9yqLvjr(5~ihY7t_{9-T_c^W`caK~`_G@tXTRnl#B#Sz~ zwAJZ1fGhIFt(xWdI0l0U2MGJ#yVGdkee`jdLOy-mMa=mPp>EU>x5TAQjl>PAc9rj;zKbkq6IY4jV zRn_X~u;|C}!l}~q^t7WfFb}!HYV>0i;cX<_NVUbyfF>a$qI`}(m;Q)o-hW6umvZ|i?(+wzB~-Ez)#)DchvX@8jC{3m z!@?Fu8-y;$YaU52p zHIs{|l~ehwBBu>UHlmuziCh8c!xX`u%Zp1WW^y&>nuSiMv_n?7ngt542`oT4=e2y1B=)3_Y@kza0n)Xe^T^yi21pHNC_$S*9Rn~ zQmM9d^7OLr{BvOncg#+CPM zj%SHlCdXXJPO>Yv5{IH>6 zRIygnz_hvPoXa`6WRfDW-MGV?lifH$LY@%EQ ze@qv?vOMeLjLB|v4_U){U4ljRk{EG0C=2ZU}Rum0Af2E zv#@x6o39Mq%rAf<4A+f0T4415U;i^%1DJz=Tn+{%kSG8kI||>Esv8^z3jmw#26&Uq z8%hTZ3;+;ZBWaTz96kqC0096103DNN93Fq&YQiuWhTqJeZ3^4iV5iH`P{!&H3`7tF zhn{RFGCUo%*0xd`Nu%Ix>>hS8yNO-PUfVc^vX(T@_vFi$uK{q4ZwTbi6GzShXN+<_ z!6|x{3-r&Hi{ux}B~f<=~gPLC~;%yu1%kc0$uix{&VGAOvEgZL zTEkttE_K$G#PFbo2rir0C=2jj!SaFFc5!4-C!GG z3<>%F$PKjMNJ1L0Dr3nd$z_t$#}uKmp?9xqrn|FAc2<>L*9H?zk)uF~83g92ut1F^ zR=B|}*0{qx9`J}KJmUqgc*8qBu)$}xRw<4w<1w!ty4VHz8&o(#y6ShnCiY`uZ+~} zd$TfraQ`SSI6GZC8ia~tkd0q;plE+c##S*e{$SrT&o$d_=T$J33c(LiYCVXkZ5-#v xqB{kY=gN}(!S|`UOq1Iz`vqrwU@ri8oMZ6b!EhodVk0ACU*rbHog9+~A8BgCTMGaH diff --git a/font/fontello.woff2 b/font/fontello.woff2 index b8c98b96e3f9b8b9ca4bf97340e974851696ffcc..dae85710040bf58bfd75af9887060d7171d950a2 100644 GIT binary patch literal 6704 zcmV-08qei-Pew8T0RR9102(j=4*&oF05U8902$Z-0RR9100000000000000000000 z0000SR0dW6g?I=c36^jX2nx4+uOJIP00A}vBm;N^AO(d@2ZC!1fd(6iEJX)m*f;=~ zpIRiMVzW;6|LK4mA_9BV+3tq$q8tjf+L~^g)@V|x;@GR!BuXpN5nhhtV5@y6&u=Qt zRA5D|K)1t|Zogp6Y1=0p-7w#uZ=EL<7sCh>;U}Y3JNYBR({n2g34;ztXzY_*|380L z-utMkK1gac@iLgOcQhb#FOcRhU>{iq;w-|@;T{K(GpChg8lY`<2zpo`254gj;)ynr z788UMqwv5gYTX!hOXe!s_W!Ubz5*BRNAtfbjKTBR?fu;?(O_@%6&bdkZWF24RA1U}x36%5#7f8~9nna_x4Ku+h*>sW1&}m4gSMzc zYdbA)_gEA~;QyJeH&T>hG?%=HF%kPRG1j62QD)^Ab&8sv8OE;&)WvO3_tc@4i{?ix6teYpMfCr4mhGQe z&+Q!B7g7iu!lJGbzF3L zsZ%s5y0mqQs?B3;fuPMCNqQ}30|^x~LbGvXv9|X-1@tWS0T_;Z$>7%m0veCW<1k;F zSplKH_HqY*I0H(Ho$ty1-uWT${b`I5l&8j%eU`sxfP?IE3GkQw56=&e#{m#tu!#Kf zHhKc)uLf%Qx*gSJ1>?mrN*z`DL(Qr1eCquUioIiDH8t}RpBt&yz_oqC0Bfug?v%Lq z|MO%;qt)q+j7^Yu^5V@08HF!D{sIIF0&u{h+`)lN;TTn1fks_Z2&oiGDut0s;iOUo zsT7G+icBg+A(f&bm7*n;q9c`}CzWDED#e&oiV3L{8>CW9Nu}5%m12ujifvLUc1Wez zC6!{2REm94DGo@bI3$(gh}13PnCg2=x0J8jr~sIN`nG(fS(cvu!`9nV;^R}|sdEy4 zWlweW7m4A2#tPb%EuHt^56Gq?3@R}|kwCQgd=@wp6=#ie<|$ zj$zB|R9?B^O-`0QRrw>O+_gxqRHS)1BIweHIk^C@3h0=COEMtM9&BNSj{^c#!#1^6 z{|t?CyL_g~ughghha((?b!ZkZdP#%0xa4(J0aYqZ8Vrk~S-rE?T1ghp6?q3|=g6wD z(eUb1_;pdgYjRfv!ctSvu-3dwW4ks#P2QQ$7kxm>M$b)ovz`WYgsLPodXnT;&ts;) zLhnfH1oSKl26+VZk40PWtYc16Q9V#~pI~7IK7E&(b<=!WpYH94YJ5z8ou0lOn$Blk z<};hvu&wv%c=E$KGERj0kch1tp*{$YOfd0E!z5S2?zQ@-n=-3oZz0NAcRY~XAWa%G zofhPQWRo<2Q_he^3*urzH z!~b+?$y2&hIbdPK{-uDGjp~C9(_qI8I4}!N%z+E@;Kl-YFaa+XZ6EjHhR#|bKe|Ez zMj?o42w?`on1u-DAc}d2VFBWpKmv=?l2mU?kn$BKl_ur$iMn&f;(kO0(j=9n#`fe4 zrNz=^?b@(qacbGQw)43tO6s4RM`XrOhgVx>WEHZs$J27uttM)D|5h>uuE8vEsn1*- z{lensGr4D5Eob6lpg{FnG|>ifKcPU8-LXDU%2tP3X-6ru(KtGzP7C0eo&C7}>BT#5 zP+Gcp7suoHq`||(7XuZ7BiJaU*Wnah+SEr}>TCV$Qq^8{`CV9#0^-UK962bzrJr(h zuy(aq4%!@p+bu+@VZo1dWg%dnm(Q1SfAZ;QR{{w6&dbJxPYK~vUQQdkY$_tOU1UJoIV@zZs>@^f5pP`SlwAnd2nxA&YQa8bMyF+B$Te>;fgo5 z1>0&b8qp6O(;DG}>LH01##d%^_81%NWKyL1I4RFCF%*twrcU#EXRRV@l2|mkzBf&A z1fDFK#s)LvD4w<8e zs>4O9&M&DngRAZaT&EgvlWM?issVT1O}I}r;UU$8$5itkPy8t^%>5}+W9cV7GMT%+ z{P8X6V+{zd?etiTI|2O!26!2WO(6Xhi`Khh0(DQ}7G7;eo6q3ny+jH;W(`){AeLeb}IP_?;>iB)#od+-7~X)p>sCz!jmOKd+{+QYUi?Bvp_FA3-|=hQx5^<& z*`&EGKG7IM?6gYcvwX&mM0x!GFF|*kh6bFm4$+vWnqnhhiM&Rzme_PhBkv_GOmXN; ze=1V=?~HfmKO|8XiOEg+9z;i>v0m6z=hkK0D@|j!Ay54>=*QMnxv!eyJ9e*);5m*G zye{1&g|_t$ssj0}lj#@GA1^YzGt^jv(;_ESvgB8ZE9iCfp(AX z<<`mi8KYXo9)n-Dqy(KQ@qupUDDW*DRTau$&|h911-dG3UpYb;DoilS{tJx%Ag}*m zEC2Dy(KiRc(<*B}u2KvqNi=4kGD^#kuwzS&Q2NYOvFV?HG4-pX5B#Dd^n=a!AU}uC zwncSrtETuc%_@J&?eV4q^T3e73-B|t1UMvN?5O$Oi>4M<;=!+79R+0wr8X49A&D__?CxlxDmx*6jo zfI0oKbV=_>gSH>AJEa)q=TaZEu!gMJ}|QCt5AYTs++>5Yxw{Xq>Pzng{xqyq)#%FI zE^}yulSS*48Y4kS!Q-lpJLgSX|A8*od<%#qopb5;W(-D*-_HVgg@c-c$0y7kbMG` z9k>zyeqx8;@)w@i*t;BzfyLY z9j%MZ7nRpOYsaHtM=BPt%+%Nc?gT!eDzKb`UxMe9gU(e>E44IH=4~G zN$e8g1?}v*I<^H^(Ja6+oL&>AIIbPO;bw`Xg~7lja?Tn!L=@ivfF_`s zT*SM%(+RALj=ItSwh3~>_eg^5eQ&7mDY0fsCN(OJw#0u=P1kpiFK}N&pY=YFMw)(| zF7al_gFYx51vj+ zqO&6{k@Nz0F9;;$L{#nCi^8*%-D_6$B!BFvc!ga_ z`vGdno^7&9X~-b3ezI)Mnud!E`9__neMbUs(W`x{JN}PD<1WSQjC&JvG3HX7DJFzX zz4YeNy0S{&O3H@uqR2Nrc#hf3@d)D*QT(#c@hI2{uJrR|e`)fGswGRRfQIwoL16!c zU`as`s5yLCBh|^MW&KdLSezX%<9pPpx!;uF-z$0m?f|(OAe{9LLZnYI{IrA0t%NP| zCB;u_P;$4NBhL#V$}cz@W>>JqCBzD1NeQ+JJ{*jN*lc~lJL-2XfBgtWH$xO#bOhLa zM(4{JOTG9BSX+VX+jVHyWaa7~C#QbW|Mb)3PyDhP=mz}m2M-dgySI%nbR*`vn3)_9~d z9MOj(-3g{GN@au>Q3@*;VawE71ldBwDi9){FO_0#`)p6o+aS|8;@Ax8{%gRFV~lBpptrx$^b|wi2te&B5z6F+pLou!Oyi_hqF@M{<= z`WFU(illjhy!M>+jXCQOi`Y`06NGk>=Y?k}zu+2VpFVv*f?u&(T-zU7|2=RCjQwB; zN7ny6VT2#E6R?m7fq0+5$sX2oV85o{0M<6$M}NhfY+&AG+V7N!`6{EI=_g9hZD+f$ zDl+2?&h=?QHT0MHo}@CpI35E}0e9^v%4U5>cW zGWJ9I=2>0$iG5*$Jw-xhead)kT2Xy@L(YSwrpcCok$4LVgW5nygfni#Mf?)(@&d$V z?*1w27$YgVy#m>Wx0kY+D@^a3flH=tw*LXL4d7z9^V)CblQNSG1Y)cB_Ji&+3=zjH zxHsS>*O`Vuag+rd$vh1(G})Q~8PaAM5TP$XwY#om+wujFJ#Umx5KpyFujl=8-fcIl z`D{FD8>{+V37k?VBQ(*e^qjbd=9~zkGcg1g2#*zLYSf`1rt&HsMz;k7kgq}n&jEs) z<_S|Q=cfA`{!_GH-jKsU&GZe95DK^i`E{6xUBXPBhnU=QyAV**RfYtcvJv9gr8vPT zFk&CI{Y($nN9oA-pBsW0pv*WG27*|!B1nOBg%L^~l|kQ2?ivZ^SRl16nv=ILpiS-k z^yF}Fdvkeder9sK-{T`bSvW%+9@lN<88pujXx3#=K2VElyW;^s6Nq{2+&Ra{5AyeX zgr@LOnw(NiXNG=BhG&w~#@7n~PWS*qj55GfTgtRHx9Qwm&biJYMl2#KPYB(iKxeqn z6{d?q{D}n!kakg-$7VSVoUhrLL69?cFF<7W;q6E}^lZsIP-ARMVhb%30x1?iLl$tM zn>uDMd7+`J`d68IeZWIKxz?PA1|0c2p)7PJSi{vQQuG?z^eGg&F@}FFLn(-O{7#SP zDbyLl;ejPX%CNYMNP?J2TEzM>v3YoQ=EE^|`gXkqWITRnsG#HqieS-fy#=KL;RKbY zj9@+WBKfcl>9=9Z1tK6#+^d>X(A=S>VM~q;@e~6LT}fU+&RxFIdymGlrQ^G%speaD zD5`LV(Gs=FQj+qdE2NM?uLz@WrC5{&{tpq|b(r~cs!rT{zoG4cey>yhmnRHH=;+4A zD75eU4?5R*HMArNL-iQxu;k=9ue2CtzUVk`cTrPYK}A>B%SzB^5%-48DGS#g% z?Nk|(w5VK1si!u%ve)OI1Zp(pQgBhg6m}aC-Su$6jf&)G;HiwR%sibAw`aqmylLlF~@U5 zE|CWmIEoJdXkb*sZBF5}muTBbl2+$uC;Ph_YbiUMO_!G8u9n`L2~#SjPf+ZTE;>UZ zn6QLF+++a<6Iz-yzkr;<0zQPJL?1UQ!!uJO)?fs4+i(S@u$jH0L|G9=iWQQk6;f8a zL=HE{1G{(UH9QX6!)!0A6DHj!LT1y7_!$vNNTzRP!X3m`F_axJP3We7br#ut5vSfS zxWlJj$g_jel5OUS;`cG&OO|MJQ#Jt{dol}lv1?@KBS8pB-01gR+mujpMyR|7rBDTK zE()$#l9HUe#|ieVmUKjmN_zuBePhtyYKDY_S*8?bY;Qm+LSdm z?Zx5Eb?;Y$KIbiIwF1EZ-oJ%#pZ1w`n+vrZ05XBz5_eVweDT1CJpd!%Cv&*k*7N=} z`|)}%-y^oH?P^_r)D1vQyFtI|+vEis?RHTr8;_(niM5$J#obodGg@VS>>@u_5>Gv` z0ckJdObR6ce`$LW%)->qdxfXvG)vjjS&@7)tFjAZWS(`c%WTMQXB!V{*?()(5EN?x z@Vf_@xJh+mvrQm37Ik6w%P zYty2Y3RMiYSX8M}&}5=&f*YxNdNjA`CesOi88wyGT9XnqrqP<6)-7lX^L=;fkp$7B z%hk%E+CuI2DAV7v|eeILSy!Cm?a>(~!-@HG5 zCiHBXe;Wn%bKiM7e7<1e+| zHvFHylh>aAGaOpiz|{qb*frD{hW2t1NS8k7K^z#~Y)gN~A*F908{hN&(=+#t!8*Sj z=Rx9|USCw(@=5#nI~NjFyiWkP{@{Z*X+ZIBn+ioTxDNyPrECiiM7Mrd39~w0ht~Mq zKl(q2;vh}HXTlX1g9!hyxS_~jHXOW(V-5evFF?DS$1ARii_LcQ?;2tEz`wa(r`TTy Gf(sZKC(cv= literal 6572 zcmV;d8B^wWPew8T0RR9102!O36^jX2nw|*C?CSapz<*>kFf zICybecv!yh(1b!_t({xv`@O8PMIselN?U$3npIy_=X&|ohWU#TlFUL8`~CKw*cZ`+ zHI-;m3ZYVoe`tY{2#rwh|J<@a!vM3c$BKuI8W9y%EOCg|=cO0b_2i{HZ?9>NhyUNN z{XTOCNr6Sh8%gsJU&AFqQVsFf-&9i+4MqG6&^9})V*v*S7}0QIG-WZ4ac9+GC5vc` zx+TkC36D!wfs1z0>{o>e^{D#{6eWN*^cuYq_GO^Q~o&!`eQ3{Bb_MDmO>`-da z$tn6}dl)9BY<2+Ocg&KF({v#1gf6^UJd%Wo&9{egi`$@XsY5Fl&5u|pWb5sM$*{Kf zVQbhLbls=@jANAXE5dhuUO|>&{E9&JzrQzi+nG7ryzxU@qhH?4-BPNx>P_eaEw4~X z0@i_|;e-g|^XV+xKeMD``%q;ViUwbwt{jgH(pZWm9gTxpZNR6HtdQ&gLXY(NS=Rbc z3J|v`sY_GjrB2bL=+f3PS<@aSEcZkZ9*d^ z{WlM#qi0}bVrF4wW9Q)H;^yJy;};MFYKA7uD6BEp*lmwp%6LTrn1nEiU=qV5fk_IJ z3??~D3Ye5&Qie$dCRLc!U{Z%k113$Fv|!SPNe3ofnDk)MhsgjYLzs+UN5*ivPljbR zt8fIjfF}KvjWCMRn}1*)eFOLT6zDjSuG5+FMgVK~pE{~Iv#IkQ*a60D*aI?_+6n}O zcvgX-x%i7f!lyp%tFh5+boe=V^Db|T<^63PDLT~PxRe`i{RM2@JL9v3s zym`$F+q7aAH z;GOxn;VVoiIGdo<4J*t5MF}HcdzB@UHe%W%tHcykSdcfZ@<{0)am5@pVys}Y9ru;>L8TcuAV{kG1}gV|`CkBhy#;(F8FiWN>2aBNn%P|yf&is7LQ zyp+I4S@ltYs8NKuM3)lFoe z#*~mvB&<<`_{BiomCPpts8kMQjcg@%Z-O+rc3FqkZCg8a-MP~Fn72grUm9&`sz94N zIdk#~xwg|2&CtUvS}p#2iFe2+fh@*rWrg7W1@zA|{?xWhvlkl`tx%&$79}vI{y-IN zsIN5@?U#*%I13%nfr6cTS+yoW46>b9`Tdl&QKv93JfaZKNL`OnKTNg4VWA?(L{X}%dmuXSP~mHme|K+9K$lsVHwx3jC)MM zGpyhpR`3lg7yFx@#d`3f$Q&(_!t@=ct#RL%Od$e-GFi~Y6WWOxK0tgQX*=4x2H7Vl zY`nX}5JV>>%y+oo^sOWBqyj&BTQ=_Ai|4Jqc5v9chve;Qbf?X>+L0rj-HqO?=XW3G zP#)MlOLn_^|CbWGO+y2ToI^C` zsixQnOd^d44m~z0Xym=5g((j0=TAk7{hjgg{DfE|)d!=dS zHspn026gC7_4}$RzT@;52hVXq@u>)F7L?ovXpq_GpG@CDQ{ojcMhfn?Bo)I+q;zZ! zXbr_Ci)bwAKwka!qe2&WZ6w7gPjAVF9v7{mZc|@BeswA^`va|B(0UVRJl&sS49Ry5 z4l9oP!}a~{jp;hFULH54=s$#8mx8{?PT<)iRrpouf|Psvy64RpPfPWbg)akhNkP(A zpa*K9?QJ@bC?oW!NSW%@A5)6Of4)DQcexDdJ}V6I46NdT?6?tjN^&4VVRnny!MIB< z-?-an*};9$I~hwVZEE4tL3>2^a_eOJoJFc~FTpQcQbNp>WLr0L6!;??RTY8hpufC2 zifn$|e6olz)TB(>{tHI-2Wk9+WB-qz&2@AGC?5gk+xd#&B#Fk%vj)=jkf9@`MlBNN z{MfWlgyZR_hXk;WFmxv00DeWh(iYXZt(xNVRP+5Qx5t|f%ryswD1gtx9^hOx_B=Be z-lpCLjaAW9c|T4{26hP;GQqS%0~sp8C=-K8g8<(!ziuBbS={rX$pH4E0mZ9wShjsC zTiQ3?Y#LKz<;(g%H|o$|H)Fg6)Tcj|F6kX<(Dnm!rxYU|d!3XS2#)Qyh^BM*j**0~ zLJuaXZVH>O~*JvA@QZvKimT^>KAv&q~>4MLU1M zF-h)vSE7Z>EJd%VfOT-WLZDcf-){{M*+ewSl-n|hFtG((A7?SmK8yZ{D@-ru@$pl!V zS^oAk#WmnM;8U3cPUMkil6e!sF*z39V=Bnqyq}Wyo09Q+UNa{wPMQ}KwoEW()z#Dp zmconfXg2pRG$V-KJJKyFK+xGj?xp z;fB%&9eU+e-hY$r6~Z-ax8f-0dqKwZKAX|fm%IKTz?kuo3_F}Wp|7&(_kW&P#pn-w zf<)7!(S>sp?YI@K?YBs+iYl(1VzY z(L9jw1_^YwcyATWMTQp%+#s60Rq(YpArVEZsa)U)>(*t49awLzWYHmRRSC8cE zWI#XaU+7-8cWV2&@p>n7ibOH) zvzX7#cQA($X6-3M#3WN0*vRYGUopmq!z3p%-2_v1?AR%rg^b#>2M-$V8yNk?hB9YG zND(j9!UrE1&x=2l*T&B~SpyP{0Lo=irc&`C-eDCFBFHrWr~#VmiCw*Q7Vx#^y0QS4 zRGI31AyLfcU#@?demZ89t2aAr&i~gnLRsHEfwGV_XuXY1@BbNrT61Jh$CF|#&%TE5 zX$^QlSC4`31SEv(=)dUW<_ip9{y338djvh0#r4vAv63iOa43p> z-ua8P$YJJ&g^RggC}nVqObD^Q(IJ>(HL1P}1E3Ttd~sP+SQvCEKoQzBu7SP^PO*2b zRZdV?jw!DGi#b(F!b(Wupc$xBB1e!Pj7Wllm0_+`XG9@WR+<(~ONyD`T9tp)VKBxK zN$dn1wJE-8e?f@%GS9Hova$}mjMQ3DrXW>S2?arBW;`mY#i-chCeIU;ifQ>Y*vyni zLrp!%1liWq{I39xpI=zAcs`ziJfxFTk-)Q}a1w*u>D z#0wV|X*sfGVJ!4xalFIIwau;h-=FaB^#y;3;kx$z>Rl|(w#{ZP9S)CQ zX(01-Iv!2MhY0fQ^JD_71sCo7?7uZxPtMGlIY3dhy%pF$Et;9+1Wwtxb4r$?#8uo3 z$4I3y0VP6O!DRlGbnf_i=ZI!R0u9@GNc3CPpf8`OzFak55 zn@QEEQqt0)Oej6wv`jzr>2fg|*E+AQK0atk2U9TsN%aaUMj24p^18yc$H4qdv!?Ys z)^EvPaC1xFE#<9STW;}NDq^X~8y-ChG;CPif$nu8&Ip~fvPWJN7g8U!cLbI@@Vq)BqJz?LrW>hDT$M>Sd2wEf()_#HcQPTP27# z7AB?dzWl&6mLl|H$KWiS>PDNv+0$ z(HE8f=pcAOENt>;N5b)+bGKutW4H6a{Vx{Nscxzaz-v8lr3YRgs97nOds;zRn0&ga zc=A*nUkRC(;gC?6m1Sz&Y-Aq1s6=5!swnxWvAia^7qfthIoN!sC$t`Rv+o}e{uO%Q zR`|RJcfw6)+C{_SPpQF3#$d1oFA8{SO4_t=64!_8J4t|8c2@MmqG;E=#s7?3;0 z5e3-KD7`!Hfy@dQdi)a%c4c%sq+Sc<_;b4*gg0Cx{cKlU%cCx-U!<%56X5!Dx~3qY zwY^;PnZ#NKz^U^kM54fB-`B)!HZMGrP5bgvC2)6pU7A6X%-lEOSGj@FZ}H*&YNaPg z6fXz0=09y+Ap^*eX$aQZy8*&{ig*_XpE7coZDPaL26`t=Bwe#Mar_l3DMwNGC) zPWOGMyGV{q=PxrVt1mpy5yt46FQ>9R6z*9!zc7Z6Nfz5yyR%*>AUMSg0E|Y$nHXlF z3I51RWxnhDTk6x--{MdBca?Uv^@fuK7j)Ckb)B1b88el9zyQEyR=g;_I(A8M>|$Im z)h9oz4K5Dj%@F>NX22U`IqRU_U1f9Ye^DAcG<)aWbTW)qau!93ky!vf>Tn6rkK%sR%>;JfyKB&0m^fff@S4G!D6#g;?sG0)5HANapE?k}Ynn7jQD zgeY(g@(;M=&*83Dkn7p85CwDFTu@+JvLT$XiW6KWwm4>Lzg2l_0%yH)#*mT;Y6=q* zNvsnIB~f;;g;uxPylYe)IwfnaQ2HLs#rq}t(l350$%lJ8YpYB1GgBkOe9Wgb7~%9p z)z>jc9u*3k7a1mI?9u++RRn-85R2)h4Nh4cwV(Pprg)34Q#7|}ce@qGhl|-DwhsUV z5iFsx~-(~Bw+_B{4AWb4JKqzeKHyds9&bV#kr?RcS^HBMTi)z!c-i!WG2dJxLvUTe-% z2afkzy<2OiTf@}=DO#QHi@h+|o?YR;o6#&n-Z>W$BSo8#fk>=lQiiQ{i=@k4CCR68 z`QqIC!bcP6OdW=oh>!eEQdsO@=`d^A*y44_gQB#_m%w$&1K z=`^?Wbuc55VFm|Rk#A7zP@la08BgSpP9B<8n(x_1G;zY<%Z$=3Dt6mJNzJ-bnPac! z*;er1MGTMO9xuB=5o0_VM_@eM)@|4H&K3r14-KI0IC3rcFYA#dMV3^flvXXKugi+d zv5RH95_X4o^9@Y4*{qFVf{Vvfry<dC!#R_};;c5S3&)p3(Mva%FF?Jp<-+R~Dvwu(+Op1Q2(*|1(7{%X_LYFBe~!MN7wK*B zbLr?{doye2^V!NW+|<&iGi|Trc9-&F4B3Q2uwV@ig=>WX3s}0WE>SCdpd%cRV?KE> zx-d0n16+o4?pP-(X);?y%eJY^k{c8&8=&0mIdFtmJoqIay+^0f@VMNH{v?YXAyU&b zt#u=e^y2nYIU^uxa#5>*rONQ)i;1zfjl+hIk2RlmYmf)1tjXO%oA{$l#F`Y^-jVEp z6W&=k1cwN_oJa|f!oBTr=)0CiPL;-wU=&T^U5dg^LQ;~K9`OWFGQ1HWQM18%WB&;3 z^>>{gSq8qHm?4G;c30)&c56k%B9@M@y|l|%at z)RS2Z`M)$kD(g1vTkO8z1)`2jWE?vWv0Y)#^TOV=bDh77JsfCp!^ps%6K_b7X99v2 z3Sd)OL%U7?vq|>ttrDtJ1$cuJx-c#gFt1_;>yiLRs*qECxy0cEAym%+K7B(9v4%xq z=9mcsh(drt#d61ja6nP%ZH97Tkc@xUc*FEqM)<20v~8mOg_TL^dl?wcwT9E7M)pq| z)D!L7Uue*6&9@vLeC6o6a$9Xv)ykI(WG1=#$4T2(+6PH}8H~Ab>A|(Ssv4CbZA^xs zO^a4N1O;>i7Xqtw=VYhYl-*F(n4&a6Ppt@2s~+*7G@p_I(Xm9pJX+)8N^Emb9hsp||m2_{D^!6jQ7Hz~SOd4-5t z)cZ8I=M}Al(F7=b?~n{&)s*WSS-f4%4C*MF0K{!@@kulPjHU1r{1XgbiD?#6@a@Z@V6SC zQ2bOH`h%byliqGCOwnZQ eJKdrB)hn*6w(+VN{A{eLy!8b05Wl=D;|K@27M3vp diff --git a/html/index.html b/html/index.html index e0fd8595..7f6edac5 100644 --- a/html/index.html +++ b/html/index.html @@ -21,6 +21,7 @@
+ diff --git a/json/config.json b/json/config.json index eec170c8..406a4421 100644 --- a/json/config.json +++ b/json/config.json @@ -43,6 +43,7 @@ "importListen": false, "log": true, "dropbox": false, - "dropboxToken": "" + "dropboxToken": "", + "userMenu": false } diff --git a/json/help.json b/json/help.json index e9455868..af6adc1a 100644 --- a/json/help.json +++ b/json/help.json @@ -42,6 +42,7 @@ "--dropbox ": "enable dropbox integration", "--dropbox-token ": "set dropbox token", "--log ": "enable logging", + "--user-menu ": "enable user menu", "--no-show-config ": "do not show config values", "--no-server ": "do not start server", "--no-auth ": "disable authorization", @@ -70,5 +71,6 @@ "--no-show-file-name ": "do not show file name in view and edit", "--no-dropbox ": "disable dropbox integration", "--no-dropbox-token ": "unset dropbox token", - "--no-log ": "disable logging" + "--no-log ": "disable logging", + "--no-user-menu ": "disable user menu" } diff --git a/json/modules.json b/json/modules.json index ad52b824..d8df33c9 100644 --- a/json/modules.json +++ b/json/modules.json @@ -15,7 +15,9 @@ "operation", "konsole", "terminal", - "cloud" + "terminal-run", + "cloud", + "user-menu" ], "remote": [{ "name": "socket", diff --git a/man/cloudcmd.1 b/man/cloudcmd.1 index 9db5e7d1..bed5672a 100644 --- a/man/cloudcmd.1 +++ b/man/cloudcmd.1 @@ -65,6 +65,7 @@ programs in browser from any computer, mobile or tablet device. --dropbox enable dropbox integration --dropbox-token set dropbox token --log enable logging + --user-menu enable user menu --no-show-config do not show config values --no-server do not start server --no-auth disable authorization @@ -94,6 +95,7 @@ programs in browser from any computer, mobile or tablet device. --no-dropbox disable dropbox integration --no-dropbox-token unset dropbox token --no-log disable logging + --no-user-menu disable user menu .SH RESOURCES AND DOCUMENTATION diff --git a/package.json b/package.json index cc715043..3a7cb3ad 100644 --- a/package.json +++ b/package.json @@ -102,6 +102,7 @@ "execon": "^1.2.0", "express": "^4.13.0", "files-io": "^3.0.0", + "find-up": "^4.0.0", "flop": "^6.0.0", "for-each-key": "^1.0.1", "format-io": "^1.0.0", diff --git a/server/cloudcmd.js b/server/cloudcmd.js index b6193626..5909f6db 100644 --- a/server/cloudcmd.js +++ b/server/cloudcmd.js @@ -11,6 +11,7 @@ const cloudfunc = require(DIR_COMMON + 'cloudfunc'); const authentication = require(DIR + 'auth'); const config = require(DIR + 'config'); const modulas = require(DIR + 'modulas'); +const userMenu = require(DIR + 'user-menu'); const rest = require(DIR + 'rest'); const route = require(DIR + 'route'); const validate = require(DIR + 'validate'); @@ -223,6 +224,7 @@ function cloudcmd(prefix, plugins, modules) { root, }), + userMenu, rest, route({ html: defaultHtml, diff --git a/server/route.js b/server/route.js index e22aeaeb..fcafb8be 100644 --- a/server/route.js +++ b/server/route.js @@ -111,6 +111,7 @@ function indexProcessing(options) { const noConfig = !config('configDialog'); const noConsole = !config('console'); const noTerminal = !config('terminal'); + const noUserMenu = !config('userMenu'); const {panel} = options; let {data} = options; @@ -139,6 +140,13 @@ function indexProcessing(options) { data = data .replace('icon-terminal', 'icon-terminal none'); + if (noUserMenu) + data = data + .replace('icon-user-menu', 'icon-user-menu none'); + else + data = data + .replace('icon-rename', 'icon-rename none'); + const left = rendy(Template.panel, { side : 'left', content : panel, diff --git a/server/route.spec.js b/server/route.spec.js index 2d167d1d..04c62a3a 100644 --- a/server/route.spec.js +++ b/server/route.spec.js @@ -264,6 +264,7 @@ test('cloudcmd: route: realpath: error', async (t) => { options, }); + /*eslint require-atomic-updates:0*/ fs.realpath = realpath; t.ok(/^ENOENT/.test(body), 'should return error'); diff --git a/server/user-menu.js b/server/user-menu.js new file mode 100644 index 00000000..162e6474 --- /dev/null +++ b/server/user-menu.js @@ -0,0 +1,53 @@ +'use strict'; + +const {homedir} = require('os'); +const fs = require('fs'); +const {join} = require('path'); +const {promisify} = require('util'); + +const tryToCatch = require('try-to-catch'); +const findUp = require('find-up'); + +const readFile = promisify(fs.readFile); +const menuName = '.cloudcmd.menu.js'; +const homeMenuPath = join(homedir(), menuName); + +module.exports = async (req, res, next) => { + if (req.url.indexOf('/api/v1/user-menu')) + return next(); + + const {method} = req; + + if (method === 'GET') + return onGET(req.query, res); + + next(); +}; + +async function onGET({dir}, res) { + const [errorFind, currentMenuPath] = await tryToCatch(findUp, [ + menuName, + ], {cwd: dir}); + + if (errorFind && errorFind.code !== 'ENOENT') + return res + .status(404) + .send(e.message); + + if (errorFind && errorFind.code === 'ENOENT') + return res.send(''); + + const menuPath = currentMenuPath || homeMenuPath; + const [e, data] = await tryToCatch(readFile, menuPath, 'utf8'); + + if (!e) + return res.send(data); + + if (e.code !== 'ENOENT') + return res + .status(404) + .send(e.message); + + return res.send(''); +} + diff --git a/server/user-menu.spec.js b/server/user-menu.spec.js new file mode 100644 index 00000000..b350f284 --- /dev/null +++ b/server/user-menu.spec.js @@ -0,0 +1,21 @@ +'use strict'; + +const fs = require('fs'); +const {join} = require('path'); + +const test = require('supertape'); +const serveOnce = require('serve-once'); + +const userMenu = require('./user-menu'); +const {request} = serveOnce(() => userMenu); + +const userMenuPath = join(__dirname, '..', '.cloudcmd.menu.js'); +const userMenuFile = fs.readFileSync(userMenuPath, 'utf8'); + +test('cloudcmd: user menu', async (t) => { + const {body} = await request.get(`/api/v1/user-menu?dir=${__dirname}`); + + t.equal(userMenuFile, body, 'should equal'); + t.end(); +}); + From ffbb96301e46257740d0f5666d3d693f8c22054c Mon Sep 17 00:00:00 2001 From: coderaiser Date: Mon, 13 May 2019 17:51:33 +0300 Subject: [PATCH 0021/1728] feature(key) add ability to rename file with Shift + F6 --- HELP.md | 1 + client/key/index.js | 2 ++ 2 files changed, 3 insertions(+) diff --git a/HELP.md b/HELP.md index 2ec743a8..057d04a7 100644 --- a/HELP.md +++ b/HELP.md @@ -172,6 +172,7 @@ Hot keys | `F5` | copy | `Alt` + `F5` | pack | `F6` | rename/move +| `Shift` + `F6` | rename current file | `F7` | new directory | `Shift + F7` | new file | `F8`, `Delete` | remove diff --git a/client/key/index.js b/client/key/index.js index 627400a4..82156cdf 100644 --- a/client/key/index.js +++ b/client/key/index.js @@ -228,6 +228,8 @@ function KeyProto() { case Key.F6: if (ctrlMeta) CloudCmd.sortPanel('size'); + else if (shift) + DOM.renameCurrent(current); else Operation.show('move'); From bb73d81256fee67937abd193ac6967accf647c70 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Mon, 13 May 2019 17:54:40 +0300 Subject: [PATCH 0022/1728] chore(package) v12.2.0 --- ChangeLog | 23 +++++++++++++++++++++++ HELP.md | 3 ++- README.md | 2 +- package.json | 2 +- 4 files changed, 27 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index 7e99e99a..9ef617d9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,26 @@ +2019.05.13, v12.2.0 + +fix: +- feature(npmignore) add fixture.json +- (operation) set-listeners: alert: noCancel -> cancel +- (cloudcmd) different title + +feature: +- (key) add ability to rename file with Shift + F6 +- (user-menu) add (#221) +- (package) clean-css-loader v2.0.0 +- (package) edward v11.0.0 +- (npmignore) add fixture.json +- (package) dword v11.0.0 +- (package) smalltalk v3.4.0 +- (package) eslint v6.0.0-alpha +- (package) eslint-plugin-node v9.0.1 +- (config) speed up load: series -> parallel +- (cloudcmd) avoid service worker reoload scripts in dev mode +- (package) putout v4.23.0 +- (package) nyc v14.0.0 + + 2019.04.15, v12.1.0 fix: diff --git a/HELP.md b/HELP.md index 057d04a7..4979cfd7 100644 --- a/HELP.md +++ b/HELP.md @@ -1,4 +1,4 @@ -# Cloud Commander v12.1.0 +# Cloud Commander v12.2.0 ### [Main][MainURL] [Blog][BlogURL] Live(![Heroku][Heroku_LIVE_IMG] [Heroku][HerokuURL], ![Now][NOW_LIVE_IMG] [Now][NowURL]) @@ -865,6 +865,7 @@ There are a lot of ways to be involved in `Cloud Commander` development: Version history --------------- +- *2019.05.13*, **[v12.2.0](//github.com/coderaiser/cloudcmd/releases/tag/v12.2.0)** - *2019.04.15*, **[v12.1.0](//github.com/coderaiser/cloudcmd/releases/tag/v12.1.0)** - *2019.04.04*, **[v12.0.2](//github.com/coderaiser/cloudcmd/releases/tag/v12.0.2)** - *2019.04.04*, **[v12.0.1](//github.com/coderaiser/cloudcmd/releases/tag/v12.0.1)** diff --git a/README.md b/README.md index f559b9c0..86050b1a 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Cloud Commander v12.1.0 [![Build Status][BuildStatusIMGURL]][BuildStatusURL] [![Now status][BuildAppveyorIMGURL]][BuildAppveyorURL] [![Codacy][CodacyIMG]][CodacyURL] [![Gitter][GitterIMGURL]][GitterURL] [![OpenCollective](https://opencollective.com/cloudcmd/backers/badge.svg)](#backers) [![OpenCollective](https://opencollective.com/cloudcmd/sponsors/badge.svg)](#sponsors) +# Cloud Commander v12.2.0 [![Build Status][BuildStatusIMGURL]][BuildStatusURL] [![Now status][BuildAppveyorIMGURL]][BuildAppveyorURL] [![Codacy][CodacyIMG]][CodacyURL] [![Gitter][GitterIMGURL]][GitterURL] [![OpenCollective](https://opencollective.com/cloudcmd/backers/badge.svg)](#backers) [![OpenCollective](https://opencollective.com/cloudcmd/sponsors/badge.svg)](#sponsors) ### [Main][MainURL] [Blog][BlogURL] Live([Heroku][HerokuURL], [Now][NowURL]) diff --git a/package.json b/package.json index 3a7cb3ad..60cb9056 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "cloudcmd", - "version": "12.1.0", + "version": "12.2.0", "author": "coderaiser (https://github.com/coderaiser)", "description": "File manager for the web with console and editor", "homepage": "http://cloudcmd.io", From ee809e1fe7e98a271a11cb31d11a39a85f38df54 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Mon, 13 May 2019 17:59:19 +0300 Subject: [PATCH 0023/1728] docs(readme) read --- HELP.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/HELP.md b/HELP.md index 4979cfd7..7492e230 100644 --- a/HELP.md +++ b/HELP.md @@ -467,7 +467,7 @@ Some config options can be overridden with environment variables, such as: ### User Menu You can enable `user menu` with help of a flag `--user-menu` (consider that file rename using `F2` will be disabled). -When you press `F2` Cloud Commander will a file `.cloudcmd.menu.js` by walking up parent directories, if can't read it will try to read `~/.cloudcmd.menu.js`. +When you press `F2` Cloud Commander will read a file `.cloudcmd.menu.js` by walking up parent directories, if can't read it will try to read `~/.cloudcmd.menu.js`. Let's consider example `user menu` works file: ```js From e7f8769f61f5ece5e0fe6cb07a32ed085df85e21 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Mon, 13 May 2019 18:01:01 +0300 Subject: [PATCH 0024/1728] docs(readme) bear in mind --- HELP.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/HELP.md b/HELP.md index 7492e230..0b945d34 100644 --- a/HELP.md +++ b/HELP.md @@ -466,8 +466,9 @@ Some config options can be overridden with environment variables, such as: ### User Menu -You can enable `user menu` with help of a flag `--user-menu` (consider that file rename using `F2` will be disabled). +You can enable `user menu` with help of a flag `--user-menu` (bear in mind that file rename using `F2` will be disabled, but you can use `Shift` + `F6` or `F2` + `F2`). When you press `F2` Cloud Commander will read a file `.cloudcmd.menu.js` by walking up parent directories, if can't read it will try to read `~/.cloudcmd.menu.js`. + Let's consider example `user menu` works file: ```js From aedafe1f4b7b39f492de1c2bb65a21188844e37e Mon Sep 17 00:00:00 2001 From: coderaiser Date: Mon, 13 May 2019 18:01:40 +0300 Subject: [PATCH 0025/1728] docs(help) UserMenu: optional --- HELP.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/HELP.md b/HELP.md index 0b945d34..df07d591 100644 --- a/HELP.md +++ b/HELP.md @@ -479,8 +479,8 @@ module.exports = { 'D - Build Dev': async ({CloudCmd}) => { await CloudCmd.TerminalRun.show({ command: 'npm run build:client:dev', - autoClose: false, - closeMessage: 'Press any button to close Terminal', + autoClose: false, // optional + closeMessage: 'Press any button to close Terminal', // optional }); CloudCmd.refresh(); @@ -488,7 +488,7 @@ module.exports = { 'P - Build Prod': async ({CloudCmd}) => { await CloudCmd.TerminalRun.show({ command: 'npm run build:client', - autoClose: true, + autoClose: true, // optional }); CloudCmd.refresh(); From f4f88da945c43cc6568461effc29325675acd025 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Mon, 13 May 2019 18:02:19 +0300 Subject: [PATCH 0026/1728] docs(help) to -> two --- HELP.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/HELP.md b/HELP.md index df07d591..e33550a7 100644 --- a/HELP.md +++ b/HELP.md @@ -500,7 +500,7 @@ You will have ability to run one of this 3 commands with help of double click, e #### User Menu API -Here you can find `API` that can be used in **User Menu**. **DOM** and **CloudCmd** to main objects you receive in arguments list using destructuring. +Here you can find `API` that can be used in **User Menu**. **DOM** and **CloudCmd** two main objects you receive in arguments list using destructuring. **DOM** contains all base functions of `Cloud Commander` (rename, remove, download etc); From e6f173df3753bea1e569d223e784f692c3ff1854 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Mon, 13 May 2019 18:11:51 +0300 Subject: [PATCH 0027/1728] chore(travis) allow_failures: node 12 --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index e05069a7..5306856d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,6 +7,7 @@ node_js: matrix: allow_failures: - os: windows + - node_js: 12 os: - linux From a727d6f6ea690ea8fe4bea96d74721d9816f07c1 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Tue, 14 May 2019 11:29:17 +0300 Subject: [PATCH 0028/1728] feature(cloudcmd) deprecate plugins --- HELP.md | 2 +- README.md | 2 +- server/plugins.js | 13 +++++++++---- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/HELP.md b/HELP.md index e33550a7..b000abdd 100644 --- a/HELP.md +++ b/HELP.md @@ -667,7 +667,7 @@ const modules = { app.use(prefix, cloudcmd({ socket, // used by Config, Edit (optional) and Console (required) config, // config data (optional) - plugins, // optional + plugins, // DEPRECATED, use User Menu instead modules, // optional })); diff --git a/README.md b/README.md index 86050b1a..9f371272 100644 --- a/README.md +++ b/README.md @@ -110,7 +110,7 @@ const modules = { app.use(prefix, cloudcmd({ socket, // used by Config, Edit (optional) and Console (required) config, // config data (optional) - plugins, // optional + plugins, // DEPRECATED, use User Menu instead modules, // optional })); diff --git a/server/plugins.js b/server/plugins.js index 2ab0a497..a9f4c8bb 100644 --- a/server/plugins.js +++ b/server/plugins.js @@ -1,7 +1,8 @@ 'use strict'; +const {deprecate} = require('util'); const currify = require('currify'); -const files = require('files-io'); +const {readPipe} = require('files-io'); module.exports = currify((plugins, req, res, next) => { if (req.url !== '/plugins.js') @@ -12,8 +13,12 @@ module.exports = currify((plugins, req, res, next) => { if (!plugins || !plugins.length) return res.send(''); - files.readPipe(plugins, res).catch((e) => { - res.end(e.message); - }); + readPlugin(plugins, res); }); +const readPlugin = deprecate((plugins, res) => { + readPipe(plugins, res).catch((e) => { + res.end(e.message); + }); +}, 'plugins deprecated. Use user menu instead', 'DEP0001'); + From 1dbcf92336f642addfcf1ad742dbbde8ed53cb3b Mon Sep 17 00:00:00 2001 From: coderaiser Date: Tue, 14 May 2019 17:52:56 +0300 Subject: [PATCH 0029/1728] refactor(user-menu) menuName --- server/cloudcmd.js | 5 ++++- server/user-menu.js | 12 ++++++------ server/user-menu.spec.js | 10 ++++++++-- 3 files changed, 18 insertions(+), 9 deletions(-) diff --git a/server/cloudcmd.js b/server/cloudcmd.js index 5909f6db..873e4624 100644 --- a/server/cloudcmd.js +++ b/server/cloudcmd.js @@ -224,7 +224,10 @@ function cloudcmd(prefix, plugins, modules) { root, }), - userMenu, + userMenu({ + menuName: '.cloudcmd.menu.js', + }), + rest, route({ html: defaultHtml, diff --git a/server/user-menu.js b/server/user-menu.js index 162e6474..82a02c87 100644 --- a/server/user-menu.js +++ b/server/user-menu.js @@ -6,25 +6,24 @@ const {join} = require('path'); const {promisify} = require('util'); const tryToCatch = require('try-to-catch'); +const currify = require('currify'); const findUp = require('find-up'); const readFile = promisify(fs.readFile); -const menuName = '.cloudcmd.menu.js'; -const homeMenuPath = join(homedir(), menuName); -module.exports = async (req, res, next) => { +module.exports = currify(async({menuName}, req, res, next) => { if (req.url.indexOf('/api/v1/user-menu')) return next(); const {method} = req; if (method === 'GET') - return onGET(req.query, res); + return onGET(menuName, req.query, res); next(); -}; +}); -async function onGET({dir}, res) { +async function onGET(menuName, {dir}, res) { const [errorFind, currentMenuPath] = await tryToCatch(findUp, [ menuName, ], {cwd: dir}); @@ -37,6 +36,7 @@ async function onGET({dir}, res) { if (errorFind && errorFind.code === 'ENOENT') return res.send(''); + const homeMenuPath = join(homedir(), menuName); const menuPath = currentMenuPath || homeMenuPath; const [e, data] = await tryToCatch(readFile, menuPath, 'utf8'); diff --git a/server/user-menu.spec.js b/server/user-menu.spec.js index b350f284..0f2f0a3b 100644 --- a/server/user-menu.spec.js +++ b/server/user-menu.spec.js @@ -7,13 +7,19 @@ const test = require('supertape'); const serveOnce = require('serve-once'); const userMenu = require('./user-menu'); -const {request} = serveOnce(() => userMenu); +const {request} = serveOnce(userMenu); const userMenuPath = join(__dirname, '..', '.cloudcmd.menu.js'); const userMenuFile = fs.readFileSync(userMenuPath, 'utf8'); test('cloudcmd: user menu', async (t) => { - const {body} = await request.get(`/api/v1/user-menu?dir=${__dirname}`); + const options = { + menuName: '.cloudcmd.menu.js', + }; + + const {body} = await request.get(`/api/v1/user-menu?dir=${__dirname}`, { + options, + }); t.equal(userMenuFile, body, 'should equal'); t.end(); From 601a7f9310b7f20550c228bd27214d2dd6fde2dd Mon Sep 17 00:00:00 2001 From: coderaiser Date: Tue, 14 May 2019 17:53:05 +0300 Subject: [PATCH 0030/1728] test(route) buttons: no user menu --- server/route.spec.js | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/server/route.spec.js b/server/route.spec.js index 04c62a3a..f9446b66 100644 --- a/server/route.spec.js +++ b/server/route.spec.js @@ -39,6 +39,36 @@ test('cloudcmd: route: buttons: no console', async (t) => { t.end(); }); +test('cloudcmd: route: buttons: user menu: disabled', async (t) => { + const options = { + config: { + userMenu: false, + }, + }; + + const {body} = await request.get('/', { + options, + }); + + t.ok(/icon-user-menu none/.test(body), 'should hide console'); + t.end(); +}); + +test('cloudcmd: route: buttons: user menu: enabled', async (t) => { + const options = { + config: { + userMenu: true, + }, + }; + + const {body} = await request.get('/', { + options, + }); + + t.ok(/icon-rename none/.test(body), 'should hide console'); + t.end(); +}); + test('cloudcmd: route: buttons: console', async (t) => { const config = { console: true, From ffd8a54d1e5767f8e928c662bd37741d614c8fea Mon Sep 17 00:00:00 2001 From: coderaiser Date: Tue, 14 May 2019 17:58:19 +0300 Subject: [PATCH 0031/1728] test(user-menu) getUserMenu: coverage --- client/modules/user-menu/get-user-menu.spec.js | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/client/modules/user-menu/get-user-menu.spec.js b/client/modules/user-menu/get-user-menu.spec.js index 77ee4fea..e0354114 100644 --- a/client/modules/user-menu/get-user-menu.spec.js +++ b/client/modules/user-menu/get-user-menu.spec.js @@ -1,6 +1,7 @@ 'use strict'; const test = require('supertape'); +const stub = require('@cloudcmd/stub'); const getUserMenu = require('./get-user-menu'); test('user-menu: getUserMenu', (t) => { @@ -21,9 +22,18 @@ test('user-menu: getUserMenu', (t) => { test('user-menu: getUserMenu: no args', (t) => { const result = getUserMenu(); - const [key] = Object.keys(result); + const renameCurrent = stub(); + const DOM = { + renameCurrent, + }; - t.equal(key, 'F2 - Rename file', 'should equal'); + const name = 'F2 - Rename file'; + + result[name]({ + DOM, + }); + + t.ok(renameCurrent.called, 'should call renameCurrent'); t.end(); }); From 6574d45939cf90d5912e5af712d3fa44cadf6507 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Tue, 14 May 2019 18:40:08 +0300 Subject: [PATCH 0032/1728] feature(user-menu) add ability to navigate with j, k --- client/modules/user-menu/index.js | 26 +++-- client/modules/user-menu/navigate.js | 35 +++++++ client/modules/user-menu/navigate.spec.js | 110 ++++++++++++++++++++++ 3 files changed, 161 insertions(+), 10 deletions(-) create mode 100644 client/modules/user-menu/navigate.js create mode 100644 client/modules/user-menu/navigate.spec.js diff --git a/client/modules/user-menu/index.js b/client/modules/user-menu/index.js index 78e1f5dc..f1b6512c 100644 --- a/client/modules/user-menu/index.js +++ b/client/modules/user-menu/index.js @@ -11,6 +11,7 @@ const createElement = require('@cloudcmd/create-element'); const Images = require('../../dom/images'); const getUserMenu = require('./get-user-menu'); +const navigate = require('./navigate'); const loadCSS = promisify(load.css); @@ -83,21 +84,26 @@ const onDblClick = currify(async (options, userMenu, e) => { }); const onKeyDown = currify(async (keys, options, userMenu, e) => { - const {keyCode} = e; + const { + keyCode, + target, + } = e; const key = e.key.toUpperCase(); - let value; - - if (keyCode === Key.ENTER) - ({value} = e.target); - else if (keys.includes(key)) - value = options.find(beginWith(key)); - else - return; - e.preventDefault(); e.stopPropagation(); + let value; + + if (keyCode === Key.ESC) + return hide(); + else if (keyCode === Key.ENTER) + ({value} = target); + else if (keys.includes(key)) + value = options.find(beginWith(key)); + else + return navigate(target, e); + await runUserMenu(value, options, userMenu); }); diff --git a/client/modules/user-menu/navigate.js b/client/modules/user-menu/navigate.js new file mode 100644 index 00000000..67c12e0a --- /dev/null +++ b/client/modules/user-menu/navigate.js @@ -0,0 +1,35 @@ +'use strict'; + +const { + J, + K, + UP, + DOWN, +} = require('../../key/key.js'); + +module.exports = (el, {keyCode}) => { + if (keyCode === DOWN || keyCode === J) + return down(el); + + if (keyCode === UP || keyCode === K) + return up(el); +}; + +function down(el) { + const {length} = el; + + if (el.selectedIndex === length - 1) + el.selectedIndex = 0; + else + ++el.selectedIndex; +} + +function up(el) { + const {length} = el; + + if (!el.selectedIndex) + el.selectedIndex = length - 1; + else + --el.selectedIndex; +} + diff --git a/client/modules/user-menu/navigate.spec.js b/client/modules/user-menu/navigate.spec.js new file mode 100644 index 00000000..7a5ba70b --- /dev/null +++ b/client/modules/user-menu/navigate.spec.js @@ -0,0 +1,110 @@ +'use strict'; + +const test = require('supertape'); +const navigate = require('./navigate'); + +const { + UP, + DOWN, + J, + K, +} = require('../../key/key.js'); + +test('cloudcmd: user-menu: navigate: DOWN', (t) => { + const el = { + length: 3, + selectedIndex: 0, + }; + + navigate(el, { + keyCode: DOWN, + }); + + t.equal(el.selectedIndex, 1); + t.end(); +}); + +test('cloudcmd: user-menu: navigate: J', (t) => { + const el = { + length: 3, + selectedIndex: 0, + }; + + navigate(el, { + keyCode: J, + }); + + t.equal(el.selectedIndex, 1); + t.end(); +}); + +test('cloudcmd: user-menu: navigate: DOWN: bottom', (t) => { + const el = { + length: 3, + selectedIndex: 2, + }; + + navigate(el, { + keyCode: DOWN, + }); + + t.equal(el.selectedIndex, 0); + t.end(); +}); + +test('cloudcmd: user-menu: navigate: K', (t) => { + const el = { + length: 3, + selectedIndex: 2, + }; + + navigate(el, { + keyCode: K, + }); + + t.equal(el.selectedIndex, 1); + t.end(); +}); + +test('cloudcmd: user-menu: navigate: UP', (t) => { + const el = { + length: 3, + selectedIndex: 2, + }; + + navigate(el, { + keyCode: UP, + }); + + t.equal(el.selectedIndex, 1); + t.end(); +}); + +test('cloudcmd: user-menu: navigate: UP: top', (t) => { + const el = { + length: 3, + selectedIndex: 0, + }; + + navigate(el, { + keyCode: UP, + }); + + t.equal(el.selectedIndex, 2); + t.end(); +}); + +test('cloudcmd: user-menu: navigate', (t) => { + const el = { + length: 3, + selectedIndex: 0, + }; + + navigate(el, { + keyCode: 0, + }); + + t.equal(el.selectedIndex, 0, 'should not change'); + t.end(); +}); + From 0b3348ee77ff5aec72381f47bc916f1a97919a25 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Wed, 15 May 2019 13:48:52 +0300 Subject: [PATCH 0033/1728] fix(dom) renameCurrent: try-to-promise RESTful.mv --- client/dom/index.js | 22 ++++++++++++---------- common/try-to-promisify.js | 11 +++++++++++ 2 files changed, 23 insertions(+), 10 deletions(-) create mode 100644 common/try-to-promisify.js diff --git a/client/dom/index.js b/client/dom/index.js index 271b563d..e2811916 100644 --- a/client/dom/index.js +++ b/client/dom/index.js @@ -8,6 +8,7 @@ const jonny = require('jonny/legacy'); const tryToCatch = require('try-to-catch/legacy'); const Util = require('../../common/util'); +const tryToPromisify = require('../../common/try-to-promisify'); const Images = require('./images'); const load = require('./load'); @@ -763,6 +764,7 @@ function CmdProto() { if (e) return; + const isExist = !!DOM.getCurrentByName(to); const dirPath = DOM.getCurrentDirPath(); @@ -774,16 +776,16 @@ function CmdProto() { to : dirPath + to, }; - RESTful.mv(files, (error) => { - if (error) - return; - - DOM.setCurrentName(to, current); - Storage.remove(dirPath); - - if (isExist) - CloudCmd.refresh(); - }); + const [error] = await tryToPromisify(RESTful.mv, files); + + if (error) + return; + + DOM.setCurrentName(to, current); + Storage.remove(dirPath); + + if (isExist) + CloudCmd.refresh(); }; /** diff --git a/common/try-to-promisify.js b/common/try-to-promisify.js new file mode 100644 index 00000000..ab4860d2 --- /dev/null +++ b/common/try-to-promisify.js @@ -0,0 +1,11 @@ +'use strict'; + +const {promisify} = require('es6-promisify'); +const tryToCatch = require('try-to-catch/legacy'); + +module.exports = (fn, ...args) => { + const promise = promisify(fn); + + return tryToCatch(promise, ...args); +}; + From 21ac9bb45bcbc7e1eb00627d299757c533226e1d Mon Sep 17 00:00:00 2001 From: coderaiser Date: Wed, 15 May 2019 18:24:50 +0300 Subject: [PATCH 0034/1728] feature(user-menu) add error handling --- client/dom/dialog.js | 5 ++++- client/modules/user-menu/index.js | 16 ++++++++++++++-- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/client/dom/dialog.js b/client/dom/dialog.js index 157e6923..904e9f4f 100644 --- a/client/dom/dialog.js +++ b/client/dom/dialog.js @@ -10,7 +10,10 @@ const { const title = 'Cloud Commander'; -module.exports.alert = (...a) => alert(title, ...a); +module.exports.alert = (...a) => alert(title, ...a, { + cancel: false, +}); + module.exports.prompt = (...a) => prompt(title, ...a); module.exports.confirm = (...a) => confirm(title, ...a); module.exports.progress = (...a) => progress(title, ...a); diff --git a/client/modules/user-menu/index.js b/client/modules/user-menu/index.js index f1b6512c..995d58d9 100644 --- a/client/modules/user-menu/index.js +++ b/client/modules/user-menu/index.js @@ -8,8 +8,11 @@ const currify = require('currify/legacy'); const {promisify} = require('es6-promisify'); const load = require('load.js'); const createElement = require('@cloudcmd/create-element'); +const tryCatch = require('try-catch'); +const tryToCatch = require('try-to-catch/legacy'); const Images = require('../../dom/images'); +const Dialog = require('../../dom/dialog'); const getUserMenu = require('./get-user-menu'); const navigate = require('./navigate'); @@ -40,7 +43,11 @@ async function show() { const {dirPath} = CurrentInfo; const res = await fetch(`/api/v1/user-menu?dir=${dirPath}`); - const userMenu = getUserMenu(await res.text()); + const [error, userMenu] = tryCatch(getUserMenu, await res.text()); + + if (error) + return Dialog.alert(`User menu error: ${error.message}`); + const options = Object.keys(userMenu); const el = createElement('select', { @@ -50,6 +57,7 @@ async function show() { }); const keys = options.map(getKey); + el.addEventListener('keydown', onKeyDown(keys, options, userMenu)); el.addEventListener('dblclick', onDblClick(options, userMenu)); @@ -88,6 +96,7 @@ const onKeyDown = currify(async (keys, options, userMenu, e) => { keyCode, target, } = e; + const key = e.key.toUpperCase(); e.preventDefault(); @@ -110,9 +119,12 @@ const onKeyDown = currify(async (keys, options, userMenu, e) => { const runUserMenu = async (value, options, userMenu) => { hide(); - await userMenu[value]({ + const [e] = await tryToCatch(userMenu[value], { DOM, CloudCmd, }); + + if (e) + Dialog.alert(e.stack); }; From aa8c944fe9ccd7c9e4b8d3384b6728765dd219bc Mon Sep 17 00:00:00 2001 From: coderaiser Date: Wed, 15 May 2019 18:26:35 +0300 Subject: [PATCH 0035/1728] chore(madrun) lint: add .cloudcmd.menu.js --- madrun.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/madrun.js b/madrun.js index 2ce906ed..48af04d4 100644 --- a/madrun.js +++ b/madrun.js @@ -31,7 +31,7 @@ module.exports = { 'lint': () => run(['putout', 'lint:*', 'spell']), 'lint:server': () => `eslint -c .eslintrc.server ${dirs} --ignore-pattern *.spec.js`, 'lint:test': () => `eslint --ignore-pattern '!.*' ${dirsTest}`, - 'lint:client': () => 'eslint --env browser client', + 'lint:client': () => 'eslint --env browser client --ignore-pattern .cloudcmd.menu.js', 'lint:css': () => 'stylelint css/*.css', 'spell': () => 'yaspeller .', 'fix:lint': () => run(['putout', 'lint:*'], '--fix'), @@ -86,6 +86,6 @@ module.exports = { 'build:client': () => run('6to5:client'), 'build:client:dev': () => run('6to5:client:dev'), 'heroku-postbuild': () => run('6to5:client'), - 'putout': () => 'putout bin client server common test', + 'putout': () => 'putout bin client server common test .cloudcmd.menu.js', }; From dbbeb063e7c236d1f7448e01d37847d644297b79 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Wed, 15 May 2019 18:30:20 +0300 Subject: [PATCH 0036/1728] chore(package) mv es6-promisify to dependencies --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 60cb9056..643c7d56 100644 --- a/package.json +++ b/package.json @@ -99,6 +99,7 @@ "deepword": "^6.0.0", "dword": "^11.0.0", "edward": "^11.0.0", + "es6-promisify": "^6.0.1", "execon": "^1.2.0", "express": "^4.13.0", "files-io": "^3.0.0", @@ -156,7 +157,6 @@ "domtokenlist-shim": "^1.2.0", "emitify": "^3.0.2", "es6-promise": "^4.0.5", - "es6-promisify": "^6.0.0", "eslint": "^6.0.0-alpha", "eslint-plugin-node": "^9.0.1", "eslint-plugin-putout": "^1.0.1", From 5fb5652f3dbb060490656bbd00ae10f6c36d9695 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Fri, 17 May 2019 14:00:52 +0300 Subject: [PATCH 0037/1728] refactor(cloudfunc) getSize: regexp --- common/cloudfunc.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/cloudfunc.js b/common/cloudfunc.js index 44020303..d30460f5 100644 --- a/common/cloudfunc.js +++ b/common/cloudfunc.js @@ -244,7 +244,7 @@ function getSize(file) { type, } = file; - if (type === 'directory') + if (/^directory$/.test(type)) return '<dir>'; if (/link/.test(type)) From 9ff5982a5bbc143c81f0f5c70403a6d0e0e05713 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Fri, 17 May 2019 19:13:58 +0300 Subject: [PATCH 0038/1728] feature(user-menu) add default option: create user menu --- client/modules/user-menu/default-menu.js | 38 +++++++++++++++++++++++ client/modules/user-menu/get-user-menu.js | 6 +--- client/modules/user-menu/index.js | 3 ++ 3 files changed, 42 insertions(+), 5 deletions(-) create mode 100644 client/modules/user-menu/default-menu.js diff --git a/client/modules/user-menu/default-menu.js b/client/modules/user-menu/default-menu.js new file mode 100644 index 00000000..ed940249 --- /dev/null +++ b/client/modules/user-menu/default-menu.js @@ -0,0 +1,38 @@ +'use strict'; + +const data = `'use strict'; + +module.exports = { + 'F2 - Rename file': async ({DOM}) => { + await DOM.renameCurrent(); + }, +}; +`; + +module.exports = { + 'F2 - Rename file': async ({DOM}) => { + await DOM.renameCurrent(); + }, + + 'C - Create User Menu File': async ({DOM, CloudCmd, tryToPromisify}) => { + const { + Dialog, + RESTful, + CurrentInfo, + } = DOM; + + const {dirPath} = CurrentInfo; + const path = `${dirPath}/.cloudcmd.menu.js`; + + const [e] = await tryToPromisify(RESTful.write, path, data); + + if (e) + return Dialog.alert(e); + + await tryToPromisify(CloudCmd.refresh); + DOM.setCurrentByName('.cloudcmd.menu.js'); + + await CloudCmd.EditFile.show(); + }, +}; + diff --git a/client/modules/user-menu/get-user-menu.js b/client/modules/user-menu/get-user-menu.js index 4b3d8923..206161bb 100644 --- a/client/modules/user-menu/get-user-menu.js +++ b/client/modules/user-menu/get-user-menu.js @@ -1,10 +1,6 @@ 'use strict'; -const defaultUserMenu = { - 'F2 - Rename file': async ({DOM}) => { - DOM.renameCurrent(); - }, -}; +const defaultUserMenu = require('./default-menu.js'); module.exports = (menuFn) => { if (!menuFn) diff --git a/client/modules/user-menu/index.js b/client/modules/user-menu/index.js index 995d58d9..03a048f2 100644 --- a/client/modules/user-menu/index.js +++ b/client/modules/user-menu/index.js @@ -11,6 +11,8 @@ const createElement = require('@cloudcmd/create-element'); const tryCatch = require('try-catch'); const tryToCatch = require('try-to-catch/legacy'); +const tryToPromisify = require('../../../common/try-to-promisify.js'); + const Images = require('../../dom/images'); const Dialog = require('../../dom/dialog'); const getUserMenu = require('./get-user-menu'); @@ -122,6 +124,7 @@ const runUserMenu = async (value, options, userMenu) => { const [e] = await tryToCatch(userMenu[value], { DOM, CloudCmd, + tryToPromisify, }); if (e) From 1b174d5f2f565e5b96862baafa3f48a6cff6e7b9 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Fri, 17 May 2019 19:19:51 +0300 Subject: [PATCH 0039/1728] refactor(client) refresh: promisify --- client/client.js | 5 +++-- client/modules/operation/index.js | 18 +++++++++--------- client/modules/user-menu/default-menu.js | 2 +- 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/client/client.js b/client/client.js index 8823df4f..28f36737 100644 --- a/client/client.js +++ b/client/client.js @@ -7,6 +7,7 @@ const inherits = require('inherits'); const rendy = require('rendy/legacy'); const exec = require('execon'); const load = require('load.js'); +const {promisify} = require('es6-promisify'); const pascalCase = require('just-pascal-case'); const isDev = process.env.NODE_ENV === 'development'; @@ -318,7 +319,7 @@ function CloudCmdProto(DOM) { func(...args); }; - this.refresh = (options = {}, callback) => { + this.refresh = promisify((options = {}, callback) => { if (!callback && typeof options === 'function') { callback = options; options = {}; @@ -340,7 +341,7 @@ function CloudCmdProto(DOM) { noCurrent, currentName, }, callback); - }; + }); /** * Функция загружает json-данные о Файловой Системе diff --git a/client/modules/operation/index.js b/client/modules/operation/index.js index 451ccd25..c96dda52 100644 --- a/client/modules/operation/index.js +++ b/client/modules/operation/index.js @@ -319,15 +319,15 @@ function deleteSilent(files = DOM.getActiveFiles()) { const currentName = DOM.getCurrentName(); const nextCurrentName = getNextCurrentName(currentName, names, removedNames); - deleteFn(path + query, removedNames, () => { - CloudCmd.refresh(() => { - const names = Info.files.map(DOM.getCurrentName); - const isCurrent = names.includes(currentName); - - const name = isCurrent ? currentName : nextCurrentName; - - DOM.setCurrentByName(name); - }); + deleteFn(path + query, removedNames, async () => { + await CloudCmd.refresh(); + + const names = Info.files.map(DOM.getCurrentName); + const isCurrent = names.includes(currentName); + + const name = isCurrent ? currentName : nextCurrentName; + + DOM.setCurrentByName(name); }); } diff --git a/client/modules/user-menu/default-menu.js b/client/modules/user-menu/default-menu.js index ed940249..3a0eaa23 100644 --- a/client/modules/user-menu/default-menu.js +++ b/client/modules/user-menu/default-menu.js @@ -29,7 +29,7 @@ module.exports = { if (e) return Dialog.alert(e); - await tryToPromisify(CloudCmd.refresh); + await CloudCmd.refresh(); DOM.setCurrentByName('.cloudcmd.menu.js'); await CloudCmd.EditFile.show(); From edf525f269788ab383b67967acac26e98ce0282c Mon Sep 17 00:00:00 2001 From: coderaiser Date: Fri, 17 May 2019 20:08:21 +0300 Subject: [PATCH 0040/1728] refactor(dom) RESTful: promisify --- client/client.js | 35 +-- client/dom/files.js | 13 +- client/dom/index.js | 84 +++--- client/dom/rest.js | 357 +++++++++++------------ client/key/index.js | 2 +- client/modules/config.js | 5 +- client/modules/menu.js | 10 +- client/modules/operation/index.js | 28 +- client/modules/user-menu/default-menu.js | 4 +- client/modules/user-menu/index.js | 4 +- common/callbackify.js | 14 + common/callbackify.spec.js | 31 ++ 12 files changed, 300 insertions(+), 287 deletions(-) create mode 100644 common/callbackify.js create mode 100644 common/callbackify.spec.js diff --git a/client/client.js b/client/client.js index 28f36737..00f8f77b 100644 --- a/client/client.js +++ b/client/client.js @@ -97,7 +97,6 @@ function CloudCmdProto(DOM) { */ this.loadDir = (params, callback) => { const p = params; - const refresh = p.isRefresh; const { @@ -354,7 +353,7 @@ function CloudCmdProto(DOM) { * */ function ajaxLoad(path, options, panel, callback) { - const create = (error, json) => { + const create = async (error, json) => { const {RESTful} = DOM; const name = options.currentName || Info.name; const obj = jonny.parse(json); @@ -373,25 +372,23 @@ function CloudCmdProto(DOM) { order, }); - RESTful.read(path + query, 'json', (error, obj) => { - if (error) - return; + const newObj = await RESTful.read(path + query, 'json'); + + /* eslint require-atomic-updates:0 */ + options.sort = sort; + options.order = order; + + createFileTable(newObj, panel, options, () => { + if (isRefresh && !noCurrent) + DOM.setCurrentByName(name); - options.sort = sort; - options.order = order; - - createFileTable(obj, panel, options, () => { - if (isRefresh && !noCurrent) - DOM.setCurrentByName(name); - - exec(callback); - }); - - if (!CloudCmd.config('dirStorage')) - return; - - Storage.set(path, obj); + exec(callback); }); + + if (!CloudCmd.config('dirStorage')) + return; + + Storage.set(path, newObj); }; if (!options) diff --git a/client/dom/files.js b/client/dom/files.js index 9897df93..1c638275 100644 --- a/client/dom/files.js +++ b/client/dom/files.js @@ -123,17 +123,12 @@ function getConfig(callback) { let is; if (!Promises.config) - Promises.config = new Promise((resolve, reject) => { + Promises.config = () => { is = true; - RESTful.Config.read((error, data) => { - if (error) - return reject(error); - - resolve(data); - }); - }); + return RESTful.Config.read(); + }; - Promises.config.then((data) => { + Promises.config().then((data) => { is = false; callback(null, data); diff --git a/client/dom/index.js b/client/dom/index.js index e2811916..e89891bc 100644 --- a/client/dom/index.js +++ b/client/dom/index.js @@ -8,7 +8,7 @@ const jonny = require('jonny/legacy'); const tryToCatch = require('try-to-catch/legacy'); const Util = require('../../common/util'); -const tryToPromisify = require('../../common/try-to-promisify'); +const callbackify = require('../../common/callbackify'); const Images = require('./images'); const load = require('./load'); @@ -17,6 +17,8 @@ const RESTful = require('./rest'); const Storage = require('./storage'); const Dialog = require('./dialog'); +const read = callbackify(RESTful.read); + const currentFile = require('./current-file'); const DOMTree = require('./dom-tree'); @@ -83,7 +85,7 @@ function CmdProto() { promptNew('file'); }; - function promptNew(typeName, type) { + async function promptNew(typeName, type) { const {Dialog} = DOM; const dir = DOM.getCurrentDirPath(); const msg = 'New ' + typeName || 'File'; @@ -97,31 +99,24 @@ function CmdProto() { }; const name = getName(); - const cancel = false; - Dialog.prompt(msg, name, {cancel}).then((name) => { - if (!name) - return; + const [, newName] = await tryToCatch(Dialog.prompt, msg, name); + + if (!newName) + return; + + const path = (type) => { + const result = dir + newName; - const path = (type) => { - const result = dir + name; - - if (!type) - return result; - - return result + type; - }; + if (!type) + return result; - RESTful.write(path(type), (error) => { - if (error) - return; - - const currentName = name; - - CloudCmd.refresh({ - currentName, - }); - }); + return result + type; + }; + + await RESTful.write(path(type)); + await CloudCmd.refresh({ + currentName: newName, }); } @@ -236,7 +231,7 @@ function CmdProto() { * get size * @currentFile */ - this.loadCurrentSize = (callback, currentFile) => { + this.loadCurrentSize = callbackify(async (currentFile) => { const current = currentFile || DOM.getCurrentFile(); const query = '?size'; const link = DOM.getCurrentPath(current); @@ -246,15 +241,13 @@ function CmdProto() { if (name === '..') return; - RESTful.read(link + query, (error, size) => { - if (error) - return; - - DOM.setCurrentSize(size, current); - exec(callback, current); - Images.hide(); - }); - }; + const size = await RESTful.read(link + query); + + DOM.setCurrentSize(size, current); + Images.hide(); + + return current; + }); /** * load hash @@ -266,7 +259,7 @@ function CmdProto() { const query = '?hash'; const link = DOM.getCurrentPath(current); - RESTful.read(link + query, callback); + read(link + query, callback); }; /** @@ -279,7 +272,7 @@ function CmdProto() { const query = '?time'; const link = DOM.getCurrentPath(current); - RESTful.read(link + query, callback); + read(link + query, callback); }; /** @@ -349,7 +342,7 @@ function CmdProto() { } if (isDir) - return RESTful.read(path, func); + return read(path, func); DOM.checkStorageHash(path, (error, equal, hashNew) => { if (error) @@ -359,7 +352,7 @@ function CmdProto() { return DOM.getDataFromStorage(path, callback); hash = hashNew; - RESTful.read(path, func); + read(path, func); }); }; @@ -370,9 +363,10 @@ function CmdProto() { * @currentFile */ this.saveCurrentData = (url, data, callback, query = '') => { - DOM.RESTful.write(url + query, data, (error) => { - !error && DOM.saveDataToStorage(url, data); - }); + RESTful.write(url + query, data) + .then(() => { + DOM.saveDataToStorage(url, data); + }); }; /** @@ -543,7 +537,6 @@ function CmdProto() { */ this.checkStorageHash = (name, callback) => { const {parallel} = exec; - const loadHash = DOM.loadCurrentHash; const nameHash = name + '-hash'; const getStoreHash = exec.with(Storage.get, nameHash); @@ -553,7 +546,7 @@ function CmdProto() { if (typeof callback !== 'function') throw Error('callback should be a function!'); - parallel([loadHash, getStoreHash], (error, loadHash, storeHash) => { + parallel([DOM.loadCurrentHash, getStoreHash], (error, loadHash, storeHash) => { let equal; const isContain = /error/.test(loadHash); @@ -776,10 +769,7 @@ function CmdProto() { to : dirPath + to, }; - const [error] = await tryToPromisify(RESTful.mv, files); - - if (error) - return; + await RESTful.mv(files); DOM.setCurrentName(to, current); Storage.remove(dirPath); diff --git a/client/dom/rest.js b/client/dom/rest.js index f6acd1b9..e6c84b7b 100644 --- a/client/dom/rest.js +++ b/client/dom/rest.js @@ -3,15 +3,18 @@ /* global CloudCmd, DOM */ const itype = require('itype/legacy'); +const {promisify} = require('es6-promisify'); const {FS} = require('../../common/cloudfunc'); const {encode} = require('../../common/entity'); -module.exports = new RESTful(); - const Images = require('./images'); const load = require('./load'); +const imgPosition = { + top: true, +}; + module.exports._replaceHash = replaceHash; function replaceHash(url) { /* @@ -21,204 +24,198 @@ function replaceHash(url) { return url.replace(/#/g, '%23'); } -function RESTful() { - this.delete = (url, data, callback) => { - const isFunc = itype.function(data); - - if (!callback && isFunc) { - callback = data; - data = null; - } - - sendRequest({ - method : 'DELETE', - url : FS + url, - data, - callback, - imgPosition : { top: !!data }, - }); - }; +module.exports.delete = promisify((url, data, callback) => { + const isFunc = itype.function(data); - this.patch = (url, data, callback) => { - const isFunc = itype.function(data); - - if (!callback && isFunc) { - callback = data; - data = null; - } - - const imgPosition = { - top: true, - }; - + if (!callback && isFunc) { + callback = data; + data = null; + } + + sendRequest({ + method : 'DELETE', + url : FS + url, + data, + callback, + imgPosition : { top: !!data }, + }); +}); + +module.exports.patch = promisify((url, data, callback) => { + const isFunc = itype.function(data); + + if (!callback && isFunc) { + callback = data; + data = null; + } + + sendRequest({ + method: 'PATCH', + url: FS + url, + data, + callback, + imgPosition, + }); +}); + +module.exports.write = promisify((url, data, callback) => { + const isFunc = itype.function(data); + + if (!callback && isFunc) { + callback = data; + data = null; + } + + sendRequest({ + method: 'PUT', + url: FS + url, + data, + callback, + imgPosition, + }); +}); + +module.exports.read = promisify((url, dataType, callback) => { + const notLog = !url.includes('?'); + const isFunc = itype.function(dataType); + + if (!callback && isFunc) { + callback = dataType; + dataType = 'text'; + } + + sendRequest({ + method: 'GET', + url: FS + url, + callback, + notLog, + dataType, + }); +}); + +module.exports.cp = promisify((data, callback) => { + sendRequest({ + method: 'PUT', + url: '/cp', + data, + callback, + imgPosition, + }); +}); + +module.exports.pack = promisify((data, callback) => { + sendRequest({ + method: 'PUT', + url: '/pack', + data, + callback, + }); +}); + +module.exports.extract = promisify((data, callback) => { + sendRequest({ + method : 'PUT', + url : '/extract', + data, + callback, + }); +}); + +module.exports.mv = promisify((data, callback) => { + sendRequest({ + method : 'PUT', + url : '/mv', + data, + callback, + imgPosition, + }); +}); + +module.exports.Config = { + read: promisify((callback) => { + sendRequest({ + method: 'GET', + url: '/config', + callback, + imgPosition, + notLog: true, + }); + }), + + write: promisify((data, callback) => { sendRequest({ method: 'PATCH', - url: FS + url, + url: '/config', data, callback, imgPosition, }); - }; - - this.write = (url, data, callback) => { - const isFunc = itype.function(data); - - if (!callback && isFunc) { - callback = data; - data = null; - } - - sendRequest({ - method: 'PUT', - url: FS + url, - data, - callback, - imgPosition : { top: true }, - }); - }; - - this.read = (url, dataType, callback) => { - const notLog = !url.includes('?'); - const isFunc = itype.function(dataType); - - if (!callback && isFunc) { - callback = dataType; - dataType = 'text'; - } - + }), +}; + +module.exports.Markdown = { + read: promisify((url, callback) => { sendRequest({ method: 'GET', - url: FS + url, + url: '/markdown' + url, callback, - notLog, - dataType, + imgPosition, + notLog: true, }); - }; + }), - this.cp = (data, callback) => { + render: promisify((data, callback) => { sendRequest({ method: 'PUT', - url: '/cp', + url: '/markdown', data, callback, - imgPosition : { top: true }, + imgPosition, + notLog: true, }); - }; + }), +}; + +function sendRequest(params) { + const p = params; + const {prefixURL} = CloudCmd; - this.pack = (data, callback) => { - sendRequest({ - method : 'PUT', - url : '/pack', - data, - callback, - }); - }; + p.url = prefixURL + p.url; + p.url = encodeURI(p.url); - this.extract = function(data, callback) { - sendRequest({ - method : 'PUT', - url : '/extract', - data, - callback, - }); - }; + p.url = replaceHash(p.url); - this.mv = function(data, callback) { - sendRequest({ - method : 'PUT', - url : '/mv', - data, - callback, - imgPosition : { top: true }, - }); - }; - - this.Config = { - read(callback) { - sendRequest({ - method : 'GET', - url : '/config', - callback, - imgPosition : { top: true }, - notLog : true, - }); + load.ajax({ + method : p.method, + url : p.url, + data : p.data, + dataType : p.dataType, + error : (jqXHR) => { + const response = jqXHR.responseText; + + const { + statusText, + status, + } = jqXHR; + + const text = status === 404 ? response : statusText; + const encoded = encode(text); + + Images.show.error(encoded); + + setTimeout(() => { + DOM.Dialog.alert(encoded); + }, 100); + + p.callback(Error(text)); }, - - write(data, callback) { - sendRequest({ - method : 'PATCH', - url : '/config', - data, - callback, - imgPosition : { top: true }, - }); + success: (data) => { + Images.hide(); + + if (!p.notLog) + CloudCmd.log(data); + + p.callback(null, data); }, - }; - - this.Markdown = { - read(url, callback) { - sendRequest({ - method : 'GET', - url : '/markdown' + url, - callback, - imgPosition : { top: true }, - notLog : true, - }); - }, - - render(data, callback) { - sendRequest({ - method : 'PUT', - url : '/markdown', - data, - callback, - imgPosition : { top: true }, - notLog : true, - }); - }, - }; - - function sendRequest(params) { - const p = params; - const {prefixURL} = CloudCmd; - - p.url = prefixURL + p.url; - p.url = encodeURI(p.url); - - p.url = replaceHash(p.url); - - load.ajax({ - method : p.method, - url : p.url, - data : p.data, - dataType : p.dataType, - error : (jqXHR) => { - const response = jqXHR.responseText; - - const { - statusText, - status, - } = jqXHR; - - const text = status === 404 ? response : statusText; - const encoded = encode(text); - - Images.show.error(encoded); - - setTimeout(() => { - DOM.Dialog.alert(encoded); - }, 100); - - p.callback(Error(text)); - }, - success: (data) => { - Images.hide(); - - if (!p.notLog) - CloudCmd.log(data); - - p.callback(null, data); - }, - }); - } + }); } diff --git a/client/key/index.js b/client/key/index.js index 82156cdf..bdf4f5bf 100644 --- a/client/key/index.js +++ b/client/key/index.js @@ -286,7 +286,7 @@ function KeyProto() { exec.if(isSelected, () => { DOM.toggleSelectedFile(current); }, (callback) => { - DOM.loadCurrentSize(callback, current); + DOM.loadCurrentSize(current, callback); }); event.preventDefault(); diff --git a/client/modules/config.js b/client/modules/config.js index b22905dd..db9cbea5 100644 --- a/client/modules/config.js +++ b/client/modules/config.js @@ -217,10 +217,7 @@ function onSave(obj) { function saveHttp(obj) { const {RESTful} = DOM; - RESTful.Config.write(obj, (error) => { - if (error) - return; - + RESTful.Config.write(obj).then(() => { onSave(obj); }); } diff --git a/client/modules/menu.js b/client/modules/menu.js index ef1c6b67..fbb994e6 100644 --- a/client/modules/menu.js +++ b/client/modules/menu.js @@ -243,15 +243,11 @@ function _uploadTo(nameModule) { function uploadFromCloud() { Images.show.load('top'); - CloudCmd.execFromModule('Cloud', 'saveFile', (currentName, data) => { + CloudCmd.execFromModule('Cloud', 'saveFile', async (currentName, data) => { const path = DOM.getCurrentDirPath() + currentName; - RESTful.write(path, data, (error) => { - if (error) - return; - - CloudCmd.refresh({currentName}); - }); + await RESTful.write(path, data); + await CloudCmd.refresh({currentName}); }); } diff --git a/client/modules/operation/index.js b/client/modules/operation/index.js index c96dda52..cbbd82e2 100644 --- a/client/modules/operation/index.js +++ b/client/modules/operation/index.js @@ -12,6 +12,7 @@ const exec = require('execon'); const loadJS = require('load.js').js; const {encode} = require('../../../common/entity'); +const callbackify = require('../../../common/callbackify'); const RESTful = require('../../dom/rest'); const removeExtension = require('./remove-extension'); @@ -32,15 +33,12 @@ const Operation = {}; let Loaded; -let { - cp: copyFn, - mv: moveFn, - delete: deleteFn, - extract: extractFn, -} = RESTful; - -let packZipFn = RESTful.pack; -let packTarFn = RESTful.pack; +let copyFn = callbackify(RESTful.copy); +let moveFn = callbackify(RESTful.mv); +let deleteFn = callbackify(RESTful.delete); +let extractFn = callbackify(RESTful.extract); +let packZipFn = callbackify(RESTful.pack); +let packTarFn = callbackify(RESTful.pack); const Info = DOM.CurrentInfo; const showLoad = Images.show.load.bind(null, 'top'); @@ -185,12 +183,12 @@ function onConnect(operator) { } function onDisconnect() { - packZipFn = RESTful.pack; - packTarFn = RESTful.pack; - deleteFn = RESTful.delete; - copyFn = RESTful.cp; - moveFn = RESTful.mv; - extractFn = RESTful.extract; + packZipFn = callbackify(RESTful.pack); + packTarFn = callbackify(RESTful.pack); + deleteFn = callbackify(RESTful.delete); + copyFn = callbackify(RESTful.cp); + moveFn = callbackify(RESTful.mv); + extractFn = callbackify(RESTful.extract); } function getPacker(type) { diff --git a/client/modules/user-menu/default-menu.js b/client/modules/user-menu/default-menu.js index 3a0eaa23..52789421 100644 --- a/client/modules/user-menu/default-menu.js +++ b/client/modules/user-menu/default-menu.js @@ -14,7 +14,7 @@ module.exports = { await DOM.renameCurrent(); }, - 'C - Create User Menu File': async ({DOM, CloudCmd, tryToPromisify}) => { + 'C - Create User Menu File': async ({DOM, CloudCmd, tryToCatch}) => { const { Dialog, RESTful, @@ -24,7 +24,7 @@ module.exports = { const {dirPath} = CurrentInfo; const path = `${dirPath}/.cloudcmd.menu.js`; - const [e] = await tryToPromisify(RESTful.write, path, data); + const [e] = await tryToCatch(RESTful.write, path, data); if (e) return Dialog.alert(e); diff --git a/client/modules/user-menu/index.js b/client/modules/user-menu/index.js index 03a048f2..6b618a95 100644 --- a/client/modules/user-menu/index.js +++ b/client/modules/user-menu/index.js @@ -11,8 +11,6 @@ const createElement = require('@cloudcmd/create-element'); const tryCatch = require('try-catch'); const tryToCatch = require('try-to-catch/legacy'); -const tryToPromisify = require('../../../common/try-to-promisify.js'); - const Images = require('../../dom/images'); const Dialog = require('../../dom/dialog'); const getUserMenu = require('./get-user-menu'); @@ -124,7 +122,7 @@ const runUserMenu = async (value, options, userMenu) => { const [e] = await tryToCatch(userMenu[value], { DOM, CloudCmd, - tryToPromisify, + tryToCatch, }); if (e) diff --git a/common/callbackify.js b/common/callbackify.js new file mode 100644 index 00000000..f661eed7 --- /dev/null +++ b/common/callbackify.js @@ -0,0 +1,14 @@ +'use strict'; + +const success = (f) => (data) => f(null, data); + +module.exports = (promise) => { + return (...a) => { + const fn = a.pop(); + + promise(...a) + .then(success(fn)) + .catch(fn); + }; +}; + diff --git a/common/callbackify.spec.js b/common/callbackify.spec.js new file mode 100644 index 00000000..0b7f6d8c --- /dev/null +++ b/common/callbackify.spec.js @@ -0,0 +1,31 @@ +'use strict'; + +const test = require('supertape'); +const callbackify = require('./callbackify'); + +test('cloudcmd: common: callbackify: error', (t) => { + const promise = async () => { + throw Error('hello'); + }; + + const fn = callbackify(promise); + + fn((e) => { + t.equal(e.message, 'hello'); + t.end(); + }); +}); + +test('cloudcmd: common: callbackify', (t) => { + const promise = async () => { + return 'hi'; + }; + + const fn = callbackify(promise); + + fn((e, data) => { + t.equal(data, 'hi'); + t.end(); + }); +}); + From 9ff5dee9790cc7db87978c67be8b7a8cc389b79f Mon Sep 17 00:00:00 2001 From: coderaiser Date: Sat, 18 May 2019 17:49:56 +0300 Subject: [PATCH 0041/1728] refactor(files) early return --- client/dom/files.js | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/client/dom/files.js b/client/dom/files.js index 1c638275..08e6bf76 100644 --- a/client/dom/files.js +++ b/client/dom/files.js @@ -31,14 +31,11 @@ function getFile(name, callback) { switch(type) { case 'string': - getModule(name, callback); - break; + return getModule(name, callback); case 'array': array = unaryMap(name, get); - - exec.parallel(array, callback); - break; + return exec.parallel(array, callback); } } @@ -59,15 +56,14 @@ function getModule(name, callback) { const isHTML = regExpHTML.test(name); const isJSON = regExpJSON.test(name); - if (!isHTML && !isJSON) { - showError(name); - } else if (name === 'config') { - getConfig(callback); - } else { - path = getPath(name, isHTML, isJSON); - - getSystemFile(path, callback); - } + if (!isHTML && !isJSON) + return showError(name); + + if (name === 'config') + return getConfig(callback); + + path = getPath(name, isHTML, isJSON); + getSystemFile(path, callback); } From a979d532d536f27b9c3e1e17b2bb62169fb9b17a Mon Sep 17 00:00:00 2001 From: coderaiser Date: Sat, 18 May 2019 18:49:44 +0300 Subject: [PATCH 0042/1728] refactor(dom) files: promisify --- client/client.js | 160 +++++++++++++++++++------------------- client/dom/files.js | 43 ++++------ client/dom/load-remote.js | 2 +- client/listeners/index.js | 11 +-- client/modules/cloud.js | 26 +++---- client/modules/config.js | 102 ++++++++++++------------ client/modules/menu.js | 3 +- client/modules/upload.js | 23 +++--- client/modules/view.js | 86 ++++++++++---------- 9 files changed, 223 insertions(+), 233 deletions(-) diff --git a/client/client.js b/client/client.js index 00f8f77b..254780d0 100644 --- a/client/client.js +++ b/client/client.js @@ -8,6 +8,7 @@ const rendy = require('rendy/legacy'); const exec = require('execon'); const load = require('load.js'); const {promisify} = require('es6-promisify'); +const tryToCatch = require('try-to-catch/legacy'); const pascalCase = require('just-pascal-case'); const isDev = process.env.NODE_ENV === 'development'; @@ -28,6 +29,8 @@ const { buildFromJSON, } = require('../common/cloudfunc'); +const callbackify = require('../common/callbackify'); + const loadModule = require('./load-module'); inherits(CloudCmdProto, Emitify); @@ -222,7 +225,7 @@ function CloudCmdProto(DOM) { }); }; - function initModules(callback) { + const initModules = callbackify(async () => { exec.if(CloudCmd.Key, () => { Key = new CloudCmd.Key(); CloudCmd.Key = Key; @@ -237,32 +240,29 @@ function CloudCmdProto(DOM) { }); }); - Files.get('modules', (error, modules) => { - const showLoad = Images.show.load; - - const doBefore = { - 'edit': showLoad, - 'menu': showLoad, - }; - - const load = (name, path, dobefore) => { - loadModule({ - name, - path, - dobefore, - }); - }; - - if (!modules) - modules = []; - - modules.local.forEach((module) => { - load(null, module, doBefore[module]); + const [, modules] = await tryToCatch(Files.get, 'modules'); + const showLoad = Images.show.load; + + const doBefore = { + 'edit': showLoad, + 'menu': showLoad, + }; + + const load = (name, path, dobefore) => { + loadModule({ + name, + path, + dobefore, }); - - callback(); + }; + + if (!modules) + return; + + modules.local.forEach((module) => { + load(null, module, doBefore[module]); }); - } + }); function baseInit(callback) { const files = DOM.getFiles(); @@ -378,12 +378,12 @@ function CloudCmdProto(DOM) { options.sort = sort; options.order = order; - createFileTable(newObj, panel, options, () => { - if (isRefresh && !noCurrent) - DOM.setCurrentByName(name); - - exec(callback); - }); + await createFileTable(newObj, panel, options); + + if (isRefresh && !noCurrent) + DOM.setCurrentByName(name); + + exec(callback); if (!CloudCmd.config('dirStorage')) return; @@ -409,7 +409,7 @@ function CloudCmdProto(DOM) { * @param history * @param callback */ - function createFileTable(json, panelParam, options, callback) { + async function createFileTable(json, panelParam, options) { const { history, noCurrent, @@ -417,59 +417,59 @@ function CloudCmdProto(DOM) { const names = ['file', 'path', 'link', 'pathLink']; - Files.get(names, (error, templFile, templPath, templLink, templPathLink) => { - const {Dialog} = DOM; - const panel = panelParam || DOM.getPanel(); - const {prefix} = CloudCmd; + const [ + error, + [templFile, templPath, templLink, templPathLink], + ] = await tryToCatch(Files.get, names); + + if (error) + return DOM.Dialog.alert(error.responseText); + + const panel = panelParam || DOM.getPanel(); + const {prefix} = CloudCmd; + + const { + dir, + name, + } = Info; + + const {childNodes} = panel; + let i = childNodes.length; + + while (i--) + panel.removeChild(panel.lastChild); + + panel.innerHTML = buildFromJSON({ + sort : options.sort, + order : options.order, + data : json, + id : panel.id, + prefix, + template : { + file : templFile, + path : templPath, + pathLink : templPathLink, + link : templLink, + }, + }); + + Listeners.setOnPanel(panel); + + if (!noCurrent) { + let current; - const { - dir, - name, - } = Info; + if (name === '..' && dir !== '/') + current = DOM.getCurrentByName(dir); - if (error) - return Dialog.alert(error.responseText); + if (!current) + [current] = DOM.getFiles(panel); - const {childNodes} = panel; - let i = childNodes.length; - - while (i--) - panel.removeChild(panel.lastChild); - - panel.innerHTML = buildFromJSON({ - sort : options.sort, - order : options.order, - data : json, - id : panel.id, - prefix, - template : { - file : templFile, - path : templPath, - pathLink : templPathLink, - link : templLink, - }, + DOM.setCurrentFile(current, { + history, }); - Listeners.setOnPanel(panel); - - if (!noCurrent) { - let current; - - if (name === '..' && dir !== '/') - current = DOM.getCurrentByName(dir); - - if (!current) - [current] = DOM.getFiles(panel); - - DOM.setCurrentFile(current, { - history, - }); - - CloudCmd.emit('active-dir', Info.dirPath); - } - - exec(callback); - }); + CloudCmd.emit('active-dir', Info.dirPath); + } } /** diff --git a/client/dom/files.js b/client/dom/files.js index 08e6bf76..dea2695f 100644 --- a/client/dom/files.js +++ b/client/dom/files.js @@ -4,7 +4,7 @@ const itype = require('itype/legacy'); const currify = require('currify/legacy'); -const exec = require('execon'); +const {promisify} = require('es6-promisify'); const load = require('./load'); const RESTful = require('./rest'); @@ -23,33 +23,23 @@ const unaryMap = (array, fn) => array.map((a) => fn(a)); module.exports.get = get; -function getFile(name, callback) { +async function getFile(name) { const type = itype(name); - let array; + check(name); - check(name, callback); + if (type === 'string') + return getModule(name); - switch(type) { - case 'string': - return getModule(name, callback); - - case 'array': - array = unaryMap(name, get); - return exec.parallel(array, callback); - } + if (type === 'array') + return Promise.all(unaryMap(name, get)); } -function check(name, callback) { +function check(name) { if (!name) throw Error('name could not be empty!'); - - if (typeof callback !== 'function') - throw Error('callback should be a function'); } -function getModule(name, callback) { - let path; - +async function getModule(name) { const regExpHTML = new RegExp(FILES_HTML + '|' + FILES_HTML_ROOT); const regExpJSON = new RegExp(FILES_JSON); @@ -60,11 +50,10 @@ function getModule(name, callback) { return showError(name); if (name === 'config') - return getConfig(callback); + return getConfig(); - path = getPath(name, isHTML, isJSON); - getSystemFile(path, callback); - + const path = getPath(name, isHTML, isJSON); + return getSystemFile(path); } function getPath(name, isHTML, isJSON) { @@ -93,7 +82,7 @@ function showError(name) { throw error; } -function getSystemFile(file, callback) { +const getSystemFile = promisify((file, callback) => { const {prefix} = CloudCmd; if (!Promises[file]) @@ -113,9 +102,9 @@ function getSystemFile(file, callback) { Promises[file] = null; callback(error); }); -} +}); -function getConfig(callback) { +const getConfig = promisify((callback) => { let is; if (!Promises.config) @@ -137,7 +126,7 @@ function getConfig(callback) { if (!is) Promises.config = null; }); -} +}); function getTimeoutOnce(time) { let is; diff --git a/client/dom/load-remote.js b/client/dom/load-remote.js index 1d814ccf..23069e0a 100644 --- a/client/dom/load-remote.js +++ b/client/dom/load-remote.js @@ -20,7 +20,7 @@ module.exports = (name, options, callback = options) => { if (o.name && window[o.name]) return callback(); - Files.get('modules', (error, modules) => { + Files.get('modules').then((modules) => { const online = config('online') && navigator.onLine; const module = findObjByNameInArr(modules.remote, name); diff --git a/client/listeners/index.js b/client/listeners/index.js index 2f8c6771..54d9d0c2 100644 --- a/client/listeners/index.js +++ b/client/listeners/index.js @@ -5,6 +5,7 @@ const exec = require('execon'); const itype = require('itype/legacy'); const currify = require('currify/legacy'); +const tryToCatch = require('try-to-catch/legacy'); const clipboard = require('@cloudcmd/clipboard'); const getRange = require('./get-range'); @@ -99,11 +100,11 @@ function getPath(el, path = []) { return getPath(el.parentElement, path.concat(el)); } -function config() { - DOM.Files.get('config', (e, config) => { - const type = config && config.packer; - EXT = DOM.getPackerExt(type); - }); +async function config() { + const [, config] = await tryToCatch(DOM.Files.get, 'config'); + const type = config && config.packer; + + EXT = DOM.getPackerExt(type); } module.exports.initKeysPanel = () => { diff --git a/client/modules/cloud.js b/client/modules/cloud.js index 32d83a1d..214d1325 100644 --- a/client/modules/cloud.js +++ b/client/modules/cloud.js @@ -5,7 +5,7 @@ const exec = require('execon'); const currify = require('currify/legacy'); const {promisify} = require('es6-promisify'); -const loadJS = require('load.js').js; +const loadJS = promisify(require('load.js').js); const {log} = CloudCmd; @@ -19,7 +19,11 @@ const Name = 'Cloud'; CloudCmd[Name] = module.exports; module.exports.init = async () => { - await loadFiles(); + const [modules] = await loadFiles(); + const {key} = modules.data.FilePicker; + + filepicker.setKey(key); + Images.hide(); }; module.exports.uploadFile = (filename, data) => { @@ -53,18 +57,12 @@ function _upload(callback, file) { }); } -const loadFiles = promisify((callback) => { +async function loadFiles() { const js = '//api.filepicker.io/v2/filepicker.js'; - loadJS(js, () => { - Files.get('modules', (error, modules) => { - const {key} = modules.data.FilePicker; - - filepicker.setKey(key); - - Images.hide(); - exec(callback); - }); - }); -}); + return Promise.all([ + Files.get('modules'), + loadJS(js), + ]); +} diff --git a/client/modules/config.js b/client/modules/config.js index db9cbea5..1e5852cf 100644 --- a/client/modules/config.js +++ b/client/modules/config.js @@ -9,6 +9,7 @@ const currify = require('currify/legacy'); const wraptile = require('wraptile/legacy'); const squad = require('squad/legacy'); const {promisify} = require('es6-promisify'); +const tryToCatch = require('try-to-catch/legacy'); const load = require('load.js'); const createElement = require('@cloudcmd/create-element'); @@ -43,7 +44,6 @@ const Config = {}; let Template; -const getFile = promisify(Files.get); const loadCSS = promisify(load.css); module.exports.init = async () => { @@ -55,7 +55,7 @@ module.exports.init = async () => { const {prefix} = CloudCmd; [Template] = await Promise.all([ - getFile('config-tmpl'), + Files.get('config-tmpl'), loadSocket(), loadCSS(prefix + '/dist/config.css'), CloudCmd.View(), @@ -127,60 +127,60 @@ Config.save = saveHttp; module.exports.show = show; -function show() { +async function show() { if (!CloudCmd.config('configDialog')) return; - fillTemplate(); + await fillTemplate(); } -function fillTemplate() { - Files.get('config', (error, config) => { - if (error) - return Dialog.alert('Could not load config!'); - - const { - editor, - packer, - columns, - configAuth, - ...obj - } = input.convert(config); - - obj[editor + '-selected'] = 'selected'; - obj[packer + '-selected'] = 'selected'; - obj[columns + '-selected'] = 'selected'; - obj.configAuth = configAuth ? '' : 'hidden'; - - const innerHTML = rendy(Template, obj); - - Element = createElement('form', { - className : 'config', - innerHTML, - }); - - const inputs = document.querySelectorAll('input, select', Element); - const [inputFirst] = inputs; - - let afterShow; - - if (inputFirst) { - onAuthChange(inputFirst.checked); - afterShow = inputFirst.focus.bind(inputFirst); - } - - const getTarget = ({target}) => target; - const handleChange = squad(onChange, getTarget); - - [...inputs] - .map(addKey(onKey)) - .map(addChange(handleChange)); - - const autoSize = true; - CloudCmd.View.show(Element, { - autoSize, - afterShow, - }); +async function fillTemplate() { + const [error, config] = await tryToCatch(Files.get, 'config'); + + if (error) + return Dialog.alert('Could not load config!'); + + const { + editor, + packer, + columns, + configAuth, + ...obj + } = input.convert(config); + + obj[editor + '-selected'] = 'selected'; + obj[packer + '-selected'] = 'selected'; + obj[columns + '-selected'] = 'selected'; + obj.configAuth = configAuth ? '' : 'hidden'; + + const innerHTML = rendy(Template, obj); + + Element = createElement('form', { + className : 'config', + innerHTML, + }); + + const inputs = document.querySelectorAll('input, select', Element); + const [inputFirst] = inputs; + + let afterShow; + + if (inputFirst) { + onAuthChange(inputFirst.checked); + afterShow = inputFirst.focus.bind(inputFirst); + } + + const getTarget = ({target}) => target; + const handleChange = squad(onChange, getTarget); + + [...inputs] + .map(addKey(onKey)) + .map(addChange(handleChange)); + + const autoSize = true; + CloudCmd.View.show(Element, { + autoSize, + afterShow, }); } diff --git a/client/modules/menu.js b/client/modules/menu.js index fbb994e6..6380ff66 100644 --- a/client/modules/menu.js +++ b/client/modules/menu.js @@ -232,9 +232,8 @@ function _uploadTo(nameModule) { return; const {name} = Info; - const execFrom = CloudCmd.execFromModule; - execFrom(nameModule, 'uploadFile', name, data); + CloudCmd.execFromModule(nameModule, 'uploadFile', name, data); }); CloudCmd.log('Uploading to ' + name + '...'); diff --git a/client/modules/upload.js b/client/modules/upload.js index eb144e93..c5135ce6 100644 --- a/client/modules/upload.js +++ b/client/modules/upload.js @@ -17,20 +17,19 @@ module.exports.init = async () => { module.exports.show = show; module.exports.hide = hide; -function show() { +async function show() { Images.show.load('top'); - Files.get('upload', (error, innerHTML) => { - const autoSize = true; - - const el = createElement('div', { - innerHTML, - }); - - CloudCmd.View.show(el, { - autoSize, - afterShow, - }); + const innerHTML = await Files.get('upload'); + const autoSize = true; + + const el = createElement('div', { + innerHTML, + }); + + CloudCmd.View.show(el, { + autoSize, + afterShow, }); const fontFamily = [ diff --git a/client/modules/view.js b/client/modules/view.js index 636842ab..8c52a830 100644 --- a/client/modules/view.js +++ b/client/modules/view.js @@ -9,6 +9,7 @@ const rendy = require('rendy/legacy'); const exec = require('execon'); const currify = require('currify/legacy'); const {promisify} = require('es6-promisify'); +const tryToCatch = require('try-to-catch/legacy'); const modal = require('@cloudcmd/modal'); const createElement = require('@cloudcmd/create-element'); @@ -81,7 +82,7 @@ module.exports.init = async () => { events.forEach(addEvent(Overlay, onOverlayClick)); }; -function show(data, options) { +async function show(data, options) { const prefixURL = CloudCmd.prefixURL + FS; if (Loading) @@ -120,22 +121,25 @@ function show(data, options) { } } -function viewMedia(path) { - getMediaElement(path, (element) => { - const allConfig = { - ...Config, - ...{ - autoSize: true, - afterShow: () => { - element - .querySelector('audio, video') - .focus(); - }, +async function viewMedia(path) { + const [e, element] = await getMediaElement(path); + + if (e) + return alert(e); + + const allConfig = { + ...Config, + ...{ + autoSize: true, + afterShow: () => { + element + .querySelector('audio, video') + .focus(); }, - }; - - modal.open(element, allConfig); - }); + }, + }; + + modal.open(element, allConfig); } function viewFile() { @@ -257,33 +261,33 @@ function getType(name) { return 'media'; } -function getMediaElement(src, callback) { - check(src, callback); +async function getMediaElement(src) { + check(src); - Files.get('view/media-tmpl', (error, template) => { - const {name} = Info; - - if (error) - return alert(error); - - if (!TemplateAudio) - TemplateAudio = template; - - const is = isAudio(name); - const type = is ? 'audio' : 'video'; - - const innerHTML = rendy(TemplateAudio, { - src, - type, - name, - }); - - const element = createElement('div', { - innerHTML, - }); - - callback(element); + const [error, template] = await tryToCatch(Files.get, 'view/media-tmpl'); + + if (error) + return [error]; + + const {name} = Info; + + if (!TemplateAudio) + TemplateAudio = template; + + const is = isAudio(name); + const type = is ? 'audio' : 'video'; + + const innerHTML = rendy(TemplateAudio, { + src, + type, + name, }); + + const element = createElement('div', { + innerHTML, + }); + + return [null, element]; } function check(src, callback) { From f7e47d21678cde267953a7a474ec041d9019271c Mon Sep 17 00:00:00 2001 From: coderaiser Date: Mon, 20 May 2019 18:38:58 +0300 Subject: [PATCH 0043/1728] chore(user-menu) double alert --- client/modules/user-menu/default-menu.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/modules/user-menu/default-menu.js b/client/modules/user-menu/default-menu.js index 52789421..d2b40097 100644 --- a/client/modules/user-menu/default-menu.js +++ b/client/modules/user-menu/default-menu.js @@ -27,7 +27,7 @@ module.exports = { const [e] = await tryToCatch(RESTful.write, path, data); if (e) - return Dialog.alert(e); + return; await CloudCmd.refresh(); DOM.setCurrentByName('.cloudcmd.menu.js'); From ee59fbf8d29936d278659edf41875ee2536df576 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Mon, 20 May 2019 18:54:26 +0300 Subject: [PATCH 0044/1728] refactor(cloudcmd) forEach -> for-of --- client/input.js | 14 +++++------ client/listeners/index.js | 30 ++++++++++-------------- client/modules/user-menu/default-menu.js | 1 - client/modules/view.js | 7 +++--- 4 files changed, 22 insertions(+), 30 deletions(-) diff --git a/client/input.js b/client/input.js index e475e77f..7eea66b8 100644 --- a/client/input.js +++ b/client/input.js @@ -29,16 +29,14 @@ module.exports.convert = (config) => { const result = { ...config, }; + const array = Object.keys(config); - const array = Object.keys(result); + const filtered = array.filter(isBool(config)); - array - .filter(isBool(result)) - .forEach((name) => { - const item = result[name]; - - result[name] = setState(item); - }); + for (const name of filtered) { + const item = config[name]; + result[name] = setState(item); + } return result; }; diff --git a/client/listeners/index.js b/client/listeners/index.js index 54d9d0c2..d2170b5d 100644 --- a/client/listeners/index.js +++ b/client/listeners/index.js @@ -44,9 +44,8 @@ const unselect = (event) => { }; const execAll = currify((funcs, event) => { - funcs.forEach((fn) => { + for (const fn of funcs) fn(event); - }); }); const Info = DOM.CurrentInfo; @@ -260,7 +259,7 @@ function toggleSelect(key, files) { return DOM.toggleSelectedFile(file); if (key.shift) - return files.forEach(DOM.selectFile); + return files.map(DOM.selectFile); } function changePanel(element) { @@ -404,16 +403,12 @@ function contextMenu() { function dragndrop() { const panels = DOM.getByClassAll('panel'); - const select = () => { - [...panels].forEach((panel) => { - panel.classList.add('selected-panel'); - }); + const select = ({target}) => { + target.classList.add('selected-panel'); }; - const unselect = () => { - [...panels].forEach((panel) => { - panel.classList.remove('selected-panel'); - }); + const unselect = ({target}) => { + target.classList.remove('selected-panel'); }; const onDrop = (event) => { @@ -458,13 +453,12 @@ function dragndrop() { event.preventDefault(); }; - Events.add('dragenter', select); - Events.add(['dragleave', 'drop'], unselect); - - [...panels].forEach((panel) => { - Events.add('dragover', panel, onDragOver) - .add('drop', panel, onDrop); - }); + for (const panel of panels) + Events + .add('dragover', panel, onDragOver) + .add('drop', panel, onDrop) + .add('dragenter', select) + .add(['dragleave', 'drop'], unselect); } function unload() { diff --git a/client/modules/user-menu/default-menu.js b/client/modules/user-menu/default-menu.js index d2b40097..ceaf37d2 100644 --- a/client/modules/user-menu/default-menu.js +++ b/client/modules/user-menu/default-menu.js @@ -16,7 +16,6 @@ module.exports = { 'C - Create User Menu File': async ({DOM, CloudCmd, tryToCatch}) => { const { - Dialog, RESTful, CurrentInfo, } = DOM; diff --git a/client/modules/view.js b/client/modules/view.js index 8c52a830..e2db1116 100644 --- a/client/modules/view.js +++ b/client/modules/view.js @@ -168,21 +168,22 @@ function initConfig(Config, options) { if (!options) return config; - Object.keys(options).forEach((name) => { + const names = Object.keys(options); + for (const name of names) { const isConfig = !!config[name]; const item = options[name]; const isFunc = itype.function(item); if (!isFunc || !isConfig) { config[name] = options[name]; - return; + continue; } const func = config[name]; config[name] = () => { exec.series([func, item]); }; - }); + } return config; } From 19239655ed2b6bb7173a80181a23d2cb5781781d Mon Sep 17 00:00:00 2001 From: coderaiser Date: Wed, 22 May 2019 11:32:39 +0300 Subject: [PATCH 0045/1728] test(menu) defaultMenu: add --- client/modules/user-menu/default-menu.js | 5 +- client/modules/user-menu/default-menu.spec.js | 121 ++++++++++++++++++ 2 files changed, 124 insertions(+), 2 deletions(-) create mode 100644 client/modules/user-menu/default-menu.spec.js diff --git a/client/modules/user-menu/default-menu.js b/client/modules/user-menu/default-menu.js index ceaf37d2..8504fded 100644 --- a/client/modules/user-menu/default-menu.js +++ b/client/modules/user-menu/default-menu.js @@ -21,7 +21,7 @@ module.exports = { } = DOM; const {dirPath} = CurrentInfo; - const path = `${dirPath}/.cloudcmd.menu.js`; + const path = `${dirPath}.cloudcmd.menu.js`; const [e] = await tryToCatch(RESTful.write, path, data); @@ -30,8 +30,9 @@ module.exports = { await CloudCmd.refresh(); DOM.setCurrentByName('.cloudcmd.menu.js'); - await CloudCmd.EditFile.show(); }, }; +module.exports._data = data; + diff --git a/client/modules/user-menu/default-menu.spec.js b/client/modules/user-menu/default-menu.spec.js new file mode 100644 index 00000000..731ab5f0 --- /dev/null +++ b/client/modules/user-menu/default-menu.spec.js @@ -0,0 +1,121 @@ +'use strict'; + +const test = require('supertape'); +const stub = require('@cloudcmd/stub'); +const wraptile = require('wraptile'); +const defaultMenu = require('./default-menu'); +const tryToCatch = require('try-to-catch'); +const {_data} = defaultMenu; +const reject = wraptile(async (a) => { + throw Error(a); +}); + +test('cloudcmd: client: user menu: RESTful.write', async (t) => { + const name = 'C - Create User Menu File'; + const DOM = getDOM(); + const CloudCmd = getCloudCmd(); + const {write} = DOM.RESTful; + + await defaultMenu[name]({ + DOM, + CloudCmd, + tryToCatch, + }); + + const path = '/.cloudcmd.menu.js'; + t.ok(write.calledWith(path, _data), 'should call RESTful.write'); + t.end(); +}); + +test('cloudcmd: client: user menu: refresh', async (t) => { + const name = 'C - Create User Menu File'; + const DOM = getDOM(); + const CloudCmd = getCloudCmd(); + const {refresh} = CloudCmd; + + await defaultMenu[name]({ + DOM, + CloudCmd, + tryToCatch, + }); + + t.ok(refresh.calledWith(), 'should call CloudCmd.refresh'); + t.end(); +}); + +test('cloudcmd: client: user menu: setCurrentByName', async (t) => { + const name = 'C - Create User Menu File'; + const DOM = getDOM(); + const CloudCmd = getCloudCmd(); + const {setCurrentByName} = DOM; + + await defaultMenu[name]({ + DOM, + CloudCmd, + tryToCatch, + }); + + const fileName = '.cloudcmd.menu.js'; + t.ok(setCurrentByName.calledWith(fileName), 'should call DOM.setCurrentByName'); + t.end(); +}); + +test('cloudcmd: client: user menu: EditFile.show', async (t) => { + const name = 'C - Create User Menu File'; + const DOM = getDOM(); + const CloudCmd = getCloudCmd(); + const {EditFile} = CloudCmd; + + await defaultMenu[name]({ + DOM, + CloudCmd, + tryToCatch, + }); + + t.ok(EditFile.show.called, 'should call EditFile.show'); + t.end(); +}); + +test('cloudcmd: client: user menu: no EditFile.show', async (t) => { + const name = 'C - Create User Menu File'; + const DOM = getDOM(); + const CloudCmd = getCloudCmd(); + const {RESTful} = DOM; + const {EditFile} = CloudCmd; + + RESTful.write = stub(reject('Error')); + + await defaultMenu[name]({ + DOM, + CloudCmd, + tryToCatch, + }); + + t.notOk(EditFile.show.called, 'should not call EditFile.show'); + t.end(); +}); + +function getDOM() { + const RESTful = { + write: stub(), + }; + + const CurrentInfo = { + dirPath: '/', + }; + + return { + RESTful, + CurrentInfo, + setCurrentByName: stub(), + }; +} + +function getCloudCmd() { + return { + refresh: stub(), + EditFile: { + show: stub(), + }, + }; +} From ba72727fba05a6163ac9ce156caa09d27d189df2 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Wed, 22 May 2019 11:44:56 +0300 Subject: [PATCH 0046/1728] refactor(select-by-pattern) forEach -> for-of --- client/dom/select-by-pattern.js | 71 ++++++++++++++++----------------- common/util.js | 2 - 2 files changed, 34 insertions(+), 39 deletions(-) diff --git a/client/dom/select-by-pattern.js b/client/dom/select-by-pattern.js index 32f7ab7d..32469b34 100644 --- a/client/dom/select-by-pattern.js +++ b/client/dom/select-by-pattern.js @@ -1,51 +1,48 @@ 'use strict'; -/* global DOM */ - let SelectType = '*.*'; const {getRegExp} = require('../../common/util'); +const { + alert, + prompt, +} = require('./dialog'); -module.exports = (msg, files) => { - const allMsg = `Specify file type for ${msg} selection`; - const cancel = false; - const {Dialog} = DOM; +const {DOM} = require('.'); + +module.exports = async (msg, files) => { + if (!files) + return; - Dialog.prompt(allMsg, SelectType, {cancel}).then((type) => { - SelectType = type; + const allMsg = `Specify file type for ${msg} selection`; + + const type = await prompt(allMsg, SelectType); + /* eslint require-atomic-updates: 0 */ + SelectType = type; + + const regExp = getRegExp(type); + + let matches = 0; + + for (const current of files) { + const name = DOM.getCurrentName(current); - const regExp = getRegExp(type); + if (name === '..' || !regExp.test(name)) + continue; - if (!files) - return; + ++matches; - let matches = 0; + let isSelected = DOM.isSelected(current); + const shouldSel = msg === 'expand'; - files.forEach((current) => { - const name = DOM.getCurrentName(current); - - if (name === '..') - return; - - const isMatch = regExp.test(name); - - if (!isMatch) - return; - - ++matches; - - let isSelected = DOM.isSelected(current); - const shouldSel = msg === 'expand'; - - if (shouldSel) - isSelected = !isSelected; - - if (isSelected) - DOM.toggleSelectedFile(current); - }); + if (shouldSel) + isSelected = !isSelected; - if (!matches) - Dialog.alert('Select Files', 'No matches found!'); - }); + if (isSelected) + DOM.toggleSelectedFile(current); + } + + if (!matches) + alert('No matches found!'); }; diff --git a/common/util.js b/common/util.js index 09d64db5..1e28d3a5 100644 --- a/common/util.js +++ b/common/util.js @@ -15,8 +15,6 @@ module.exports.escapeRegExp = (str) => { * get regexp from wild card */ module.exports.getRegExp = (wildcard) => { - wildcard = wildcard || '*'; - const escaped = '^' + wildcard // search from start of line .replace('.', '\\.') .replace('*', '.*') From 7e98ad725d69894e5eb471bf47f7e4f1943e1cb3 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Wed, 22 May 2019 12:25:31 +0300 Subject: [PATCH 0047/1728] refactor(input) mv client -> client/modules/config --- .webpack/js.js | 2 +- client/modules/{config.js => config/index.js} | 12 ++++++------ client/{ => modules/config}/input.js | 0 3 files changed, 7 insertions(+), 7 deletions(-) rename client/modules/{config.js => config/index.js} (95%) rename client/{ => modules/config}/input.js (100%) diff --git a/.webpack/js.js b/.webpack/js.js index e156fbd1..1d54442b 100644 --- a/.webpack/js.js +++ b/.webpack/js.js @@ -83,7 +83,7 @@ module.exports = { [modules + '/view']: `${dirModules}/view.js`, [modules + '/help']: `${dirModules}/help.js`, [modules + '/markdown']: `${dirModules}/markdown.js`, - [modules + '/config']: `${dirModules}/config.js`, + [modules + '/config']: `${dirModules}/config/index.js`, [modules + '/contact']: `${dirModules}/contact.js`, [modules + '/upload']: `${dirModules}/upload.js`, [modules + '/operation']: `${dirModules}/operation/index.js`, diff --git a/client/modules/config.js b/client/modules/config/index.js similarity index 95% rename from client/modules/config.js rename to client/modules/config/index.js index 1e5852cf..4ca85b03 100644 --- a/client/modules/config.js +++ b/client/modules/config/index.js @@ -2,7 +2,7 @@ /* global CloudCmd, DOM, io */ -require('../../css/config.css'); +require('../../../css/config.css'); const rendy = require('rendy/legacy'); const currify = require('currify/legacy'); @@ -13,12 +13,12 @@ const tryToCatch = require('try-to-catch/legacy'); const load = require('load.js'); const createElement = require('@cloudcmd/create-element'); -const input = require('../input'); -const Images = require('../dom/images'); -const Events = require('../dom/events'); -const Files = require('../dom/files'); +const input = require('./input'); +const Images = require('../../dom/images'); +const Events = require('../../dom/events'); +const Files = require('../../dom/files'); -const {getTitle} = require('../../common/cloudfunc'); +const {getTitle} = require('../../../common/cloudfunc'); const {Dialog, setTitle} = DOM; const Name = 'Config'; diff --git a/client/input.js b/client/modules/config/input.js similarity index 100% rename from client/input.js rename to client/modules/config/input.js From ef38bd7aa397f34f3ef508b75b04199a010c10d6 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Wed, 22 May 2019 12:59:06 +0300 Subject: [PATCH 0048/1728] feature(dialog) cancel -> tryToCatch --- client/dom/dialog.js | 9 ++++--- client/dom/index.js | 31 +++++++++++++---------- client/dom/select-by-pattern.js | 7 +++-- client/modules/edit-file.js | 13 +++++----- client/modules/edit-names.js | 3 ++- client/modules/operation/index.js | 26 ++++++++++--------- client/modules/operation/set-listeners.js | 16 ++++++------ 7 files changed, 58 insertions(+), 47 deletions(-) diff --git a/client/dom/dialog.js b/client/dom/dialog.js index 904e9f4f..13b36b2a 100644 --- a/client/dom/dialog.js +++ b/client/dom/dialog.js @@ -1,6 +1,7 @@ - 'use strict'; +const tryToCatch = require('try-to-catch/legacy'); + const { alert, prompt, @@ -14,9 +15,9 @@ module.exports.alert = (...a) => alert(title, ...a, { cancel: false, }); -module.exports.prompt = (...a) => prompt(title, ...a); -module.exports.confirm = (...a) => confirm(title, ...a); -module.exports.progress = (...a) => progress(title, ...a); +module.exports.prompt = (...a) => tryToCatch(prompt, title, ...a); +module.exports.confirm = (...a) => tryToCatch(confirm, title, ...a); +module.exports.progress = (...a) => tryToCatch(progress, title, ...a); module.exports.alert.noFiles = () => { return alert(title, 'No files selected!', { diff --git a/client/dom/index.js b/client/dom/index.js index e89891bc..e731c893 100644 --- a/client/dom/index.js +++ b/client/dom/index.js @@ -5,7 +5,6 @@ const itype = require('itype/legacy'); const exec = require('execon'); const jonny = require('jonny/legacy'); -const tryToCatch = require('try-to-catch/legacy'); const Util = require('../../common/util'); const callbackify = require('../../common/callbackify'); @@ -100,9 +99,9 @@ function CmdProto() { const name = getName(); - const [, newName] = await tryToCatch(Dialog.prompt, msg, name); + const [cancel, newName] = await Dialog.prompt(msg, name); - if (!newName) + if (cancel) return; const path = (type) => { @@ -753,9 +752,9 @@ function CmdProto() { if (from === '..') return Dialog.alert.noFiles(); - const [e, to] = await tryToCatch(Dialog.prompt, 'Rename', from); + const [cancel, to] = await Dialog.prompt('Rename', from); - if (e) + if (cancel) return; const isExist = !!DOM.getCurrentByName(to); @@ -856,18 +855,22 @@ function CmdProto() { return '.tar.gz'; }; - this.goToDirectory = () => { + this.goToDirectory = async () => { const msg = 'Go to directory:'; - const path = CurrentInfo.dirPath; const {Dialog} = DOM; - const cancel = false; - const setPath = (path) => ({ - path, - }); + const {dirPath} = CurrentInfo; - Dialog.prompt(msg, path, {cancel}) - .then(setPath) - .then(CloudCmd.loadDir); + const [ + cancel, + path = dirPath, + ] = await Dialog.prompt(msg, path); + + if (cancel) + return; + + CloudCmd.loadDir({ + path + }); }, this.duplicatePanel = () => { diff --git a/client/dom/select-by-pattern.js b/client/dom/select-by-pattern.js index 32469b34..b64a77dd 100644 --- a/client/dom/select-by-pattern.js +++ b/client/dom/select-by-pattern.js @@ -16,12 +16,15 @@ module.exports = async (msg, files) => { const allMsg = `Specify file type for ${msg} selection`; - const type = await prompt(allMsg, SelectType); /* eslint require-atomic-updates: 0 */ + const [cancel, type] = await prompt(allMsg, SelectType); + + if (cancel) + return; + SelectType = type; const regExp = getRegExp(type); - let matches = 0; for (const current of files) { diff --git a/client/modules/edit-file.js b/client/modules/edit-file.js index a91f901c..941b88d1 100644 --- a/client/modules/edit-file.js +++ b/client/modules/edit-file.js @@ -180,17 +180,18 @@ function setMsgChanged(name) { module.exports.isChanged = isChanged; -function isChanged() { +async function isChanged() { const editor = CloudCmd.Edit.getEditor(); const is = editor.isChanged(); if (!is) return; - const cancel = false; - Dialog.confirm(MSG_CHANGED, {cancel}) - .then(() => { - editor.save(); - }); + const [cancel] = await Dialog.confirm(MSG_CHANGED); + + if (cancel) + return; + + editor.save(); } diff --git a/client/modules/edit-names.js b/client/modules/edit-names.js index 117cb49d..90bfc59a 100644 --- a/client/modules/edit-names.js +++ b/client/modules/edit-names.js @@ -4,6 +4,7 @@ CloudCmd.EditNames = exports; +const smalltalk = require('smalltalk'); const currify = require('currify/legacy'); const exec = require('execon'); const supermenu = require('supermenu'); @@ -69,7 +70,7 @@ function keyListener(event) { EditNames.hide(); else if (ctrlMeta && event.keyCode === Key.P) - Dialog + smalltalk .prompt('Apply pattern:', '[n][e]', {cancel: false}) .then(applyPattern); diff --git a/client/modules/operation/index.js b/client/modules/operation/index.js index cbbd82e2..875f3ddb 100644 --- a/client/modules/operation/index.js +++ b/client/modules/operation/index.js @@ -255,7 +255,7 @@ Operation.extract = () => { * * @currentFile */ -function promptDelete() { +async function promptDelete() { if (noFilesCheck()) return; @@ -291,11 +291,12 @@ function promptDelete() { msg = msgAsk + msgSel + type + name + '?'; } - const cancel = false; + const [cancel] = await Dialog.confirm(msg); - Dialog.confirm(msg, {cancel}).then(() => { - deleteSilent(files); - }); + if (cancel) + return; + + deleteSilent(files); } /** @@ -380,9 +381,12 @@ function _processFiles(options, data) { const title = isCopy ? 'Copy' : 'Rename/Move'; const operation = isCopy ? copyFn : moveFn; - if (shouldAsk && config(option)) - return message(title, to, names.map(encode)) - .then(ask); + if (shouldAsk && config(option)) { + const [cancel, to] = message(title, to, names.map(encode)); + + if (!cancel) + ask(to); + } ask(to); @@ -492,7 +496,7 @@ function twopack(operation, type) { }); } -function message(msg, to, names) { +async function message(msg, to, names) { const n = names.length; const [name] = names; @@ -505,9 +509,7 @@ function message(msg, to, names) { msg += ' to'; - const cancel = false; - - return Dialog.prompt(msg, to, {cancel}); + return Dialog.prompt(msg, to); } function load(callback) { diff --git a/client/modules/operation/set-listeners.js b/client/modules/operation/set-listeners.js index 71d7b64e..2b773050 100644 --- a/client/modules/operation/set-listeners.js +++ b/client/modules/operation/set-listeners.js @@ -61,7 +61,7 @@ module.exports = (options) => (emitter) => { callback(); }, - error: (error) => { + error: async (error) => { lastError = error; if (noContinue) { @@ -71,13 +71,13 @@ module.exports = (options) => (emitter) => { return; } - Dialog.confirm(error + '\n Continue?') - .then(() => { - emitter.continue(); - }, () => { - emitter.abort(); - progress.remove(); - }); + const [cancel] = await Dialog.confirm(error + '\n Continue?'); + + if (!cancel) + emitter.continue(); + + emitter.abort(); + progress.remove(); }, }; From 8ac3211a864946bb6e1a92c868b6ea98e9fd7584 Mon Sep 17 00:00:00 2001 From: tarzak Date: Thu, 23 May 2019 18:11:55 +0300 Subject: [PATCH 0049/1728] fix(user-menu) prefix (#244) --- client/modules/user-menu/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/modules/user-menu/index.js b/client/modules/user-menu/index.js index 6b618a95..d76733b5 100644 --- a/client/modules/user-menu/index.js +++ b/client/modules/user-menu/index.js @@ -42,7 +42,7 @@ async function show() { Images.show.load('top'); const {dirPath} = CurrentInfo; - const res = await fetch(`/api/v1/user-menu?dir=${dirPath}`); + const res = await fetch(`${CloudCmd.prefix}/api/v1/user-menu?dir=${dirPath}`); const [error, userMenu] = tryCatch(getUserMenu, await res.text()); if (error) From 7b6e767ccbc0687da423c1d7f0ee783f1bce58f8 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Wed, 22 May 2019 21:14:11 +0300 Subject: [PATCH 0050/1728] refactor(dom) RESTful: add tryToCatch wrapper --- client/client.js | 5 +++- client/dom/files.js | 20 ++++++------- client/dom/index.js | 28 ++++++------------- client/dom/rest.js | 2 +- client/modules/config/index.js | 14 ++++++---- client/modules/menu.js | 5 +++- client/modules/user-menu/default-menu.js | 4 +-- client/modules/user-menu/default-menu.spec.js | 6 ---- client/modules/user-menu/index.js | 1 - common/try-to-promisify.js | 6 ++-- 10 files changed, 40 insertions(+), 51 deletions(-) diff --git a/client/client.js b/client/client.js index 254780d0..f151c803 100644 --- a/client/client.js +++ b/client/client.js @@ -372,7 +372,10 @@ function CloudCmdProto(DOM) { order, }); - const newObj = await RESTful.read(path + query, 'json'); + const [, newObj] = await RESTful.read(path + query, 'json'); + + if (!newObj) + return; /* eslint require-atomic-updates:0 */ options.sort = sort; diff --git a/client/dom/files.js b/client/dom/files.js index dea2695f..c64f2a47 100644 --- a/client/dom/files.js +++ b/client/dom/files.js @@ -104,7 +104,7 @@ const getSystemFile = promisify((file, callback) => { }); }); -const getConfig = promisify((callback) => { +const getConfig = async () => { let is; if (!Promises.config) @@ -113,20 +113,18 @@ const getConfig = promisify((callback) => { return RESTful.Config.read(); }; - Promises.config().then((data) => { + const [, data] = await Promises.config(); + + if (data) is = false; - - callback(null, data); - - timeout(() => { - if (!is) - Promises.config = null; - }); - }, () => { + + timeout(() => { if (!is) Promises.config = null; }); -}); + + return data; +}; function getTimeoutOnce(time) { let is; diff --git a/client/dom/index.js b/client/dom/index.js index e731c893..6c276866 100644 --- a/client/dom/index.js +++ b/client/dom/index.js @@ -99,13 +99,13 @@ function CmdProto() { const name = getName(); - const [cancel, newName] = await Dialog.prompt(msg, name); + const [cancel, currentName] = await Dialog.prompt(msg, name); if (cancel) return; const path = (type) => { - const result = dir + newName; + const result = dir + currentName; if (!type) return result; @@ -115,7 +115,7 @@ function CmdProto() { await RESTful.write(path(type)); await CloudCmd.refresh({ - currentName: newName, + currentName, }); } @@ -240,7 +240,7 @@ function CmdProto() { if (name === '..') return; - const size = await RESTful.read(link + query); + const [, size] = await RESTful.read(link + query); DOM.setCurrentSize(size, current); Images.hide(); @@ -355,19 +355,6 @@ function CmdProto() { }); }; - /** - * unified way to save current file content - * - * @callback - function({data, name}) {} - * @currentFile - */ - this.saveCurrentData = (url, data, callback, query = '') => { - RESTful.write(url + query, data) - .then(() => { - DOM.saveDataToStorage(url, data); - }); - }; - /** * unified way to get RefreshButton */ @@ -768,7 +755,10 @@ function CmdProto() { to : dirPath + to, }; - await RESTful.mv(files); + const [e] = await RESTful.mv(files); + + if (e) + return; DOM.setCurrentName(to, current); Storage.remove(dirPath); @@ -869,7 +859,7 @@ function CmdProto() { return; CloudCmd.loadDir({ - path + path, }); }, diff --git a/client/dom/rest.js b/client/dom/rest.js index e6c84b7b..9b36e27a 100644 --- a/client/dom/rest.js +++ b/client/dom/rest.js @@ -3,7 +3,7 @@ /* global CloudCmd, DOM */ const itype = require('itype/legacy'); -const {promisify} = require('es6-promisify'); +const promisify = require('../../common/try-to-promisify'); const {FS} = require('../../common/cloudfunc'); const {encode} = require('../../common/entity'); diff --git a/client/modules/config/index.js b/client/modules/config/index.js index 4ca85b03..d85d2942 100644 --- a/client/modules/config/index.js +++ b/client/modules/config/index.js @@ -190,7 +190,7 @@ function hide() { CloudCmd.View.hide(); } -function onChange(el) { +async function onChange(el) { const obj = {}; const name = input.getName(el); const data = input.getValue(name, Element); @@ -202,7 +202,7 @@ function onChange(el) { obj[name] = data; - Config.save(obj); + await Config.save(obj); } function onSave(obj) { @@ -214,12 +214,14 @@ function onSave(obj) { }); } -function saveHttp(obj) { +async function saveHttp(obj) { const {RESTful} = DOM; + const [e] = await RESTful.Config.write(obj); - RESTful.Config.write(obj).then(() => { - onSave(obj); - }); + if (e) + return; + + onSave(obj); } function onAuthChange(checked) { diff --git a/client/modules/menu.js b/client/modules/menu.js index 6380ff66..502d4100 100644 --- a/client/modules/menu.js +++ b/client/modules/menu.js @@ -244,8 +244,11 @@ function uploadFromCloud() { CloudCmd.execFromModule('Cloud', 'saveFile', async (currentName, data) => { const path = DOM.getCurrentDirPath() + currentName; + const [e] = await RESTful.write(path, data); + + if (e) + return; - await RESTful.write(path, data); await CloudCmd.refresh({currentName}); }); } diff --git a/client/modules/user-menu/default-menu.js b/client/modules/user-menu/default-menu.js index 8504fded..fb75a834 100644 --- a/client/modules/user-menu/default-menu.js +++ b/client/modules/user-menu/default-menu.js @@ -14,7 +14,7 @@ module.exports = { await DOM.renameCurrent(); }, - 'C - Create User Menu File': async ({DOM, CloudCmd, tryToCatch}) => { + 'C - Create User Menu File': async ({DOM, CloudCmd}) => { const { RESTful, CurrentInfo, @@ -23,7 +23,7 @@ module.exports = { const {dirPath} = CurrentInfo; const path = `${dirPath}.cloudcmd.menu.js`; - const [e] = await tryToCatch(RESTful.write, path, data); + const [e] = await RESTful.write(path, data); if (e) return; diff --git a/client/modules/user-menu/default-menu.spec.js b/client/modules/user-menu/default-menu.spec.js index 731ab5f0..78514a2b 100644 --- a/client/modules/user-menu/default-menu.spec.js +++ b/client/modules/user-menu/default-menu.spec.js @@ -4,7 +4,6 @@ const test = require('supertape'); const stub = require('@cloudcmd/stub'); const wraptile = require('wraptile'); const defaultMenu = require('./default-menu'); -const tryToCatch = require('try-to-catch'); const {_data} = defaultMenu; const reject = wraptile(async (a) => { throw Error(a); @@ -19,7 +18,6 @@ test('cloudcmd: client: user menu: RESTful.write', async (t) => { await defaultMenu[name]({ DOM, CloudCmd, - tryToCatch, }); const path = '/.cloudcmd.menu.js'; @@ -36,7 +34,6 @@ test('cloudcmd: client: user menu: refresh', async (t) => { await defaultMenu[name]({ DOM, CloudCmd, - tryToCatch, }); t.ok(refresh.calledWith(), 'should call CloudCmd.refresh'); @@ -52,7 +49,6 @@ test('cloudcmd: client: user menu: setCurrentByName', async (t) => { await defaultMenu[name]({ DOM, CloudCmd, - tryToCatch, }); const fileName = '.cloudcmd.menu.js'; @@ -69,7 +65,6 @@ test('cloudcmd: client: user menu: EditFile.show', async (t) => { await defaultMenu[name]({ DOM, CloudCmd, - tryToCatch, }); t.ok(EditFile.show.called, 'should call EditFile.show'); @@ -88,7 +83,6 @@ test('cloudcmd: client: user menu: no EditFile.show', async (t) => { await defaultMenu[name]({ DOM, CloudCmd, - tryToCatch, }); t.notOk(EditFile.show.called, 'should not call EditFile.show'); diff --git a/client/modules/user-menu/index.js b/client/modules/user-menu/index.js index d76733b5..02d734e1 100644 --- a/client/modules/user-menu/index.js +++ b/client/modules/user-menu/index.js @@ -122,7 +122,6 @@ const runUserMenu = async (value, options, userMenu) => { const [e] = await tryToCatch(userMenu[value], { DOM, CloudCmd, - tryToCatch, }); if (e) diff --git a/common/try-to-promisify.js b/common/try-to-promisify.js index ab4860d2..0bb49b88 100644 --- a/common/try-to-promisify.js +++ b/common/try-to-promisify.js @@ -1,11 +1,11 @@ 'use strict'; const {promisify} = require('es6-promisify'); +const wraptile = require('wraptile/legacy'); const tryToCatch = require('try-to-catch/legacy'); -module.exports = (fn, ...args) => { +module.exports = wraptile((fn, ...args) => { const promise = promisify(fn); - return tryToCatch(promise, ...args); -}; +}); From 76184c0251342442b09400cd316f2e8d7c6822a4 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Thu, 23 May 2019 18:16:49 +0300 Subject: [PATCH 0051/1728] feature(user-menu) add default user menu --- client/dom/dialog.js | 2 +- client/dom/index.js | 13 +- client/dom/io.js | 214 ++++++++++++++++++++ client/dom/rest.js | 232 +++------------------- client/modules/user-menu/default-menu.js | 38 ---- client/modules/user-menu/get-user-menu.js | 5 - client/modules/user-menu/index.js | 1 + common/try-to-promisify.js | 11 - madrun.js | 4 +- server/user-menu.js | 35 +++- static/user-menu.js | 42 ++++ 11 files changed, 325 insertions(+), 272 deletions(-) create mode 100644 client/dom/io.js delete mode 100644 client/modules/user-menu/default-menu.js delete mode 100644 common/try-to-promisify.js create mode 100644 static/user-menu.js diff --git a/client/dom/dialog.js b/client/dom/dialog.js index 13b36b2a..768ccfcc 100644 --- a/client/dom/dialog.js +++ b/client/dom/dialog.js @@ -17,7 +17,7 @@ module.exports.alert = (...a) => alert(title, ...a, { module.exports.prompt = (...a) => tryToCatch(prompt, title, ...a); module.exports.confirm = (...a) => tryToCatch(confirm, title, ...a); -module.exports.progress = (...a) => tryToCatch(progress, title, ...a); +module.exports.progress = (...a) => progress(title, ...a); module.exports.alert.noFiles = () => { return alert(title, 'No files selected!', { diff --git a/client/dom/index.js b/client/dom/index.js index 6c276866..2207c666 100644 --- a/client/dom/index.js +++ b/client/dom/index.js @@ -13,11 +13,10 @@ const Images = require('./images'); const load = require('./load'); const Files = require('./files'); const RESTful = require('./rest'); +const IO = require('./io'); const Storage = require('./storage'); const Dialog = require('./dialog'); -const read = callbackify(RESTful.read); - const currentFile = require('./current-file'); const DOMTree = require('./dom-tree'); @@ -27,10 +26,20 @@ const DOM = { ...new CmdProto(), }; +const read = callbackify(async (...args) => { + const [e, data] = await RESTful.read(...args); + + if (e) + throw e; + + return data; +}); + DOM.Images = Images; DOM.load = load; DOM.Files = Files; DOM.RESTful = RESTful; +DOM.IO = IO; DOM.Storage = Storage; DOM.Dialog = Dialog; diff --git a/client/dom/io.js b/client/dom/io.js new file mode 100644 index 00000000..24abe841 --- /dev/null +++ b/client/dom/io.js @@ -0,0 +1,214 @@ +'use strict'; + +/* global CloudCmd*/ + +const itype = require('itype/legacy'); +const {promisify} = require('es6-promisify'); + +const {FS} = require('../../common/cloudfunc'); + +const Images = require('./images'); +const load = require('./load'); + +const imgPosition = { + top: true, +}; + +module.exports._replaceHash = replaceHash; +function replaceHash(url) { + /* + * if we send ajax request - + * no need in hash so we escape # + */ + return url.replace(/#/g, '%23'); +} + +module.exports.delete = promisify((url, data, callback) => { + const isFunc = itype.function(data); + + if (!callback && isFunc) { + callback = data; + data = null; + } + + sendRequest({ + method : 'DELETE', + url : FS + url, + data, + callback, + imgPosition : { top: !!data }, + }); +}); + +module.exports.patch = promisify((url, data, callback) => { + const isFunc = itype.function(data); + + if (!callback && isFunc) { + callback = data; + data = null; + } + + sendRequest({ + method: 'PATCH', + url: FS + url, + data, + callback, + imgPosition, + }); +}); + +module.exports.write = promisify((url, data, callback) => { + const isFunc = itype.function(data); + + if (!callback && isFunc) { + callback = data; + data = null; + } + + sendRequest({ + method: 'PUT', + url: FS + url, + data, + callback, + imgPosition, + }); +}); + +module.exports.read = promisify((url, dataType, callback) => { + const notLog = !url.includes('?'); + const isFunc = itype.function(dataType); + + if (!callback && isFunc) { + callback = dataType; + dataType = 'text'; + } + + sendRequest({ + method: 'GET', + url: FS + url, + callback, + notLog, + dataType, + }); +}); + +module.exports.cp = promisify((data, callback) => { + sendRequest({ + method: 'PUT', + url: '/cp', + data, + callback, + imgPosition, + }); +}); + +module.exports.pack = promisify((data, callback) => { + sendRequest({ + method: 'PUT', + url: '/pack', + data, + callback, + }); +}); + +module.exports.extract = promisify((data, callback) => { + sendRequest({ + method : 'PUT', + url : '/extract', + data, + callback, + }); +}); + +module.exports.mv = promisify((data, callback) => { + sendRequest({ + method : 'PUT', + url : '/mv', + data, + callback, + imgPosition, + }); +}); + +module.exports.Config = { + read: promisify((callback) => { + sendRequest({ + method: 'GET', + url: '/config', + callback, + imgPosition, + notLog: true, + }); + }), + + write: promisify((data, callback) => { + sendRequest({ + method: 'PATCH', + url: '/config', + data, + callback, + imgPosition, + }); + }), +}; + +module.exports.Markdown = { + read: promisify((url, callback) => { + sendRequest({ + method: 'GET', + url: '/markdown' + url, + callback, + imgPosition, + notLog: true, + }); + }), + + render: promisify((data, callback) => { + sendRequest({ + method: 'PUT', + url: '/markdown', + data, + callback, + imgPosition, + notLog: true, + }); + }), +}; + +function sendRequest(params) { + const p = params; + const {prefixURL} = CloudCmd; + + p.url = prefixURL + p.url; + p.url = encodeURI(p.url); + + p.url = replaceHash(p.url); + + load.ajax({ + method : p.method, + url : p.url, + data : p.data, + dataType : p.dataType, + error : (jqXHR) => { + const response = jqXHR.responseText; + + const { + statusText, + status, + } = jqXHR; + + const text = status === 404 ? response : statusText; + + p.callback(Error(text)); + }, + success: (data) => { + Images.hide(); + + if (!p.notLog) + CloudCmd.log(data); + + p.callback(null, data); + }, + }); +} + diff --git a/client/dom/rest.js b/client/dom/rest.js index 9b36e27a..3a9d2f62 100644 --- a/client/dom/rest.js +++ b/client/dom/rest.js @@ -1,221 +1,43 @@ 'use strict'; -/* global CloudCmd, DOM */ +const tryToCatch = require('try-to-catch/legacy'); -const itype = require('itype/legacy'); -const promisify = require('../../common/try-to-promisify'); - -const {FS} = require('../../common/cloudfunc'); const {encode} = require('../../common/entity'); const Images = require('./images'); -const load = require('./load'); +const IO = require('./io'); +const Dialog = require('./dialog'); -const imgPosition = { - top: true, +const handleError = (promise) => async (...args) => { + const [e, data] = await tryToCatch(promise, ...args); + + if (!e) + return [e, data]; + + const encoded = encode(e.message); + + Images.show.error(encoded); + Dialog.alert(encoded); + + return [e, data]; }; -module.exports._replaceHash = replaceHash; -function replaceHash(url) { - /* - * if we send ajax request - - * no need in hash so we escape # - */ - return url.replace(/#/g, '%23'); -} - -module.exports.delete = promisify((url, data, callback) => { - const isFunc = itype.function(data); - - if (!callback && isFunc) { - callback = data; - data = null; - } - - sendRequest({ - method : 'DELETE', - url : FS + url, - data, - callback, - imgPosition : { top: !!data }, - }); -}); - -module.exports.patch = promisify((url, data, callback) => { - const isFunc = itype.function(data); - - if (!callback && isFunc) { - callback = data; - data = null; - } - - sendRequest({ - method: 'PATCH', - url: FS + url, - data, - callback, - imgPosition, - }); -}); - -module.exports.write = promisify((url, data, callback) => { - const isFunc = itype.function(data); - - if (!callback && isFunc) { - callback = data; - data = null; - } - - sendRequest({ - method: 'PUT', - url: FS + url, - data, - callback, - imgPosition, - }); -}); - -module.exports.read = promisify((url, dataType, callback) => { - const notLog = !url.includes('?'); - const isFunc = itype.function(dataType); - - if (!callback && isFunc) { - callback = dataType; - dataType = 'text'; - } - - sendRequest({ - method: 'GET', - url: FS + url, - callback, - notLog, - dataType, - }); -}); - -module.exports.cp = promisify((data, callback) => { - sendRequest({ - method: 'PUT', - url: '/cp', - data, - callback, - imgPosition, - }); -}); - -module.exports.pack = promisify((data, callback) => { - sendRequest({ - method: 'PUT', - url: '/pack', - data, - callback, - }); -}); - -module.exports.extract = promisify((data, callback) => { - sendRequest({ - method : 'PUT', - url : '/extract', - data, - callback, - }); -}); - -module.exports.mv = promisify((data, callback) => { - sendRequest({ - method : 'PUT', - url : '/mv', - data, - callback, - imgPosition, - }); -}); +module.exports.delete = handleError(IO.delete); +module.exports.patch = handleError(IO.patch); +module.exports.write = handleError(IO.write); +module.exports.read = handleError(IO.read); +module.exports.cp = handleError(IO.cp); +module.exports.pack = handleError(IO.pack); +module.exports.extract = handleError(IO.extract); +module.exports.mv = handleError(IO.mv); module.exports.Config = { - read: promisify((callback) => { - sendRequest({ - method: 'GET', - url: '/config', - callback, - imgPosition, - notLog: true, - }); - }), - - write: promisify((data, callback) => { - sendRequest({ - method: 'PATCH', - url: '/config', - data, - callback, - imgPosition, - }); - }), + read: handleError(IO.Config.read), + write: handleError(IO.Config.write), }; module.exports.Markdown = { - read: promisify((url, callback) => { - sendRequest({ - method: 'GET', - url: '/markdown' + url, - callback, - imgPosition, - notLog: true, - }); - }), - - render: promisify((data, callback) => { - sendRequest({ - method: 'PUT', - url: '/markdown', - data, - callback, - imgPosition, - notLog: true, - }); - }), + read: handleError(IO.Markdown.read), + render: handleError(IO.Markdown.render), }; -function sendRequest(params) { - const p = params; - const {prefixURL} = CloudCmd; - - p.url = prefixURL + p.url; - p.url = encodeURI(p.url); - - p.url = replaceHash(p.url); - - load.ajax({ - method : p.method, - url : p.url, - data : p.data, - dataType : p.dataType, - error : (jqXHR) => { - const response = jqXHR.responseText; - - const { - statusText, - status, - } = jqXHR; - - const text = status === 404 ? response : statusText; - const encoded = encode(text); - - Images.show.error(encoded); - - setTimeout(() => { - DOM.Dialog.alert(encoded); - }, 100); - - p.callback(Error(text)); - }, - success: (data) => { - Images.hide(); - - if (!p.notLog) - CloudCmd.log(data); - - p.callback(null, data); - }, - }); -} diff --git a/client/modules/user-menu/default-menu.js b/client/modules/user-menu/default-menu.js deleted file mode 100644 index fb75a834..00000000 --- a/client/modules/user-menu/default-menu.js +++ /dev/null @@ -1,38 +0,0 @@ -'use strict'; - -const data = `'use strict'; - -module.exports = { - 'F2 - Rename file': async ({DOM}) => { - await DOM.renameCurrent(); - }, -}; -`; - -module.exports = { - 'F2 - Rename file': async ({DOM}) => { - await DOM.renameCurrent(); - }, - - 'C - Create User Menu File': async ({DOM, CloudCmd}) => { - const { - RESTful, - CurrentInfo, - } = DOM; - - const {dirPath} = CurrentInfo; - const path = `${dirPath}.cloudcmd.menu.js`; - - const [e] = await RESTful.write(path, data); - - if (e) - return; - - await CloudCmd.refresh(); - DOM.setCurrentByName('.cloudcmd.menu.js'); - await CloudCmd.EditFile.show(); - }, -}; - -module.exports._data = data; - diff --git a/client/modules/user-menu/get-user-menu.js b/client/modules/user-menu/get-user-menu.js index 206161bb..2df17696 100644 --- a/client/modules/user-menu/get-user-menu.js +++ b/client/modules/user-menu/get-user-menu.js @@ -1,11 +1,6 @@ 'use strict'; -const defaultUserMenu = require('./default-menu.js'); - module.exports = (menuFn) => { - if (!menuFn) - return defaultUserMenu; - const module = {}; const fn = Function('module', menuFn); diff --git a/client/modules/user-menu/index.js b/client/modules/user-menu/index.js index 02d734e1..d76733b5 100644 --- a/client/modules/user-menu/index.js +++ b/client/modules/user-menu/index.js @@ -122,6 +122,7 @@ const runUserMenu = async (value, options, userMenu) => { const [e] = await tryToCatch(userMenu[value], { DOM, CloudCmd, + tryToCatch, }); if (e) diff --git a/common/try-to-promisify.js b/common/try-to-promisify.js deleted file mode 100644 index 0bb49b88..00000000 --- a/common/try-to-promisify.js +++ /dev/null @@ -1,11 +0,0 @@ -'use strict'; - -const {promisify} = require('es6-promisify'); -const wraptile = require('wraptile/legacy'); -const tryToCatch = require('try-to-catch/legacy'); - -module.exports = wraptile((fn, ...args) => { - const promise = promisify(fn); - return tryToCatch(promise, ...args); -}); - diff --git a/madrun.js b/madrun.js index 48af04d4..13f53612 100644 --- a/madrun.js +++ b/madrun.js @@ -31,7 +31,7 @@ module.exports = { 'lint': () => run(['putout', 'lint:*', 'spell']), 'lint:server': () => `eslint -c .eslintrc.server ${dirs} --ignore-pattern *.spec.js`, 'lint:test': () => `eslint --ignore-pattern '!.*' ${dirsTest}`, - 'lint:client': () => 'eslint --env browser client --ignore-pattern .cloudcmd.menu.js', + 'lint:client': () => 'eslint --env browser client static --ignore-pattern .cloudcmd.menu.js', 'lint:css': () => 'stylelint css/*.css', 'spell': () => 'yaspeller .', 'fix:lint': () => run(['putout', 'lint:*'], '--fix'), @@ -86,6 +86,6 @@ module.exports = { 'build:client': () => run('6to5:client'), 'build:client:dev': () => run('6to5:client:dev'), 'heroku-postbuild': () => run('6to5:client'), - 'putout': () => 'putout bin client server common test .cloudcmd.menu.js', + 'putout': () => 'putout bin client static server common test .cloudcmd.menu.js', }; diff --git a/server/user-menu.js b/server/user-menu.js index 82a02c87..7f81683c 100644 --- a/server/user-menu.js +++ b/server/user-menu.js @@ -2,6 +2,7 @@ const {homedir} = require('os'); const fs = require('fs'); + const {join} = require('path'); const {promisify} = require('util'); @@ -11,19 +12,32 @@ const findUp = require('find-up'); const readFile = promisify(fs.readFile); +const URL = '/api/v1/user-menu'; +const DEFAULT_MENU_PATH = join(__dirname, '../static/user-menu.js'); + module.exports = currify(async({menuName}, req, res, next) => { - if (req.url.indexOf('/api/v1/user-menu')) + if (req.url.indexOf(URL)) return next(); const {method} = req; if (method === 'GET') - return onGET(menuName, req.query, res); + return onGET({ + req, + res, + menuName, + }); next(); }); -async function onGET(menuName, {dir}, res) { +async function onGET({req, res, menuName}) { + const {dir} = req.query; + const url = req.url.replace(URL, ''); + + if (url === '/default') + return sendDefaultMenu(res); + const [errorFind, currentMenuPath] = await tryToCatch(findUp, [ menuName, ], {cwd: dir}); @@ -33,21 +47,26 @@ async function onGET(menuName, {dir}, res) { .status(404) .send(e.message); - if (errorFind && errorFind.code === 'ENOENT') - return res.send(''); - const homeMenuPath = join(homedir(), menuName); const menuPath = currentMenuPath || homeMenuPath; const [e, data] = await tryToCatch(readFile, menuPath, 'utf8'); if (!e) - return res.send(data); + return res + .type('js') + .send(data); if (e.code !== 'ENOENT') return res .status(404) .send(e.message); - return res.send(''); + sendDefaultMenu(res); +} + +function sendDefaultMenu(res) { + res.sendFile(DEFAULT_MENU_PATH, { + cacheControl: false, + }); } diff --git a/static/user-menu.js b/static/user-menu.js new file mode 100644 index 00000000..49e87c18 --- /dev/null +++ b/static/user-menu.js @@ -0,0 +1,42 @@ +'use strict'; + +module.exports = { + 'F2 - Rename file': async ({DOM}) => { + await DOM.renameCurrent(); + }, + + 'C - Create User Menu File': async ({DOM, CloudCmd}) => { + const {CurrentInfo} = DOM; + + const {dirPath} = CurrentInfo; + const path = `${dirPath}.cloudcmd.menu.js`; + const {prefix} = CloudCmd; + + const data = await readDefaultMenu({prefix}); + await createDefaultMenu({ + path, + data, + DOM, + CloudCmd, + }); + }, +}; + +async function createDefaultMenu({path, data, DOM, CloudCmd}) { + const {IO} = DOM; + + await IO.write(path, data); + await CloudCmd.refresh(); + + DOM.setCurrentByName('.cloudcmd.menu.js'); + + await CloudCmd.EditFile.show(); +} + +async function readDefaultMenu({prefix}) { + const res = await fetch(`${prefix}/api/v1/user-menu/default`); + const data = await res.text(); + + return data; +} + From 093966f6927ded45c14867fb0e2b253862d53c97 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Thu, 23 May 2019 19:16:12 +0300 Subject: [PATCH 0052/1728] test(user-menu) clear --- client/dom/{rest.spec.js => io.spec.js} | 6 +++--- client/modules/user-menu/get-user-menu.spec.js | 18 ------------------ .../user-menu.spec.js | 10 +++++----- 3 files changed, 8 insertions(+), 26 deletions(-) rename client/dom/{rest.spec.js => io.spec.js} (67%) rename client/modules/user-menu/default-menu.spec.js => static/user-menu.spec.js (87%) diff --git a/client/dom/rest.spec.js b/client/dom/io.spec.js similarity index 67% rename from client/dom/rest.spec.js rename to client/dom/io.spec.js index 186ca650..c73efbac 100644 --- a/client/dom/rest.spec.js +++ b/client/dom/io.spec.js @@ -1,10 +1,10 @@ 'use strict'; const test = require('supertape'); -const rest = require('./rest'); +const io = require('./io'); -test('cloudcmd: client: rest: replaceHash', (t) => { - const {_replaceHash} = rest; +test('cloudcmd: client: io: replaceHash', (t) => { + const {_replaceHash} = io; const url = '/hello/####world'; const result = _replaceHash(url); const expected = '/hello/%23%23%23%23world'; diff --git a/client/modules/user-menu/get-user-menu.spec.js b/client/modules/user-menu/get-user-menu.spec.js index e0354114..5da03054 100644 --- a/client/modules/user-menu/get-user-menu.spec.js +++ b/client/modules/user-menu/get-user-menu.spec.js @@ -1,7 +1,6 @@ 'use strict'; const test = require('supertape'); -const stub = require('@cloudcmd/stub'); const getUserMenu = require('./get-user-menu'); test('user-menu: getUserMenu', (t) => { @@ -20,20 +19,3 @@ test('user-menu: getUserMenu', (t) => { t.end(); }); -test('user-menu: getUserMenu: no args', (t) => { - const result = getUserMenu(); - const renameCurrent = stub(); - const DOM = { - renameCurrent, - }; - - const name = 'F2 - Rename file'; - - result[name]({ - DOM, - }); - - t.ok(renameCurrent.called, 'should call renameCurrent'); - t.end(); -}); - diff --git a/client/modules/user-menu/default-menu.spec.js b/static/user-menu.spec.js similarity index 87% rename from client/modules/user-menu/default-menu.spec.js rename to static/user-menu.spec.js index 78514a2b..c3b80c33 100644 --- a/client/modules/user-menu/default-menu.spec.js +++ b/static/user-menu.spec.js @@ -9,7 +9,7 @@ const reject = wraptile(async (a) => { throw Error(a); }); -test('cloudcmd: client: user menu: RESTful.write', async (t) => { +test('cloudcmd: static: user menu: client: RESTful.write', async (t) => { const name = 'C - Create User Menu File'; const DOM = getDOM(); const CloudCmd = getCloudCmd(); @@ -25,7 +25,7 @@ test('cloudcmd: client: user menu: RESTful.write', async (t) => { t.end(); }); -test('cloudcmd: client: user menu: refresh', async (t) => { +test('cloudcmd: static: user menu: refresh', async (t) => { const name = 'C - Create User Menu File'; const DOM = getDOM(); const CloudCmd = getCloudCmd(); @@ -40,7 +40,7 @@ test('cloudcmd: client: user menu: refresh', async (t) => { t.end(); }); -test('cloudcmd: client: user menu: setCurrentByName', async (t) => { +test('cloudcmd: static: user menu: setCurrentByName', async (t) => { const name = 'C - Create User Menu File'; const DOM = getDOM(); const CloudCmd = getCloudCmd(); @@ -56,7 +56,7 @@ test('cloudcmd: client: user menu: setCurrentByName', async (t) => { t.end(); }); -test('cloudcmd: client: user menu: EditFile.show', async (t) => { +test('cloudcmd: static: user menu: EditFile.show', async (t) => { const name = 'C - Create User Menu File'; const DOM = getDOM(); const CloudCmd = getCloudCmd(); @@ -71,7 +71,7 @@ test('cloudcmd: client: user menu: EditFile.show', async (t) => { t.end(); }); -test('cloudcmd: client: user menu: no EditFile.show', async (t) => { +test('cloudcmd: static: user menu: no EditFile.show', async (t) => { const name = 'C - Create User Menu File'; const DOM = getDOM(); const CloudCmd = getCloudCmd(); From f80f87d77d6fb201c230baf6034ccbe60b0c07ae Mon Sep 17 00:00:00 2001 From: coderaiser Date: Fri, 24 May 2019 12:04:08 +0300 Subject: [PATCH 0053/1728] test(user-menu) coverage --- madrun.js | 2 +- static/user-menu.spec.js | 40 ++++++++++++++++++++++++++++++---------- 2 files changed, 31 insertions(+), 11 deletions(-) diff --git a/madrun.js b/madrun.js index 13f53612..74da8336 100644 --- a/madrun.js +++ b/madrun.js @@ -35,7 +35,7 @@ module.exports = { 'lint:css': () => 'stylelint css/*.css', 'spell': () => 'yaspeller .', 'fix:lint': () => run(['putout', 'lint:*'], '--fix'), - 'test': () => `tape 'test/**/*.js' '{client,common,server}/**/*.spec.js'`, + 'test': () => `tape 'test/**/*.js' '{client,static,common,server}/**/*.spec.js'`, 'test:client': () => `tape 'test/client/**/*.js`, 'test:server': () => `tape 'test/**/*.js' 'server/**/*.spec.js' 'common/**/*.spec.js'`, 'wisdom': () => run(['lint', 'build', 'test']), diff --git a/static/user-menu.spec.js b/static/user-menu.spec.js index c3b80c33..accb3636 100644 --- a/static/user-menu.spec.js +++ b/static/user-menu.spec.js @@ -1,19 +1,37 @@ 'use strict'; -const test = require('supertape'); +const autoGlobals = require('auto-globals'); +const test = autoGlobals(require('supertape')); const stub = require('@cloudcmd/stub'); +const tryToCatch = require('try-to-catch'); const wraptile = require('wraptile'); -const defaultMenu = require('./default-menu'); + +const defaultMenu = require('./user-menu'); + const {_data} = defaultMenu; const reject = wraptile(async (a) => { throw Error(a); }); -test('cloudcmd: static: user menu: client: RESTful.write', async (t) => { +test('cloudcmd: static: user menu: Rename', async (t) => { + const name = 'F2 - Rename file'; + const DOM = getDOM(); + + const {renameCurrent} = DOM; + + await defaultMenu[name]({ + DOM, + }); + + t.ok(renameCurrent.called, 'should call renameCurrent'); + t.end(); +}); + +test('cloudcmd: static: user menu: IO.write', async (t) => { const name = 'C - Create User Menu File'; const DOM = getDOM(); const CloudCmd = getCloudCmd(); - const {write} = DOM.RESTful; + const {write} = DOM.IO; await defaultMenu[name]({ DOM, @@ -21,7 +39,7 @@ test('cloudcmd: static: user menu: client: RESTful.write', async (t) => { }); const path = '/.cloudcmd.menu.js'; - t.ok(write.calledWith(path, _data), 'should call RESTful.write'); + t.ok(write.calledWith(path, _data), 'should call IO.write'); t.end(); }); @@ -75,12 +93,12 @@ test('cloudcmd: static: user menu: no EditFile.show', async (t) => { const name = 'C - Create User Menu File'; const DOM = getDOM(); const CloudCmd = getCloudCmd(); - const {RESTful} = DOM; + const {IO} = DOM; const {EditFile} = CloudCmd; - RESTful.write = stub(reject('Error')); + IO.write = stub(reject('Error')); - await defaultMenu[name]({ + await tryToCatch(defaultMenu[name], { DOM, CloudCmd, }); @@ -90,7 +108,7 @@ test('cloudcmd: static: user menu: no EditFile.show', async (t) => { }); function getDOM() { - const RESTful = { + const IO = { write: stub(), }; @@ -99,9 +117,10 @@ function getDOM() { }; return { - RESTful, + IO, CurrentInfo, setCurrentByName: stub(), + renameCurrent: stub(), }; } @@ -113,3 +132,4 @@ function getCloudCmd() { }, }; } + From 070ccc4fbbcbfba62e794dbc81aba1688aadf1c9 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Fri, 24 May 2019 12:06:01 +0300 Subject: [PATCH 0054/1728] feature(user-menu) imrove error output --- client/modules/user-menu/index.js | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/client/modules/user-menu/index.js b/client/modules/user-menu/index.js index d76733b5..0494b42b 100644 --- a/client/modules/user-menu/index.js +++ b/client/modules/user-menu/index.js @@ -75,9 +75,8 @@ async function show() { function fillTemplate(options) { const result = []; - for (const option of options) { + for (const option of options) result.push(``); - } return result.join(''); } @@ -125,7 +124,12 @@ const runUserMenu = async (value, options, userMenu) => { tryToCatch, }); - if (e) - Dialog.alert(e.stack); + if (!e) + return; + + if (e.name === 'Error') + return Dialog.alert(e.message); + + return Dialog.alert(e.stack); }; From 8859587768cfa91e4df7580a9f48827182d3565c Mon Sep 17 00:00:00 2001 From: coderaiser Date: Fri, 24 May 2019 12:31:38 +0300 Subject: [PATCH 0055/1728] feature(upload) improve style --- client/modules/upload.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/client/modules/upload.js b/client/modules/upload.js index c5135ce6..f0822955 100644 --- a/client/modules/upload.js +++ b/client/modules/upload.js @@ -41,11 +41,11 @@ async function show() { createElement('style', { dataName: 'upload-css', - innerText: '[data-name=js-upload-file-button] {' + - `font-family: ${fontFamily};` + - 'font-size: 20px;' + - 'width: 97%' + - '}', + innerText: `[data-name=js-upload-file-button] { + font-family: ${fontFamily}; + font-size: 16px; + margin: 10px 0 10px 0; + }` }); } From 10cc40ec5a8ac6598836b50bbc17e674a45d8091 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Fri, 24 May 2019 12:31:53 +0300 Subject: [PATCH 0056/1728] feature(user-menu) add ability to run in mobile devices --- client/modules/user-menu/index.js | 21 ++++++++++++++++----- client/modules/view.js | 7 ++++++- css/user-menu.css | 10 +++++++++- 3 files changed, 31 insertions(+), 7 deletions(-) diff --git a/client/modules/user-menu/index.js b/client/modules/user-menu/index.js index 0494b42b..68be5c6a 100644 --- a/client/modules/user-menu/index.js +++ b/client/modules/user-menu/index.js @@ -5,6 +5,7 @@ require('../../../css/user-menu.css'); const currify = require('currify/legacy'); +const wraptile = require('wraptile/legacy'); const {promisify} = require('es6-promisify'); const load = require('load.js'); const createElement = require('@cloudcmd/create-element'); @@ -50,7 +51,12 @@ async function show() { const options = Object.keys(userMenu); - const el = createElement('select', { + const button = createElement('button', { + className: 'cloudcmd-user-menu-button', + innerText: 'User Menu', + }); + + const select = createElement('select', { className: 'cloudcmd-user-menu', innerHTML: fillTemplate(options), size: 10, @@ -58,15 +64,16 @@ async function show() { const keys = options.map(getKey); - el.addEventListener('keydown', onKeyDown(keys, options, userMenu)); - el.addEventListener('dblclick', onDblClick(options, userMenu)); + button.addEventListener('click', onButtonClick(options, userMenu, select)); + select.addEventListener('keydown', onKeyDown(keys, options, userMenu)); + select.addEventListener('dblclick', onDblClick(options, userMenu)); - const afterShow = () => el.focus(); + const afterShow = () => select.focus(); const autoSize = true; Images.hide(); - CloudCmd.View.show(el, { + CloudCmd.View.show([button, select], { autoSize, afterShow, }); @@ -90,6 +97,10 @@ const onDblClick = currify(async (options, userMenu, e) => { await runUserMenu(value, options, userMenu); }); +const onButtonClick = wraptile(async (options, userMenu, {value}) => { + await runUserMenu(value, options, userMenu); +}); + const onKeyDown = currify(async (keys, options, userMenu, e) => { const { keyCode, diff --git a/client/modules/view.js b/client/modules/view.js index e2db1116..0dd6f6dd 100644 --- a/client/modules/view.js +++ b/client/modules/view.js @@ -24,6 +24,7 @@ const Images = require('../dom/images'); const {encode} = require('../../common/entity'); +const {isArray} = Array; const testRegExp = currify((name, reg) => reg.test(name)); const lifo = currify((fn, el, cb, name) => fn(name, el, cb)); @@ -99,7 +100,11 @@ async function show(data, options) { El.tabIndex = 0; if (data) { - El.append(data); + if (isArray(data)) + El.append(...data); + else + El.append(data); + modal.open(El, initConfig(Config, options)); return; } diff --git a/css/user-menu.css b/css/user-menu.css index 37f07c14..dc65b50c 100644 --- a/css/user-menu.css +++ b/css/user-menu.css @@ -1,7 +1,6 @@ .cloudcmd-user-menu { font-size: 16px; font-family: 'Droid Sans Mono', 'Ubuntu Mono', 'Consolas', monospace; - width: 400px; } .cloudcmd-user-menu:focus { @@ -12,3 +11,12 @@ box-shadow: 20px -20px 0 2px rgba(49, 123, 249) inset; } +.cloudcmd-user-menu-button { + display: block; + width: 100%; + font-size: 16px; + padding: 2px; + -webkit-appearance: none; + border: 0; +} + From 0b0f9e80e49460db98fa8cbe728e27dfab895445 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Fri, 24 May 2019 12:51:50 +0300 Subject: [PATCH 0057/1728] chore(cloudcmd) lint --- client/modules/upload.js | 2 +- client/modules/view.js | 4 ++-- css/user-menu.css | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/client/modules/upload.js b/client/modules/upload.js index f0822955..868428ad 100644 --- a/client/modules/upload.js +++ b/client/modules/upload.js @@ -45,7 +45,7 @@ async function show() { font-family: ${fontFamily}; font-size: 16px; margin: 10px 0 10px 0; - }` + }`, }); } diff --git a/client/modules/view.js b/client/modules/view.js index 0dd6f6dd..00120ee9 100644 --- a/client/modules/view.js +++ b/client/modules/view.js @@ -102,9 +102,9 @@ async function show(data, options) { if (data) { if (isArray(data)) El.append(...data); - else + else El.append(data); - + modal.open(El, initConfig(Config, options)); return; } diff --git a/css/user-menu.css b/css/user-menu.css index dc65b50c..769ad074 100644 --- a/css/user-menu.css +++ b/css/user-menu.css @@ -16,7 +16,7 @@ width: 100%; font-size: 16px; padding: 2px; - -webkit-appearance: none; - border: 0; + -webkit-appearance: none; + border: 0; } From d617dbfc03fb68b3149dff0fb74cb34af838f5e1 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Fri, 24 May 2019 13:03:02 +0300 Subject: [PATCH 0058/1728] feature(user-menu) hide scroll when small amount of items --- css/user-menu.css | 1 + 1 file changed, 1 insertion(+) diff --git a/css/user-menu.css b/css/user-menu.css index 769ad074..bc806ce9 100644 --- a/css/user-menu.css +++ b/css/user-menu.css @@ -18,5 +18,6 @@ padding: 2px; -webkit-appearance: none; border: 0; + overflow: auto; } From e1de247dbbccfd9f6a053c259c3ac35737f3259e Mon Sep 17 00:00:00 2001 From: coderaiser Date: Fri, 24 May 2019 13:12:59 +0300 Subject: [PATCH 0059/1728] chore(package) v12.3.0 --- ChangeLog | 19 +++++++++++++++++++ HELP.md | 3 ++- README.md | 2 +- package.json | 2 +- 4 files changed, 23 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index 9ef617d9..e0d301bd 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,22 @@ +2019.05.24, v12.3.0 + +fix: +- (user-menu) prefix (#244) +- (dom) renameCurrent: try-to-promise RESTful.mv + +feature: +- (user-menu) hide scroll when small amount of items +- (user-menu) add ability to run in mobile devices +- (upload) improve style +- (user-menu) imrove error output +- (user-menu) add default user menu +- (dialog) cancel -> tryToCatch +- (user-menu) add default option: create user menu +- (user-menu) add error handling +- (user-menu) add ability to navigate with j, k +- (cloudcmd) deprecate plugins + + 2019.05.13, v12.2.0 fix: diff --git a/HELP.md b/HELP.md index b000abdd..e0f95850 100644 --- a/HELP.md +++ b/HELP.md @@ -1,4 +1,4 @@ -# Cloud Commander v12.2.0 +# Cloud Commander v12.3.0 ### [Main][MainURL] [Blog][BlogURL] Live(![Heroku][Heroku_LIVE_IMG] [Heroku][HerokuURL], ![Now][NOW_LIVE_IMG] [Now][NowURL]) @@ -866,6 +866,7 @@ There are a lot of ways to be involved in `Cloud Commander` development: Version history --------------- +- *2019.05.24*, **[v12.3.0](//github.com/coderaiser/cloudcmd/releases/tag/v12.3.0)** - *2019.05.13*, **[v12.2.0](//github.com/coderaiser/cloudcmd/releases/tag/v12.2.0)** - *2019.04.15*, **[v12.1.0](//github.com/coderaiser/cloudcmd/releases/tag/v12.1.0)** - *2019.04.04*, **[v12.0.2](//github.com/coderaiser/cloudcmd/releases/tag/v12.0.2)** diff --git a/README.md b/README.md index 9f371272..4d016dad 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Cloud Commander v12.2.0 [![Build Status][BuildStatusIMGURL]][BuildStatusURL] [![Now status][BuildAppveyorIMGURL]][BuildAppveyorURL] [![Codacy][CodacyIMG]][CodacyURL] [![Gitter][GitterIMGURL]][GitterURL] [![OpenCollective](https://opencollective.com/cloudcmd/backers/badge.svg)](#backers) [![OpenCollective](https://opencollective.com/cloudcmd/sponsors/badge.svg)](#sponsors) +# Cloud Commander v12.3.0 [![Build Status][BuildStatusIMGURL]][BuildStatusURL] [![Now status][BuildAppveyorIMGURL]][BuildAppveyorURL] [![Codacy][CodacyIMG]][CodacyURL] [![Gitter][GitterIMGURL]][GitterURL] [![OpenCollective](https://opencollective.com/cloudcmd/backers/badge.svg)](#backers) [![OpenCollective](https://opencollective.com/cloudcmd/sponsors/badge.svg)](#sponsors) ### [Main][MainURL] [Blog][BlogURL] Live([Heroku][HerokuURL], [Now][NowURL]) diff --git a/package.json b/package.json index 643c7d56..45001031 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "cloudcmd", - "version": "12.2.0", + "version": "12.3.0", "author": "coderaiser (https://github.com/coderaiser)", "description": "File manager for the web with console and editor", "homepage": "http://cloudcmd.io", From 4382d8ca7365885d72e31768fd26f9e3433ea286 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Fri, 24 May 2019 13:28:20 +0300 Subject: [PATCH 0060/1728] docs(help) improve User Menu Example --- HELP.md | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/HELP.md b/HELP.md index e0f95850..c0e468b0 100644 --- a/HELP.md +++ b/HELP.md @@ -493,7 +493,40 @@ module.exports = { CloudCmd.refresh(); }, + 'C - Create User Menu File': async ({DOM, CloudCmd}) => { + const {CurrentInfo} = DOM; + + const {dirPath} = CurrentInfo; + const path = `${dirPath}.cloudcmd.menu.js`; + const {prefix} = CloudCmd; + + const data = await readDefaultMenu({prefix}); + await createDefaultMenu({ + path, + data, + DOM, + CloudCmd, + }); + }, }; + +async function createDefaultMenu({path, data, DOM, CloudCmd}) { + const {IO} = DOM; + + await IO.write(path, data); + await CloudCmd.refresh(); + + DOM.setCurrentByName('.cloudcmd.menu.js'); + + await CloudCmd.EditFile.show(); +} + +async function readDefaultMenu({prefix}) { + const res = await fetch(`${prefix}/api/v1/user-menu/default`); + const data = await res.text(); + + return data; +} ``` You will have ability to run one of this 3 commands with help of double click, enter, or binded key (`F2`, `D` or `P` in this example). Also you can run commands in terminal, or execute any built-in function of `Cloud Commander` extended it's interface. From 035a63f19ed3f35fdbea264f5aae59cf74828d53 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Fri, 24 May 2019 18:02:34 +0300 Subject: [PATCH 0061/1728] fix(cloudcmd) copy --- client/modules/operation/index.js | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/client/modules/operation/index.js b/client/modules/operation/index.js index 875f3ddb..ff913638 100644 --- a/client/modules/operation/index.js +++ b/client/modules/operation/index.js @@ -335,7 +335,7 @@ function deleteSilent(files = DOM.getActiveFiles()) { * @param data * @param operation */ -function _processFiles(options, data) { +async function _processFiles(options, data) { let selFiles; let files; let panel; @@ -382,10 +382,12 @@ function _processFiles(options, data) { const operation = isCopy ? copyFn : moveFn; if (shouldAsk && config(option)) { - const [cancel, to] = message(title, to, names.map(encode)); + const [cancel, newTo] = await prompt(title, to, names.map(encode)); if (!cancel) - ask(to); + ask(newTo); + + return; } ask(to); @@ -496,7 +498,7 @@ function twopack(operation, type) { }); } -async function message(msg, to, names) { +async function prompt(msg, to, names) { const n = names.length; const [name] = names; From fc747792a1d331941e507507f5d8b57c55ae8934 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Fri, 24 May 2019 18:03:13 +0300 Subject: [PATCH 0062/1728] chore(package) v12.3.1 --- ChangeLog | 6 ++++++ HELP.md | 3 ++- README.md | 2 +- package.json | 2 +- 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index e0d301bd..a5e8b86e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2019.05.24, v12.3.1 + +fix: +- (cloudcmd) copy + + 2019.05.24, v12.3.0 fix: diff --git a/HELP.md b/HELP.md index c0e468b0..5f144ca4 100644 --- a/HELP.md +++ b/HELP.md @@ -1,4 +1,4 @@ -# Cloud Commander v12.3.0 +# Cloud Commander v12.3.1 ### [Main][MainURL] [Blog][BlogURL] Live(![Heroku][Heroku_LIVE_IMG] [Heroku][HerokuURL], ![Now][NOW_LIVE_IMG] [Now][NowURL]) @@ -899,6 +899,7 @@ There are a lot of ways to be involved in `Cloud Commander` development: Version history --------------- +- *2019.05.24*, **[v12.3.1](//github.com/coderaiser/cloudcmd/releases/tag/v12.3.1)** - *2019.05.24*, **[v12.3.0](//github.com/coderaiser/cloudcmd/releases/tag/v12.3.0)** - *2019.05.13*, **[v12.2.0](//github.com/coderaiser/cloudcmd/releases/tag/v12.2.0)** - *2019.04.15*, **[v12.1.0](//github.com/coderaiser/cloudcmd/releases/tag/v12.1.0)** diff --git a/README.md b/README.md index 4d016dad..e722f46e 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Cloud Commander v12.3.0 [![Build Status][BuildStatusIMGURL]][BuildStatusURL] [![Now status][BuildAppveyorIMGURL]][BuildAppveyorURL] [![Codacy][CodacyIMG]][CodacyURL] [![Gitter][GitterIMGURL]][GitterURL] [![OpenCollective](https://opencollective.com/cloudcmd/backers/badge.svg)](#backers) [![OpenCollective](https://opencollective.com/cloudcmd/sponsors/badge.svg)](#sponsors) +# Cloud Commander v12.3.1 [![Build Status][BuildStatusIMGURL]][BuildStatusURL] [![Now status][BuildAppveyorIMGURL]][BuildAppveyorURL] [![Codacy][CodacyIMG]][CodacyURL] [![Gitter][GitterIMGURL]][GitterURL] [![OpenCollective](https://opencollective.com/cloudcmd/backers/badge.svg)](#backers) [![OpenCollective](https://opencollective.com/cloudcmd/sponsors/badge.svg)](#sponsors) ### [Main][MainURL] [Blog][BlogURL] Live([Heroku][HerokuURL], [Now][NowURL]) diff --git a/package.json b/package.json index 45001031..4e9426e9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "cloudcmd", - "version": "12.3.0", + "version": "12.3.1", "author": "coderaiser (https://github.com/coderaiser)", "description": "File manager for the web with console and editor", "homepage": "http://cloudcmd.io", From 9149f77a372ec4b79bae5676f3253b6e340205c2 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Fri, 24 May 2019 19:04:16 +0300 Subject: [PATCH 0063/1728] fix(select-by-pattern) crash --- client/dom/select-by-pattern.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/dom/select-by-pattern.js b/client/dom/select-by-pattern.js index b64a77dd..eec89bb4 100644 --- a/client/dom/select-by-pattern.js +++ b/client/dom/select-by-pattern.js @@ -8,7 +8,7 @@ const { prompt, } = require('./dialog'); -const {DOM} = require('.'); +const DOM = require('.'); module.exports = async (msg, files) => { if (!files) From fc8eda07f7b35dda4fe11fb6252356963f4d91c7 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Fri, 24 May 2019 19:14:51 +0300 Subject: [PATCH 0064/1728] fix(user-menu) F1 and F keys overlapping --- client/modules/user-menu/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/modules/user-menu/index.js b/client/modules/user-menu/index.js index 68be5c6a..94eaac8a 100644 --- a/client/modules/user-menu/index.js +++ b/client/modules/user-menu/index.js @@ -35,7 +35,7 @@ module.exports.show = show; module.exports.hide = hide; const getKey = (a) => a.split(' - ')[0]; -const beginWith = (a) => (b) => !b.indexOf(a); +const beginWith = (a) => (b) => a === getKey(b); const {CurrentInfo} = DOM; From b374437fb6173934069c496d33b5981c13be6057 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Fri, 24 May 2019 19:15:55 +0300 Subject: [PATCH 0065/1728] chore(package) v12.3.2 --- ChangeLog | 7 +++++++ HELP.md | 3 ++- README.md | 2 +- package.json | 2 +- 4 files changed, 11 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index a5e8b86e..4b95330e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2019.05.24, v12.3.2 + +fix: +- (user-menu) F1 and F keys overlapping +- (select-by-pattern) crash + + 2019.05.24, v12.3.1 fix: diff --git a/HELP.md b/HELP.md index 5f144ca4..fd048bf7 100644 --- a/HELP.md +++ b/HELP.md @@ -1,4 +1,4 @@ -# Cloud Commander v12.3.1 +# Cloud Commander v12.3.2 ### [Main][MainURL] [Blog][BlogURL] Live(![Heroku][Heroku_LIVE_IMG] [Heroku][HerokuURL], ![Now][NOW_LIVE_IMG] [Now][NowURL]) @@ -899,6 +899,7 @@ There are a lot of ways to be involved in `Cloud Commander` development: Version history --------------- +- *2019.05.24*, **[v12.3.2](//github.com/coderaiser/cloudcmd/releases/tag/v12.3.2)** - *2019.05.24*, **[v12.3.1](//github.com/coderaiser/cloudcmd/releases/tag/v12.3.1)** - *2019.05.24*, **[v12.3.0](//github.com/coderaiser/cloudcmd/releases/tag/v12.3.0)** - *2019.05.13*, **[v12.2.0](//github.com/coderaiser/cloudcmd/releases/tag/v12.2.0)** diff --git a/README.md b/README.md index e722f46e..bf74cd9b 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Cloud Commander v12.3.1 [![Build Status][BuildStatusIMGURL]][BuildStatusURL] [![Now status][BuildAppveyorIMGURL]][BuildAppveyorURL] [![Codacy][CodacyIMG]][CodacyURL] [![Gitter][GitterIMGURL]][GitterURL] [![OpenCollective](https://opencollective.com/cloudcmd/backers/badge.svg)](#backers) [![OpenCollective](https://opencollective.com/cloudcmd/sponsors/badge.svg)](#sponsors) +# Cloud Commander v12.3.2 [![Build Status][BuildStatusIMGURL]][BuildStatusURL] [![Now status][BuildAppveyorIMGURL]][BuildAppveyorURL] [![Codacy][CodacyIMG]][CodacyURL] [![Gitter][GitterIMGURL]][GitterURL] [![OpenCollective](https://opencollective.com/cloudcmd/backers/badge.svg)](#backers) [![OpenCollective](https://opencollective.com/cloudcmd/sponsors/badge.svg)](#sponsors) ### [Main][MainURL] [Blog][BlogURL] Live([Heroku][HerokuURL], [Now][NowURL]) diff --git a/package.json b/package.json index 4e9426e9..378fcdc4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "cloudcmd", - "version": "12.3.1", + "version": "12.3.2", "author": "coderaiser (https://github.com/coderaiser)", "description": "File manager for the web with console and editor", "homepage": "http://cloudcmd.io", From c212acd90baf412feb9c442c22cd93cfb60c9bf0 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Mon, 27 May 2019 12:35:42 +0300 Subject: [PATCH 0066/1728] fix(terminal-run) resolve before close --- client/load-module.js | 2 +- client/modules/terminal-run.js | 37 ++++++++++++++++++---------------- 2 files changed, 21 insertions(+), 18 deletions(-) diff --git a/client/load-module.js b/client/load-module.js index 9c203e87..17afdef7 100644 --- a/client/load-module.js +++ b/client/load-module.js @@ -54,7 +54,7 @@ module.exports = function loadModule(params) { if (e) return console.error(e); - a.show(...args); + await a.show(...args); }; }; diff --git a/client/modules/terminal-run.js b/client/modules/terminal-run.js index 02ce4f28..01cadf38 100644 --- a/client/modules/terminal-run.js +++ b/client/modules/terminal-run.js @@ -53,7 +53,26 @@ module.exports.init = async () => { await loadAll(); }; -module.exports.show = show; +module.exports.show = promisify((options = {}, fn) => { + if (!Loaded) + return; + + if (!config('terminal')) + return; + + create(options); + + CloudCmd.View.show(Terminal.element, { + afterShow: () => { + Terminal.focus(); + }, + afterClose: (/* exec.series args */) => { + fn(); + }, + }); +}); + + module.exports.hide = hide; function hide () { @@ -128,19 +147,3 @@ function authCheck(spawn) { }); } -async function show(options = {}) { - if (!Loaded) - return; - - if (!config('terminal')) - return; - - await create(options); - - CloudCmd.View.show(Terminal.element, { - afterShow: () => { - Terminal.focus(); - }, - }); -} - From a360301759f85b929001e745401e8028b932c5f2 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Mon, 27 May 2019 19:26:17 +0300 Subject: [PATCH 0067/1728] chore(cloudfunc) rm no-multi-space --- test/common/cloudfunc.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/test/common/cloudfunc.js b/test/common/cloudfunc.js index 682d530d..94750b8e 100644 --- a/test/common/cloudfunc.js +++ b/test/common/cloudfunc.js @@ -51,8 +51,6 @@ const JSON_FILES = { }], }; -/* eslint no-multi-space: 0 */ - let Expect = '
' + ' Date: Mon, 27 May 2019 20:02:43 +0300 Subject: [PATCH 0068/1728] feature(terminal-run) add ability to resolve exit code --- client/modules/terminal-run.js | 10 +++++++--- package.json | 2 +- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/client/modules/terminal-run.js b/client/modules/terminal-run.js index 01cadf38..fa39ddc9 100644 --- a/client/modules/terminal-run.js +++ b/client/modules/terminal-run.js @@ -4,6 +4,7 @@ const {promisify} = require('es6-promisify'); const tryToCatch = require('try-to-catch/legacy'); +const fullstore = require('fullstore/legacy'); require('../../css/terminal.css'); @@ -26,6 +27,8 @@ let Loaded; let Terminal; let Socket; +const exitCodeStore = fullstore(); + const loadAll = async () => { const {prefix} = CloudCmd; @@ -67,12 +70,11 @@ module.exports.show = promisify((options = {}, fn) => { Terminal.focus(); }, afterClose: (/* exec.series args */) => { - fn(); + fn(null, exitCodeStore()); }, }); }); - module.exports.hide = hide; function hide () { @@ -128,7 +130,9 @@ function create(createOptions) { } }); - Socket.on('exit', () => { + Socket.on('exit', (code) => { + exitCodeStore(code); + if (autoClose) return hide(); diff --git a/package.json b/package.json index 378fcdc4..5415f92d 100644 --- a/package.json +++ b/package.json @@ -163,7 +163,7 @@ "extract-text-webpack-plugin": "^4.0.0-alpha.0", "fast-async": "^7.0.6", "file-loader": "^3.0.1", - "gritty": "^4.0.0", + "gritty": "^4.6.0", "gunzip-maybe": "^1.3.1", "html-looks-like": "^1.0.2", "html-webpack-plugin": "^3.0.7", From 744983cfc4efd660b95fc4c85887c8ca28f70b3a Mon Sep 17 00:00:00 2001 From: coderaiser Date: Mon, 27 May 2019 20:30:35 +0300 Subject: [PATCH 0069/1728] docs(help) add User Menu Cookbook --- HELP.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/HELP.md b/HELP.md index fd048bf7..daa0f07b 100644 --- a/HELP.md +++ b/HELP.md @@ -529,7 +529,7 @@ async function readDefaultMenu({prefix}) { } ``` -You will have ability to run one of this 3 commands with help of double click, enter, or binded key (`F2`, `D` or `P` in this example). Also you can run commands in terminal, or execute any built-in function of `Cloud Commander` extended it's interface. +You will have ability to run one of this 3 commands with help of double click, enter, or binded key (`F2`, `D` or `P` in this example). Also you can run commands in terminal, or execute any built-in function of `Cloud Commander` extended it's interface. You can find more examples in [User Menu Cookbook](https://github.com/coderaiser/cloudcmd/wiki/User-Menu-Cookbook). #### User Menu API From 303213c48b461611796c00ad6eccba2d49043686 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Mon, 27 May 2019 20:33:57 +0300 Subject: [PATCH 0070/1728] chore(package) v12.4.0 --- ChangeLog | 9 +++++++++ HELP.md | 3 ++- README.md | 2 +- package.json | 2 +- 4 files changed, 13 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index 4b95330e..d1f827d9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2019.05.27, v12.4.0 + +fix: +- (terminal-run) resolve before close + +feature: +- (terminal-run) add ability to resolve exit code + + 2019.05.24, v12.3.2 fix: diff --git a/HELP.md b/HELP.md index daa0f07b..a5de974e 100644 --- a/HELP.md +++ b/HELP.md @@ -1,4 +1,4 @@ -# Cloud Commander v12.3.2 +# Cloud Commander v12.4.0 ### [Main][MainURL] [Blog][BlogURL] Live(![Heroku][Heroku_LIVE_IMG] [Heroku][HerokuURL], ![Now][NOW_LIVE_IMG] [Now][NowURL]) @@ -899,6 +899,7 @@ There are a lot of ways to be involved in `Cloud Commander` development: Version history --------------- +- *2019.05.27*, **[v12.4.0](//github.com/coderaiser/cloudcmd/releases/tag/v12.4.0)** - *2019.05.24*, **[v12.3.2](//github.com/coderaiser/cloudcmd/releases/tag/v12.3.2)** - *2019.05.24*, **[v12.3.1](//github.com/coderaiser/cloudcmd/releases/tag/v12.3.1)** - *2019.05.24*, **[v12.3.0](//github.com/coderaiser/cloudcmd/releases/tag/v12.3.0)** diff --git a/README.md b/README.md index bf74cd9b..7d121be6 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Cloud Commander v12.3.2 [![Build Status][BuildStatusIMGURL]][BuildStatusURL] [![Now status][BuildAppveyorIMGURL]][BuildAppveyorURL] [![Codacy][CodacyIMG]][CodacyURL] [![Gitter][GitterIMGURL]][GitterURL] [![OpenCollective](https://opencollective.com/cloudcmd/backers/badge.svg)](#backers) [![OpenCollective](https://opencollective.com/cloudcmd/sponsors/badge.svg)](#sponsors) +# Cloud Commander v12.4.0 [![Build Status][BuildStatusIMGURL]][BuildStatusURL] [![Now status][BuildAppveyorIMGURL]][BuildAppveyorURL] [![Codacy][CodacyIMG]][CodacyURL] [![Gitter][GitterIMGURL]][GitterURL] [![OpenCollective](https://opencollective.com/cloudcmd/backers/badge.svg)](#backers) [![OpenCollective](https://opencollective.com/cloudcmd/sponsors/badge.svg)](#sponsors) ### [Main][MainURL] [Blog][BlogURL] Live([Heroku][HerokuURL], [Now][NowURL]) diff --git a/package.json b/package.json index 5415f92d..43164f34 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "cloudcmd", - "version": "12.3.2", + "version": "12.4.0", "author": "coderaiser (https://github.com/coderaiser)", "description": "File manager for the web with console and editor", "homepage": "http://cloudcmd.io", From 3273c1abe523c645a58cd3a19fdcb28ff96e7143 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Tue, 28 May 2019 13:56:13 +0300 Subject: [PATCH 0071/1728] feature(user-menu) add Compare Directories (#220) --- static/user-menu.js | 51 ++++++++++++++++++++++++++++++++++++++++ static/user-menu.spec.js | 23 ++++++++++++++++++ 2 files changed, 74 insertions(+) diff --git a/static/user-menu.js b/static/user-menu.js index 49e87c18..a26b2020 100644 --- a/static/user-menu.js +++ b/static/user-menu.js @@ -20,6 +20,37 @@ module.exports = { CloudCmd, }); }, + 'D - Compare directories': async ({DOM}) => { + const { + CurrentInfo, + getFilenames, + getCurrentByName, + selectFile, + } = DOM; + + const { + files, + filesPassive, + panel, + panelPassive, + } = CurrentInfo; + + const names = getFilenames(files); + const namesPassive = getFilenames(filesPassive); + + const selectedNames = compare(names, namesPassive); + const selectedNamesPassive = compare(namesPassive, names); + + selectNames(selectedNames, panel, { + selectFile, + getCurrentByName, + }); + + selectNames(selectedNamesPassive, panelPassive, { + selectFile, + getCurrentByName, + }); + }, }; async function createDefaultMenu({path, data, DOM, CloudCmd}) { @@ -40,3 +71,23 @@ async function readDefaultMenu({prefix}) { return data; } +function selectNames(names, panel, {selectFile, getCurrentByName}) { + for (const name of names) { + const file = getCurrentByName(name, panel); + selectFile(file); + } +} + +function compare(a, b) { + const result = []; + + for (const el of a) { + if (b.includes(el)) + continue; + + result.push(el); + } + + return result; +} + diff --git a/static/user-menu.spec.js b/static/user-menu.spec.js index accb3636..827ac76e 100644 --- a/static/user-menu.spec.js +++ b/static/user-menu.spec.js @@ -8,6 +8,8 @@ const wraptile = require('wraptile'); const defaultMenu = require('./user-menu'); +const {create} = autoGlobals; + const {_data} = defaultMenu; const reject = wraptile(async (a) => { throw Error(a); @@ -107,6 +109,21 @@ test('cloudcmd: static: user menu: no EditFile.show', async (t) => { t.end(); }); +test('cloudcmd: static: user menu: compare directories', async (t) => { + const name = 'D - Compare directories'; + const DOM = getDOM(); + const CloudCmd = getCloudCmd(); + + await defaultMenu[name]({ + DOM, + CloudCmd, + }); + + const {files} = DOM.CurrentInfo.files; + t.ok(DOM.getFilenames.calledWith(files), 'should call getFilenames'); + t.end(); +}); + function getDOM() { const IO = { write: stub(), @@ -114,12 +131,18 @@ function getDOM() { const CurrentInfo = { dirPath: '/', + files: [], + filesPasive: [], + panel: create(), + panelPassive: create(), }; return { IO, CurrentInfo, setCurrentByName: stub(), + getFilenames: stub().returns([]), + getCurrentByName: stub(), renameCurrent: stub(), }; } From 24aa355ed0866503b26b3b77d530c2f217204378 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Tue, 28 May 2019 14:04:09 +0300 Subject: [PATCH 0072/1728] chore(user-menu) rm "\n" --- static/user-menu.js | 1 - 1 file changed, 1 deletion(-) diff --git a/static/user-menu.js b/static/user-menu.js index a26b2020..32aedb5e 100644 --- a/static/user-menu.js +++ b/static/user-menu.js @@ -7,7 +7,6 @@ module.exports = { 'C - Create User Menu File': async ({DOM, CloudCmd}) => { const {CurrentInfo} = DOM; - const {dirPath} = CurrentInfo; const path = `${dirPath}.cloudcmd.menu.js`; const {prefix} = CloudCmd; From 71ce9fea5a82f6743795aa586770ec7bfd414727 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Tue, 28 May 2019 18:50:29 +0300 Subject: [PATCH 0073/1728] docs(readme) add auth info (#219) --- HELP.md | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/HELP.md b/HELP.md index a5de974e..19448757 100644 --- a/HELP.md +++ b/HELP.md @@ -707,10 +707,6 @@ app.use(prefix, cloudcmd({ server.listen(port); ``` -Now you're ready to go! - -### Authorization - If you want to enable authorization, you can pass credentials to Cloud Commander with a config. To generate a password, you can install `criton` with `npm i criton --save`, and use it (or any other way) to generate a hash of a password. ```js @@ -734,6 +730,20 @@ const config = { } ``` +Now you're ready to go! + +## Authorization + +`~/.cloudcmd.json` contains [password hash](https://github.com/coderaiser/cloudcmd/blob/v11.8.3/json/config.json#L5) because of security reason, if someone steal your config, he wouldn't know your password, because hash is [very strong](https://github.com/coderaiser/cloudcmd/blob/v11.8.3/json/config.json#L6) and can be customized. + +You should never write your password as plain text to `~/.cloudcmd.json`, you can generate password using `cloudcmd` itself: + +``` +cloudcmd --username name --password password --auth --save --no-server +``` + +This command will create hash of your password and write it to `~/.cloudcmd.json`. + Server --------------- Standard practices dictate that no non-root process get to talk to the internet on a port less than 1024. Despite this, **I suggest you start Cloud Commander as a non-root process**. How can we get around this limitation? There's a couple of fast & easy ways. One of them is port forwarding: From 554023c83949fe7e83852547b988d689f9f5f2de Mon Sep 17 00:00:00 2001 From: coderaiser Date: Tue, 28 May 2019 18:53:53 +0300 Subject: [PATCH 0074/1728] chore(package) v12.5.0 --- ChangeLog | 6 ++++++ HELP.md | 3 ++- README.md | 2 +- package.json | 2 +- 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index d1f827d9..d40c77f3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2019.05.28, v12.5.0 + +feature: +- (user-menu) add Compare Directories (#220) + + 2019.05.27, v12.4.0 fix: diff --git a/HELP.md b/HELP.md index 19448757..64ba9052 100644 --- a/HELP.md +++ b/HELP.md @@ -1,4 +1,4 @@ -# Cloud Commander v12.4.0 +# Cloud Commander v12.5.0 ### [Main][MainURL] [Blog][BlogURL] Live(![Heroku][Heroku_LIVE_IMG] [Heroku][HerokuURL], ![Now][NOW_LIVE_IMG] [Now][NowURL]) @@ -909,6 +909,7 @@ There are a lot of ways to be involved in `Cloud Commander` development: Version history --------------- +- *2019.05.28*, **[v12.5.0](//github.com/coderaiser/cloudcmd/releases/tag/v12.5.0)** - *2019.05.27*, **[v12.4.0](//github.com/coderaiser/cloudcmd/releases/tag/v12.4.0)** - *2019.05.24*, **[v12.3.2](//github.com/coderaiser/cloudcmd/releases/tag/v12.3.2)** - *2019.05.24*, **[v12.3.1](//github.com/coderaiser/cloudcmd/releases/tag/v12.3.1)** diff --git a/README.md b/README.md index 7d121be6..cf42c931 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Cloud Commander v12.4.0 [![Build Status][BuildStatusIMGURL]][BuildStatusURL] [![Now status][BuildAppveyorIMGURL]][BuildAppveyorURL] [![Codacy][CodacyIMG]][CodacyURL] [![Gitter][GitterIMGURL]][GitterURL] [![OpenCollective](https://opencollective.com/cloudcmd/backers/badge.svg)](#backers) [![OpenCollective](https://opencollective.com/cloudcmd/sponsors/badge.svg)](#sponsors) +# Cloud Commander v12.5.0 [![Build Status][BuildStatusIMGURL]][BuildStatusURL] [![Now status][BuildAppveyorIMGURL]][BuildAppveyorURL] [![Codacy][CodacyIMG]][CodacyURL] [![Gitter][GitterIMGURL]][GitterURL] [![OpenCollective](https://opencollective.com/cloudcmd/backers/badge.svg)](#backers) [![OpenCollective](https://opencollective.com/cloudcmd/sponsors/badge.svg)](#sponsors) ### [Main][MainURL] [Blog][BlogURL] Live([Heroku][HerokuURL], [Now][NowURL]) diff --git a/package.json b/package.json index 43164f34..a79ddb06 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "cloudcmd", - "version": "12.4.0", + "version": "12.5.0", "author": "coderaiser (https://github.com/coderaiser)", "description": "File manager for the web with console and editor", "homepage": "http://cloudcmd.io", From 89618418472a35e28ff2f90d91bcfe9cc19f68bd Mon Sep 17 00:00:00 2001 From: coderaiser Date: Tue, 28 May 2019 19:04:22 +0300 Subject: [PATCH 0075/1728] feature(user-menu) add ability to ignore private methods --- client/modules/user-menu/index.js | 5 +++- static/user-menu.js | 2 ++ static/user-menu.spec.js | 50 +++++++++++++++++++++++++++++++ 3 files changed, 56 insertions(+), 1 deletion(-) diff --git a/client/modules/user-menu/index.js b/client/modules/user-menu/index.js index 94eaac8a..249e4e9c 100644 --- a/client/modules/user-menu/index.js +++ b/client/modules/user-menu/index.js @@ -36,6 +36,7 @@ module.exports.hide = hide; const getKey = (a) => a.split(' - ')[0]; const beginWith = (a) => (b) => a === getKey(b); +const notPrivate = ([a]) => a !== '_'; const {CurrentInfo} = DOM; @@ -49,7 +50,9 @@ async function show() { if (error) return Dialog.alert(`User menu error: ${error.message}`); - const options = Object.keys(userMenu); + const options = Object + .keys(userMenu) + .filter(notPrivate); const button = createElement('button', { className: 'cloudcmd-user-menu-button', diff --git a/static/user-menu.js b/static/user-menu.js index 32aedb5e..42acb5da 100644 --- a/static/user-menu.js +++ b/static/user-menu.js @@ -70,6 +70,7 @@ async function readDefaultMenu({prefix}) { return data; } +module.exports._selectNames = selectNames; function selectNames(names, panel, {selectFile, getCurrentByName}) { for (const name of names) { const file = getCurrentByName(name, panel); @@ -77,6 +78,7 @@ function selectNames(names, panel, {selectFile, getCurrentByName}) { } } +module.exports._compare = compare; function compare(a, b) { const result = []; diff --git a/static/user-menu.spec.js b/static/user-menu.spec.js index 827ac76e..b493cc81 100644 --- a/static/user-menu.spec.js +++ b/static/user-menu.spec.js @@ -124,6 +124,56 @@ test('cloudcmd: static: user menu: compare directories', async (t) => { t.end(); }); +test('cloudcmd: static: user menu: compare directories: select names', async (t) => { + const {_selectNames} = defaultMenu; + const selectFile = stub(); + const file = {}; + const getCurrentByName = stub().returns(file); + + const names = ['hi']; + const panel = {}; + + _selectNames(names, panel, { + selectFile, + getCurrentByName, + }); + + t.ok(selectFile.calledWith(file), 'should call selectFile'); + t.end(); +}); + +test('cloudcmd: static: user menu: compare directories: select names: getCurrentByName', async (t) => { + const {_selectNames} = defaultMenu; + const selectFile = stub(); + const getCurrentByName = stub(); + + const name = 'hi'; + const names = [name]; + const panel = {}; + + _selectNames(names, panel, { + selectFile, + getCurrentByName, + }); + + t.ok(getCurrentByName.calledWith(name, panel), 'should call selectFile'); + t.end(); +}); + +test('cloudcmd: static: user menu: compare directories: select names: compare', async (t) => { + const {_compare} = defaultMenu; + const a = [1, 2]; + const b = [1, 3]; + + const result = _compare(a, b); + const expected = [ + 2, + ]; + + t.deepEqual(result, expected, 'should equal'); + t.end(); +}); + function getDOM() { const IO = { write: stub(), From 4914c22b5d417e5d8d4428c604850a1f536ba846 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Tue, 28 May 2019 19:10:24 +0300 Subject: [PATCH 0076/1728] docs(help) refresh -> await refresh --- HELP.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/HELP.md b/HELP.md index 64ba9052..0b134b95 100644 --- a/HELP.md +++ b/HELP.md @@ -483,7 +483,7 @@ module.exports = { closeMessage: 'Press any button to close Terminal', // optional }); - CloudCmd.refresh(); + await CloudCmd.refresh(); }, 'P - Build Prod': async ({CloudCmd}) => { await CloudCmd.TerminalRun.show({ @@ -491,7 +491,7 @@ module.exports = { autoClose: true, // optional }); - CloudCmd.refresh(); + await CloudCmd.refresh(); }, 'C - Create User Menu File': async ({DOM, CloudCmd}) => { const {CurrentInfo} = DOM; From fe9723fa1522cdb4a4df60b2b42320080b57aefc Mon Sep 17 00:00:00 2001 From: coderaiser Date: Fri, 31 May 2019 12:47:25 +0300 Subject: [PATCH 0077/1728] feature(package) add support of cwd in TerminalRun with help of gritty v4.7.0 --- client/modules/terminal-run.js | 2 ++ package.json | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/client/modules/terminal-run.js b/client/modules/terminal-run.js index fa39ddc9..72d8a5fb 100644 --- a/client/modules/terminal-run.js +++ b/client/modules/terminal-run.js @@ -100,12 +100,14 @@ function getEnv() { function create(createOptions) { const { + cwd = DOM.getCurrentDirPath(), command, autoClose, closeMessage = 'Press any key to close Terminal...', } = createOptions; const options = { + cwd, env: getEnv(), prefix: getPrefixSocket(), socketPath: CloudCmd.prefix, diff --git a/package.json b/package.json index a79ddb06..81ac544a 100644 --- a/package.json +++ b/package.json @@ -163,7 +163,7 @@ "extract-text-webpack-plugin": "^4.0.0-alpha.0", "fast-async": "^7.0.6", "file-loader": "^3.0.1", - "gritty": "^4.6.0", + "gritty": "^4.7.0", "gunzip-maybe": "^1.3.1", "html-looks-like": "^1.0.2", "html-webpack-plugin": "^3.0.7", From f9c659612a515479a71f1a8f3e43e06032041ec4 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Thu, 30 May 2019 19:27:21 +0300 Subject: [PATCH 0078/1728] feature(config-manager) add (#208) --- HELP.md | 3 + bin/cloudcmd.js | 13 +- common/util.spec.js | 2 +- package.json | 1 + server/auth.js | 13 +- server/cloudcmd.js | 63 +++--- server/cloudcmd.spec.js | 87 ++++----- server/config.js | 184 +++++++++++------- server/config.spec.js | 29 ++- server/distribute/export.js | 35 ++-- server/distribute/import.js | 25 +-- server/distribute/import.spec.js | 29 ++- server/distribute/log.js | 3 +- server/markdown.js | 12 +- server/markdown.spec.js | 6 +- server/rest/index.js | 126 ++++++------ server/rest/index.spec.js | 47 ++--- server/rest/info.js | 5 +- server/root.js | 7 +- server/root.spec.js | 14 -- server/route.js | 27 +-- server/route.spec.js | 11 +- server/server.js | 3 + server/terminal.js | 10 +- .../terminal.js => server/terminal.spec.js | 57 ++---- server/validate.js | 6 +- server/validate.spec.js | 24 +-- test/rest/config.js | 1 + test/rest/cp.js | 4 + test/rest/fs.js | 6 +- test/rest/mv.js | 18 +- test/rest/pack.js | 3 + test/rest/rest.js | 49 ----- 33 files changed, 446 insertions(+), 477 deletions(-) rename test/server/terminal.js => server/terminal.spec.js (53%) delete mode 100644 test/rest/rest.js diff --git a/HELP.md b/HELP.md index 0b134b95..090f80d3 100644 --- a/HELP.md +++ b/HELP.md @@ -671,6 +671,8 @@ const app = require('express')(); const port = 1337; const prefix = '/'; +const {createConfigManager} = cloudcmd; + const server = http.createServer(app); const socket = io.listen(server, { path: `{prefix}socket.io` @@ -702,6 +704,7 @@ app.use(prefix, cloudcmd({ config, // config data (optional) plugins, // DEPRECATED, use User Menu instead modules, // optional + configManager: createConfigManager(), //optional })); server.listen(port); diff --git a/bin/cloudcmd.js b/bin/cloudcmd.js index 1e4e3ac5..ce3e0eaf 100755 --- a/bin/cloudcmd.js +++ b/bin/cloudcmd.js @@ -203,7 +203,7 @@ function main() { if (password) config('password', getPassword(password)); - validateRoot(options.root); + validateRoot(options.root, config); if (args['show-config']) showConfig(); @@ -213,14 +213,19 @@ function main() { const importConfig = promisify(distribute.import); const caller = (fn) => fn(); - importConfig() + importConfig(config) .then(args.save ? caller(config.save) : noop) .then(startWraped(options)); } -function validateRoot(root) { +function validateRoot(root, config) { const validate = require(DIR_SERVER + 'validate'); - validate.root(root, console.log); + validate.root(root, config); + + if (root === '/') + return; + + console.log(`root: ${root}`); } function getPassword(password) { diff --git a/common/util.spec.js b/common/util.spec.js index 458abbd8..3393dc6c 100644 --- a/common/util.spec.js +++ b/common/util.spec.js @@ -96,7 +96,7 @@ test('util: getRegExp', (t) => { test('util: getRegExp: no', (t) => { const reg = getRegExp(''); - t.deepEqual(reg, RegExp('^.*$'), 'should return regexp'); + t.deepEqual(reg, RegExp('^$'), 'should return regexp'); t.end(); }); diff --git a/package.json b/package.json index 81ac544a..aa2034bd 100644 --- a/package.json +++ b/package.json @@ -118,6 +118,7 @@ "minimist": "^1.2.0", "nomine": "^3.0.0", "object.omit": "^3.0.0", + "once": "^1.4.0", "onezip": "^3.0.0", "open": "^6.0.0", "package-json": "^6.0.0", diff --git a/server/auth.js b/server/auth.js index ce125170..d8f72956 100644 --- a/server/auth.js +++ b/server/auth.js @@ -4,18 +4,17 @@ const httpAuth = require('http-auth'); const criton = require('criton'); const currify = require('currify'); const middle = currify(_middle); +const check = currify(_check); -const config = require('./config'); - -module.exports = () => { +module.exports = (config) => { const auth = httpAuth.basic({ realm: 'Cloud Commander', - }, check); + }, check(config)); - return middle(auth); + return middle(config, auth); }; -function _middle(authentication, req, res, next) { +function _middle(config, authentication, req, res, next) { const is = config('auth'); if (!is) @@ -25,7 +24,7 @@ function _middle(authentication, req, res, next) { authentication.check(req, res, success); } -function check(username, password, callback) { +function _check(config, username, password, callback) { const BAD_CREDENTIALS = false; const name = config('username'); const pass = config('password'); diff --git a/server/cloudcmd.js b/server/cloudcmd.js index 873e4624..e49b3ba4 100644 --- a/server/cloudcmd.js +++ b/server/cloudcmd.js @@ -9,7 +9,7 @@ const fs = require('fs'); const cloudfunc = require(DIR_COMMON + 'cloudfunc'); const authentication = require(DIR + 'auth'); -const config = require(DIR + 'config'); +const defaultConfig = require(DIR + 'config'); const modulas = require(DIR + 'modulas'); const userMenu = require(DIR + 'user-menu'); const rest = require(DIR + 'rest'); @@ -38,15 +38,15 @@ const getDist = (isDev) => isDev ? 'dist-dev' : 'dist'; const getIndexPath = (isDev) => path.join(DIR, '..', `${getDist(isDev)}/index.html`); const defaultHtml = fs.readFileSync(getIndexPath(isDev), 'utf8'); -const auth = currify(_auth); -const root = () => config('root'); - +const initAuth = currify(_initAuth); const notEmpty = (a) => a; const clean = (a) => a.filter(notEmpty); module.exports = (params) => { const p = params || {}; const options = p.config || {}; + const config = p.configManager || defaultConfig; + const { modules, plugins, @@ -59,7 +59,10 @@ module.exports = (params) => { keys.forEach((name) => { let value = options[name]; - if (/root|editor|packer|columns/.test(name)) + if (/root/.test(name)) + validate.root(value, config); + + if (/editor|packer|columns/.test(name)) validate[name](value); if (/prefix/.test(name)) @@ -68,21 +71,31 @@ module.exports = (params) => { config(name, value); }); - config('console', defaultValue('console', options)); - config('configDialog', defaultValue('configDialog', options)); + config('console', defaultValue(config, 'console', options)); + config('configDialog', defaultValue(config, 'configDialog', options)); - const {prefix} = prefixer(options.prefix); const prefixSocket = prefixer(options.prefixSocket); if (p.socket) - listen(prefixSocket, p.socket); + listen({ + prefixSocket, + config, + socket: p.socket, + }); - return cloudcmd(prefix, plugins, modules); + return cloudcmd({ + plugins, + modules, + config, + }); }; +module.exports.createConfigManager = defaultConfig.create; +module.exports.configPath = defaultConfig.path; + module.exports._getIndexPath = getIndexPath; -function defaultValue(name, options) { +function defaultValue(config, name, options) { const value = options[name]; const previous = config(name); @@ -100,8 +113,8 @@ function getPrefix(prefix) { return prefix || ''; } -module.exports._auth = _auth; -function _auth(accept, reject, username, password) { +module.exports._initAuth = _initAuth; +function _initAuth(config, accept, reject, username, password) { if (!config('auth')) return accept(); @@ -114,10 +127,14 @@ function _auth(accept, reject, username, password) { reject(); } -function listen(prefixSocket, socket) { +function listen({prefixSocket, socket, config}) { + const root = () => config('root'); + const auth = initAuth(config); + prefixSocket = getPrefix(prefixSocket); - config.listen(socket, auth); + if (config.listen) + config.listen(socket, auth); edward.listen(socket, { root, @@ -148,17 +165,17 @@ function listen(prefixSocket, socket) { prefix: prefixSocket + '/fileop', }); - config('terminal') && terminal().listen(socket, { + config('terminal') && terminal(config).listen(socket, { auth, prefix: prefixSocket + '/gritty', command: config('terminalCommand'), autoRestart: config('terminalAutoRestart'), }); - distribute.export(socket); + distribute.export(config, socket); } -function cloudcmd(prefix, plugins, modules) { +function cloudcmd({plugins, modules, config}) { const online = apart(config, 'online'); const cache = false; const diff = apart(config, 'diff'); @@ -169,13 +186,14 @@ function cloudcmd(prefix, plugins, modules) { const dropbox = config('dropbox'); const dropboxToken = config('dropboxToken'); + const root = () => config('root'); const funcs = clean([ config('console') && konsole({ online, }), - config('terminal') && terminal({}), + config('terminal') && terminal(config, {}), edward({ online, @@ -202,13 +220,12 @@ function cloudcmd(prefix, plugins, modules) { }), fileop(), - nomine(), setUrl, setSW, logout, - authentication(), + authentication(config), config.middle, modules && modulas(modules), @@ -228,8 +245,8 @@ function cloudcmd(prefix, plugins, modules) { menuName: '.cloudcmd.menu.js', }), - rest, - route({ + rest(config), + route(config, { html: defaultHtml, }), diff --git a/server/cloudcmd.spec.js b/server/cloudcmd.spec.js index 73fa9883..4f32cfc8 100644 --- a/server/cloudcmd.spec.js +++ b/server/cloudcmd.spec.js @@ -4,17 +4,16 @@ const path = require('path'); const test = require('supertape'); const stub = require('@cloudcmd/stub'); -const currify = require('currify'); const {reRequire} = require('mock-require'); const DIR = './'; const cloudcmdPath = DIR + 'cloudcmd'; -const config = require(DIR + 'config'); const cloudcmd = require(cloudcmdPath); const { + createConfigManager, _getPrefix, - _auth, + _initAuth, } = cloudcmd; const {request} = require('serve-once')(cloudcmd, { @@ -41,25 +40,27 @@ test('cloudcmd: args: plugins: error', (t) => { }); test('cloudcmd: defaults: config', (t) => { - const configDialog = config('configDialog'); + const configManager = createConfigManager(); - config('configDialog', false); - cloudcmd(); - t.notOk(config('configDialog'), 'should not override config with defaults'); + configManager('configDialog', false); - config('configDialog', configDialog); + cloudcmd({ + configManager, + }); + t.notOk(configManager('configDialog'), 'should not override config with defaults'); t.end(); }); test('cloudcmd: defaults: console', (t) => { - const console = config('console'); - config('console', false); - cloudcmd(); - t.notOk(config('console'), 'should not override config with defaults'); + const configManager = createConfigManager(); + configManager('console', false); - config('console', console); + cloudcmd({ + configManager, + }); + t.notOk(configManager('console'), 'should not override config with defaults'); t.end(); }); @@ -120,79 +121,61 @@ test('cloudcmd: replaceDist: !isDev', (t) => { }); test('cloudcmd: auth: reject', (t) => { - const auth = config('auth'); const accept = stub(); const reject = stub(); + + const config = createConfigManager(); + const username = 'root'; const password = 'toor'; - - const set = credentials(); - const reset = set('hello', 'world'); config('auth', true); + config('username', username); + config('password', password); - _auth(accept, reject, username, password); + _initAuth(config, accept, reject, username, 'abc'); - config('auth', auth); - reset(); - - t.ok(reject.called, 'should accept'); + t.ok(reject.called, 'should reject'); t.end(); }); test('cloudcmd: auth: accept', (t) => { - const auth = config('auth'); const accept = stub(); const reject = stub(); + const username = 'root'; const password = 'toor'; + const auth = true; - const set = credentials(); - const reset = set(username, password); - config('auth', true); - - _auth(accept, reject, username, password); - + const config = createConfigManager(); + config('username', username); + config('password', password); config('auth', auth); - reset(); + + _initAuth(config, accept, reject, username, password); t.ok(accept.called, 'should accept'); t.end(); }); test('cloudcmd: auth: accept: no auth', (t) => { - const auth = config('auth'); const accept = stub(); const reject = stub(); + + const auth = false; const username = 'root'; const password = 'toor'; - config('auth', false); - _auth(accept, reject, username, password); + const config = createConfigManager(); + config('username', username); + config('password', password); config('auth', auth); + _initAuth(config, accept, reject, username, password); + t.ok(accept.called, 'should accept'); t.end(); }); -function credentials() { - const username = config('username'); - const password = config('password'); - - const reset = () => { - config('username', username); - config('password', password); - }; - - const set = currify((fn, a, b) => { - config('username', a); - config('password', b); - - return fn; - }); - - return set(reset); -} - test('cloudcmd: getIndexPath: production', (t) => { const isDev = false; const name = path.join(__dirname, '..', 'dist', 'index.html'); diff --git a/server/config.js b/server/config.js index c96a99f1..09874931 100644 --- a/server/config.js +++ b/server/config.js @@ -15,70 +15,73 @@ const CloudFunc = require(DIR_COMMON + 'cloudfunc'); const currify = require('currify'); const wraptile = require('wraptile'); -const squad = require('squad'); const tryToCatch = require('try-to-catch'); const pullout = require('pullout'); const ponse = require('ponse'); const jonny = require('jonny'); const jju = require('jju'); -const writejson = require('writejson'); +const writejson = promisify(require('writejson')); const tryCatch = require('try-catch'); const criton = require('criton'); const HOME = homedir(); -const manageConfig = squad(traverse, cryptoPass); -const save = promisify(_save); - +const resolve = Promise.resolve.bind(Promise); const formatMsg = currify((a, b) => CloudFunc.formatMsg(a, b)); const {apiURL} = CloudFunc; const changeEmitter = new Emitter(); +const key = (a) => Object.keys(a).pop(); + const ConfigPath = path.join(DIR, 'json/config.json'); const ConfigHome = path.join(HOME, '.cloudcmd.json'); -const readjsonSync = (name) => { - return jju.parse(fs.readFileSync(name, 'utf8'), { - mode: 'json', - }); -}; +const config = read(); -const rootConfig = readjsonSync(ConfigPath); -const key = (a) => Object.keys(a).pop(); +const connection = currify(_connection); +const connectionWraped = wraptile(_connection); +const middle = currify(_middle); -const [error, configHome] = tryCatch(readjsonSync, ConfigHome); - -if (error && error.code !== 'ENOENT') - exit(`cloudcmd --config ${ConfigHome}: ${error.message}`); - -const config = { - ...rootConfig, - ...configHome, -}; - -const connectionWraped = wraptile(connection); +function read(filename = ConfigHome) { + const readjsonSync = (name) => { + return jju.parse(fs.readFileSync(name, 'utf8'), { + mode: 'json', + }); + }; + + const rootConfig = readjsonSync(ConfigPath); + const [error, configHome] = tryCatch(readjsonSync, ConfigHome); + + if (error && error.code !== 'ENOENT') + exit(`cloudcmd --config ${filename}: ${error.message}`); + + return { + ...rootConfig, + ...configHome, + }; +} module.exports = manage; -module.exports.save = save; -module.exports.middle = middle; +module.exports.create = create; +module.exports.middle = middle(manage); module.exports.subscribe = (fn) => { changeEmitter.on('change', fn); }; +module.exports.path = ConfigHome; + module.exports.unsubscribe = (fn) => { changeEmitter.removeListener('change', fn); }; -module.exports.listen = (socket, auth) => { - check(socket, auth); - +const manageListen = currify((manage, socket, auth) => { if (!manage('configDialog')) return middle; - listen(socket, auth); + listen(manage, socket, auth); return middle; -}; +}); function manage(key, value) { if (!key) @@ -97,25 +100,59 @@ function manage(key, value) { return `${key} = ${value}`; } -function _save(callback) { - writejson(ConfigHome, config, {mode: 0o600}, callback); -} - -function listen(sock, auth) { - const prefix = manage('prefixSocket'); +function initWrite(filename, configManager) { + if (filename) + return write.bind(null, filename, configManager); - sock.of(prefix + '/config') - .on('connection', (socket) => { - if (!manage('auth')) - return connection(socket); - - const reject = () => socket.emit('reject'); - socket.on('auth', auth(connectionWraped(socket), reject)); - }); + return resolve; } -function connection(socket) { - socket.emit('config', config); +function readConfig(filename) { + if (filename) + return read(filename); + + return config; +} + +function create({filename} = {}) { + const config = {}; + + const configManager = (key, value) => { + if (key === '*') + return { + ...config, + }; + + if (value === undefined) + return config[key]; + + config[key] = value; + }; + + spread(configManager); + Object.assign(config, readConfig(filename)); + + configManager.middle = middle(configManager); + configManager.listen = manageListen(configManager); + configManager.write = initWrite(filename, configManager); + + return configManager; +} + +function spread(store) { + const entries = Object.entries(config); + + for (const [name, value] of entries) { + store(name, value); + } +} + +const write = async (filename, config) => { + return writejson(filename, config('*'), {mode: 0o600}); +}; + +function _connection(manage, socket) { + socket.emit('config', manage('*')); const emit = currify((socket, name, e) => { return socket.emit(name, e.message); @@ -125,7 +162,7 @@ function connection(socket) { if (typeof json !== 'object') return socket.emit('err', 'Error: Wrong data type!'); - manageConfig(json); + traverse(cryptoPass(manage, json)); const send = () => { const data = CloudFunc.formatMsg('config', key(json)); @@ -134,13 +171,26 @@ function connection(socket) { socket.emit('log', data); }; - save() + manage.write() .then(send) .catch(emit(socket, 'err')); }); } -function middle(req, res, next) { +function listen(manage, sock, auth) { + const prefix = manage('prefixSocket'); + + sock.of(prefix + '/config') + .on('connection', (socket) => { + if (!manage('auth')) + return connection(manage, socket); + + const reject = () => socket.emit('reject'); + socket.on('auth', auth(connectionWraped(manage, socket), reject)); + }); +} + +function _middle(manage, req, res, next) { const noConfigDialog = !manage('configDialog'); if (req.url !== `${apiURL}/config`) @@ -148,7 +198,7 @@ function middle(req, res, next) { switch(req.method) { case 'GET': - get(req, res, next); + get(manage, req, res, next); break; case 'PATCH': @@ -157,7 +207,7 @@ function middle(req, res, next) { .status(404) .send('Config is disabled'); - patch(req, res); + patch(manage, req, res); break; default: @@ -165,8 +215,8 @@ function middle(req, res, next) { } } -function get(request, response) { - const data = jonny.stringify(config); +function get(manage, request, response) { + const data = jonny.stringify(manage('*')); ponse.send(data, { name : 'config.json', @@ -176,7 +226,7 @@ function get(request, response) { }); } -async function patch(request, response) { +async function patch(manage, request, response) { const name = 'config.json'; const cache = false; const options = { @@ -186,18 +236,18 @@ async function patch(request, response) { cache, }; - const [e] = await tryToCatch(patchConfig, options); + const [e] = await tryToCatch(patchConfig, manage, options); if (e) ponse.sendError(e, options); } -async function patchConfig({name, request, response, cache}) { +async function patchConfig(manage, {name, request, response, cache}) { const str = await pullout(request); const json = jonny.parse(str); - manageConfig(json); - await save(); + traverse(cryptoPass(manage, json)); + await manage.write(); const msg = formatMsg('config', key(json)); ponse.send(msg, { @@ -208,32 +258,24 @@ async function patchConfig({name, request, response, cache}) { }); } -function traverse(json) { +function traverse([manage, json]) { Object.keys(json).forEach((name) => { manage(name, json[name]); }); } module.exports._cryptoPass = cryptoPass; -function cryptoPass(json) { +function cryptoPass(manage, json) { const algo = manage('algo'); if (!json.password) - return json; + return [manage, json]; const password = criton(json.password, algo); - return { + return [manage, { ...json, password, - }; -} - -function check(socket, auth) { - if (!socket) - throw Error('socket could not be empty!'); - - if (auth && typeof auth !== 'function') - throw Error('auth should be function!'); + }]; } diff --git a/server/config.spec.js b/server/config.spec.js index 7c656dcb..2d6a500b 100644 --- a/server/config.spec.js +++ b/server/config.spec.js @@ -7,7 +7,11 @@ const root = '../'; const configPath = './config'; const config = require(configPath); -const {_cryptoPass} = config; +const { + _cryptoPass, + create, +} = config; + const {apiURL} = require(root + 'common/cloudfunc'); const fixture = require('./config.fixture'); @@ -54,27 +58,15 @@ test('config: manage: get: *', (t) => { t.end(); }); -test('config: listen: no socket', (t) => { - t.throws(config.listen, 'should throw when no socket'); - t.end(); -}); - -test('config: listen: authCheck: not function', (t) => { - const socket = {}; - const fn = () => config.listen(socket, 'hello'); - - t.throws(fn, 'should throw when authCheck not function'); - t.end(); -}); - test('config: cryptoPass: no password', (t) => { const json = { hello: 'world', }; - const result = _cryptoPass(json); + const config = create(); + const result = _cryptoPass(config, json); - t.equal(result, json, 'should not change json'); + t.deepEqual(result, [config, json], 'should not change json'); t.end(); }); @@ -89,9 +81,10 @@ test('config: cryptoPass', (t) => { password, }; - const result = _cryptoPass(json); + const config = create(); + const result = _cryptoPass(config, json); - t.deepEqual(result, expected, 'should crypt password'); + t.deepEqual(result, [config, expected], 'should crypt password'); t.end(); }); diff --git a/server/distribute/export.js b/server/distribute/export.js index 4bfc84ce..7b2e3641 100644 --- a/server/distribute/export.js +++ b/server/distribute/export.js @@ -5,7 +5,6 @@ const wraptile = require('wraptile'); const squad = require('squad'); const omit = require('object.omit'); -const config = require('../config'); const log = require('./log'); const { @@ -39,22 +38,23 @@ const omitList = [ const omitConfig = (config) => omit(config, omitList); -module.exports = (socket) => { +module.exports = (config, socket) => { if (!config('export')) return; const prefix = config('prefix'); const distributePrefix = `${prefix}/distribute`; + const isLog = config('log'); const onError = squad( - logWraped(exportStr), + logWraped(isLog, exportStr), getMessage, ); - const onConnectError = squad(logWraped(exportStr), getDescription); + const onConnectError = squad(logWraped(isLog, exportStr), getDescription); socket.of(distributePrefix) - .on('connection', onConnection(push)) + .on('connection', onConnection(push, config)) .on('error', onError) .on('connect_error', onConnectError); }; @@ -83,41 +83,46 @@ function getHost(socket) { return `${colorName} [${remoteAddress}:${port}]`; } -const connectPush = wraptile((push, socket) => { +const connectPush = wraptile((push, config, socket) => { socket.emit('accept'); + const isLog = config('log'); const host = getHost(socket); const subscription = push(socket); - socket.on('disconnect', onDisconnect(subscription, host)); + socket.on('disconnect', onDisconnect(subscription, config, host)); - log(exportStr, `${connectedStr} to ${host}`); + log(isLog, exportStr, `${connectedStr} to ${host}`); socket.emit('config', omitConfig(config('*'))); - log(exportStr, `config send to ${host}`); + log(isLog, exportStr, `config send to ${host}`); config.subscribe(subscription); }); -const onConnection = currify((push, socket) => { +const onConnection = currify((push, config, socket) => { const host = getHost(socket); const reject = () => { socket.emit('reject'); socket.disconnect(); }; - log(exportStr, `${authTryStr} from ${host}`); - socket.on('auth', auth(connectPush(push, socket), reject)); + const isLog = config('log'); + + log(isLog, exportStr, `${authTryStr} from ${host}`); + socket.on('auth', auth(config, reject, connectPush(push, config, socket))); }); -const auth = currify((fn, reject, token) => { +const auth = currify((config, reject, fn, token) => { if (token === config('exportToken')) return fn(); reject(); }); -const onDisconnect = wraptile((subscription, host) => { +const onDisconnect = wraptile((subscription, config, host) => { + const isLog = config('log'); + config.unsubscribe(subscription); - log(exportStr, `${disconnectedStr} from ${host}`); + log(isLog, exportStr, `${disconnectedStr} from ${host}`); }); diff --git a/server/distribute/import.js b/server/distribute/import.js index ba671579..6b0191e8 100644 --- a/server/distribute/import.js +++ b/server/distribute/import.js @@ -8,7 +8,6 @@ const fullstore = require('fullstore'); const io = require('socket.io-client'); const forEachKey = currify(require('for-each-key')); -const config = require('../config'); const log = require('./log'); const { @@ -57,12 +56,13 @@ const done = wraptile((fn, store) => fn(null, { status: store(), })); -const emitAuth = wraptile((importUrl, socket) => { - log(importStr, `${authTryStr} to ${importUrl}`); +const emitAuth = wraptile((importUrl, config, socket) => { + const isLog = config('log'); + log(isLog, importStr, `${authTryStr} to ${importUrl}`); socket.emit('auth', config('importToken')); }); -module.exports = (options, fn) => { +module.exports = (config, options, fn) => { fn = fn || options; if (!config('import')) @@ -72,6 +72,7 @@ module.exports = (options, fn) => { const importListen = config('importListen'); const name = config('name'); const port = config('port'); + const isLog = config('log'); const query = toLine({ name, @@ -93,30 +94,30 @@ module.exports = (options, fn) => { const onConfig = squad( close, - logWraped(importStr, `config received from ${colorUrl}`), + logWraped(isLog, importStr, `config received from ${colorUrl}`), statusStoreWraped('received'), forEachKey(config), ); const onError = squad( superFn('error'), - logWraped(importStr), + logWraped(isLog, config, importStr), addUrl(colorUrl), getMessage, ); const onConnectError = squad( superFn('connect_error'), - logWraped(importStr), + logWraped(isLog, importStr), addUrl(colorUrl), getDescription, ); - const onConnect = emitAuth(importUrl, socket); - const onAccept = logWraped(importStr,`${connectedStr} to ${colorUrl}`); + const onConnect = emitAuth(importUrl, config, socket); + const onAccept = logWraped(isLog, importStr,`${connectedStr} to ${colorUrl}`); const onDisconnect = squad( done(fn, statusStore), - logWraped(importStr, `${disconnectedStr} from ${colorUrl}`), + logWraped(isLog, importStr, `${disconnectedStr} from ${colorUrl}`), rmListeners(socket, { onError, onConnect, @@ -125,13 +126,13 @@ module.exports = (options, fn) => { ); const onChange = squad( - logWraped(importStr), + logWraped(isLog, importStr), config, ); const onReject = squad( superFn('reject'), - logWraped(importStr, tokenRejectedStr), + logWraped(isLog, importStr, tokenRejectedStr), ); socket.on('connect', onConnect); diff --git a/server/distribute/import.spec.js b/server/distribute/import.spec.js index e06eff3d..76938248 100644 --- a/server/distribute/import.spec.js +++ b/server/distribute/import.spec.js @@ -4,11 +4,13 @@ const test = require('supertape'); const {promisify} = require('util'); const tryToCatch = require('try-to-catch'); const {connect} = require('../../test/before'); -const config = require('../config'); +const {createConfigManager} = require('../cloudcmd'); const distribute = { import: promisify(require('./import')), }; +const config = createConfigManager(); + test('distribute: import: canceled', async (t) => { const {done} = await connect({ config: { @@ -19,7 +21,7 @@ test('distribute: import: canceled', async (t) => { }, }); - const {status} = await distribute.import(); + const {status} = await distribute.import(config); await done(); @@ -39,7 +41,7 @@ test('distribute: import: received: no error', async (t) => { config('importUrl', `http://localhost:${port}`); - const [e] = await tryToCatch(distribute.import); + const [e] = await tryToCatch(distribute.import, config); await done(); @@ -60,9 +62,10 @@ test('distribute: import: received', async (t) => { }, }); + const config = createConfigManager(); config('importUrl', `http://localhost:${port}`); - const {status} = await distribute.import(); + const {status} = await distribute.import(config); await done(); t.equal(status, 'received','should equal'); @@ -82,12 +85,13 @@ test('distribute: import: received: auth: reject', async (t) => { }, }); + const config = createConfigManager(); config('importUrl', `http://localhost:${port}`); - const {status} = await distribute.import(); + const {status} = await distribute.import(config); await done(); - t.equal(status, 'reject','should equal'); + t.equal(status, 'reject', 'should equal'); t.end(); }); @@ -104,9 +108,10 @@ test('distribute: import: received: auth: accept', async (t) => { }, }); + const config = createConfigManager(); config('importUrl', `http://localhost:${port}`); - const {status} = await distribute.import(); + const {status} = await distribute.import(config); await done(); t.equal(status, 'received','should equal'); @@ -124,9 +129,10 @@ test('distribute: import: received: no name', async (t) => { }, }); + const config = createConfigManager(); config('importUrl', `http://localhost:${port}`); - const {status} = await distribute.import(); + const {status} = await distribute.import(config); await done(); t.equal(status, 'received','should equal'); @@ -143,9 +149,10 @@ test('distribute: import: error', async (t) => { }, }); + const config = createConfigManager(); config('importUrl', `http://localhost:0`); - const {status} = await distribute.import({ + const {status} = await distribute.import(config, { reconnection: false, }); @@ -165,7 +172,9 @@ test('distribute: import: config:change: no export', async (t) => { }, }); - const {status} = await distribute.import({ + const config = createConfigManager(); + + const {status} = await distribute.import(config, { reconnection: false, }); diff --git a/server/distribute/log.js b/server/distribute/log.js index f37d06e9..8ec98e1d 100644 --- a/server/distribute/log.js +++ b/server/distribute/log.js @@ -3,10 +3,9 @@ const wraptile = require('wraptile'); const chalk = require('chalk'); -const config = require('../config'); const datetime = require('../../common/datetime'); -const log = (name, msg) => config('log') && console.log(`${datetime()} -> ${name}: ${msg}`); +const log = (isLog, name, msg) => isLog && console.log(`${datetime()} -> ${name}: ${msg}`); const makeColor = (a, color) => chalk.rgb(...(color || stringToRGB(a)))(a); const getMessage = (e) => e.message || e; const getDescription = (e) => `${e.type}: ${e.description}`; diff --git a/server/markdown.js b/server/markdown.js index 9500591c..5982701f 100644 --- a/server/markdown.js +++ b/server/markdown.js @@ -15,32 +15,32 @@ const readFile = promisify(fs.readFile); const root = require('./root'); -module.exports = callbackify(async (name, request) => { +module.exports = callbackify(async (name, rootDir, request) => { check(name, request); const {method} = request; switch(method) { case 'GET': - return onGET(request, name); + return onGET(request, name, rootDir); case 'PUT': return onPUT(request); } }); -function parseName(query, name) { +function parseName(query, name, rootDir) { const shortName = name.replace('/markdown', ''); if (query === 'relative') return DIR_ROOT + shortName; - return root(shortName); + return root(shortName, rootDir); } -async function onGET(request, name) { +async function onGET(request, name, root) { const query = ponse.getQuery(request); - const fileName = parseName(query, name); + const fileName = parseName(query, name, root); const data = await readFile(fileName, 'utf8'); return parse(data); diff --git a/server/markdown.spec.js b/server/markdown.spec.js index b177c044..05510a65 100644 --- a/server/markdown.spec.js +++ b/server/markdown.spec.js @@ -15,8 +15,12 @@ const cloudcmd = require('..'); const config = { auth: false, }; + +const configManager = cloudcmd.createConfigManager(); + const {request} = require('serve-once')(cloudcmd, { config, + configManager, }); test('cloudcmd: markdown: error', async (t) => { @@ -64,7 +68,7 @@ test('cloudcmd: markdown: put: error', async (t) => { mdStream.url = 'http://hello.world'; mdStream.method = 'PUT'; - const [e] = await tryToCatch(_markdown, name, mdStream); + const [e] = await tryToCatch(_markdown, name, '/', mdStream); t.ok(e.message.includes('ENOENT: no such file or directory'), 'should emit error'); t.end(); diff --git a/server/rest/index.js b/server/rest/index.js index a9f4aaf5..27074b92 100644 --- a/server/rest/index.js +++ b/server/rest/index.js @@ -7,7 +7,6 @@ const path = require('path'); const fs = require('fs'); const root = require(DIR + 'root'); -const config = require(DIR + 'config'); const CloudFunc = require(DIR_COMMON + 'cloudfunc'); const markdown = require(DIR + 'markdown'); const info = require('./info'); @@ -16,6 +15,7 @@ const jaguar = require('jaguar'); const onezip = require('onezip'); const inly = require('inly'); const wraptile = require('wraptile'); +const currify = require('currify'); const pullout = require('pullout'); const json = require('jonny'); const ponse = require('ponse'); @@ -27,9 +27,7 @@ const swap = wraptile((fn, a, b) => fn(b, a)); const isWin32 = process.platform === 'win32'; const {apiURL} = CloudFunc; -module.exports = (request, response, next) => { - check(request, response, next); - +module.exports = currify((config, request, response, next) => { const name = ponse.getPathName(request); const regExp = RegExp('^' + apiURL); const is = regExp.test(name); @@ -37,10 +35,10 @@ module.exports = (request, response, next) => { if (!is) return next(); - rest(request, response); -}; + rest(config, request, response); +}); -function rest(request, response) { +function rest(config, request, response) { const name = ponse.getPathName(request); const params = { request, @@ -48,7 +46,7 @@ function rest(request, response) { name: name.replace(apiURL, '') || '/', }; - sendData(params, (error, options, data) => { + sendData(params, config, (error, options, data) => { params.gzip = !error; if (!data) { @@ -65,9 +63,12 @@ function rest(request, response) { if (options.query) params.query = options.query; - if (error) + if (error && error.code) return ponse.sendError(error, params); + if (error) + return ponse.sendError(error.stack, params); + ponse.send(data, params); }); } @@ -77,44 +78,53 @@ function rest(request, response) { * * @param params {name, method, body, requrest, response} */ -function sendData(params, callback) { +function sendData(params, config, callback) { const p = params; const isMD = RegExp('^/markdown').test(p.name); + const rootDir = config('root'); if (isMD) - return markdown(p.name, p.request, callback); + return markdown(p.name, rootDir, p.request, callback); const {method} = p.request; switch(method) { case 'GET': - return onGET(params, callback); + return onGET(params, config, callback); case 'PUT': return pullout(p.request) .then((body) => { - onPUT(p.name, body, callback); + onPUT({ + name: p.name, + config, + body, + callback, + }); }) .catch(callback); } } -function onGET(params, callback) { +function onGET(params, config, callback) { let cmd; const p = params; + const packer = config('packer'); + const prefix = config('prefix'); + const rootDir = config('root'); if (p.name[0] === '/') cmd = p.name.replace('/', ''); if (/^pack/.test(cmd)) { cmd = cmd.replace(/^pack/, ''); - streamPack(root(cmd), p.response); + streamPack(root(cmd, rootDir), p.response, packer); return; } switch(cmd) { case '': - p.data = json.stringify(info()); + p.data = json.stringify(info(prefix)); callback(null, {name: 'api.json'}, p.data); break; @@ -127,22 +137,22 @@ function onGET(params, callback) { } } -function getPackReg() { - if (config('packer') === 'zip') +function getPackReg(packer) { + if (packer === 'zip') return /\.zip$/; return /\.tar\.gz$/; } -function streamPack(cmd, response) { +function streamPack(cmd, response, packer) { const noop = () => {}; - const filename = cmd.replace(getPackReg(), ''); + const filename = cmd.replace(getPackReg(packer), ''); const dir = path.dirname(filename); const names = [ path.basename(filename), ]; - operation('pack', dir, response, names, noop); + operation('pack', packer, dir, response, names, noop); } function getCMD(cmd) { @@ -160,25 +170,26 @@ const getMoveMsg = (files) => { }; module.exports._onPUT = onPUT; -function onPUT(name, body, callback) { +function onPUT({name, config, body, callback}) { checkPut(name, body, callback); const cmd = getCMD(name); const files = json.parse(body); + const rootDir = config('root'); switch(cmd) { case 'mv': { if (!files.from || !files.to) return callback(body); - if (isRootAll([files.to, files.from])) + if (isRootAll(rootDir, [files.to, files.from])) return callback(getWin32RootMsg()); const msg = getMoveMsg(files); const fn = swap(callback, msg); - const from = root(files.from); - const to = root(files.to); + const from = root(files.from, rootDir); + const to = root(files.to, rootDir); const {names} = files; if (!names) @@ -191,11 +202,11 @@ function onPUT(name, body, callback) { if (!files.from || !files.names || !files.to) return callback(body); - if (isRootAll([files.to, files.from])) + if (isRootAll(rootDir, [files.to, files.from])) return callback(getWin32RootMsg()); - files.from = root(files.from); - files.to = root(files.to); + files.from = root(files.from, rootDir); + files.to = root(files.to, rootDir); copy(files.from, files.to, files.names, (error) => { const msg = formatMsg('copy', files.names); @@ -207,14 +218,14 @@ function onPUT(name, body, callback) { if (!files.from) return callback(body); - pack(files.from, files.to, files.names, callback); + pack(files.from, files.to, files.names, config, callback); break; case 'extract': if (!files.from) return callback(body); - extract(files.from, files.to, callback); + extract(files.from, files.to, config, callback); break; @@ -224,9 +235,12 @@ function onPUT(name, body, callback) { } } -function pack(from, to, names, fn) { - from = root(from); - to = root(to); +function pack(from, to, names, config, fn) { + const rootDir = config('root'); + const packer = config('packer'); + + from = root(from, rootDir); + to = root(to, rootDir); if (!names) { names = [ @@ -236,31 +250,33 @@ function pack(from, to, names, fn) { from = path.dirname(from); } - operation('pack', from, to, names, fn); + operation('pack', packer, from, to, names, fn); } -function extract(from, to, fn) { - from = root(from); +function extract(from, to, config, fn) { + const rootDir = config('root'); + + from = root(from, rootDir); if (to) - to = root(to); + to = root(to, rootDir); else to = from.replace(/\.tar\.gz$/, ''); - operation('extract', from, to, fn); + operation('extract', config('packer'), from, to, fn); } -function getPacker(operation) { +function getPacker(operation, packer) { if (operation === 'extract') return inly; - if (config('packer') === 'zip') + if (packer === 'zip') return onezip.pack; return jaguar.pack; } -function operation(op, from, to, names, fn) { +function operation(op, packer, from, to, names, fn) { if (!fn) { fn = names; names = [ @@ -268,8 +284,8 @@ function operation(op, from, to, names, fn) { ]; } - const packer = getPacker(op); - const pack = packer(from, to, names); + const packerFn = getPacker(op, packer); + const pack = packerFn(from, to, names); pack.on('error', fn); @@ -300,17 +316,18 @@ function copy(from, to, names, fn) { }); } -module.exports._isRootWin32 = isRootWin32; -function isRootWin32(path) { +const isRootWin32 = currify((root, path) => { const isRoot = path === '/'; - const isConfig = config('root') === '/'; + const isConfig = root === '/'; return isWin32 && isRoot && isConfig; -} +}); +module.exports._isRootWin32 = isRootWin32; module.exports._isRootAll = isRootAll; -function isRootAll(names) { - return names.some(isRootWin32); + +function isRootAll(root, names) { + return names.some(isRootWin32(root)); } module.exports._getWin32RootMsg = getWin32RootMsg; @@ -339,17 +356,6 @@ function formatMsg(msg, data, status) { return CloudFunc.formatMsg(msg, value, status); } -function check(request, response, next) { - if (typeof request !== 'object') - throw Error('request should be an object!'); - - if (typeof response !== 'object') - throw Error('response should be an object!'); - - if (typeof next !== 'function') - throw Error('next should be a function!'); -} - function checkPut(name, body, callback) { if (typeof name !== 'string') throw Error('name should be a string!'); diff --git a/server/rest/index.spec.js b/server/rest/index.spec.js index e7059a62..58e215a4 100644 --- a/server/rest/index.spec.js +++ b/server/rest/index.spec.js @@ -1,6 +1,8 @@ 'use strict'; const test = require('supertape'); +const tryToCatch = require('try-to-catch'); + const rest = require('.'); const { _formatMsg, @@ -34,50 +36,41 @@ test('rest: getWin32RootMsg', (t) => { }); test('rest: isRootWin32', (t) => { - const result = _isRootWin32('/'); + const result = _isRootWin32('/', '/'); t.notOk(result, 'should equal'); t.end(); }); test('rest: isRootAll', (t) => { - const result = _isRootAll(['/', '/h']); + const result = _isRootAll('/', ['/', '/h']); t.notOk(result, 'should equal'); t.end(); }); -test('rest: onPUT: no args', (t) => { - t.throws(_onPUT, /name should be a string!/, 'should throw when no args'); +test('rest: onPUT: no args', async (t) => { + const [e] = await tryToCatch(_onPUT, {}); + t.equal(e.message, 'name should be a string!', 'should throw when no args'); t.end(); }); -test('rest: onPUT: no body', (t) => { - const fn = () => _onPUT('hello'); - t.throws(fn, /body should be a string!/, 'should throw when no body'); +test('rest: onPUT: no body', async (t) => { + const [e] = await tryToCatch(_onPUT, { + name: 'hello', + }); + + t.equal(e.message, 'body should be a string!', 'should throw when no body'); t.end(); }); -test('rest: onPUT: no callback', (t) => { - const fn = () => _onPUT('hello', 'world'); - t.throws(fn, /callback should be a function!/, 'should throw when no callback'); - t.end(); -}); - -test('rest: no args', (t) => { - t.throws(rest, /request should be an object!/, 'should throw when no args'); - t.end(); -}); - -test('rest: no response', (t) => { - const fn = () => rest({}); - t.throws(fn, /response should be an object!/, 'should throw when no response'); - t.end(); -}); - -test('rest: no next', (t) => { - const fn = () => rest({}, {}); - t.throws(fn, /next should be a function!/, 'should throw when no response'); +test('rest: onPUT: no callback', async (t) => { + const [e] = await tryToCatch(_onPUT, { + name: 'hello', + body: 'world', + }); + + t.equal(e.message, 'callback should be a function!', 'should throw when no callback'); t.end(); }); diff --git a/server/rest/info.js b/server/rest/info.js index bc63fffa..13758b21 100644 --- a/server/rest/info.js +++ b/server/rest/info.js @@ -3,16 +3,15 @@ const format = require('format-io'); const {version} = require('../../package'); -const config = require('../config'); const getMemory = () => { const {rss} = process.memoryUsage(); return format.size(rss); }; -module.exports = () => ({ +module.exports = (prefix) => ({ version, + prefix, memory: getMemory(), - prefix: config('prefix'), }); diff --git a/server/root.js b/server/root.js index 5c3ea26b..fcbfcf7e 100644 --- a/server/root.js +++ b/server/root.js @@ -1,11 +1,8 @@ 'use strict'; -const config = require('./config'); const mellow = require('mellow'); -module.exports = (dir) => { - const root = config('root') || '/'; - - return mellow.pathToWin(dir, root); +module.exports = (dir, root) => { + return mellow.pathToWin(dir, root || '/'); }; diff --git a/server/root.spec.js b/server/root.spec.js index 783145c4..a8c65079 100644 --- a/server/root.spec.js +++ b/server/root.spec.js @@ -8,20 +8,6 @@ const {reRequire} = mockRequire; const pathConfig = './config'; const pathRoot = './root'; -test('cloudcmd: root: config', (t) => { - const config = stub().returns(false); - - mockRequire(pathConfig, config); - const root = reRequire(pathRoot); - - root('hello'); - - mockRequire.stop(pathConfig); - - t.ok(config.calledWith('root'), 'should call config'); - t.end(); -}); - test('cloudcmd: root: mellow', (t) => { const config = stub().returns(''); const pathToWin = stub(); diff --git a/server/route.js b/server/route.js index fcafb8be..1e014205 100644 --- a/server/route.js +++ b/server/route.js @@ -14,6 +14,7 @@ const squad = require('squad'); const apart = require('apart'); const currify = require('currify'); const tryToCatch = require('try-to-catch'); +const once = require('once'); const config = require(DIR_SERVER + 'config'); const root = require(DIR_SERVER + 'root'); @@ -22,6 +23,8 @@ const CloudFunc = require(DIR_COMMON + 'cloudfunc'); const prefix = squad(prefixer, apart(config, 'prefix')); +const onceRequire = once(require); + const sendIndex = (params, data) => { const ponseParams = { ...params, @@ -36,36 +39,35 @@ const {FS} = CloudFunc; const Columns = require(`${DIR_SERVER}/columns`); const Template = require(`${DIR_SERVER}/template`); -const getReadDir = () => { +const tokenize = (fn, a) => (b) => fn(a, b); +const getReadDir = (config) => { if (!config('dropbox')) return promisify(flop.read); - const tokenize = (fn, a) => (b) => fn(a, b); - const {readDir} = require('@cloudcmd/dropbox'); + const {readDir} = onceRequire('@cloudcmd/dropbox'); return tokenize(readDir, config('dropboxToken')); }; -const read = getReadDir(); const realpath = promisify(fs.realpath); /** * routing of server queries */ -module.exports = currify((options, request, response, next) => { +module.exports = currify((config, options, request, response, next) => { const name = ponse.getPathName(request); const isFS = RegExp('^/$|^' + FS).test(name); if (!isFS) return next(); - route(options, request, response) + route({config, options, request, response}) .catch(next); }); module.exports._getReadDir = getReadDir; -async function route(options, request, response) { +async function route({config, options, request, response}) { const name = ponse.getPathName(request); const gzip = true; const p = { @@ -78,13 +80,14 @@ async function route(options, request, response) { config('prefix', prefixer(request.baseUrl)); const rootName = name.replace(CloudFunc.FS, '') || '/'; - const fullPath = root(rootName); + const fullPath = root(rootName, config('root')); + const read = getReadDir(config); const [error, dir] = await tryToCatch(read, fullPath); const {html} = options; if (!error) - return sendIndex(p, buildIndex(html, { + return sendIndex(p, buildIndex(config, html, { ...dir, path: format.addSlashToEnd(rootName), })); @@ -104,7 +107,7 @@ async function route(options, request, response) { /** * additional processing of index file */ -function indexProcessing(options) { +function indexProcessing(config, options) { const oneFilePanel = config('oneFilePanel'); const noKeysPanel = !config('keysPanel'); const noContact = !config('contact'); @@ -177,14 +180,14 @@ function indexProcessing(options) { return data; } -function buildIndex(html, json) { +function buildIndex(config, html, json) { const panel = CloudFunc.buildFromJSON({ data: json, prefix: prefix(), template: Template, }); - return indexProcessing({ + return indexProcessing(config, { panel, data: html, }); diff --git a/server/route.spec.js b/server/route.spec.js index f9446b66..cd99868f 100644 --- a/server/route.spec.js +++ b/server/route.spec.js @@ -14,6 +14,7 @@ const routePath = './route'; const cloudcmdPath = './cloudcmd'; const cloudcmd = require(cloudcmdPath); +const {createConfigManager} = cloudcmd; const serveOnce = require('serve-once'); const defaultConfig = { auth: false, @@ -476,21 +477,15 @@ test('cloudcmd: route: buttons: contact', async (t) => { }); test('cloudcmd: route: dropbox', async (t) => { - const config = require('./config'); - const dropbox = config('dropbox'); - const dropboxToken = config('dropboxToken'); - + const config = createConfigManager(); config('dropbox', true); config('dropboxToken', ''); const {_getReadDir} = reRequire(routePath); - const readdir = _getReadDir(); + const readdir = _getReadDir(config); const [e] = await tryToCatch(readdir, '/root'); - config('dropbox', dropbox); - config('dropboxToken', dropboxToken); - t.ok(/token/.test(e.message), 'should contain word token in message'); t.end(); }); diff --git a/server/server.js b/server/server.js index 1c83f2b6..23d35b63 100644 --- a/server/server.js +++ b/server/server.js @@ -57,6 +57,9 @@ module.exports = async (options) => { app.use(prefix, cloudcmd({ config: options, socket: socketServer, + configManager: cloudcmd.createConfigManager({ + filename: cloudcmd.configPath, + }), })); if (port < 0 || port > 65535) diff --git a/server/terminal.js b/server/terminal.js index 5be754d0..9d1e9c35 100644 --- a/server/terminal.js +++ b/server/terminal.js @@ -1,17 +1,15 @@ 'use strict'; const tryCatch = require('try-catch'); -const config = require('./config'); const noop = (req, res, next) => { next && next(); }; + noop.listen = noop; -module.exports = (arg) => getTerminal(config('terminal'), arg); - -function getTerminal(term, arg) { - if (!term) +module.exports = (config, arg) => { + if (!config('terminal')) return noop; const [e, terminalModule] = tryCatch(require, config('terminalPath')); @@ -26,5 +24,5 @@ function getTerminal(term, arg) { console.log(`cloudcmd --terminal: ${e.message}`); return noop; -} +}; diff --git a/test/server/terminal.js b/server/terminal.spec.js similarity index 53% rename from test/server/terminal.js rename to server/terminal.spec.js index e734c85b..2b6d8f99 100644 --- a/test/server/terminal.js +++ b/server/terminal.spec.js @@ -4,33 +4,26 @@ const test = require('supertape'); const stub = require('@cloudcmd/stub'); const mockRequire = require('mock-require'); -const {reRequire} = mockRequire; -const configPath = '../../server/config'; -const terminalPath = '../../server/terminal'; +const terminalPath = './terminal'; +const terminal = require('./terminal'); +const {createConfigManager} = require('./cloudcmd'); test('cloudcmd: terminal: disabled', (t) => { - mockRequire(configPath, () => { - return false; - }); + const config = createConfigManager(); + config('terminal', false); - const terminal = reRequire('../../server/terminal'); - const fn = terminal(); - - mockRequire.stop(configPath); + const fn = terminal(config); t.notOk(fn(), 'should return noop'); t.end(); }); test('cloudcmd: terminal: disabled: listen', (t) => { - mockRequire(configPath, () => false); + const config = createConfigManager(); + config('terminal', false); - const terminal = reRequire(terminalPath); - const fn = terminal().listen(); - - mockRequire.stop(configPath); - reRequire(terminalPath); + const fn = terminal(config).listen(); t.notOk(fn, 'should return noop'); t.end(); @@ -40,15 +33,11 @@ test('cloudcmd: terminal: enabled', (t) => { const term = stub(); const arg = 'hello'; - mockRequire(configPath, () => '/terminal'); mockRequire(terminalPath, term); const terminal = require(terminalPath); terminal(arg); - mockRequire.stop(configPath); - mockRequire.stop(terminalPath); - t.ok(term.calledWith(arg), 'should call terminal'); t.end(); }); @@ -57,18 +46,16 @@ test('cloudcmd: terminal: enabled: no string', (t) => { const {log:originalLog} = console; const log = stub(); - mockRequire(configPath, () => 'hello'); - console.log = log; - const terminal = reRequire(terminalPath); - terminal(); + const config = createConfigManager(); + + config('terminal', true); + config('terminalPath', 'hello'); + terminal(config); + console.log = originalLog; - mockRequire.stop(configPath); - reRequire(terminalPath); - const msg = 'cloudcmd --terminal: Cannot find module \'hello\''; - const [arg] = log.args[0]; t.ok(arg.includes(msg), 'should call with msg'); @@ -79,19 +66,13 @@ test('cloudcmd: terminal: no arg', (t) => { const gritty = {}; mockRequire('gritty', gritty); - mockRequire(configPath, (a) => { - if (a === 'terminal') - return true; - - return 'gritty'; - }); + const config = createConfigManager(); + config('terminal', true); + config('terminalPath', 'gritty'); - const terminal = reRequire(terminalPath); - const result = terminal(); + const result = terminal(config); mockRequire.stop('gritty'); - mockRequire.stop(configPath); - reRequire(terminalPath); t.equal(result, gritty, 'should equal'); t.end(); diff --git a/server/validate.js b/server/validate.js index 8a091605..e87ce5a5 100644 --- a/server/validate.js +++ b/server/validate.js @@ -2,11 +2,10 @@ const tryCatch = require('try-catch'); -const config = require('./config'); const exit = require('./exit'); const columns = require('./columns'); -module.exports.root = (dir, fn) => { +module.exports.root = (dir, config) => { if (typeof dir !== 'string') throw Error('dir should be a string'); @@ -21,9 +20,6 @@ module.exports.root = (dir, fn) => { if (error) return exit('cloudcmd --root: %s', error.message); - - if (typeof fn === 'function') - fn('root:', dir); }; module.exports.editor = (name) => { diff --git a/server/validate.spec.js b/server/validate.spec.js index ba2ab305..a82fe004 100644 --- a/server/validate.spec.js +++ b/server/validate.spec.js @@ -14,7 +14,6 @@ const validatePath = `${dir}/server/validate`; const exitPath = `${dir}/server/exit`; const columnsPath = `${dir}/server/columns`; const cloudcmdPath = `${dir}/server/cloudcmd`; -const configPath = `${dir}/server/config`; const validate = require(validatePath); const cloudcmd = require(cloudcmdPath); @@ -30,17 +29,11 @@ test('validate: root: bad', (t) => { }); test('validate: root: config', (t) => { - const configFn = stub() - .returns(true); + const config = stub().returns(true); - mockRequire(configPath, configFn); + validate.root('/hello', config); - const validate = reRequire(validatePath); - validate.root('/hello'); - - mockRequire.stop(configPath); - - t.ok(configFn.calledWith('dropbox'), 'should call config'); + t.ok(config.calledWith('dropbox'), 'should call config'); t.end(); }); @@ -52,17 +45,6 @@ test('validate: root: /', (t) => { t.end(); }); -test('validate: root: /home', (t) => { - const fn = stub(); - - validate.root('/home', (...args) => { - fn(...args); - - t.ok(fn.calledWith('root:', '/home'), 'should not call fn'); - t.end(); - }); -}); - test('validate: root: stat', (t) => { const fn = stub(); const {statSync} = fs; diff --git a/test/rest/config.js b/test/rest/config.js index 57ffb01f..3ae84f4b 100644 --- a/test/rest/config.js +++ b/test/rest/config.js @@ -12,6 +12,7 @@ const {request} = require('serve-once')(cloudcmd, { config: { auth: false, }, + configManager: cloudcmd.createConfigManager(), }); const manageConfig = require('../../server/config'); diff --git a/test/rest/cp.js b/test/rest/cp.js index d2d3cb16..e3bce034 100644 --- a/test/rest/cp.js +++ b/test/rest/cp.js @@ -11,8 +11,12 @@ const config = { }; const cloudcmd = require('../..'); +const configManager = cloudcmd.createConfigManager(); +configManager('auth', false); + const {request} = require('serve-once')(cloudcmd, { config, + configManager, }); test('cloudcmd: rest: cp', async (t) => { diff --git a/test/rest/fs.js b/test/rest/fs.js index 9659b708..8fd0497d 100644 --- a/test/rest/fs.js +++ b/test/rest/fs.js @@ -3,7 +3,11 @@ const test = require('supertape'); const cloudcmd = require('../..'); -const {request} = require('serve-once')(cloudcmd); +const {request} = require('serve-once')(cloudcmd, { + config: { + auth: false, + }, +}); test('cloudcmd: rest: fs: path', async (t) => { const {body} = await request.get(`/api/v1/fs`, { diff --git a/test/rest/mv.js b/test/rest/mv.js index 58ada557..3ee8031e 100644 --- a/test/rest/mv.js +++ b/test/rest/mv.js @@ -33,11 +33,14 @@ test('cloudcmd: rest: mv', async (t) => { reRequire(restPath); const cloudcmd = reRequire(cloudcmdPath); + const {createConfigManager} = cloudcmd; + + const configManager = createConfigManager(); + configManager('auth', false); + configManager('root', '/'); const {request} = serveOnce(cloudcmd, { - config: { - root: '/', - }, + configManager, }); const files = { @@ -77,11 +80,14 @@ test('cloudcmd: rest: mv: rename', async (t) => { reRequire(restPath); const cloudcmd = reRequire(cloudcmdPath); + const {createConfigManager} = cloudcmd; + const configManager = createConfigManager(); + + configManager('auth', false); + configManager('root', '/'); const {request} = serveOnce(cloudcmd, { - config: { - root: '/', - }, + configManager, }); const files = { diff --git a/test/rest/pack.js b/test/rest/pack.js index f90a1b60..276ffe6c 100644 --- a/test/rest/pack.js +++ b/test/rest/pack.js @@ -25,6 +25,7 @@ const defaultOptions = { }, }; const cloudcmd = require(cloudcmdPath); + const serveOnce = require('serve-once'); const {request} = serveOnce(cloudcmd); @@ -37,6 +38,7 @@ const once = promisify((name, extract, fn) => { test('cloudcmd: rest: pack: tar: get', async (t) => { const config = { packer: 'tar', + auth: false, }; const options = { @@ -202,6 +204,7 @@ test('cloudcmd: rest: pack: zip: put: response', async (t) => { test('cloudcmd: rest: pack: zip: put: error', async (t) => { const config = { packer: 'zip', + auth: false, }; const options = { diff --git a/test/rest/rest.js b/test/rest/rest.js deleted file mode 100644 index 70da208a..00000000 --- a/test/rest/rest.js +++ /dev/null @@ -1,49 +0,0 @@ -'use strict'; - -const test = require('supertape'); -const rest = require('../../server/rest'); - -const { - _formatMsg, - _getWin32RootMsg, - _isRootWin32, - _isRootAll, -} = rest; - -test('rest: formatMsg', (t) => { - const result = _formatMsg('hello', 'world'); - - t.equal(result, 'hello: ok("world")', 'should be equal'); - t.end(); -}); - -test('rest: formatMsg: json', (t) => { - const result = _formatMsg('hello', { - name: 'world', - }); - - t.equal(result, 'hello: ok("{"name":"world"}")', 'should parse json'); - t.end(); -}); - -test('rest: getWin32RootMsg', (t) => { - const {message} = _getWin32RootMsg(); - - t.equal(message,'Could not copy from/to root on windows!', 'should return error'); - t.end(); -}); - -test('rest: isRootWin32', (t) => { - const result = _isRootWin32('/'); - - t.notOk(result, 'should equal'); - t.end(); -}); - -test('rest: isRootAll', (t) => { - const result = _isRootAll(['/', '/h']); - - t.notOk(result, 'should equal'); - t.end(); -}); - From d81149dd156b874d4c6cb730a4b5c38b94e2d9cc Mon Sep 17 00:00:00 2001 From: coderaiser Date: Fri, 31 May 2019 17:59:24 +0300 Subject: [PATCH 0079/1728] chore(package) v12.6.0 --- ChangeLog | 8 ++++++++ HELP.md | 3 ++- README.md | 2 +- package.json | 2 +- 4 files changed, 12 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index d40c77f3..e9f81308 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2019.05.31, v12.6.0 + +feature: +- (config-manager) add (#208) +- (package) add support of cwd in TerminalRun with help of gritty v4.7.0 +- (user-menu) add ability to ignore private methods + + 2019.05.28, v12.5.0 feature: diff --git a/HELP.md b/HELP.md index 090f80d3..c5b737e2 100644 --- a/HELP.md +++ b/HELP.md @@ -1,4 +1,4 @@ -# Cloud Commander v12.5.0 +# Cloud Commander v12.6.0 ### [Main][MainURL] [Blog][BlogURL] Live(![Heroku][Heroku_LIVE_IMG] [Heroku][HerokuURL], ![Now][NOW_LIVE_IMG] [Now][NowURL]) @@ -912,6 +912,7 @@ There are a lot of ways to be involved in `Cloud Commander` development: Version history --------------- +- *2019.05.31*, **[v12.6.0](//github.com/coderaiser/cloudcmd/releases/tag/v12.6.0)** - *2019.05.28*, **[v12.5.0](//github.com/coderaiser/cloudcmd/releases/tag/v12.5.0)** - *2019.05.27*, **[v12.4.0](//github.com/coderaiser/cloudcmd/releases/tag/v12.4.0)** - *2019.05.24*, **[v12.3.2](//github.com/coderaiser/cloudcmd/releases/tag/v12.3.2)** diff --git a/README.md b/README.md index cf42c931..7bfe875c 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Cloud Commander v12.5.0 [![Build Status][BuildStatusIMGURL]][BuildStatusURL] [![Now status][BuildAppveyorIMGURL]][BuildAppveyorURL] [![Codacy][CodacyIMG]][CodacyURL] [![Gitter][GitterIMGURL]][GitterURL] [![OpenCollective](https://opencollective.com/cloudcmd/backers/badge.svg)](#backers) [![OpenCollective](https://opencollective.com/cloudcmd/sponsors/badge.svg)](#sponsors) +# Cloud Commander v12.6.0 [![Build Status][BuildStatusIMGURL]][BuildStatusURL] [![Now status][BuildAppveyorIMGURL]][BuildAppveyorURL] [![Codacy][CodacyIMG]][CodacyURL] [![Gitter][GitterIMGURL]][GitterURL] [![OpenCollective](https://opencollective.com/cloudcmd/backers/badge.svg)](#backers) [![OpenCollective](https://opencollective.com/cloudcmd/sponsors/badge.svg)](#sponsors) ### [Main][MainURL] [Blog][BlogURL] Live([Heroku][HerokuURL], [Now][NowURL]) diff --git a/package.json b/package.json index aa2034bd..03782b8f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "cloudcmd", - "version": "12.5.0", + "version": "12.6.0", "author": "coderaiser (https://github.com/coderaiser)", "description": "File manager for the web with console and editor", "homepage": "http://cloudcmd.io", From ce794fe0bedc65f338960d3621542f6a0cc18251 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Fri, 31 May 2019 18:17:22 +0300 Subject: [PATCH 0080/1728] chore(webpack) js: maxAssetSize --- .webpack/js.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.webpack/js.js b/.webpack/js.js index 1d54442b..dea0d877 100644 --- a/.webpack/js.js +++ b/.webpack/js.js @@ -110,8 +110,8 @@ module.exports = { }, plugins, performance: { - maxEntrypointSize: 500000, - maxAssetSize: 500000, + maxEntrypointSize: 600000, + maxAssetSize: 600000, }, }; From 2abe7d688d26be2db52a08df7011834ea56ff632 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Fri, 31 May 2019 18:30:16 +0300 Subject: [PATCH 0081/1728] test(config) coverage --- test/rest/config.js | 24 +++++------------------- 1 file changed, 5 insertions(+), 19 deletions(-) diff --git a/test/rest/config.js b/test/rest/config.js index 3ae84f4b..dfd022d5 100644 --- a/test/rest/config.js +++ b/test/rest/config.js @@ -1,24 +1,17 @@ 'use strict'; -const path = require('path'); -const os = require('os'); - const test = require('supertape'); -const readjson = require('readjson'); -const writejson = require('writejson'); const cloudcmd = require('../..'); +const configManager = cloudcmd.createConfigManager(); + const {request} = require('serve-once')(cloudcmd, { config: { auth: false, }, - configManager: cloudcmd.createConfigManager(), + configManager, }); -const manageConfig = require('../../server/config'); - -const pathConfig = path.join(os.homedir(), '.cloudcmd.json'); - test('cloudcmd: rest: config: get', async (t) => { const {body} = await request.get('/api/v1/config', { type: 'json', @@ -93,7 +86,7 @@ test('cloudcmd: rest: config: patch: no configDialog: statusCode', async (t) => options, }); - manageConfig('configDialog', true); + configManager('configDialog', true); t.equal(response.status, 404); t.end(); @@ -104,18 +97,11 @@ test('cloudcmd: rest: config: patch: save config', async (t) => { editor: 'dword', }; - const originalConfig = readjson.sync.try(pathConfig); - await request.patch(`/api/v1/config`, { body, }); - const config = readjson.sync(pathConfig); - - t.equal(config.editor, 'dword', 'should change config file on patch'); + t.equal(configManager('editor'), 'dword', 'should change config file on patch'); t.end(); - - if (originalConfig) - writejson.sync(pathConfig, originalConfig); }); From b6ed7da0a7a5e30bc9ff4f3a8d0e113ae2c53e11 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Tue, 4 Jun 2019 18:49:03 +0300 Subject: [PATCH 0082/1728] fix(config) configManager: totally move away from singletone --- HELP.md | 15 ++++-- README.md | 10 ++++ bin/cloudcmd.js | 19 +++++-- server/cloudcmd.js | 14 +++-- server/config.js | 88 +++++++++++--------------------- server/config.spec.js | 14 ++--- server/distribute/export.spec.js | 3 +- server/distribute/import.spec.js | 41 ++++++++------- server/distribute/log.spec.js | 4 +- server/route.js | 9 ++-- server/route.spec.js | 6 ++- server/server.js | 8 +-- test/before.js | 2 + test/rest/pack.js | 5 +- test/server/console.js | 2 +- test/static.js | 2 +- 16 files changed, 127 insertions(+), 115 deletions(-) diff --git a/HELP.md b/HELP.md index c5b737e2..0ddf5ccc 100644 --- a/HELP.md +++ b/HELP.md @@ -671,8 +671,6 @@ const app = require('express')(); const port = 1337; const prefix = '/'; -const {createConfigManager} = cloudcmd; - const server = http.createServer(app); const socket = io.listen(server, { path: `{prefix}socket.io` @@ -699,13 +697,22 @@ const modules = { filePicker, }; +const { + createConfigManager, + configPath, +} = cloudcmd; + +const configManager = createConfigManager({ + configPath, +}), + app.use(prefix, cloudcmd({ socket, // used by Config, Edit (optional) and Console (required) config, // config data (optional) plugins, // DEPRECATED, use User Menu instead modules, // optional - configManager: createConfigManager(), //optional -})); + configManager, // optional +)); server.listen(port); ``` diff --git a/README.md b/README.md index 7bfe875c..33ad49a4 100644 --- a/README.md +++ b/README.md @@ -107,11 +107,21 @@ const modules = { filePicker, }; +const { + createConfigManager, + configPath, +} = cloudcmd; + +const configManager = createConfigManager({ + configPath, +}), + app.use(prefix, cloudcmd({ socket, // used by Config, Edit (optional) and Console (required) config, // config data (optional) plugins, // DEPRECATED, use User Menu instead modules, // optional + configManager, // optional })); server.listen(port); diff --git a/bin/cloudcmd.js b/bin/cloudcmd.js index ce3e0eaf..afda5cb8 100755 --- a/bin/cloudcmd.js +++ b/bin/cloudcmd.js @@ -6,10 +6,19 @@ const Info = require('../package'); const DIR_SERVER = '../server/'; const {promisify} = require('util'); + const wraptile = require('wraptile'); const exit = require(DIR_SERVER + 'exit'); -const config = require(DIR_SERVER + 'config'); +const { + createConfig, + configPath, +} = require(DIR_SERVER + 'config'); + +const config = createConfig({ + configPath, +}); + const env = require(DIR_SERVER + 'env'); const prefixer = require(DIR_SERVER + '/prefixer'); @@ -208,14 +217,14 @@ function main() { if (args['show-config']) showConfig(); - const startWraped = wraptile(start, options); + const startWraped = wraptile(start, options, config); const distribute = require('../server/distribute'); const importConfig = promisify(distribute.import); const caller = (fn) => fn(); importConfig(config) .then(args.save ? caller(config.save) : noop) - .then(startWraped(options)); + .then(startWraped); } function validateRoot(root, config) { @@ -237,14 +246,14 @@ function version() { console.log('v' + Info.version); } -function start(config) { +function start(options, config) { const SERVER = DIR_SERVER + 'server'; if (!args.server) return; const server = require(SERVER); - server(config); + server(options, config); } function port(arg) { diff --git a/server/cloudcmd.js b/server/cloudcmd.js index e49b3ba4..e878ea15 100644 --- a/server/cloudcmd.js +++ b/server/cloudcmd.js @@ -9,7 +9,11 @@ const fs = require('fs'); const cloudfunc = require(DIR_COMMON + 'cloudfunc'); const authentication = require(DIR + 'auth'); -const defaultConfig = require(DIR + 'config'); +const { + createConfig, + configPath, +} = require(DIR + 'config'); + const modulas = require(DIR + 'modulas'); const userMenu = require(DIR + 'user-menu'); const rest = require(DIR + 'rest'); @@ -45,7 +49,9 @@ const clean = (a) => a.filter(notEmpty); module.exports = (params) => { const p = params || {}; const options = p.config || {}; - const config = p.configManager || defaultConfig; + const config = p.configManager || createConfig({ + configPath, + }); const { modules, @@ -90,8 +96,8 @@ module.exports = (params) => { }); }; -module.exports.createConfigManager = defaultConfig.create; -module.exports.configPath = defaultConfig.path; +module.exports.createConfigManager = createConfig; +module.exports.configPath = configPath; module.exports._getIndexPath = getIndexPath; diff --git a/server/config.js b/server/config.js index 09874931..4927f2fe 100644 --- a/server/config.js +++ b/server/config.js @@ -29,28 +29,29 @@ const resolve = Promise.resolve.bind(Promise); const formatMsg = currify((a, b) => CloudFunc.formatMsg(a, b)); const {apiURL} = CloudFunc; -const changeEmitter = new Emitter(); const key = (a) => Object.keys(a).pop(); const ConfigPath = path.join(DIR, 'json/config.json'); const ConfigHome = path.join(HOME, '.cloudcmd.json'); -const config = read(); - const connection = currify(_connection); const connectionWraped = wraptile(_connection); const middle = currify(_middle); -function read(filename = ConfigHome) { - const readjsonSync = (name) => { - return jju.parse(fs.readFileSync(name, 'utf8'), { - mode: 'json', - }); - }; +const readjsonSync = (name) => { + return jju.parse(fs.readFileSync(name, 'utf8'), { + mode: 'json', + }); +}; + +const rootConfig = readjsonSync(ConfigPath); + +function read(filename) { + if (!filename) + return rootConfig; - const rootConfig = readjsonSync(ConfigPath); - const [error, configHome] = tryCatch(readjsonSync, ConfigHome); + const [error, configHome] = tryCatch(readjsonSync, filename); if (error && error.code !== 'ENOENT') exit(`cloudcmd --config ${filename}: ${error.message}`); @@ -61,18 +62,8 @@ function read(filename = ConfigHome) { }; } -module.exports = manage; -module.exports.create = create; -module.exports.middle = middle(manage); -module.exports.subscribe = (fn) => { - changeEmitter.on('change', fn); -}; - -module.exports.path = ConfigHome; - -module.exports.unsubscribe = (fn) => { - changeEmitter.removeListener('change', fn); -}; +module.exports.createConfig = createConfig; +module.exports.configPath = ConfigHome; const manageListen = currify((manage, socket, auth) => { if (!manage('configDialog')) @@ -83,23 +74,6 @@ const manageListen = currify((manage, socket, auth) => { return middle; }); -function manage(key, value) { - if (!key) - return; - - if (key === '*') - return config; - - if (value === undefined) - return config[key]; - - config[key] = value; - - changeEmitter.emit('change', key, value); - - return `${key} = ${value}`; -} - function initWrite(filename, configManager) { if (filename) return write.bind(null, filename, configManager); @@ -107,15 +81,9 @@ function initWrite(filename, configManager) { return resolve; } -function readConfig(filename) { - if (filename) - return read(filename); - - return config; -} - -function create({filename} = {}) { +function createConfig({configPath} = {}) { const config = {}; + const changeEmitter = new Emitter(); const configManager = (key, value) => { if (key === '*') @@ -127,26 +95,28 @@ function create({filename} = {}) { return config[key]; config[key] = value; + changeEmitter.emit('change', key, value); + + return `${key} = ${value}`; }; - spread(configManager); - Object.assign(config, readConfig(filename)); + Object.assign(config, read(configPath)); configManager.middle = middle(configManager); configManager.listen = manageListen(configManager); - configManager.write = initWrite(filename, configManager); + configManager.write = initWrite(configPath, configManager); + configManager.subscribe = (fn) => { + changeEmitter.on('change', fn); + }; + + configManager.unsubscribe = (fn) => { + // replace to off on node v10 + changeEmitter.removeListener('change', fn); + }; return configManager; } -function spread(store) { - const entries = Object.entries(config); - - for (const [name, value] of entries) { - store(name, value); - } -} - const write = async (filename, config) => { return writejson(filename, config('*'), {mode: 0o600}); }; diff --git a/server/config.spec.js b/server/config.spec.js index 2d6a500b..a9c6ad69 100644 --- a/server/config.spec.js +++ b/server/config.spec.js @@ -6,11 +6,11 @@ const stub = require('@cloudcmd/stub'); const root = '../'; const configPath = './config'; -const config = require(configPath); const { + createConfig, _cryptoPass, - create, -} = config; +} = require(configPath); +const config = createConfig(); const {apiURL} = require(root + 'common/cloudfunc'); @@ -24,14 +24,16 @@ test('config: manage', (t) => { test('config: manage: get', async (t) => { const editor = 'deepword'; + const configManager = createConfig(); const {done} = await connect({ config: {editor}, + configManager, }); done(); - t.equal(config('editor'), editor, 'should get config'); + t.equal(configManager('editor'), editor, 'should get config'); t.end(); }); @@ -63,7 +65,7 @@ test('config: cryptoPass: no password', (t) => { hello: 'world', }; - const config = create(); + const config = createConfig(); const result = _cryptoPass(config, json); t.deepEqual(result, [config, json], 'should not change json'); @@ -81,7 +83,7 @@ test('config: cryptoPass', (t) => { password, }; - const config = create(); + const config = createConfig(); const result = _cryptoPass(config, json); t.deepEqual(result, [config, expected], 'should crypt password'); diff --git a/server/distribute/export.spec.js b/server/distribute/export.spec.js index d984adaf..c828415a 100644 --- a/server/distribute/export.spec.js +++ b/server/distribute/export.spec.js @@ -4,7 +4,7 @@ const test = require('supertape'); const io = require('socket.io-client'); const {connect} = require('../../test/before'); -const config = require('../config'); +const config = require('../config').createConfig(); test('distribute: export', async (t) => { const defaultConfig = { @@ -17,6 +17,7 @@ test('distribute: export', async (t) => { const {port, done} = await connect({ config: defaultConfig, + configManager: config, }); const url = `http://localhost:${port}/distribute?port=${1111}`; diff --git a/server/distribute/import.spec.js b/server/distribute/import.spec.js index 76938248..2b77c52a 100644 --- a/server/distribute/import.spec.js +++ b/server/distribute/import.spec.js @@ -50,7 +50,9 @@ test('distribute: import: received: no error', async (t) => { }); test('distribute: import: received', async (t) => { + const configManager = createConfigManager(); const {done, port} = await connect({ + configManager, config: { name: 'bill', import: true, @@ -62,10 +64,9 @@ test('distribute: import: received', async (t) => { }, }); - const config = createConfigManager(); - config('importUrl', `http://localhost:${port}`); + configManager('importUrl', `http://localhost:${port}`); - const {status} = await distribute.import(config); + const {status} = await distribute.import(configManager); await done(); t.equal(status, 'received','should equal'); @@ -73,7 +74,9 @@ test('distribute: import: received', async (t) => { }); test('distribute: import: received: auth: reject', async (t) => { + const configManager = createConfigManager(); const {done, port} = await connect({ + configManager, config: { name: 'bill', import: true, @@ -85,10 +88,9 @@ test('distribute: import: received: auth: reject', async (t) => { }, }); - const config = createConfigManager(); - config('importUrl', `http://localhost:${port}`); + configManager('importUrl', `http://localhost:${port}`); - const {status} = await distribute.import(config); + const {status} = await distribute.import(configManager); await done(); t.equal(status, 'reject', 'should equal'); @@ -96,7 +98,9 @@ test('distribute: import: received: auth: reject', async (t) => { }); test('distribute: import: received: auth: accept', async (t) => { + const configManager = createConfigManager(); const {done, port} = await connect({ + configManager, config: { name: 'bill', import: true, @@ -108,10 +112,9 @@ test('distribute: import: received: auth: accept', async (t) => { }, }); - const config = createConfigManager(); - config('importUrl', `http://localhost:${port}`); + configManager('importUrl', `http://localhost:${port}`); - const {status} = await distribute.import(config); + const {status} = await distribute.import(configManager); await done(); t.equal(status, 'received','should equal'); @@ -119,7 +122,9 @@ test('distribute: import: received: auth: accept', async (t) => { }); test('distribute: import: received: no name', async (t) => { + const configManager = createConfigManager(); const {done, port} = await connect({ + configManager, config: { name: '', import: true, @@ -129,10 +134,9 @@ test('distribute: import: received: no name', async (t) => { }, }); - const config = createConfigManager(); - config('importUrl', `http://localhost:${port}`); + configManager('importUrl', `http://localhost:${port}`); - const {status} = await distribute.import(config); + const {status} = await distribute.import(configManager); await done(); t.equal(status, 'received','should equal'); @@ -140,7 +144,9 @@ test('distribute: import: received: no name', async (t) => { }); test('distribute: import: error', async (t) => { + const configManager = createConfigManager(); const {done} = await connect({ + configManager, config: { import: true, export: false, @@ -149,10 +155,9 @@ test('distribute: import: error', async (t) => { }, }); - const config = createConfigManager(); - config('importUrl', `http://localhost:0`); + configManager('importUrl', `http://localhost:0`); - const {status} = await distribute.import(config, { + const {status} = await distribute.import(configManager, { reconnection: false, }); @@ -163,7 +168,9 @@ test('distribute: import: error', async (t) => { }); test('distribute: import: config:change: no export', async (t) => { + const configManager = createConfigManager(); const {done} = await connect({ + configManager, config: { import: true, export: false, @@ -172,9 +179,7 @@ test('distribute: import: config:change: no export', async (t) => { }, }); - const config = createConfigManager(); - - const {status} = await distribute.import(config, { + const {status} = await distribute.import(configManager, { reconnection: false, }); diff --git a/server/distribute/log.spec.js b/server/distribute/log.spec.js index 962700b7..83c7a963 100644 --- a/server/distribute/log.spec.js +++ b/server/distribute/log.spec.js @@ -2,7 +2,7 @@ const test = require('supertape'); const log = require('./log'); -const config = require('../config'); +const {createConfig} = require('../config'); test('distribute: log: getMessage', (t) => { const e = 'hello'; @@ -23,7 +23,9 @@ test('distribute: log: getMessage: message', (t) => { }); test('distribute: log: config', (t) => { + const config = createConfig(); const logOriginal = config('log'); + config('log', true); log('log', 'test message'); config('log', logOriginal); diff --git a/server/route.js b/server/route.js index 1e014205..845dcbbb 100644 --- a/server/route.js +++ b/server/route.js @@ -10,18 +10,15 @@ const flop = require('flop'); const ponse = require('ponse'); const rendy = require('rendy'); const format = require('format-io'); -const squad = require('squad'); -const apart = require('apart'); const currify = require('currify'); const tryToCatch = require('try-to-catch'); const once = require('once'); -const config = require(DIR_SERVER + 'config'); const root = require(DIR_SERVER + 'root'); const prefixer = require(DIR_SERVER + 'prefixer'); const CloudFunc = require(DIR_COMMON + 'cloudfunc'); -const prefix = squad(prefixer, apart(config, 'prefix')); +const getPrefix = (config) => prefixer(config('prefix')); const onceRequire = once(require); @@ -172,7 +169,7 @@ function indexProcessing(config, options) { name, }), fm: left + right, - prefix: prefix(), + prefix: getPrefix(config), config: JSON.stringify(config('*')), columns: Columns[config('columns')], }); @@ -183,7 +180,7 @@ function indexProcessing(config, options) { function buildIndex(config, html, json) { const panel = CloudFunc.buildFromJSON({ data: json, - prefix: prefix(), + prefix: getPrefix(config), template: Template, }); diff --git a/server/route.spec.js b/server/route.spec.js index cd99868f..892fcceb 100644 --- a/server/route.spec.js +++ b/server/route.spec.js @@ -321,7 +321,10 @@ test('cloudcmd: route: sendIndex: encode', async (t) => { reRequire(routePath); const cloudcmd = reRequire(cloudcmdPath); - const {request} = serveOnce(cloudcmd); + const {request} = serveOnce(cloudcmd, { + configManager: createConfigManager(), + }); + const {body} = await request.get('/'); mockRequire.stop('flop'); @@ -411,6 +414,7 @@ test('cloudcmd: route: no termianl: /fs', async (t) => { const options = { config, + configManager: createConfigManager(), }; const {request} = serveOnce(cloudcmd); diff --git a/server/server.js b/server/server.js index 23d35b63..601407e8 100644 --- a/server/server.js +++ b/server/server.js @@ -10,8 +10,6 @@ const squad = require('squad'); const tryToCatch = require('try-to-catch'); const wraptile = require('wraptile'); -const config = require(DIR_SERVER + 'config'); - const two = currify((f, a, b) => f(a, b)); const exit = require(DIR_SERVER + 'exit'); @@ -32,7 +30,7 @@ const io = require('socket.io'); const tryRequire = require('tryrequire'); const logger = tryRequire('morgan'); -module.exports = async (options) => { +module.exports = async (options, config) => { const prefix = config('prefix'); const port = process.env.PORT || /* c9 */ config('port'); @@ -57,9 +55,7 @@ module.exports = async (options) => { app.use(prefix, cloudcmd({ config: options, socket: socketServer, - configManager: cloudcmd.createConfigManager({ - filename: cloudcmd.configPath, - }), + configManager: config, })); if (port < 0 || port > 65535) diff --git a/test/before.js b/test/before.js index 495d07a2..78ad0b73 100644 --- a/test/before.js +++ b/test/before.js @@ -24,6 +24,7 @@ function before(options, fn = options) { config, plugins, modules, + configManager, } = options; const app = express(); @@ -41,6 +42,7 @@ function before(options, fn = options) { socket, plugins, config: assign(defaultConfig(), config), + configManager, modules, })); diff --git a/test/rest/pack.js b/test/rest/pack.js index 276ffe6c..a22966d8 100644 --- a/test/rest/pack.js +++ b/test/rest/pack.js @@ -21,13 +21,15 @@ const fixture = { const defaultOptions = { config: { + auth: false, root: join(__dirname, '..'), }, }; + const cloudcmd = require(cloudcmdPath); const serveOnce = require('serve-once'); -const {request} = serveOnce(cloudcmd); +const {request} = serveOnce(cloudcmd, defaultOptions); const once = promisify((name, extract, fn) => { extract.once(name, (header, stream) => { @@ -76,7 +78,6 @@ test('cloudcmd: rest: pack: tar: put: file', async (t) => { const name = String(Math.random()) + '.tar.gz'; - const cloudcmd = reRequire(cloudcmdPath); const {request} = serveOnce(cloudcmd, defaultOptions); await request.put(`/api/v1/pack`, { diff --git a/test/server/console.js b/test/server/console.js index 689665b4..909b9da6 100644 --- a/test/server/console.js +++ b/test/server/console.js @@ -7,7 +7,7 @@ const io = require('socket.io-client'); const configPath = path.join(__dirname, '../..', 'server', 'config'); const {connect} = require('../before'); -const configFn = require(configPath); +const configFn = require(configPath).createConfig(); test('cloudcmd: console: enabled', async (t) => { const config = { diff --git a/test/static.js b/test/static.js index 29fec47c..f8f3e8a8 100644 --- a/test/static.js +++ b/test/static.js @@ -4,7 +4,7 @@ const test = require('supertape'); const criton = require('criton'); const cloudcmd = require('..'); -const configFn = require('../server/config'); +const configFn = cloudcmd.createConfigManager(); const config = { auth: false, From aca5ad0c4baee716c6859e1d6d9d24fc7acf1c83 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Tue, 4 Jun 2019 19:10:50 +0300 Subject: [PATCH 0083/1728] chore(package) v12.6.1 --- ChangeLog | 6 ++++++ HELP.md | 3 ++- README.md | 2 +- package.json | 2 +- 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index e9f81308..1143fb6b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2019.06.04, v12.6.1 + +fix: +- (config) configManager: totally move away from singletone + + 2019.05.31, v12.6.0 feature: diff --git a/HELP.md b/HELP.md index 0ddf5ccc..405905ba 100644 --- a/HELP.md +++ b/HELP.md @@ -1,4 +1,4 @@ -# Cloud Commander v12.6.0 +# Cloud Commander v12.6.1 ### [Main][MainURL] [Blog][BlogURL] Live(![Heroku][Heroku_LIVE_IMG] [Heroku][HerokuURL], ![Now][NOW_LIVE_IMG] [Now][NowURL]) @@ -919,6 +919,7 @@ There are a lot of ways to be involved in `Cloud Commander` development: Version history --------------- +- *2019.06.04*, **[v12.6.1](//github.com/coderaiser/cloudcmd/releases/tag/v12.6.1)** - *2019.05.31*, **[v12.6.0](//github.com/coderaiser/cloudcmd/releases/tag/v12.6.0)** - *2019.05.28*, **[v12.5.0](//github.com/coderaiser/cloudcmd/releases/tag/v12.5.0)** - *2019.05.27*, **[v12.4.0](//github.com/coderaiser/cloudcmd/releases/tag/v12.4.0)** diff --git a/README.md b/README.md index 33ad49a4..facfb145 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Cloud Commander v12.6.0 [![Build Status][BuildStatusIMGURL]][BuildStatusURL] [![Now status][BuildAppveyorIMGURL]][BuildAppveyorURL] [![Codacy][CodacyIMG]][CodacyURL] [![Gitter][GitterIMGURL]][GitterURL] [![OpenCollective](https://opencollective.com/cloudcmd/backers/badge.svg)](#backers) [![OpenCollective](https://opencollective.com/cloudcmd/sponsors/badge.svg)](#sponsors) +# Cloud Commander v12.6.1 [![Build Status][BuildStatusIMGURL]][BuildStatusURL] [![Now status][BuildAppveyorIMGURL]][BuildAppveyorURL] [![Codacy][CodacyIMG]][CodacyURL] [![Gitter][GitterIMGURL]][GitterURL] [![OpenCollective](https://opencollective.com/cloudcmd/backers/badge.svg)](#backers) [![OpenCollective](https://opencollective.com/cloudcmd/sponsors/badge.svg)](#sponsors) ### [Main][MainURL] [Blog][BlogURL] Live([Heroku][HerokuURL], [Now][NowURL]) diff --git a/package.json b/package.json index 03782b8f..23b53346 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "cloudcmd", - "version": "12.6.0", + "version": "12.6.1", "author": "coderaiser (https://github.com/coderaiser)", "description": "File manager for the web with console and editor", "homepage": "http://cloudcmd.io", From d52fe75e4348d5006df5899b1ae6d09bda5804e7 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Thu, 6 Jun 2019 17:56:44 +0300 Subject: [PATCH 0084/1728] fix(cloudcmd) config: save -> write (#247) --- bin/cloudcmd.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/cloudcmd.js b/bin/cloudcmd.js index afda5cb8..9baa5beb 100755 --- a/bin/cloudcmd.js +++ b/bin/cloudcmd.js @@ -223,7 +223,7 @@ function main() { const caller = (fn) => fn(); importConfig(config) - .then(args.save ? caller(config.save) : noop) + .then(args.save ? caller(config.write) : noop) .then(startWraped); } From 17498dbc07d60faa5af1d46658efc231c2c996f2 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Thu, 6 Jun 2019 17:59:01 +0300 Subject: [PATCH 0085/1728] feature(package) url-loader v2.0.0 --- .webpack/css.js | 7 ++++++- package.json | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/.webpack/css.js b/.webpack/css.js index 2338b53d..df2919b4 100644 --- a/.webpack/css.js +++ b/.webpack/css.js @@ -43,7 +43,12 @@ const rules = [{ }, ...cssPlugins.map(extract), { test: /\.(png|gif|svg|woff|woff2|eot|ttf)$/, - loader: 'url-loader?limit=100000', + use: { + loader: 'url-loader', + options: { + limit: 100000, + }, + }, }]; module.exports = { diff --git a/package.json b/package.json index 23b53346..0f1c428d 100644 --- a/package.json +++ b/package.json @@ -199,7 +199,7 @@ "supertape": "^1.0.3", "tar-stream": "^2.0.0", "unionfs": "^4.0.0", - "url-loader": "^1.0.1", + "url-loader": "^2.0.0", "version-io": "^2.0.1", "webpack": "^4.0.0", "webpack-cli": "^3.0.1", From b35762b1ec958d370036b1e1f87c60aa85fb4fea Mon Sep 17 00:00:00 2001 From: coderaiser Date: Thu, 6 Jun 2019 17:59:05 +0300 Subject: [PATCH 0086/1728] feature(package) remove file-loader --- package.json | 1 - 1 file changed, 1 deletion(-) diff --git a/package.json b/package.json index 0f1c428d..413a58b5 100644 --- a/package.json +++ b/package.json @@ -163,7 +163,6 @@ "eslint-plugin-putout": "^1.0.1", "extract-text-webpack-plugin": "^4.0.0-alpha.0", "fast-async": "^7.0.6", - "file-loader": "^3.0.1", "gritty": "^4.7.0", "gunzip-maybe": "^1.3.1", "html-looks-like": "^1.0.2", From 1fb920e039b3e065c5d3a060288a57e6e57e5c9f Mon Sep 17 00:00:00 2001 From: coderaiser Date: Thu, 6 Jun 2019 18:19:59 +0300 Subject: [PATCH 0087/1728] chore(package) v12.6.2 --- ChangeLog | 10 ++++++++++ HELP.md | 3 ++- README.md | 2 +- package.json | 2 +- 4 files changed, 14 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index 1143fb6b..a853d980 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2019.06.06, v12.6.2 + +fix: +- (cloudcmd) config: save -> write (#247) + +feature: +- (package) remove file-loader +- (package) url-loader v2.0.0 + + 2019.06.04, v12.6.1 fix: diff --git a/HELP.md b/HELP.md index 405905ba..50e26cae 100644 --- a/HELP.md +++ b/HELP.md @@ -1,4 +1,4 @@ -# Cloud Commander v12.6.1 +# Cloud Commander v12.6.2 ### [Main][MainURL] [Blog][BlogURL] Live(![Heroku][Heroku_LIVE_IMG] [Heroku][HerokuURL], ![Now][NOW_LIVE_IMG] [Now][NowURL]) @@ -919,6 +919,7 @@ There are a lot of ways to be involved in `Cloud Commander` development: Version history --------------- +- *2019.06.06*, **[v12.6.2](//github.com/coderaiser/cloudcmd/releases/tag/v12.6.2)** - *2019.06.04*, **[v12.6.1](//github.com/coderaiser/cloudcmd/releases/tag/v12.6.1)** - *2019.05.31*, **[v12.6.0](//github.com/coderaiser/cloudcmd/releases/tag/v12.6.0)** - *2019.05.28*, **[v12.5.0](//github.com/coderaiser/cloudcmd/releases/tag/v12.5.0)** diff --git a/README.md b/README.md index facfb145..6232c89f 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Cloud Commander v12.6.1 [![Build Status][BuildStatusIMGURL]][BuildStatusURL] [![Now status][BuildAppveyorIMGURL]][BuildAppveyorURL] [![Codacy][CodacyIMG]][CodacyURL] [![Gitter][GitterIMGURL]][GitterURL] [![OpenCollective](https://opencollective.com/cloudcmd/backers/badge.svg)](#backers) [![OpenCollective](https://opencollective.com/cloudcmd/sponsors/badge.svg)](#sponsors) +# Cloud Commander v12.6.2 [![Build Status][BuildStatusIMGURL]][BuildStatusURL] [![Now status][BuildAppveyorIMGURL]][BuildAppveyorURL] [![Codacy][CodacyIMG]][CodacyURL] [![Gitter][GitterIMGURL]][GitterURL] [![OpenCollective](https://opencollective.com/cloudcmd/backers/badge.svg)](#backers) [![OpenCollective](https://opencollective.com/cloudcmd/sponsors/badge.svg)](#sponsors) ### [Main][MainURL] [Blog][BlogURL] Live([Heroku][HerokuURL], [Now][NowURL]) diff --git a/package.json b/package.json index 413a58b5..2dce9b16 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "cloudcmd", - "version": "12.6.1", + "version": "12.6.2", "author": "coderaiser (https://github.com/coderaiser)", "description": "File manager for the web with console and editor", "homepage": "http://cloudcmd.io", From e4e05e20137c99ce8197a4439ef53bb8138d1c8d Mon Sep 17 00:00:00 2001 From: coderaiser Date: Mon, 10 Jun 2019 18:13:17 +0300 Subject: [PATCH 0088/1728] feature(package) rm Object.assign polyfill --- .babelrc | 1 - package.json | 1 - 2 files changed, 2 deletions(-) diff --git a/.babelrc b/.babelrc index d4dfda3d..4edbb326 100644 --- a/.babelrc +++ b/.babelrc @@ -7,7 +7,6 @@ }], ], "plugins": [ - "@babel/plugin-transform-object-assign", "@babel/plugin-syntax-dynamic-import", ["module:fast-async", { "compiler": { diff --git a/package.json b/package.json index 2dce9b16..adc1fa76 100644 --- a/package.json +++ b/package.json @@ -141,7 +141,6 @@ "devDependencies": { "@babel/core": "^7.0.0", "@babel/plugin-syntax-dynamic-import": "^7.0.0", - "@babel/plugin-transform-object-assign": "^7.0.0", "@babel/preset-env": "^7.0.0", "@cloudcmd/clipboard": "^1.0.2", "@cloudcmd/create-element": "^1.0.0", From 62053d9a3466d8de99ed852c611356829da7e9a9 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Mon, 10 Jun 2019 18:16:04 +0300 Subject: [PATCH 0089/1728] feature(cloudcmd) rm Promise polyfill --- .webpack/js.js | 4 +--- client/cloudcmd.js | 1 - package.json | 1 - 3 files changed, 1 insertion(+), 5 deletions(-) diff --git a/.webpack/js.js b/.webpack/js.js index dea0d877..a3ef66ba 100644 --- a/.webpack/js.js +++ b/.webpack/js.js @@ -119,9 +119,7 @@ function externals(context, request, fn) { if (!isDev) return fn(); - const list = [ - 'es6-promise', - ]; + const list = []; if (list.includes(request)) return fn(null, request); diff --git a/client/cloudcmd.js b/client/cloudcmd.js index 49a81d50..667d3f55 100644 --- a/client/cloudcmd.js +++ b/client/cloudcmd.js @@ -20,7 +20,6 @@ const { window.Emitify = require('emitify/legacy'); module.exports = window.CloudCmd = (config) => { - window.Promise = window.Promise || require('es6-promise'); window.Util = require('../common/util'); window.CloudFunc = require('../common/cloudfunc'); diff --git a/package.json b/package.json index adc1fa76..959878b7 100644 --- a/package.json +++ b/package.json @@ -156,7 +156,6 @@ "css-loader": "^2.0.1", "domtokenlist-shim": "^1.2.0", "emitify": "^3.0.2", - "es6-promise": "^4.0.5", "eslint": "^6.0.0-alpha", "eslint-plugin-node": "^9.0.1", "eslint-plugin-putout": "^1.0.1", From 669f412869265db633bb7b77ecb454b56a7ad9fd Mon Sep 17 00:00:00 2001 From: coderaiser Date: Mon, 10 Jun 2019 18:24:36 +0300 Subject: [PATCH 0090/1728] feature(babel) remove unused @babel/plugin-syntax-dynamic-import --- .babelrc | 1 - package.json | 1 - 2 files changed, 2 deletions(-) diff --git a/.babelrc b/.babelrc index 4edbb326..b6260752 100644 --- a/.babelrc +++ b/.babelrc @@ -7,7 +7,6 @@ }], ], "plugins": [ - "@babel/plugin-syntax-dynamic-import", ["module:fast-async", { "compiler": { "generators": false, diff --git a/package.json b/package.json index 959878b7..1d4f90e6 100644 --- a/package.json +++ b/package.json @@ -140,7 +140,6 @@ }, "devDependencies": { "@babel/core": "^7.0.0", - "@babel/plugin-syntax-dynamic-import": "^7.0.0", "@babel/preset-env": "^7.0.0", "@cloudcmd/clipboard": "^1.0.2", "@cloudcmd/create-element": "^1.0.0", From aaeb90372ee38c65ea2ab98a103358b89dee5cfe Mon Sep 17 00:00:00 2001 From: coderaiser Date: Tue, 11 Jun 2019 13:30:38 +0300 Subject: [PATCH 0091/1728] chore(cloudcmd) lint: no-paren --- client/dom/images.js | 2 +- client/dom/load.js | 2 +- server/distribute/log.js | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/client/dom/images.js b/client/dom/images.js index 034d65ca..ac3592f2 100644 --- a/client/dom/images.js +++ b/client/dom/images.js @@ -92,7 +92,7 @@ function show(position, panel) { current = refreshButton.parentElement; } - if (!parent || (parent && parent !== current)) + if (!parent || parent && parent !== current) current.appendChild(image); DOM.show(image); diff --git a/client/dom/load.js b/client/dom/load.js index d81ee747..56bfe759 100644 --- a/client/dom/load.js +++ b/client/dom/load.js @@ -105,7 +105,7 @@ module.exports.put = (url, body) => { if (!event.lengthComputable) return; - const percent = (event.loaded / event.total) * 100; + const percent = event.loaded / event.total * 100; const count = Math.round(percent); emitter.emit('progress', count); diff --git a/server/distribute/log.js b/server/distribute/log.js index 8ec98e1d..f08fc58c 100644 --- a/server/distribute/log.js +++ b/server/distribute/log.js @@ -6,7 +6,7 @@ const chalk = require('chalk'); const datetime = require('../../common/datetime'); const log = (isLog, name, msg) => isLog && console.log(`${datetime()} -> ${name}: ${msg}`); -const makeColor = (a, color) => chalk.rgb(...(color || stringToRGB(a)))(a); +const makeColor = (a, color) => chalk.rgb(color || stringToRGB(a))(a); const getMessage = (e) => e.message || e; const getDescription = (e) => `${e.type}: ${e.description}`; From bed4f1ae13c8339be1219be9a5c145247b4b6ac8 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Tue, 11 Jun 2019 18:31:11 +0300 Subject: [PATCH 0092/1728] feature(package) css-loader v3.0.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 1d4f90e6..cad123db 100644 --- a/package.json +++ b/package.json @@ -152,7 +152,7 @@ "clean-css-loader": "^2.0.0", "codegen.macro": "^3.0.0", "coveralls": "^3.0.0", - "css-loader": "^2.0.1", + "css-loader": "^3.0.0", "domtokenlist-shim": "^1.2.0", "emitify": "^3.0.2", "eslint": "^6.0.0-alpha", From 83a138f38c51a91c8a16a24b6f07caa7d151df19 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Fri, 14 Jun 2019 14:10:13 +0300 Subject: [PATCH 0093/1728] chore(cloudcmd) lint: sequence expressions --- client/dom/index.js | 8 ++++---- client/dom/storage.js | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/client/dom/index.js b/client/dom/index.js index 2207c666..ab54010a 100644 --- a/client/dom/index.js +++ b/client/dom/index.js @@ -628,8 +628,8 @@ function CmdProto() { if (!current) { panel = DOM.getByDataName('js-left'); } else { - files = current.parentElement, - panel = files.parentElement, + files = current.parentElement; + panel = files.parentElement; isLeft = panel.getAttribute('data-name') === 'js-left'; } @@ -870,7 +870,7 @@ function CmdProto() { CloudCmd.loadDir({ path, }); - }, + }; this.duplicatePanel = () => { const Info = CurrentInfo; @@ -930,7 +930,7 @@ function CmdProto() { }); }; - this.CurrentInfo = CurrentInfo, + this.CurrentInfo = CurrentInfo; this.updateCurrentInfo = (currentFile) => { const info = DOM.CurrentInfo; diff --git a/client/dom/storage.js b/client/dom/storage.js index 21f4e394..c1a5fbd4 100644 --- a/client/dom/storage.js +++ b/client/dom/storage.js @@ -45,7 +45,7 @@ module.exports.set = (name, data, callback) => { exec(callback, error); return module.exports; -}, +}; /** Если доступен Storage принимаем из него данные*/ module.exports.get = (name, callback) => { @@ -54,7 +54,7 @@ module.exports.get = (name, callback) => { exec(callback, null, ret); return module.exports; -}, +}; /** функция чистит весь кэш для всех каталогов*/ module.exports.clear = (callback) => { From ea8ec97f49c7ad16a0ce1626612830c7a5701949 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Wed, 19 Jun 2019 15:05:02 +0300 Subject: [PATCH 0094/1728] chore(cloudcmd) lint --- client/dom/dialog.js | 2 +- client/dom/events/index.js | 18 ++++++------------ client/key/vim/index.spec.js | 2 +- server/cloudcmd.spec.js | 2 +- server/columns.js | 2 +- server/distribute/export.js | 6 ++---- server/distribute/import.js | 36 ++++++++++++------------------------ server/exit.js | 2 +- test/common/cloudfunc.js | 6 ++---- 9 files changed, 27 insertions(+), 49 deletions(-) diff --git a/client/dom/dialog.js b/client/dom/dialog.js index 768ccfcc..6133d25d 100644 --- a/client/dom/dialog.js +++ b/client/dom/dialog.js @@ -7,7 +7,7 @@ const { prompt, confirm, progress, -}= require('smalltalk'); +} = require('smalltalk'); const title = 'Cloud Commander'; diff --git a/client/dom/events/index.js b/client/dom/events/index.js index 8e6b553a..692360d8 100644 --- a/client/dom/events/index.js +++ b/client/dom/events/index.js @@ -35,12 +35,10 @@ function EventsProto() { if (!/element$/.test(type)) throw Error('unknown eventName: ' + type); - parseArgs( - args[EVENT_NAME], + parseArgs(args[EVENT_NAME], args[ELEMENT], listener, - callback - ); + callback); break; case 'string': @@ -63,12 +61,10 @@ function EventsProto() { case 'array': eventName.forEach((eventName) => { - parseArgs( - eventName, + parseArgs(eventName, element, listener, - callback - ); + callback); }); break; @@ -76,12 +72,10 @@ function EventsProto() { Object.keys(eventName).forEach((name) => { const eventListener = eventName[name]; - parseArgs( - name, + parseArgs(name, element, eventListener, - callback - ); + callback); }); break; diff --git a/client/key/vim/index.spec.js b/client/key/vim/index.spec.js index f5b5e104..abfa3f0f 100644 --- a/client/key/vim/index.spec.js +++ b/client/key/vim/index.spec.js @@ -297,7 +297,7 @@ test('cloudcmd: client: key: set last file current', (t) => { test('cloudcmd: client: key: set first file current', (t) => { const first = 'first'; - const previousSibling= { + const previousSibling = { previousSibling: first, }; diff --git a/server/cloudcmd.spec.js b/server/cloudcmd.spec.js index 4f32cfc8..0e7533b0 100644 --- a/server/cloudcmd.spec.js +++ b/server/cloudcmd.spec.js @@ -193,7 +193,7 @@ test('cloudcmd: getIndexPath: development', (t) => { }); test('cloudcmd: sw', async (t) => { - const {status}= await request.get('/sw.js'); + const {status} = await request.get('/sw.js'); t.equal(status, 200, 'should return sw'); t.end(); diff --git a/server/columns.js b/server/columns.js index d6f2b952..ac257560 100644 --- a/server/columns.js +++ b/server/columns.js @@ -1,7 +1,7 @@ 'use strict'; const path = require('path'); -const fs= require('fs'); +const fs = require('fs'); const readFilesSync = require('@cloudcmd/read-files-sync'); const isMap = (a) => /\.map$/.test(a); const not = (fn) => (a) => !fn(a); diff --git a/server/distribute/export.js b/server/distribute/export.js index 7b2e3641..b4c054de 100644 --- a/server/distribute/export.js +++ b/server/distribute/export.js @@ -46,10 +46,8 @@ module.exports = (config, socket) => { const distributePrefix = `${prefix}/distribute`; const isLog = config('log'); - const onError = squad( - logWraped(isLog, exportStr), - getMessage, - ); + const onError = squad(logWraped(isLog, exportStr), + getMessage,); const onConnectError = squad(logWraped(isLog, exportStr), getDescription); diff --git a/server/distribute/import.js b/server/distribute/import.js index 6b0191e8..7369cf1e 100644 --- a/server/distribute/import.js +++ b/server/distribute/import.js @@ -92,48 +92,36 @@ module.exports = (config, options, fn) => { const statusStore = fullstore(); const statusStoreWraped = wraptile(statusStore); - const onConfig = squad( - close, + const onConfig = squad(close, logWraped(isLog, importStr, `config received from ${colorUrl}`), statusStoreWraped('received'), - forEachKey(config), - ); + forEachKey(config),); - const onError = squad( - superFn('error'), + const onError = squad(superFn('error'), logWraped(isLog, config, importStr), addUrl(colorUrl), - getMessage, - ); + getMessage,); - const onConnectError = squad( - superFn('connect_error'), + const onConnectError = squad(superFn('connect_error'), logWraped(isLog, importStr), addUrl(colorUrl), - getDescription, - ); + getDescription,); const onConnect = emitAuth(importUrl, config, socket); const onAccept = logWraped(isLog, importStr,`${connectedStr} to ${colorUrl}`); - const onDisconnect = squad( - done(fn, statusStore), + const onDisconnect = squad(done(fn, statusStore), logWraped(isLog, importStr, `${disconnectedStr} from ${colorUrl}`), rmListeners(socket, { onError, onConnect, onConfig, - }), - ); + }),); - const onChange = squad( - logWraped(isLog, importStr), - config, - ); + const onChange = squad(logWraped(isLog, importStr), + config,); - const onReject = squad( - superFn('reject'), - logWraped(isLog, importStr, tokenRejectedStr), - ); + const onReject = squad(superFn('reject'), + logWraped(isLog, importStr, tokenRejectedStr),); socket.on('connect', onConnect); socket.on('accept', onAccept); diff --git a/server/exit.js b/server/exit.js index 698adee0..f01cd130 100644 --- a/server/exit.js +++ b/server/exit.js @@ -2,7 +2,7 @@ const getMessage = (a) => a && a.message || a; -module.exports= (...args) => { +module.exports = (...args) => { const messages = args.map(getMessage); console.error(...messages); diff --git a/test/common/cloudfunc.js b/test/common/cloudfunc.js index 94750b8e..ce668ea5 100644 --- a/test/common/cloudfunc.js +++ b/test/common/cloudfunc.js @@ -95,11 +95,9 @@ test('cloudfunc: render', (t) => { timeEnd('CloudFunc.buildFromJSON'); if (isNotOk) { - console.log( - `Error in char number: ${i}\n`, + console.log(`Error in char number: ${i}\n`, `Expect: ${Expect.substr(i)}\n`, - `Result: ${result.substr(i)}` - ); + `Result: ${result.substr(i)}`); console.log('buildFromJSON: Not OK'); } From 6d69cd3a488bd823191aacbe0e8254235055e05f Mon Sep 17 00:00:00 2001 From: coderaiser Date: Mon, 24 Jun 2019 15:29:38 +0300 Subject: [PATCH 0095/1728] chore(set-current-by-char) lint --- client/key/set-current-by-char.js | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/client/key/set-current-by-char.js b/client/key/set-current-by-char.js index 42705377..f08284eb 100644 --- a/client/key/set-current-by-char.js +++ b/client/key/set-current-by-char.js @@ -38,12 +38,13 @@ module.exports = function setCurrentByChar(char, charStore) { setted = true; DOM.setCurrentFile(byName); return true; - } else { - if (skipN === skipCount) - firstByName = byName; - - --skipCount; } + + if (skipN === skipCount) + firstByName = byName; + + --skipCount; + }; names From fd6d384ba2a24341e0edc8f77419472d67640d70 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Tue, 25 Jun 2019 20:12:34 +0300 Subject: [PATCH 0096/1728] chore(cloudcmd) lint: convert forEach to for-of --- client/client.js | 4 ++-- client/dom/buffer.js | 8 ++++---- client/dom/events/index.js | 9 +++++---- client/dom/load.js | 4 ++-- client/modules/config/index.js | 4 ++-- client/modules/menu.js | 4 ++-- common/entity.js | 8 ++++---- server/cloudcmd.js | 4 ++-- server/config.js | 4 ++-- 9 files changed, 25 insertions(+), 24 deletions(-) diff --git a/client/client.js b/client/client.js index f151c803..5d7ac82f 100644 --- a/client/client.js +++ b/client/client.js @@ -259,9 +259,9 @@ function CloudCmdProto(DOM) { if (!modules) return; - modules.local.forEach((module) => { + for (const module of modules.local) { load(null, module, doBefore[module]); - }); + } }); function baseInit(callback) { diff --git a/client/dom/buffer.js b/client/dom/buffer.js index a844384f..6d7f05e8 100644 --- a/client/dom/buffer.js +++ b/client/dom/buffer.js @@ -36,17 +36,17 @@ function BufferProto() { function addCutClass() { const files = DOM.getActiveFiles(); - files.forEach((element) => { + for (const element of files) { element.classList.add(CLASS); - }); + } } function rmCutClass() { const files = DOM.getByClassAll(CLASS); - [...files].forEach((element) => { + for (const element of [...files]) { element.classList.remove(CLASS); - }); + } } function callIfEnabled(callback) { diff --git a/client/dom/events/index.js b/client/dom/events/index.js index 692360d8..4bfd290a 100644 --- a/client/dom/events/index.js +++ b/client/dom/events/index.js @@ -60,23 +60,24 @@ function EventsProto() { break; case 'array': - eventName.forEach((eventName) => { + for (const eventName of eventName) { parseArgs(eventName, element, listener, callback); - }); + } + break; case 'object': - Object.keys(eventName).forEach((name) => { + for (const name of Object.keys(eventName)) { const eventListener = eventName[name]; parseArgs(name, element, eventListener, callback); - }); + } break; } diff --git a/client/dom/load.js b/client/dom/load.js index 56bfe759..513de732 100644 --- a/client/dom/load.js +++ b/client/dom/load.js @@ -48,10 +48,10 @@ module.exports.ajax = (params) => { xhr.open(type, p.url, true); - Object.keys(headers).forEach((name) => { + for (const name of Object.keys(headers)) { const value = headers[name]; xhr.setRequestHeader(name, value); - }); + } if (p.responseType) xhr.responseType = p.responseType; diff --git a/client/modules/config/index.js b/client/modules/config/index.js index d85d2942..5db8ee06 100644 --- a/client/modules/config/index.js +++ b/client/modules/config/index.js @@ -206,12 +206,12 @@ async function onChange(el) { } function onSave(obj) { - Object.keys(obj).forEach((name) => { + for (const name of Object.keys(obj)) { const data = obj[name]; CloudCmd._config(name, data); input.setValue(name, data, Element); - }); + } } async function saveHttp(obj) { diff --git a/client/modules/menu.js b/client/modules/menu.js index 502d4100..5616400c 100644 --- a/client/modules/menu.js +++ b/client/modules/menu.js @@ -267,7 +267,7 @@ function download(type) { if (!files.length) return alertNoFiles(); - files.forEach((file) => { + for (const file of files) { const selected = DOM.isSelected(file); const isDir = DOM.isCurrentIsDir(file); const path = DOM.getCurrentPath(file); @@ -302,7 +302,7 @@ function download(type) { if (selected) DOM.toggleSelectedFile(file); - }); + } } function getCurrentPosition() { diff --git a/common/entity.js b/common/entity.js index c3c718c4..bad8ef77 100644 --- a/common/entity.js +++ b/common/entity.js @@ -10,23 +10,23 @@ const Entities = { const keys = Object.keys(Entities); module.exports.encode = (str) => { - keys.forEach((code) => { + for (const code of keys) { const char = Entities[code]; const reg = RegExp(char, 'g'); str = str.replace(reg, code); - }); + } return str; }; module.exports.decode = (str) => { - keys.forEach((code) => { + for (const code of keys) { const char = Entities[code]; const reg = RegExp(code, 'g'); str = str.replace(reg, char); - }); + } return str; }; diff --git a/server/cloudcmd.js b/server/cloudcmd.js index e878ea15..03fa26eb 100644 --- a/server/cloudcmd.js +++ b/server/cloudcmd.js @@ -62,7 +62,7 @@ module.exports = (params) => { checkPlugins(plugins); - keys.forEach((name) => { + for (const name of keys) { let value = options[name]; if (/root/.test(name)) @@ -75,7 +75,7 @@ module.exports = (params) => { value = prefixer(value); config(name, value); - }); + } config('console', defaultValue(config, 'console', options)); config('configDialog', defaultValue(config, 'configDialog', options)); diff --git a/server/config.js b/server/config.js index 4927f2fe..bba94351 100644 --- a/server/config.js +++ b/server/config.js @@ -229,9 +229,9 @@ async function patchConfig(manage, {name, request, response, cache}) { } function traverse([manage, json]) { - Object.keys(json).forEach((name) => { + for (const name of Object.keys(json)) { manage(name, json[name]); - }); + } } module.exports._cryptoPass = cryptoPass; From 9483fbeb5df97eef518696df778fd8432932a3c2 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Wed, 26 Jun 2019 14:34:38 +0300 Subject: [PATCH 0097/1728] chore(cloudcmd) lint: new-line-function-call-arguments --- client/dom/events/index.js | 18 ++++++++++++------ client/listeners/index.js | 6 ++++-- server/distribute/export.js | 6 ++++-- server/distribute/import.js | 36 ++++++++++++++++++++++++------------ test/common/cloudfunc.js | 6 ++++-- 5 files changed, 48 insertions(+), 24 deletions(-) diff --git a/client/dom/events/index.js b/client/dom/events/index.js index 4bfd290a..d4ca0128 100644 --- a/client/dom/events/index.js +++ b/client/dom/events/index.js @@ -35,10 +35,12 @@ function EventsProto() { if (!/element$/.test(type)) throw Error('unknown eventName: ' + type); - parseArgs(args[EVENT_NAME], + parseArgs( + args[EVENT_NAME], args[ELEMENT], listener, - callback); + callback + ); break; case 'string': @@ -61,10 +63,12 @@ function EventsProto() { case 'array': for (const eventName of eventName) { - parseArgs(eventName, + parseArgs( + eventName, element, listener, - callback); + callback + ); } break; @@ -73,10 +77,12 @@ function EventsProto() { for (const name of Object.keys(eventName)) { const eventListener = eventName[name]; - parseArgs(name, + parseArgs( + name, element, eventListener, - callback); + callback + ); } break; diff --git a/client/listeners/index.js b/client/listeners/index.js index d2170b5d..7c4ec348 100644 --- a/client/listeners/index.js +++ b/client/listeners/index.js @@ -325,10 +325,12 @@ function onDragStart(event) { link.href = prefixURL + '/pack' + Info.path + EXT; } - event.dataTransfer.setData('DownloadURL', + event.dataTransfer.setData( + 'DownloadURL', 'application/octet-stream' + ':' + name + ':' + - link); + link + ); } function getLIElement(element) { diff --git a/server/distribute/export.js b/server/distribute/export.js index b4c054de..7b2e3641 100644 --- a/server/distribute/export.js +++ b/server/distribute/export.js @@ -46,8 +46,10 @@ module.exports = (config, socket) => { const distributePrefix = `${prefix}/distribute`; const isLog = config('log'); - const onError = squad(logWraped(isLog, exportStr), - getMessage,); + const onError = squad( + logWraped(isLog, exportStr), + getMessage, + ); const onConnectError = squad(logWraped(isLog, exportStr), getDescription); diff --git a/server/distribute/import.js b/server/distribute/import.js index 7369cf1e..6b0191e8 100644 --- a/server/distribute/import.js +++ b/server/distribute/import.js @@ -92,36 +92,48 @@ module.exports = (config, options, fn) => { const statusStore = fullstore(); const statusStoreWraped = wraptile(statusStore); - const onConfig = squad(close, + const onConfig = squad( + close, logWraped(isLog, importStr, `config received from ${colorUrl}`), statusStoreWraped('received'), - forEachKey(config),); + forEachKey(config), + ); - const onError = squad(superFn('error'), + const onError = squad( + superFn('error'), logWraped(isLog, config, importStr), addUrl(colorUrl), - getMessage,); + getMessage, + ); - const onConnectError = squad(superFn('connect_error'), + const onConnectError = squad( + superFn('connect_error'), logWraped(isLog, importStr), addUrl(colorUrl), - getDescription,); + getDescription, + ); const onConnect = emitAuth(importUrl, config, socket); const onAccept = logWraped(isLog, importStr,`${connectedStr} to ${colorUrl}`); - const onDisconnect = squad(done(fn, statusStore), + const onDisconnect = squad( + done(fn, statusStore), logWraped(isLog, importStr, `${disconnectedStr} from ${colorUrl}`), rmListeners(socket, { onError, onConnect, onConfig, - }),); + }), + ); - const onChange = squad(logWraped(isLog, importStr), - config,); + const onChange = squad( + logWraped(isLog, importStr), + config, + ); - const onReject = squad(superFn('reject'), - logWraped(isLog, importStr, tokenRejectedStr),); + const onReject = squad( + superFn('reject'), + logWraped(isLog, importStr, tokenRejectedStr), + ); socket.on('connect', onConnect); socket.on('accept', onAccept); diff --git a/test/common/cloudfunc.js b/test/common/cloudfunc.js index ce668ea5..94750b8e 100644 --- a/test/common/cloudfunc.js +++ b/test/common/cloudfunc.js @@ -95,9 +95,11 @@ test('cloudfunc: render', (t) => { timeEnd('CloudFunc.buildFromJSON'); if (isNotOk) { - console.log(`Error in char number: ${i}\n`, + console.log( + `Error in char number: ${i}\n`, `Expect: ${Expect.substr(i)}\n`, - `Result: ${result.substr(i)}`); + `Result: ${result.substr(i)}` + ); console.log('buildFromJSON: Not OK'); } From f662ec0e673d405994d312a12b2ef40368871d60 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Wed, 26 Jun 2019 14:41:55 +0300 Subject: [PATCH 0098/1728] fix(cloudcmd) server start when importListen enabled --- bin/cloudcmd.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/cloudcmd.js b/bin/cloudcmd.js index 9baa5beb..118ed390 100755 --- a/bin/cloudcmd.js +++ b/bin/cloudcmd.js @@ -217,14 +217,14 @@ function main() { if (args['show-config']) showConfig(); - const startWraped = wraptile(start, options, config); const distribute = require('../server/distribute'); const importConfig = promisify(distribute.import); const caller = (fn) => fn(); importConfig(config) .then(args.save ? caller(config.write) : noop) - .then(startWraped); + + start(options, config); } function validateRoot(root, config) { From d4ff1f97a9a31a7113beb4f74a20a831b24a77e5 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Mon, 1 Jul 2019 16:06:04 +0300 Subject: [PATCH 0099/1728] chore(cloudcmd) lint --- bin/cloudcmd.js | 4 +- client/client.js | 6 ++- client/dom/load.js | 4 +- client/load-module.js | 6 ++- common/cloudfunc.js | 91 ++++++++++++++++++++++++------------------- 5 files changed, 63 insertions(+), 48 deletions(-) diff --git a/bin/cloudcmd.js b/bin/cloudcmd.js index 118ed390..59bc17f8 100755 --- a/bin/cloudcmd.js +++ b/bin/cloudcmd.js @@ -7,8 +7,6 @@ const DIR_SERVER = '../server/'; const {promisify} = require('util'); -const wraptile = require('wraptile'); - const exit = require(DIR_SERVER + 'exit'); const { createConfig, @@ -222,7 +220,7 @@ function main() { const caller = (fn) => fn(); importConfig(config) - .then(args.save ? caller(config.write) : noop) + .then(args.save ? caller(config.write) : noop); start(options, config); } diff --git a/client/client.js b/client/client.js index 5d7ac82f..6c9793c6 100644 --- a/client/client.js +++ b/client/client.js @@ -324,13 +324,15 @@ function CloudCmdProto(DOM) { options = {}; } - const panel = options.panel || Info.panel; + const { + panel = Info.panel, + currentName, + } = options; const path = DOM.getCurrentDirPath(panel); const isRefresh = true; const history = false; const noCurrent = options ? options.noCurrent : false; - const {currentName} = options; CloudCmd.loadDir({ path, diff --git a/client/dom/load.js b/client/dom/load.js index 513de732..5596a384 100644 --- a/client/dom/load.js +++ b/client/dom/load.js @@ -43,7 +43,9 @@ module.exports.ajax = (params) => { const isArray = itype.array(p.data); const isArrayBuf = itype(p.data) === 'arraybuffer'; const type = p.type || p.method || 'GET'; - const headers = p.headers || {}; + const { + headers = {}, + } = p; const xhr = new XMLHttpRequest(); xhr.open(type, p.url, true); diff --git a/client/load-module.js b/client/load-module.js index 17afdef7..bade6710 100644 --- a/client/load-module.js +++ b/client/load-module.js @@ -18,8 +18,10 @@ module.exports = function loadModule(params) { if (!params) return; - const {path} = params; - const name = params.name || path && noJS(pascalCase(path)); + const { + path, + name = path && noJS(pascalCase(path)), + } = params; const doBefore = params.dobefore; if (CloudCmd[name]) diff --git a/common/cloudfunc.js b/common/cloudfunc.js index d30460f5..95df933b 100644 --- a/common/cloudfunc.js +++ b/common/cloudfunc.js @@ -41,8 +41,10 @@ module.exports.formatMsg = (msg, name, status) => { module.exports.getTitle = (options) => { options = options || {}; - const path = options.path || Path(); - const {name} = options; + const { + path = Path(), + name, + } = options; const array = [ name || NAME, @@ -110,6 +112,8 @@ module.exports.buildFromJSON = (params) => { const { prefix, template, + sort = 'name', + order = 'asc', } = params; const templateFile = template.file; @@ -120,9 +124,6 @@ module.exports.buildFromJSON = (params) => { const {files} = json; - const sort = params.sort || 'name'; - const order = params.order || 'asc'; - /* * Строим путь каталога в котором мы находимся * со всеми подкаталогами @@ -189,47 +190,57 @@ module.exports.buildFromJSON = (params) => { }); } - fileTable += files.map((file) => { - const name = encode(file.name); - const link = prefix + FS + path + name; - - const { - type, - mode, - } = file; - const size = getSize(file); - - const date = file.date || '--.--.----'; - const owner = file.owner || 'root'; - - const linkResult = rendy(templateLink, { - link, - title: name, - name, - attribute: getAttribute(file.type), - }); - - const dataName = getDataName(file.name); - const attribute = `draggable="true" ${dataName}`; - - return rendy(templateFile, { - tag: 'li', - attribute, - className: '', - type, - name: linkResult, - size, - date, - owner, - mode, - }); - }).join(''); + fileTable += files + .map(updateField) + .map((file) => { + const name = encode(file.name); + const link = prefix + FS + path + name; + + const { + type, + mode, + date, + owner, + size, + } = file; + + const linkResult = rendy(templateLink, { + link, + title: name, + name, + attribute: getAttribute(file.type), + }); + + const dataName = getDataName(file.name); + const attribute = `draggable="true" ${dataName}`; + + return rendy(templateFile, { + tag: 'li', + attribute, + className: '', + type, + name: linkResult, + size, + date, + owner, + mode, + }); + }).join(''); fileTable += ''; return fileTable; }; +function updateField(file) { + return { + ...file, + date: file.date || '--.--.----', + owner: file.owner || 'root', + size: getSize(file), + }; +} + function getAttribute(type) { if (type === 'directory') return ''; From ed3bdf1586be4dbc7c8d9b7b63d13768ffc8b273 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Mon, 8 Jul 2019 12:12:34 +0300 Subject: [PATCH 0100/1728] feature(package) yaspeller v6.0.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index cad123db..d58dcc35 100644 --- a/package.json +++ b/package.json @@ -200,7 +200,7 @@ "webpack": "^4.0.0", "webpack-cli": "^3.0.1", "webpack-merge": "^4.1.2", - "yaspeller": "^5.0.0" + "yaspeller": "^6.0.0" }, "engines": { "node": ">=8.3.0" From 2f2cd58c30a0838730738574f59f497b11adc9f3 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Mon, 8 Jul 2019 12:18:07 +0300 Subject: [PATCH 0101/1728] chore(client) lint: merge-if-statements --- client/client.js | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/client/client.js b/client/client.js index 6c9793c6..ad911e33 100644 --- a/client/client.js +++ b/client/client.js @@ -111,11 +111,10 @@ function CloudCmdProto(DOM) { let panelChanged; - if (!noCurrent) - if (panel && panel !== Info.panel) { - DOM.changePanel(); - panelChanged = true; - } + if (!noCurrent && panel && panel !== Info.panel) { + DOM.changePanel(); + panelChanged = true; + } let imgPosition; From af28ddf201804e270b904c887369bdb137ad51cf Mon Sep 17 00:00:00 2001 From: coderaiser Date: Wed, 10 Jul 2019 15:31:46 +0300 Subject: [PATCH 0102/1728] feature(package) deepmerge v4.0.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d58dcc35..89c09194 100644 --- a/package.json +++ b/package.json @@ -95,7 +95,7 @@ "copymitter": "^4.0.2", "criton": "^2.0.0", "currify": "^3.0.0", - "deepmerge": "^3.0.0", + "deepmerge": "^4.0.0", "deepword": "^6.0.0", "dword": "^11.0.0", "edward": "^11.0.0", From b4629a86e4ae103412196ff5d488e05587d0aed4 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Thu, 11 Jul 2019 13:16:10 +0300 Subject: [PATCH 0103/1728] feature(package) markdown-it v9.0.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 89c09194..5cbf5a48 100644 --- a/package.json +++ b/package.json @@ -113,7 +113,7 @@ "jaguar": "^5.0.0", "jju": "^1.3.0", "jonny": "^2.0.3", - "markdown-it": "^8.0.0", + "markdown-it": "^9.0.0", "mellow": "^2.0.0", "minimist": "^1.2.0", "nomine": "^3.0.0", From ecd2624d2b65d1cab8309ac8e0fdc5ff9b12eeb2 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Mon, 22 Jul 2019 15:08:30 +0300 Subject: [PATCH 0104/1728] feature(cloudcmd) simplify lint --- .eslintrc.js | 28 ++++++++++++++++++++++++++++ .eslintrc.json | 11 ----------- .eslintrc.server | 11 ----------- bin/cloudcmd.js | 42 +++++++++++++++++++++--------------------- madrun.js | 24 ++++++++++-------------- package.json | 37 ++++++++++++++++++++++++++++--------- 6 files changed, 87 insertions(+), 66 deletions(-) create mode 100644 .eslintrc.js delete mode 100644 .eslintrc.json delete mode 100644 .eslintrc.server diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 00000000..62b14e6c --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,28 @@ +'use strict'; + +module.exports = { + rules: { + 'no-console': 0, + }, + extends: [ + 'plugin:putout/recommended', + ], + plugins: [ + 'putout', + 'node', + ], + overrides: [{ + files: ['server'], + rules: { + 'no-process-exit': 0, + }, + extends: [ + 'plugin:node/recommended', + ], + }, { + files: ['client', 'static'], + env: { + browser: true, + }, + }], +}; diff --git a/.eslintrc.json b/.eslintrc.json deleted file mode 100644 index 4d8409a4..00000000 --- a/.eslintrc.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "rules": { - "no-console": 0 - }, - "extends": [ - "plugin:putout/recommended" - ], - "plugins": [ - "putout" - ] -} diff --git a/.eslintrc.server b/.eslintrc.server deleted file mode 100644 index 56c3a514..00000000 --- a/.eslintrc.server +++ /dev/null @@ -1,11 +0,0 @@ -{ - "rules": { - "no-process-exit": 0, - }, - "extends": [ - "plugin:node/recommended", - ], - "plugins": [ - "node" - ] -} diff --git a/bin/cloudcmd.js b/bin/cloudcmd.js index 59bc17f8..306f9ca7 100755 --- a/bin/cloudcmd.js +++ b/bin/cloudcmd.js @@ -83,30 +83,30 @@ const args = require('minimist')(argv.slice(2), { 'user-menu', ], default: { - server : true, - name : choose(env('name'), config('name')), - auth : choose(env.bool('auth'), config('auth')), - port : config('port'), - online : config('online'), - open : choose(env.bool('open'), config('open')), - editor : env('editor') || config('editor'), - packer : config('packer') || 'tar', - zip : config('zip'), - username : env('username') || config('username'), - root : choose(env('root'), config('root')), - prefix : config('prefix'), - progress : config('progress'), - console : choose(env.bool('console'), config('console')), - contact : choose(env.bool('contact'), config('contact')), - terminal : choose(env.bool('terminal'), config('terminal')), - columns : env('columns') || config('columns') || '', - vim : choose(env.bool('vim'), config('vim')), - log : config('log'), + 'server' : true, + 'name' : choose(env('name'), config('name')), + 'auth' : choose(env.bool('auth'), config('auth')), + 'port' : config('port'), + 'online' : config('online'), + 'open' : choose(env.bool('open'), config('open')), + 'editor' : env('editor') || config('editor'), + 'packer' : config('packer') || 'tar', + 'zip' : config('zip'), + 'username' : env('username') || config('username'), + 'root' : choose(env('root'), config('root')), + 'prefix' : config('prefix'), + 'progress' : config('progress'), + 'console' : choose(env.bool('console'), config('console')), + 'contact' : choose(env.bool('contact'), config('contact')), + 'terminal' : choose(env.bool('terminal'), config('terminal')), + 'columns' : env('columns') || config('columns') || '', + 'vim' : choose(env.bool('vim'), config('vim')), + 'log' : config('log'), 'import-url': env('import_url') || config('importUrl'), 'import-listen': choose(env.bool('import_listen'), config('importListen')), - import : choose(env.bool('import'), config('import')), - export : choose(env.bool('export'), config('export')), + 'import' : choose(env.bool('import'), config('import')), + 'export' : choose(env.bool('export'), config('export')), 'prefix-socket': config('prefixSocket'), 'show-file-name': choose(env.bool('show_file_name'), config('showFileName')), diff --git a/madrun.js b/madrun.js index 74da8336..e87dcf1c 100644 --- a/madrun.js +++ b/madrun.js @@ -3,42 +3,40 @@ const { run, parallel, + predefined, } = require('madrun'); const {version} = require('./package'); +const {eslint} = predefined; -const dirs = [ +const names = [ 'bin/cloudcmd.js', 'common', 'server', -].join(' '); - -const dirsTest = [ 'test', 'bin/release.js', 'webpack.config.js', 'cssnano.config.js', '.webpack', + '.eslintrc.js', 'madrun.js', '{client,server,common}/**/*.spec.js', -].join(' '); +]; module.exports = { 'start': () => 'node bin/cloudcmd.js', 'start:dev': () => `NODE_ENV=development ${run('start')}`, 'build:start': () => run(['build:client', 'start']), 'build:start:dev': () => run(['build:client:dev', 'start:dev']), - 'lint': () => run(['putout', 'lint:*', 'spell']), - 'lint:server': () => `eslint -c .eslintrc.server ${dirs} --ignore-pattern *.spec.js`, - 'lint:test': () => `eslint --ignore-pattern '!.*' ${dirsTest}`, - 'lint:client': () => 'eslint --env browser client static --ignore-pattern .cloudcmd.menu.js', + 'lint:all': () => run(['lint', 'lint:css', 'spell']), + 'lint': () => eslint({names}), 'lint:css': () => 'stylelint css/*.css', 'spell': () => 'yaspeller .', - 'fix:lint': () => run(['putout', 'lint:*'], '--fix'), + 'fix:lint': () => run('lint', '--fix'), 'test': () => `tape 'test/**/*.js' '{client,static,common,server}/**/*.spec.js'`, 'test:client': () => `tape 'test/client/**/*.js`, 'test:server': () => `tape 'test/**/*.js' 'server/**/*.spec.js' 'common/**/*.spec.js'`, - 'wisdom': () => run(['lint', 'build', 'test']), + 'wisdom': () => run(['lint:all', 'build', 'test']), 'wisdom:type': () => 'bin/release.js', 'docker:pull:node': () => 'docker pull node', 'docker:pull:alpine': () => 'docker pull mhart/alpine-node', @@ -75,9 +73,7 @@ module.exports = { 'watch:client': () => run('6to5:client','--watch'), 'watch:client:dev': () => run('6to5:client:dev', '--watch'), 'watch:server': () => 'nodemon bin/cloudcmd.js', - 'watch:lint': () => `nodemon -w client -w server -w webpack.config.js -x ${run(['lint:client', 'lint:server'])}`, - 'watch:lint:client': () => `nodemon -w client -w webpack.config.js -x ${run('lint:client')}`, - 'watch:lint:server': () => `nodemon -w server -w common -x ${run('lint:server')}`, + 'watch:lint': () => `nodemon -w client -w server -w webpack.config.js -x ${run('lint')}`, 'watch:test': () => `nodemon -w client -w server -w test -w common -x ${run('test')}`, 'watch:test:client': () => `nodemon -w client -w test/client -x ${run('test:client')}`, 'watch:test:server': () => `nodemon -w client -w test/client -x ${run('test:server')}`, diff --git a/package.json b/package.json index 5cbf5a48..6f00ef30 100644 --- a/package.json +++ b/package.json @@ -49,35 +49,54 @@ "start:dev": "madrun start:dev", "build:start": "madrun build:start", "build:start:dev": "madrun build:start:dev", + "lint:all": "madrun lint:all", "lint": "madrun lint", - "lint:server": "madrun lint:server", - "lint:test": "madrun lint:test", - "lint:client": "madrun lint:client", "lint:css": "madrun lint:css", - "spell": "medrun spell", + "spell": "madrun spell", "fix:lint": "madrun fix:lint", "test": "madrun test", "test:client": "madrun test:client", "test:server": "madrun test:server", - "wisdom": "madrun lint build test", - "wisdom:type": "bin/release.js", + "wisdom": "madrun wisdom", + "wisdom:type": "madrun wisdom:type", + "docker:pull:node": "madrun docker:pull:node", + "docker:pull:alpine": "madrun docker:pull:alpine", + "docker:push": "madrun docker:push", + "docker:push:latest": "madrun docker:push:latest", + "docker:push:alpine": "madrun docker:push:alpine", + "docker:push:alpine:latest": "madrun docker:push:alpine:latest", + "docker:build": "madrun docker:build", + "docker:build:alpine": "madrun docker:build:alpine", "docker": "madrun docker", "docker-ci": "madrun docker-ci", + "docker-login": "madrun docker-login", + "docker:alpine": "madrun docker:alpine", + "docker:tag": "madrun docker:tag", + "docker:tag:alpine": "madrun docker:tag:alpine", + "docker:rm:version": "madrun docker:rm:version", + "docker:rm:latest": "madrun docker:rm:latest", + "docker:rm:alpine": "madrun docker:rm:alpine", + "docker:rm:latest-alpine": "madrun docker:rm:latest-alpine", + "docker:rm-old": "madrun docker:rm-old", "coverage": "madrun coverage", "report": "madrun report", + "6to5": "madrun 6to5", + "6to5:client": "madrun 6to5:client", + "6to5:client:dev": "madrun 6to5:client:dev", + "pre6to5:client": "madrun pre6to5:client", + "pre6to5:client:dev": "madrun pre6to5:client:dev", "watch:client": "madrun watch:client", "watch:client:dev": "madrun watch:client:dev", "watch:server": "madrun watch:server", "watch:lint": "madrun watch:lint", - "watch:lint:client": "madrun watch:lint:client", - "watch:lint:server": "madrun watch:lint:server", "watch:test": "madrun watch:test", "watch:test:client": "madrun watch:test:client", "watch:test:server": "madrun watch:test:server", + "watch:coverage": "madrun watch:coverage", "build": "madrun build", "build:client": "madrun build:client", "build:client:dev": "madrun build:client:dev", - "heroku-postbuild": "madrun 6to5:client", + "heroku-postbuild": "madrun heroku-postbuild", "putout": "madrun putout" }, "directories": { From 551fc98498c4b1d59aaf36aa2cc9f64bd9b84572 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Mon, 22 Jul 2019 20:35:04 +0300 Subject: [PATCH 0105/1728] fix(client) load --- client/dom/events/index.js | 4 ++-- client/load-module.js | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/client/dom/events/index.js b/client/dom/events/index.js index d4ca0128..57267f9a 100644 --- a/client/dom/events/index.js +++ b/client/dom/events/index.js @@ -62,9 +62,9 @@ function EventsProto() { break; case 'array': - for (const eventName of eventName) { + for (const name of eventName) { parseArgs( - eventName, + name, element, listener, callback diff --git a/client/load-module.js b/client/load-module.js index bade6710..495cad84 100644 --- a/client/load-module.js +++ b/client/load-module.js @@ -20,8 +20,9 @@ module.exports = function loadModule(params) { const { path, - name = path && noJS(pascalCase(path)), } = params; + + const name = path && noJS(pascalCase(path)); const doBefore = params.dobefore; if (CloudCmd[name]) From a6c7d443ae962dea191752f6a4f7146e36571fe9 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Mon, 22 Jul 2019 20:42:09 +0300 Subject: [PATCH 0106/1728] chore(cloudcmd) lint --- .eslintrc.js | 8 +++----- client/client.js | 4 ++-- client/load-module.js | 4 +--- client/modules/konsole.js | 2 +- client/modules/menu.js | 4 ++-- common/btoa.js | 2 -- madrun.js | 1 + 7 files changed, 10 insertions(+), 15 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index 62b14e6c..be18c172 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -1,6 +1,9 @@ 'use strict'; module.exports = { + env: { + browser: true, + }, rules: { 'no-console': 0, }, @@ -19,10 +22,5 @@ module.exports = { extends: [ 'plugin:node/recommended', ], - }, { - files: ['client', 'static'], - env: { - browser: true, - }, }], }; diff --git a/client/client.js b/client/client.js index ad911e33..8fd3ccf6 100644 --- a/client/client.js +++ b/client/client.js @@ -243,8 +243,8 @@ function CloudCmdProto(DOM) { const showLoad = Images.show.load; const doBefore = { - 'edit': showLoad, - 'menu': showLoad, + edit: showLoad, + menu: showLoad, }; const load = (name, path, dobefore) => { diff --git a/client/load-module.js b/client/load-module.js index 495cad84..dffcf3f3 100644 --- a/client/load-module.js +++ b/client/load-module.js @@ -18,9 +18,7 @@ module.exports = function loadModule(params) { if (!params) return; - const { - path, - } = params; + const {path} = params; const name = path && noJS(pascalCase(path)); const doBefore = params.dobefore; diff --git a/client/modules/konsole.js b/client/modules/konsole.js index 0683ef09..86b8c9c2 100644 --- a/client/modules/konsole.js +++ b/client/modules/konsole.js @@ -105,7 +105,7 @@ const create = async () => { CloudCmd.on('active-dir', config.if('syncConsolePath', cd(konsole.handler))); konsole.addShortCuts({ - 'P': () => { + P: () => { const command = konsole.getPromptText(); const path = DOM.getCurrentDirPath(); diff --git a/client/modules/menu.js b/client/modules/menu.js index 5616400c..ff9b405c 100644 --- a/client/modules/menu.js +++ b/client/modules/menu.js @@ -117,8 +117,8 @@ function getMenuData(isAuth) { const menu = { 'Paste': Buffer.paste, 'New': { - 'File': DOM.promptNewFile, - 'Directory': DOM.promptNewDir, + File: DOM.promptNewFile, + Directory: DOM.promptNewDir, }, 'Upload': () => { CloudCmd.Upload.show(); diff --git a/common/btoa.js b/common/btoa.js index 0293ebbc..bf26630b 100644 --- a/common/btoa.js +++ b/common/btoa.js @@ -1,7 +1,5 @@ 'use strict'; -/* global btoa */ - module.exports = (str) => { if (typeof btoa === 'function') return btoa(str); diff --git a/madrun.js b/madrun.js index e87dcf1c..e17d6493 100644 --- a/madrun.js +++ b/madrun.js @@ -11,6 +11,7 @@ const {eslint} = predefined; const names = [ 'bin/cloudcmd.js', + 'client', 'common', 'server', 'test', From 74ee33ee4c90360da7a4c08ed04c2acf74d4ce38 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Tue, 23 Jul 2019 15:18:44 +0300 Subject: [PATCH 0107/1728] chore(travis) disable cache for npm --- .travis.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.travis.yml b/.travis.yml index 5306856d..474e137f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,6 +4,9 @@ node_js: - 10 - 8 +cache: + npm: false + matrix: allow_failures: - os: windows From 96cb2875c011c818f1b13246e93dda36656379bf Mon Sep 17 00:00:00 2001 From: fossabot Date: Wed, 3 Jul 2019 02:17:59 -0700 Subject: [PATCH 0108/1728] docs(readme) add license scan report and status Signed-off-by: fossabot --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index 6232c89f..0fabb1bc 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Cloud Commander v12.6.2 [![Build Status][BuildStatusIMGURL]][BuildStatusURL] [![Now status][BuildAppveyorIMGURL]][BuildAppveyorURL] [![Codacy][CodacyIMG]][CodacyURL] [![Gitter][GitterIMGURL]][GitterURL] [![OpenCollective](https://opencollective.com/cloudcmd/backers/badge.svg)](#backers) [![OpenCollective](https://opencollective.com/cloudcmd/sponsors/badge.svg)](#sponsors) +# Cloud Commander v12.6.2 [![Build Status][BuildStatusIMGURL]][BuildStatusURL] [![Now status][BuildAppveyorIMGURL]][BuildAppveyorURL] [![Codacy][CodacyIMG]][CodacyURL] [![Gitter][GitterIMGURL]][GitterURL] [![OpenCollective](https://opencollective.com/cloudcmd/backers/badge.svg)](#backers) [![OpenCollective](https://opencollective.com/cloudcmd/sponsors/badge.svg)](#sponsors) [![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fcoderaiser%2Fcloudcmd.svg?type=shield)](https://app.fossa.io/projects/git%2Bgithub.com%2Fcoderaiser%2Fcloudcmd?ref=badge_shield) ### [Main][MainURL] [Blog][BlogURL] Live([Heroku][HerokuURL], [Now][NowURL]) @@ -238,4 +238,3 @@ Become a sponsor and get your logo on our README on Github with a link to your s ## License MIT - From 4b98fa70c0c36c1b1d774edf56f9303e7b55d9d5 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Wed, 24 Jul 2019 13:29:58 +0300 Subject: [PATCH 0109/1728] docs(readme) rm open collective --- README.md | 70 +------------------------------------------------------ 1 file changed, 1 insertion(+), 69 deletions(-) diff --git a/README.md b/README.md index 0fabb1bc..44d7fafc 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Cloud Commander v12.6.2 [![Build Status][BuildStatusIMGURL]][BuildStatusURL] [![Now status][BuildAppveyorIMGURL]][BuildAppveyorURL] [![Codacy][CodacyIMG]][CodacyURL] [![Gitter][GitterIMGURL]][GitterURL] [![OpenCollective](https://opencollective.com/cloudcmd/backers/badge.svg)](#backers) [![OpenCollective](https://opencollective.com/cloudcmd/sponsors/badge.svg)](#sponsors) [![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fcoderaiser%2Fcloudcmd.svg?type=shield)](https://app.fossa.io/projects/git%2Bgithub.com%2Fcoderaiser%2Fcloudcmd?ref=badge_shield) +# Cloud Commander v12.6.2 [![Build Status][BuildStatusIMGURL]][BuildStatusURL] [![Now status][BuildAppveyorIMGURL]][BuildAppveyorURL] [![Codacy][CodacyIMG]][CodacyURL] [![Gitter][GitterIMGURL]][GitterURL] [![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fcoderaiser%2Fcloudcmd.svg?type=shield)](https://app.fossa.io/projects/git%2Bgithub.com%2Fcoderaiser%2Fcloudcmd?ref=badge_shield) ### [Main][MainURL] [Blog][BlogURL] Live([Heroku][HerokuURL], [Now][NowURL]) @@ -167,74 +167,6 @@ There is a lot ways to be involved in `Cloud Commander` development: - if you fixed a bug, typo or implemented new feature [create pull request](https://github.com/coderaiser/cloudcmd/compare "Create pull request"); - if you know languages you can help with [site translations](https://github.com/coderaiser/cloudcmd/wiki "Cloud Commander community wiki"); -## Backers -Support us with a monthly donation and help us continue our activities. [[Become a backer](https://opencollective.com/cloudcmd#backer)] - -[![](https://opencollective.com/cloudcmd/backer/0/avatar.svg)](https://opencollective.com/cloudcmd/backer/0/website) -[![](https://opencollective.com/cloudcmd/backer/1/avatar.svg)](https://opencollective.com/cloudcmd/backer/1/website) -[![](https://opencollective.com/cloudcmd/backer/2/avatar.svg)](https://opencollective.com/cloudcmd/backer/2/website) -[![](https://opencollective.com/cloudcmd/backer/3/avatar.svg)](https://opencollective.com/cloudcmd/backer/3/website) -[![](https://opencollective.com/cloudcmd/backer/4/avatar.svg)](https://opencollective.com/cloudcmd/backer/4/website) -[![](https://opencollective.com/cloudcmd/backer/5/avatar.svg)](https://opencollective.com/cloudcmd/backer/5/website) -[![](https://opencollective.com/cloudcmd/backer/6/avatar.svg)](https://opencollective.com/cloudcmd/backer/6/website) -[![](https://opencollective.com/cloudcmd/backer/7/avatar.svg)](https://opencollective.com/cloudcmd/backer/7/website) -[![](https://opencollective.com/cloudcmd/backer/8/avatar.svg)](https://opencollective.com/cloudcmd/backer/8/website) -[![](https://opencollective.com/cloudcmd/backer/9/avatar.svg)](https://opencollective.com/cloudcmd/backer/9/website) -[![](https://opencollective.com/cloudcmd/backer/10/avatar.svg)](https://opencollective.com/cloudcmd/backer/10/website) -[![](https://opencollective.com/cloudcmd/backer/11/avatar.svg)](https://opencollective.com/cloudcmd/backer/11/website) -[![](https://opencollective.com/cloudcmd/backer/12/avatar.svg)](https://opencollective.com/cloudcmd/backer/12/website) -[![](https://opencollective.com/cloudcmd/backer/13/avatar.svg)](https://opencollective.com/cloudcmd/backer/13/website) -[![](https://opencollective.com/cloudcmd/backer/14/avatar.svg)](https://opencollective.com/cloudcmd/backer/14/website) -[![](https://opencollective.com/cloudcmd/backer/15/avatar.svg)](https://opencollective.com/cloudcmd/backer/15/website) -[![](https://opencollective.com/cloudcmd/backer/16/avatar.svg)](https://opencollective.com/cloudcmd/backer/16/website) -[![](https://opencollective.com/cloudcmd/backer/17/avatar.svg)](https://opencollective.com/cloudcmd/backer/17/website) -[![](https://opencollective.com/cloudcmd/backer/18/avatar.svg)](https://opencollective.com/cloudcmd/backer/18/website) -[![](https://opencollective.com/cloudcmd/backer/19/avatar.svg)](https://opencollective.com/cloudcmd/backer/19/website) -[![](https://opencollective.com/cloudcmd/backer/20/avatar.svg)](https://opencollective.com/cloudcmd/backer/20/website) -[![](https://opencollective.com/cloudcmd/backer/21/avatar.svg)](https://opencollective.com/cloudcmd/backer/21/website) -[![](https://opencollective.com/cloudcmd/backer/22/avatar.svg)](https://opencollective.com/cloudcmd/backer/22/website) -[![](https://opencollective.com/cloudcmd/backer/23/avatar.svg)](https://opencollective.com/cloudcmd/backer/23/website) -[![](https://opencollective.com/cloudcmd/backer/24/avatar.svg)](https://opencollective.com/cloudcmd/backer/24/website) -[![](https://opencollective.com/cloudcmd/backer/25/avatar.svg)](https://opencollective.com/cloudcmd/backer/25/website) -[![](https://opencollective.com/cloudcmd/backer/26/avatar.svg)](https://opencollective.com/cloudcmd/backer/26/website) -[![](https://opencollective.com/cloudcmd/backer/27/avatar.svg)](https://opencollective.com/cloudcmd/backer/27/website) -[![](https://opencollective.com/cloudcmd/backer/28/avatar.svg)](https://opencollective.com/cloudcmd/backer/28/website) -[![](https://opencollective.com/cloudcmd/backer/29/avatar.svg)](https://opencollective.com/cloudcmd/backer/29/website) - -## Sponsors -Become a sponsor and get your logo on our README on Github with a link to your site. [[Become a sponsor](https://opencollective.com/cloudcmd#sponsor)] - -[![](https://opencollective.com/cloudcmd/sponsor/0/avatar.svg)](https://opencollective.com/cloudcmd/sponsor/0/website) -[![](https://opencollective.com/cloudcmd/sponsor/1/avatar.svg)](https://opencollective.com/cloudcmd/sponsor/1/website) -[![](https://opencollective.com/cloudcmd/sponsor/2/avatar.svg)](https://opencollective.com/cloudcmd/sponsor/2/website) -[![](https://opencollective.com/cloudcmd/sponsor/3/avatar.svg)](https://opencollective.com/cloudcmd/sponsor/3/website) -[![](https://opencollective.com/cloudcmd/sponsor/4/avatar.svg)](https://opencollective.com/cloudcmd/sponsor/4/website) -[![](https://opencollective.com/cloudcmd/sponsor/5/avatar.svg)](https://opencollective.com/cloudcmd/sponsor/5/website) -[![](https://opencollective.com/cloudcmd/sponsor/6/avatar.svg)](https://opencollective.com/cloudcmd/sponsor/6/website) -[![](https://opencollective.com/cloudcmd/sponsor/7/avatar.svg)](https://opencollective.com/cloudcmd/sponsor/7/website) -[![](https://opencollective.com/cloudcmd/sponsor/8/avatar.svg)](https://opencollective.com/cloudcmd/sponsor/8/website) -[![](https://opencollective.com/cloudcmd/sponsor/9/avatar.svg)](https://opencollective.com/cloudcmd/sponsor/9/website) -[![](https://opencollective.com/cloudcmd/sponsor/10/avatar.svg)](https://opencollective.com/cloudcmd/sponsor/10/website) -[![](https://opencollective.com/cloudcmd/sponsor/11/avatar.svg)](https://opencollective.com/cloudcmd/sponsor/11/website) -[![](https://opencollective.com/cloudcmd/sponsor/12/avatar.svg)](https://opencollective.com/cloudcmd/sponsor/12/website) -[![](https://opencollective.com/cloudcmd/sponsor/13/avatar.svg)](https://opencollective.com/cloudcmd/sponsor/13/website) -[![](https://opencollective.com/cloudcmd/sponsor/14/avatar.svg)](https://opencollective.com/cloudcmd/sponsor/14/website) -[![](https://opencollective.com/cloudcmd/sponsor/15/avatar.svg)](https://opencollective.com/cloudcmd/sponsor/15/website) -[![](https://opencollective.com/cloudcmd/sponsor/16/avatar.svg)](https://opencollective.com/cloudcmd/sponsor/16/website) -[![](https://opencollective.com/cloudcmd/sponsor/17/avatar.svg)](https://opencollective.com/cloudcmd/sponsor/17/website) -[![](https://opencollective.com/cloudcmd/sponsor/18/avatar.svg)](https://opencollective.com/cloudcmd/sponsor/18/website) -[![](https://opencollective.com/cloudcmd/sponsor/19/avatar.svg)](https://opencollective.com/cloudcmd/sponsor/19/website) -[![](https://opencollective.com/cloudcmd/sponsor/20/avatar.svg)](https://opencollective.com/cloudcmd/sponsor/20/website) -[![](https://opencollective.com/cloudcmd/sponsor/21/avatar.svg)](https://opencollective.com/cloudcmd/sponsor/21/website) -[![](https://opencollective.com/cloudcmd/sponsor/22/avatar.svg)](https://opencollective.com/cloudcmd/sponsor/22/website) -[![](https://opencollective.com/cloudcmd/sponsor/23/avatar.svg)](https://opencollective.com/cloudcmd/sponsor/23/website) -[![](https://opencollective.com/cloudcmd/sponsor/24/avatar.svg)](https://opencollective.com/cloudcmd/sponsor/24/website) -[![](https://opencollective.com/cloudcmd/sponsor/25/avatar.svg)](https://opencollective.com/cloudcmd/sponsor/25/website) -[![](https://opencollective.com/cloudcmd/sponsor/26/avatar.svg)](https://opencollective.com/cloudcmd/sponsor/26/website) -[![](https://opencollective.com/cloudcmd/sponsor/27/avatar.svg)](https://opencollective.com/cloudcmd/sponsor/27/website) -[![](https://opencollective.com/cloudcmd/sponsor/28/avatar.svg)](https://opencollective.com/cloudcmd/sponsor/28/website) -[![](https://opencollective.com/cloudcmd/sponsor/29/avatar.svg)](https://opencollective.com/cloudcmd/sponsor/29/website) - ## License MIT From ab183d89eb6431130051e2167b9946ed372d7c0c Mon Sep 17 00:00:00 2001 From: coderaiser Date: Wed, 24 Jul 2019 14:29:44 +0300 Subject: [PATCH 0110/1728] docs(help) code example --- HELP.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/HELP.md b/HELP.md index 50e26cae..c7ccb44d 100644 --- a/HELP.md +++ b/HELP.md @@ -673,7 +673,7 @@ const prefix = '/'; const server = http.createServer(app); const socket = io.listen(server, { - path: `{prefix}socket.io` + path: `${prefix}socket.io` }); const config = { From 7c52d622ba49c287aeb53b21355c4186a16ba9a8 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Wed, 24 Jul 2019 14:41:47 +0300 Subject: [PATCH 0111/1728] docs(help) add two config managers example (#250) --- HELP.md | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/HELP.md b/HELP.md index c7ccb44d..290eb77e 100644 --- a/HELP.md +++ b/HELP.md @@ -717,6 +717,48 @@ app.use(prefix, cloudcmd({ server.listen(port); ``` +Here is example with two `Config Managers`: + +```js +const http = require('http'); +const cloudcmd = require('cloudcmd'); +const io = require('socket.io'); +const app = require('express')(); + +const port = 8000; +const prefix1 = '/1'; +const prefix2 = '/2'; + +const {createConfigManager} = cloudcmd; + +const server = http.createServer(app); +const socket1 = io.listen(server, { + path: `${prefix1}/socket.io` +}); + +const socket2 = io.listen(server, { + path: `${prefix2}/socket.io` +}); + +const configManager1 = createConfigManager(); +configManager1('name', '1'); + +const configManager2 = createConfigManager(); +configManager2('name', '2'); + +app.use(prefix1, cloudcmd({ + socket: socket1, + configManager: configManager1, +})); + +app.use(prefix2, cloudcmd({ + socket: socket2, + configManager: configManager2, +})); + +server.listen(port); +``` + If you want to enable authorization, you can pass credentials to Cloud Commander with a config. To generate a password, you can install `criton` with `npm i criton --save`, and use it (or any other way) to generate a hash of a password. ```js From 86417d478199c178a9a204fbde0f288207c3dde4 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Fri, 2 Aug 2019 13:36:12 +0300 Subject: [PATCH 0112/1728] fix(key) chrome keydown event double pass --- client/key/index.js | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/client/key/index.js b/client/key/index.js index bdf4f5bf..d4f99594 100644 --- a/client/key/index.js +++ b/client/key/index.js @@ -40,7 +40,7 @@ function KeyProto() { }; this.bind = () => { - Events.addKey(listener); + Events.addKey(listener, true); Binded = true; }; @@ -57,7 +57,16 @@ function KeyProto() { } function listener(event) { - const {keyCode} = event; + const {body} = document; + const { + keyCode, + target, + } = event; + + // chrome double event pass + if (target != body) + return; + const alt = event.altKey; const ctrl = event.ctrlKey; const shift = event.shiftKey; From 3c87ce0fa36154acdcaf8180c6a7b00737585aa4 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Fri, 2 Aug 2019 13:50:52 +0300 Subject: [PATCH 0113/1728] fix(operation) first copy after startup fails (close #251) --- client/modules/operation/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/modules/operation/index.js b/client/modules/operation/index.js index ff913638..82a0e75d 100644 --- a/client/modules/operation/index.js +++ b/client/modules/operation/index.js @@ -33,7 +33,7 @@ const Operation = {}; let Loaded; -let copyFn = callbackify(RESTful.copy); +let copyFn = callbackify(RESTful.cp); let moveFn = callbackify(RESTful.mv); let deleteFn = callbackify(RESTful.delete); let extractFn = callbackify(RESTful.extract); From a021090dc914597a3c56fbaa0041be0679055b14 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Fri, 2 Aug 2019 13:53:17 +0300 Subject: [PATCH 0114/1728] chore(package) v12.6.3 --- ChangeLog | 19 +++++++++++++++++++ HELP.md | 3 ++- README.md | 2 +- package.json | 2 +- 4 files changed, 23 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index a853d980..280f9747 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,22 @@ +2019.08.02, v12.6.3 + +fix: +- (operation) first copy after startup fails (close #251) +- (key) chrome keydown event double pass +- (client) load +- (cloudcmd) server start when importListen enabled + +feature: +- (cloudcmd) simplify lint +- (package) markdown-it v9.0.0 +- (package) deepmerge v4.0.0 +- (package) yaspeller v6.0.0 +- (package) css-loader v3.0.0 +- (babel) remove unused @babel/plugin-syntax-dynamic-import +- (cloudcmd) rm Promise polyfill +- (package) rm Object.assign polyfill + + 2019.06.06, v12.6.2 fix: diff --git a/HELP.md b/HELP.md index 290eb77e..d70d0791 100644 --- a/HELP.md +++ b/HELP.md @@ -1,4 +1,4 @@ -# Cloud Commander v12.6.2 +# Cloud Commander v12.6.3 ### [Main][MainURL] [Blog][BlogURL] Live(![Heroku][Heroku_LIVE_IMG] [Heroku][HerokuURL], ![Now][NOW_LIVE_IMG] [Now][NowURL]) @@ -961,6 +961,7 @@ There are a lot of ways to be involved in `Cloud Commander` development: Version history --------------- +- *2019.08.02*, **[v12.6.3](//github.com/coderaiser/cloudcmd/releases/tag/v12.6.3)** - *2019.06.06*, **[v12.6.2](//github.com/coderaiser/cloudcmd/releases/tag/v12.6.2)** - *2019.06.04*, **[v12.6.1](//github.com/coderaiser/cloudcmd/releases/tag/v12.6.1)** - *2019.05.31*, **[v12.6.0](//github.com/coderaiser/cloudcmd/releases/tag/v12.6.0)** diff --git a/README.md b/README.md index 44d7fafc..c20bb310 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Cloud Commander v12.6.2 [![Build Status][BuildStatusIMGURL]][BuildStatusURL] [![Now status][BuildAppveyorIMGURL]][BuildAppveyorURL] [![Codacy][CodacyIMG]][CodacyURL] [![Gitter][GitterIMGURL]][GitterURL] [![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fcoderaiser%2Fcloudcmd.svg?type=shield)](https://app.fossa.io/projects/git%2Bgithub.com%2Fcoderaiser%2Fcloudcmd?ref=badge_shield) +# Cloud Commander v12.6.3 [![Build Status][BuildStatusIMGURL]][BuildStatusURL] [![Now status][BuildAppveyorIMGURL]][BuildAppveyorURL] [![Codacy][CodacyIMG]][CodacyURL] [![Gitter][GitterIMGURL]][GitterURL] [![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fcoderaiser%2Fcloudcmd.svg?type=shield)](https://app.fossa.io/projects/git%2Bgithub.com%2Fcoderaiser%2Fcloudcmd?ref=badge_shield) ### [Main][MainURL] [Blog][BlogURL] Live([Heroku][HerokuURL], [Now][NowURL]) diff --git a/package.json b/package.json index 6f00ef30..a50b227f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "cloudcmd", - "version": "12.6.2", + "version": "12.6.3", "author": "coderaiser (https://github.com/coderaiser)", "description": "File manager for the web with console and editor", "homepage": "http://cloudcmd.io", From a3ef3ae60d21aa66e007cbe9baab2edf50a3ded1 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Mon, 5 Aug 2019 18:10:16 +0300 Subject: [PATCH 0115/1728] chore(cloudcmd) lint --- .eslintrc.js | 24 ++++++++++++++++-------- client/dom/upload-files.js | 3 +-- common/cloudfunc.spec.js | 3 +-- madrun.js | 8 +++++--- package.json | 1 + server/rest/index.spec.js | 3 +-- 6 files changed, 25 insertions(+), 17 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index be18c172..9e542834 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -1,12 +1,6 @@ 'use strict'; module.exports = { - env: { - browser: true, - }, - rules: { - 'no-console': 0, - }, extends: [ 'plugin:putout/recommended', ], @@ -15,12 +9,26 @@ module.exports = { 'node', ], overrides: [{ - files: ['server'], + files: ['bin/release.js'], rules: { - 'no-process-exit': 0, + 'no-console': 'off', + 'node/shebang': 'off', }, extends: [ 'plugin:node/recommended', ], + },{ + files: ['bin/cloudcmd.js'], + rules: { + 'no-console': 'off', + }, + extends: [ + 'plugin:node/recommended', + ], + }, { + files: ['{client,common}/**/*.js'], + env: { + browser: true, + }, }], }; diff --git a/client/dom/upload-files.js b/client/dom/upload-files.js index 0b313311..f4f9dc62 100644 --- a/client/dom/upload-files.js +++ b/client/dom/upload-files.js @@ -5,7 +5,6 @@ const {eachSeries} = require('execon'); const wraptile = require('wraptile/legacy'); -const DOM = require('.'); const load = require('./load'); const Images = require('./images'); const {alert} = require('./dialog'); @@ -15,7 +14,7 @@ const {FS} = require('../../common/cloudfunc'); const onEnd = wraptile(_onEnd); const loadFile = wraptile(_loadFile); -const {getCurrentDirPath: getPathWhenRootEmpty} = DOM; +const {getCurrentDirPath: getPathWhenRootEmpty} = require('.'); module.exports = (dir, files) => { if (!files) { diff --git a/common/cloudfunc.spec.js b/common/cloudfunc.spec.js index c72c0a80..217d9ca5 100644 --- a/common/cloudfunc.spec.js +++ b/common/cloudfunc.spec.js @@ -1,8 +1,7 @@ 'use strict'; const test = require('supertape'); -const cloudfunc = require('./cloudfunc'); -const {_getSize} = cloudfunc; +const {_getSize} = require('./cloudfunc'); test('cloudfunc: getSize: dir', (t) => { const type = 'directory'; diff --git a/madrun.js b/madrun.js index e17d6493..d6c23998 100644 --- a/madrun.js +++ b/madrun.js @@ -7,7 +7,6 @@ const { } = require('madrun'); const {version} = require('./package'); -const {eslint} = predefined; const names = [ 'bin/cloudcmd.js', @@ -24,16 +23,19 @@ const names = [ '{client,server,common}/**/*.spec.js', ]; +const {putout} = predefined; + module.exports = { 'start': () => 'node bin/cloudcmd.js', 'start:dev': () => `NODE_ENV=development ${run('start')}`, 'build:start': () => run(['build:client', 'start']), 'build:start:dev': () => run(['build:client:dev', 'start:dev']), 'lint:all': () => run(['lint', 'lint:css', 'spell']), - 'lint': () => eslint({names}), + 'lint': () => putout(names), 'lint:css': () => 'stylelint css/*.css', 'spell': () => 'yaspeller .', - 'fix:lint': () => run('lint', '--fix'), + 'fix:lint': () => run(['lint', 'lint:css'], '--fix'), + 'lint:progress': () => run('lint', '-f progress'), 'test': () => `tape 'test/**/*.js' '{client,static,common,server}/**/*.spec.js'`, 'test:client': () => `tape 'test/client/**/*.js`, 'test:server': () => `tape 'test/**/*.js' 'server/**/*.spec.js' 'common/**/*.spec.js'`, diff --git a/package.json b/package.json index a50b227f..eaa227de 100644 --- a/package.json +++ b/package.json @@ -54,6 +54,7 @@ "lint:css": "madrun lint:css", "spell": "madrun spell", "fix:lint": "madrun fix:lint", + "lint:progress": "madrun lint:progress", "test": "madrun test", "test:client": "madrun test:client", "test:server": "madrun test:server", diff --git a/server/rest/index.spec.js b/server/rest/index.spec.js index 58e215a4..c9d4ff77 100644 --- a/server/rest/index.spec.js +++ b/server/rest/index.spec.js @@ -3,14 +3,13 @@ const test = require('supertape'); const tryToCatch = require('try-to-catch'); -const rest = require('.'); const { _formatMsg, _getWin32RootMsg, _isRootWin32, _isRootAll, _onPUT, -} = rest; +} = require('.'); test('rest: formatMsg', (t) => { const result = _formatMsg('hello', 'world'); From e75948ec016e8d035ac690d04d0531b1e1255790 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Wed, 7 Aug 2019 13:43:10 +0300 Subject: [PATCH 0116/1728] feature(package) style-loader v1.0.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index eaa227de..fc17d43f 100644 --- a/package.json +++ b/package.json @@ -208,7 +208,7 @@ "serve-once": "^1.5.0", "serviceworker-webpack-plugin": "^1.0.1", "smalltalk": "^3.4.0", - "style-loader": "^0.23.0", + "style-loader": "^1.0.0", "stylelint": "^10.0.0", "stylelint-config-standard": "^18.0.0", "supermenu": "^2.1.2", From 66e0acbb8f7ab10fc9d6e220809a7156d07e06ed Mon Sep 17 00:00:00 2001 From: coderaiser Date: Mon, 12 Aug 2019 16:54:34 +0300 Subject: [PATCH 0117/1728] feature(package) putout v5.2.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index fc17d43f..9ef82879 100644 --- a/package.json +++ b/package.json @@ -200,7 +200,7 @@ "optimize-css-assets-webpack-plugin": "^5.0.0", "philip": "^2.0.0", "place": "^1.1.4", - "putout": "^4.23.0", + "putout": "^5.2.1", "readjson": "^1.1.3", "request": "^2.76.0", "rimraf": "^2.5.4", From b93e759ba694d5f27c31765fde683eb7f5a8a8b6 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Wed, 14 Aug 2019 15:15:45 +0300 Subject: [PATCH 0118/1728] fix(view) getMediaElement: play video/audio --- client/modules/view.js | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/client/modules/view.js b/client/modules/view.js index 00120ee9..75043da8 100644 --- a/client/modules/view.js +++ b/client/modules/view.js @@ -296,12 +296,9 @@ async function getMediaElement(src) { return [null, element]; } -function check(src, callback) { +function check(src) { if (typeof src !== 'string') throw Error('src should be a string!'); - - if (typeof callback !== 'function') - throw Error('callback should be a function'); } /** From a61eb22b62dcdcb519133d1dd4c2931bb00c4649 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Tue, 14 May 2019 11:33:15 +0300 Subject: [PATCH 0119/1728] feature(cloudcmd) remove plugins --- HELP.md | 5 -- README.md | 5 -- client/client.js | 8 --- server/cloudcmd.js | 20 +------- server/cloudcmd.spec.js | 16 ------ server/plugins.js | 24 --------- server/plugins.spec.js | 105 ---------------------------------------- 7 files changed, 2 insertions(+), 181 deletions(-) delete mode 100644 server/plugins.js delete mode 100644 server/plugins.spec.js diff --git a/HELP.md b/HELP.md index d70d0791..db279b6f 100644 --- a/HELP.md +++ b/HELP.md @@ -680,10 +680,6 @@ const config = { name: 'cloudcmd :)' }; -const plugins = [ - __dirname + '/plugin.js' -]; - const filePicker = { data: { FilePicker: { @@ -709,7 +705,6 @@ const configManager = createConfigManager({ app.use(prefix, cloudcmd({ socket, // used by Config, Edit (optional) and Console (required) config, // config data (optional) - plugins, // DEPRECATED, use User Menu instead modules, // optional configManager, // optional )); diff --git a/README.md b/README.md index c20bb310..79cab258 100644 --- a/README.md +++ b/README.md @@ -90,10 +90,6 @@ const config = { name: 'cloudcmd :)', }; -const plugins = [ - __dirname + '/plugin.js' -]; - const filePicker = { data: { FilePicker: { @@ -119,7 +115,6 @@ const configManager = createConfigManager({ app.use(prefix, cloudcmd({ socket, // used by Config, Edit (optional) and Console (required) config, // config data (optional) - plugins, // DEPRECATED, use User Menu instead modules, // optional configManager, // optional })); diff --git a/client/client.js b/client/client.js index 8fd3ccf6..dacecc3b 100644 --- a/client/client.js +++ b/client/client.js @@ -141,7 +141,6 @@ function CloudCmdProto(DOM) { const func = bind(exec.series, [ initModules, baseInit, - loadPlugins, loadStyle, exec.with(CloudCmd.route, location.hash), ], noop); @@ -182,13 +181,6 @@ function CloudCmdProto(DOM) { load.css(name, callback); } - function loadPlugins(callback) { - const {prefix} = CloudCmd; - const plugins = prefix + '/plugins.js'; - - load.js(plugins, callback); - } - this.route = (path) => { const query = path.split('/'); diff --git a/server/cloudcmd.js b/server/cloudcmd.js index 03fa26eb..ad832214 100644 --- a/server/cloudcmd.js +++ b/server/cloudcmd.js @@ -20,7 +20,6 @@ const rest = require(DIR + 'rest'); const route = require(DIR + 'route'); const validate = require(DIR + 'validate'); const prefixer = require(DIR + 'prefixer'); -const pluginer = require(DIR + 'plugins'); const terminal = require(DIR + 'terminal'); const distribute = require(DIR + 'distribute'); @@ -53,15 +52,10 @@ module.exports = (params) => { configPath, }); - const { - modules, - plugins, - } = p; + const {modules} = p; const keys = Object.keys(options); - checkPlugins(plugins); - for (const name of keys) { let value = options[name]; @@ -90,7 +84,6 @@ module.exports = (params) => { }); return cloudcmd({ - plugins, modules, config, }); @@ -181,7 +174,7 @@ function listen({prefixSocket, socket, config}) { distribute.export(config, socket); } -function cloudcmd({plugins, modules, config}) { +function cloudcmd({modules, config}) { const online = apart(config, 'online'); const cache = false; const diff = apart(config, 'diff'); @@ -256,7 +249,6 @@ function cloudcmd({plugins, modules, config}) { html: defaultHtml, }), - pluginer(plugins), ponseStatic, ]); @@ -297,11 +289,3 @@ function setSW(req, res, next) { next(); } -function checkPlugins(plugins) { - if (typeof plugins === 'undefined') - return; - - if (!Array.isArray(plugins)) - throw Error('plugins should be an array!'); -} - diff --git a/server/cloudcmd.spec.js b/server/cloudcmd.spec.js index 0e7533b0..ae4208db 100644 --- a/server/cloudcmd.spec.js +++ b/server/cloudcmd.spec.js @@ -23,22 +23,6 @@ const {request} = require('serve-once')(cloudcmd, { }, }); -test('cloudcmd: args: no', (t) => { - const fn = () => cloudcmd(); - - t.doesNotThrow(fn, /plugins should be an array!/, 'should throw when plugins not an array'); - t.end(); -}); - -test('cloudcmd: args: plugins: error', (t) => { - const fn = () => cloudcmd({ - plugins: '', - }); - - t.throws(fn, /plugins should be an array!/, 'should throw when plugins not an array'); - t.end(); -}); - test('cloudcmd: defaults: config', (t) => { const configManager = createConfigManager(); diff --git a/server/plugins.js b/server/plugins.js deleted file mode 100644 index a9f4c8bb..00000000 --- a/server/plugins.js +++ /dev/null @@ -1,24 +0,0 @@ -'use strict'; - -const {deprecate} = require('util'); -const currify = require('currify'); -const {readPipe} = require('files-io'); - -module.exports = currify((plugins, req, res, next) => { - if (req.url !== '/plugins.js') - return next(); - - res.setHeader('content-type', 'application/javascript; charset=utf-8'); - - if (!plugins || !plugins.length) - return res.send(''); - - readPlugin(plugins, res); -}); - -const readPlugin = deprecate((plugins, res) => { - readPipe(plugins, res).catch((e) => { - res.end(e.message); - }); -}, 'plugins deprecated. Use user menu instead', 'DEP0001'); - diff --git a/server/plugins.spec.js b/server/plugins.spec.js deleted file mode 100644 index d4ff35d2..00000000 --- a/server/plugins.spec.js +++ /dev/null @@ -1,105 +0,0 @@ -'use strict'; - -const fs = require('fs'); -const test = require('supertape'); -const cloudcmd = require('./cloudcmd'); - -const config = { - auth: false, -}; - -const {request} = require('serve-once')(cloudcmd, { - config, -}); - -test('cloudcmd: plugins: empty', async (t) => { - const plugins = []; - const options = { - plugins, - }; - - const {body} = await request.get('/plugins.js', { - options, - }); - - t.equal(body, '', 'should content be empty'); - t.end(); -}); - -test('cloudcmd: plugins: empty: header', async (t) => { - const plugins = []; - const options = { - plugins, - }; - - const {headers} = await request.get('/plugins.js', { - options, - }); - - const expected = 'application/javascript; charset=utf-8'; - - t.equal(headers.get('content-type'), expected, 'should content be empty'); - t.end(); -}); - -test('cloudcmd: plugins: one', async (t) => { - const plugins = [ - __filename, - ]; - - const options = { - plugins, - }; - - const {body} = await request.get('/plugins.js', { - options, - }); - - const file = fs.readFileSync(__filename, 'utf8'); - - t.equal(body, file, 'should return file plugin content'); - t.end(); -}); - -test('cloudcmd: plugins: one', async (t) => { - const plugins = [ - __filename, - ]; - - const options = { - plugins, - }; - - const {headers} = await request.get('/plugins.js', { - options, - }); - - const expected = 'application/javascript; charset=utf-8'; - - t.equal(headers.get('content-type'), expected, 'should content be empty'); - t.end(); -}); - -test('cloudcmd: plugins: load error', async (t) => { - const noEntry = __filename + Math.random(); - const plugins = [ - __filename, - noEntry, - ]; - - const msg = `ENOENT: no such file or directory, open '${noEntry}'`; - - const options = { - plugins, - }; - - const {body} = await request.get('/plugins.js', { - options, - }); - - const file = fs.readFileSync(__filename, 'utf8') + msg; - - t.equal(body, file, 'should return file plugin content'); - t.end(); -}); - From a8e679bf036b22b4c14489f469cc4da006ed4511 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Tue, 14 May 2019 18:01:46 +0300 Subject: [PATCH 0120/1728] feature(cloudcmd) only user menu on f2 --- HELP.md | 3 +-- client/key/index.js | 5 +---- client/listeners/index.js | 5 +---- html/index.html | 1 - json/config.json | 3 +-- server/route.js | 8 -------- server/route.spec.js | 30 ------------------------------ 7 files changed, 4 insertions(+), 51 deletions(-) diff --git a/HELP.md b/HELP.md index db279b6f..309616e0 100644 --- a/HELP.md +++ b/HELP.md @@ -164,7 +164,7 @@ Hot keys |Key |Operation |:----------------------|:-------------------------------------------- | `F1` | help -| `F2` | rename or show `user menu` +| `F2` | show `user menu` | `F3` | view, change directory | `Shift + F3` | view as markdown | `F4` | edit @@ -466,7 +466,6 @@ Some config options can be overridden with environment variables, such as: ### User Menu -You can enable `user menu` with help of a flag `--user-menu` (bear in mind that file rename using `F2` will be disabled, but you can use `Shift` + `F6` or `F2` + `F2`). When you press `F2` Cloud Commander will read a file `.cloudcmd.menu.js` by walking up parent directories, if can't read it will try to read `~/.cloudcmd.menu.js`. Let's consider example `user menu` works file: diff --git a/client/key/index.js b/client/key/index.js index d4f99594..e530c81d 100644 --- a/client/key/index.js +++ b/client/key/index.js @@ -195,10 +195,7 @@ function KeyProto() { break; case Key.F2: - if (CloudCmd.config('userMenu')) - return CloudCmd.UserMenu.show(); - - DOM.renameCurrent(current); + CloudCmd.UserMenu.show(); break; case Key.F3: diff --git a/client/listeners/index.js b/client/listeners/index.js index 7c4ec348..c523232d 100644 --- a/client/listeners/index.js +++ b/client/listeners/index.js @@ -142,10 +142,7 @@ module.exports.initKeysPanel = () => { }; function initF2() { - if (CloudCmd.config('userMenu')) - return CloudCmd.UserMenu.show(); - - return DOM.renameCurrent(); + CloudCmd.UserMenu.show(); } const getPanel = (side) => { diff --git a/html/index.html b/html/index.html index 7f6edac5..00ae977e 100644 --- a/html/index.html +++ b/html/index.html @@ -20,7 +20,6 @@
{{ fm }}
- diff --git a/json/config.json b/json/config.json index 406a4421..eec170c8 100644 --- a/json/config.json +++ b/json/config.json @@ -43,7 +43,6 @@ "importListen": false, "log": true, "dropbox": false, - "dropboxToken": "", - "userMenu": false + "dropboxToken": "" } diff --git a/server/route.js b/server/route.js index 845dcbbb..0dece5f1 100644 --- a/server/route.js +++ b/server/route.js @@ -111,7 +111,6 @@ function indexProcessing(config, options) { const noConfig = !config('configDialog'); const noConsole = !config('console'); const noTerminal = !config('terminal'); - const noUserMenu = !config('userMenu'); const {panel} = options; let {data} = options; @@ -140,13 +139,6 @@ function indexProcessing(config, options) { data = data .replace('icon-terminal', 'icon-terminal none'); - if (noUserMenu) - data = data - .replace('icon-user-menu', 'icon-user-menu none'); - else - data = data - .replace('icon-rename', 'icon-rename none'); - const left = rendy(Template.panel, { side : 'left', content : panel, diff --git a/server/route.spec.js b/server/route.spec.js index 892fcceb..b2bd808d 100644 --- a/server/route.spec.js +++ b/server/route.spec.js @@ -40,36 +40,6 @@ test('cloudcmd: route: buttons: no console', async (t) => { t.end(); }); -test('cloudcmd: route: buttons: user menu: disabled', async (t) => { - const options = { - config: { - userMenu: false, - }, - }; - - const {body} = await request.get('/', { - options, - }); - - t.ok(/icon-user-menu none/.test(body), 'should hide console'); - t.end(); -}); - -test('cloudcmd: route: buttons: user menu: enabled', async (t) => { - const options = { - config: { - userMenu: true, - }, - }; - - const {body} = await request.get('/', { - options, - }); - - t.ok(/icon-rename none/.test(body), 'should hide console'); - t.end(); -}); - test('cloudcmd: route: buttons: console', async (t) => { const config = { console: true, From a493e5a4d1571491dfd4b5c834b22019e021d49d Mon Sep 17 00:00:00 2001 From: coderaiser Date: Wed, 14 Aug 2019 15:37:37 +0300 Subject: [PATCH 0121/1728] fix(set-listeners) can not continue first error operation error --- client/modules/operation/set-listeners.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/modules/operation/set-listeners.js b/client/modules/operation/set-listeners.js index 2b773050..70eb69df 100644 --- a/client/modules/operation/set-listeners.js +++ b/client/modules/operation/set-listeners.js @@ -73,8 +73,8 @@ module.exports = (options) => (emitter) => { const [cancel] = await Dialog.confirm(error + '\n Continue?'); - if (!cancel) - emitter.continue(); + if (!done && !cancel) + return emitter.continue(); emitter.abort(); progress.remove(); From 1ab5b189dce1aff7b8aa629a50ee23bb408e5eb1 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Wed, 14 Aug 2019 15:42:07 +0300 Subject: [PATCH 0122/1728] chore(workflow) add --- .github/workflows/nodejs.yml | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 .github/workflows/nodejs.yml diff --git a/.github/workflows/nodejs.yml b/.github/workflows/nodejs.yml new file mode 100644 index 00000000..15f55f5e --- /dev/null +++ b/.github/workflows/nodejs.yml @@ -0,0 +1,20 @@ +name: Node CI + +on: [push] + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@master + - name: Use Node.js 12.x + uses: actions/setup-node@v1 + with: + version: 12.x + - name: npm install, build, and test + run: | + npm install + npm run build + npm test From 9f2989fb62634f9534aed141c356ef41a6f4c912 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Wed, 14 Aug 2019 15:49:02 +0300 Subject: [PATCH 0123/1728] chore(package) v13.0.0 --- ChangeLog | 13 +++++++++++++ HELP.md | 3 ++- README.md | 2 +- package.json | 2 +- 4 files changed, 17 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index 280f9747..5cd20104 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,16 @@ +2019.08.14, v13.0.0 + +fix: +- (set-listeners) can not continue first error operation error +- (view) getMediaElement: play video/audio + +feature: +- (cloudcmd) only user menu on f2 +- (cloudcmd) remove plugins +- (package) putout v5.2.1 +- (package) style-loader v1.0.0 + + 2019.08.02, v12.6.3 fix: diff --git a/HELP.md b/HELP.md index 309616e0..b018ebf5 100644 --- a/HELP.md +++ b/HELP.md @@ -1,4 +1,4 @@ -# Cloud Commander v12.6.3 +# Cloud Commander v13.0.0 ### [Main][MainURL] [Blog][BlogURL] Live(![Heroku][Heroku_LIVE_IMG] [Heroku][HerokuURL], ![Now][NOW_LIVE_IMG] [Now][NowURL]) @@ -955,6 +955,7 @@ There are a lot of ways to be involved in `Cloud Commander` development: Version history --------------- +- *2019.08.14*, **[v13.0.0](//github.com/coderaiser/cloudcmd/releases/tag/v13.0.0)** - *2019.08.02*, **[v12.6.3](//github.com/coderaiser/cloudcmd/releases/tag/v12.6.3)** - *2019.06.06*, **[v12.6.2](//github.com/coderaiser/cloudcmd/releases/tag/v12.6.2)** - *2019.06.04*, **[v12.6.1](//github.com/coderaiser/cloudcmd/releases/tag/v12.6.1)** diff --git a/README.md b/README.md index 79cab258..1a5a9098 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Cloud Commander v12.6.3 [![Build Status][BuildStatusIMGURL]][BuildStatusURL] [![Now status][BuildAppveyorIMGURL]][BuildAppveyorURL] [![Codacy][CodacyIMG]][CodacyURL] [![Gitter][GitterIMGURL]][GitterURL] [![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fcoderaiser%2Fcloudcmd.svg?type=shield)](https://app.fossa.io/projects/git%2Bgithub.com%2Fcoderaiser%2Fcloudcmd?ref=badge_shield) +# Cloud Commander v13.0.0 [![Build Status][BuildStatusIMGURL]][BuildStatusURL] [![Now status][BuildAppveyorIMGURL]][BuildAppveyorURL] [![Codacy][CodacyIMG]][CodacyURL] [![Gitter][GitterIMGURL]][GitterURL] [![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fcoderaiser%2Fcloudcmd.svg?type=shield)](https://app.fossa.io/projects/git%2Bgithub.com%2Fcoderaiser%2Fcloudcmd?ref=badge_shield) ### [Main][MainURL] [Blog][BlogURL] Live([Heroku][HerokuURL], [Now][NowURL]) diff --git a/package.json b/package.json index 9ef82879..91f4fe5d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "cloudcmd", - "version": "12.6.3", + "version": "13.0.0", "author": "coderaiser (https://github.com/coderaiser)", "description": "File manager for the web with console and editor", "homepage": "http://cloudcmd.io", From a92948ee7e41790e6668609c3c7018c14cbb2e23 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Wed, 14 Aug 2019 21:30:27 +0300 Subject: [PATCH 0124/1728] fix(cloudcmd) rm --user-menu: always enabled --- HELP.md | 3 --- bin/cloudcmd.js | 3 --- json/help.json | 4 +--- man/cloudcmd.1 | 2 -- 4 files changed, 1 insertion(+), 11 deletions(-) diff --git a/HELP.md b/HELP.md index b018ebf5..dfa117d9 100644 --- a/HELP.md +++ b/HELP.md @@ -109,7 +109,6 @@ Cloud Commander supports the following command-line parameters: | `--dropbox` | enable dropbox integration | `--dropbox-token` | set dropbox token | `--log` | enable logging -| `--user-menu` | enable user menu | `--no-show-config` | do not show config values | `--no-server` | do not start server | `--no-auth` | disable authorization @@ -138,7 +137,6 @@ Cloud Commander supports the following command-line parameters: | `--no-dropbox` | disable dropbox integration | `--no-dropbox-token` | unset dropbox token | `--no-log` | disable logging -| `--no-user-menu` | disable user menu For options not specified by command-line parameters, Cloud Commander then reads configuration data from `~/.cloudcmd.json`. It uses port `8000` by default. @@ -425,7 +423,6 @@ Here's a description of all options: "dropbox" : false, // disable dropbox integration "dropboxToken" : "", // unset dropbox token "log" : true, // logging - "userMenu" : false // do not show user menu } ``` diff --git a/bin/cloudcmd.js b/bin/cloudcmd.js index 306f9ca7..cf887908 100755 --- a/bin/cloudcmd.js +++ b/bin/cloudcmd.js @@ -80,7 +80,6 @@ const args = require('minimist')(argv.slice(2), { 'import-listen', 'log', 'dropbox', - 'user-menu', ], default: { 'server' : true, @@ -119,7 +118,6 @@ const args = require('minimist')(argv.slice(2), { 'one-file-panel': choose(env.bool('one_file_panel'), config('oneFilePanel')), 'confirm-copy': choose(env.bool('confirm_copy'), config('confirmCopy')), 'confirm-move': choose(env.bool('confirm_move'), config('confirmMove')), - 'user-menu': choose(env.bool('user_menu'), config('userMenu')), 'keys-panel': env.bool('keys_panel') || config('keysPanel'), 'import-token': env('import_token') || config('importToken'), 'export-token': env('export_token') || config('exportToken'), @@ -189,7 +187,6 @@ function main() { config('importToken', args['import-token']); config('importListen', args['import-listen']); config('importUrl', args['import-url']); - config('userMenu', args['user-menu']); config('dropbox', args['dropbox']); config('dropboxToken', args['dropbox-token'] || ''); diff --git a/json/help.json b/json/help.json index af6adc1a..e9455868 100644 --- a/json/help.json +++ b/json/help.json @@ -42,7 +42,6 @@ "--dropbox ": "enable dropbox integration", "--dropbox-token ": "set dropbox token", "--log ": "enable logging", - "--user-menu ": "enable user menu", "--no-show-config ": "do not show config values", "--no-server ": "do not start server", "--no-auth ": "disable authorization", @@ -71,6 +70,5 @@ "--no-show-file-name ": "do not show file name in view and edit", "--no-dropbox ": "disable dropbox integration", "--no-dropbox-token ": "unset dropbox token", - "--no-log ": "disable logging", - "--no-user-menu ": "disable user menu" + "--no-log ": "disable logging" } diff --git a/man/cloudcmd.1 b/man/cloudcmd.1 index bed5672a..9db5e7d1 100644 --- a/man/cloudcmd.1 +++ b/man/cloudcmd.1 @@ -65,7 +65,6 @@ programs in browser from any computer, mobile or tablet device. --dropbox enable dropbox integration --dropbox-token set dropbox token --log enable logging - --user-menu enable user menu --no-show-config do not show config values --no-server do not start server --no-auth disable authorization @@ -95,7 +94,6 @@ programs in browser from any computer, mobile or tablet device. --no-dropbox disable dropbox integration --no-dropbox-token unset dropbox token --no-log disable logging - --no-user-menu disable user menu .SH RESOURCES AND DOCUMENTATION From 196ccb29fcf13b89a6f735f091d4ecd8275e5531 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Wed, 14 Aug 2019 21:31:22 +0300 Subject: [PATCH 0125/1728] feature(package) rimraf v3.0.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 91f4fe5d..3a515a91 100644 --- a/package.json +++ b/package.json @@ -203,7 +203,7 @@ "putout": "^5.2.1", "readjson": "^1.1.3", "request": "^2.76.0", - "rimraf": "^2.5.4", + "rimraf": "^3.0.0", "scroll-into-view-if-needed": "^2.2.5", "serve-once": "^1.5.0", "serviceworker-webpack-plugin": "^1.0.1", From ce8eea7b78c2700c2dfa921feb9246be154c78b9 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Wed, 14 Aug 2019 21:39:06 +0300 Subject: [PATCH 0126/1728] chore(package) v13.0.1 --- ChangeLog | 9 +++++++++ HELP.md | 3 ++- README.md | 2 +- package.json | 2 +- 4 files changed, 13 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index 5cd20104..c4615e5a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2019.08.14, v13.0.1 + +fix: +- (cloudcmd) rm --user-menu: always enabled + +feature: +- (package) rimraf v3.0.0 + + 2019.08.14, v13.0.0 fix: diff --git a/HELP.md b/HELP.md index dfa117d9..3d5eeaa4 100644 --- a/HELP.md +++ b/HELP.md @@ -1,4 +1,4 @@ -# Cloud Commander v13.0.0 +# Cloud Commander v13.0.1 ### [Main][MainURL] [Blog][BlogURL] Live(![Heroku][Heroku_LIVE_IMG] [Heroku][HerokuURL], ![Now][NOW_LIVE_IMG] [Now][NowURL]) @@ -952,6 +952,7 @@ There are a lot of ways to be involved in `Cloud Commander` development: Version history --------------- +- *2019.08.14*, **[v13.0.1](//github.com/coderaiser/cloudcmd/releases/tag/v13.0.1)** - *2019.08.14*, **[v13.0.0](//github.com/coderaiser/cloudcmd/releases/tag/v13.0.0)** - *2019.08.02*, **[v12.6.3](//github.com/coderaiser/cloudcmd/releases/tag/v12.6.3)** - *2019.06.06*, **[v12.6.2](//github.com/coderaiser/cloudcmd/releases/tag/v12.6.2)** diff --git a/README.md b/README.md index 1a5a9098..1b3041f7 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Cloud Commander v13.0.0 [![Build Status][BuildStatusIMGURL]][BuildStatusURL] [![Now status][BuildAppveyorIMGURL]][BuildAppveyorURL] [![Codacy][CodacyIMG]][CodacyURL] [![Gitter][GitterIMGURL]][GitterURL] [![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fcoderaiser%2Fcloudcmd.svg?type=shield)](https://app.fossa.io/projects/git%2Bgithub.com%2Fcoderaiser%2Fcloudcmd?ref=badge_shield) +# Cloud Commander v13.0.1 [![Build Status][BuildStatusIMGURL]][BuildStatusURL] [![Now status][BuildAppveyorIMGURL]][BuildAppveyorURL] [![Codacy][CodacyIMG]][CodacyURL] [![Gitter][GitterIMGURL]][GitterURL] [![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fcoderaiser%2Fcloudcmd.svg?type=shield)](https://app.fossa.io/projects/git%2Bgithub.com%2Fcoderaiser%2Fcloudcmd?ref=badge_shield) ### [Main][MainURL] [Blog][BlogURL] Live([Heroku][HerokuURL], [Now][NowURL]) diff --git a/package.json b/package.json index 3a515a91..cb63b789 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "cloudcmd", - "version": "13.0.0", + "version": "13.0.1", "author": "coderaiser (https://github.com/coderaiser)", "description": "File manager for the web with console and editor", "homepage": "http://cloudcmd.io", From b083de710bad6ecff51566976b994f2533cdeb3d Mon Sep 17 00:00:00 2001 From: coderaiser Date: Thu, 15 Aug 2019 23:47:59 +0300 Subject: [PATCH 0127/1728] feature(server) add compress: speed up client side load --- server/server.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/server/server.js b/server/server.js index 601407e8..4937ced7 100644 --- a/server/server.js +++ b/server/server.js @@ -9,6 +9,7 @@ const currify = require('currify'); const squad = require('squad'); const tryToCatch = require('try-to-catch'); const wraptile = require('wraptile'); +const compression = require('compression'); const two = currify((f, a, b) => f(a, b)); const exit = require(DIR_SERVER + 'exit'); @@ -52,6 +53,8 @@ module.exports = async (options, config) => { path: `${prefix}/socket.io`, }); + app.use(compression()); + app.use(prefix, cloudcmd({ config: options, socket: socketServer, From f989880d48637ccf75ba7f52e207ef5cfec64b81 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Thu, 15 Aug 2019 23:48:55 +0300 Subject: [PATCH 0128/1728] fix(key) keys block --- client/key/index.js | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/client/key/index.js b/client/key/index.js index e530c81d..e35ad9de 100644 --- a/client/key/index.js +++ b/client/key/index.js @@ -57,15 +57,7 @@ function KeyProto() { } function listener(event) { - const {body} = document; - const { - keyCode, - target, - } = event; - - // chrome double event pass - if (target != body) - return; + const {keyCode} = event; const alt = event.altKey; const ctrl = event.ctrlKey; From bba2f7b570e9543f1c814c08d92e2891f29dfd08 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Thu, 15 Aug 2019 23:49:08 +0300 Subject: [PATCH 0129/1728] fix(user-menu) hide load on error --- client/modules/user-menu/index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/modules/user-menu/index.js b/client/modules/user-menu/index.js index 249e4e9c..58f3ff1c 100644 --- a/client/modules/user-menu/index.js +++ b/client/modules/user-menu/index.js @@ -47,6 +47,8 @@ async function show() { const res = await fetch(`${CloudCmd.prefix}/api/v1/user-menu?dir=${dirPath}`); const [error, userMenu] = tryCatch(getUserMenu, await res.text()); + Images.hide(); + if (error) return Dialog.alert(`User menu error: ${error.message}`); @@ -74,8 +76,6 @@ async function show() { const afterShow = () => select.focus(); const autoSize = true; - Images.hide(); - CloudCmd.View.show([button, select], { autoSize, afterShow, From 9301506d82089e4159a2e6a8c9c0f751ee7d3487 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Thu, 15 Aug 2019 23:49:50 +0300 Subject: [PATCH 0130/1728] feature(user-menu) add ability to used EcmaScript Modules, improve error handling --- package.json | 3 ++- server/user-menu.js | 38 ++++++++++++++++++++++++++++++-------- 2 files changed, 32 insertions(+), 9 deletions(-) diff --git a/package.json b/package.json index cb63b789..632b0f8d 100644 --- a/package.json +++ b/package.json @@ -111,6 +111,7 @@ "@cloudcmd/read-files-sync": "^2.0.0", "apart": "^2.0.0", "chalk": "^2.0.1", + "compression": "^1.7.4", "console-io": "^10.0.0", "copymitter": "^4.0.2", "criton": "^2.0.0", @@ -144,6 +145,7 @@ "package-json": "^6.0.0", "ponse": "^3.0.0", "pullout": "^3.0.0", + "putout": "^5.5.0", "rendy": "^2.0.0", "restafary": "^6.0.0", "restbox": "^1.0.1", @@ -200,7 +202,6 @@ "optimize-css-assets-webpack-plugin": "^5.0.0", "philip": "^2.0.0", "place": "^1.1.4", - "putout": "^5.2.1", "readjson": "^1.1.3", "request": "^2.76.0", "rimraf": "^3.0.0", diff --git a/server/user-menu.js b/server/user-menu.js index 7f81683c..64b38e2f 100644 --- a/server/user-menu.js +++ b/server/user-menu.js @@ -6,9 +6,12 @@ const fs = require('fs'); const {join} = require('path'); const {promisify} = require('util'); +const tryCatch = require('try-catch'); const tryToCatch = require('try-to-catch'); const currify = require('currify'); const findUp = require('find-up'); +const putout = require('putout'); +const {codeframe} = putout; const readFile = promisify(fs.readFile); @@ -49,19 +52,38 @@ async function onGET({req, res, menuName}) { const homeMenuPath = join(homedir(), menuName); const menuPath = currentMenuPath || homeMenuPath; - const [e, data] = await tryToCatch(readFile, menuPath, 'utf8'); + const [e, source] = await tryToCatch(readFile, menuPath, 'utf8'); - if (!e) - return res - .type('js') - .send(data); - - if (e.code !== 'ENOENT') + if (e && e.code !== 'ENOENT') return res .status(404) .send(e.message); - sendDefaultMenu(res); + if (e) + return sendDefaultMenu(res); + + const [parseError, result] = tryCatch(putout, source, { + plugins: [ + 'convert-esm-to-commonjs', + 'strict-mode', + ], + }); + + if (parseError) + return res + .type('js') + .send(` + throw Error(\`
path: ${menuPath}\n\n${codeframe({
+    error: parseError,
+    source,
+    highlightCode: false,
+})}
+                
\`); + `); + + res + .type('js') + .send(result.code); } function sendDefaultMenu(res) { From 36b8e5903d5b39d058c30c7bf2ff5b118c82bc22 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Fri, 16 Aug 2019 12:13:50 +0300 Subject: [PATCH 0131/1728] feature(user-menu) speed up user menu parsing with help of worker threads --- package.json | 1 + server/server.js | 2 ++ server/user-menu.js | 26 +++++++++++++++++--------- server/user-menu.spec.js | 3 +++ 4 files changed, 23 insertions(+), 9 deletions(-) diff --git a/package.json b/package.json index 632b0f8d..4e3ec8f2 100644 --- a/package.json +++ b/package.json @@ -154,6 +154,7 @@ "socket.io-client": "^2.1.1", "squad": "^3.0.0", "table": "^5.0.2", + "thread-it": "^1.0.1", "try-catch": "^2.0.0", "try-to-catch": "^1.0.2", "tryrequire": "^2.0.1", diff --git a/server/server.js b/server/server.js index 4937ced7..5a622728 100644 --- a/server/server.js +++ b/server/server.js @@ -10,6 +10,7 @@ const squad = require('squad'); const tryToCatch = require('try-to-catch'); const wraptile = require('wraptile'); const compression = require('compression'); +const threadIt = require('thread-it'); const two = currify((f, a, b) => f(a, b)); const exit = require(DIR_SERVER + 'exit'); @@ -21,6 +22,7 @@ const promisifySelf = squad(promisify, bind); const shutdown = wraptile(async (promises) => { console.log('closing cloudcmd...'); await Promise.all(promises); + threadIt.terminate(); process.exit(0); }); diff --git a/server/user-menu.js b/server/user-menu.js index 64b38e2f..318d9158 100644 --- a/server/user-menu.js +++ b/server/user-menu.js @@ -6,12 +6,17 @@ const fs = require('fs'); const {join} = require('path'); const {promisify} = require('util'); -const tryCatch = require('try-catch'); const tryToCatch = require('try-to-catch'); const currify = require('currify'); const findUp = require('find-up'); -const putout = require('putout'); -const {codeframe} = putout; +const threadIt = require('thread-it'); +const {codeframe} = require('putout'); +const putout = threadIt('putout'); + +threadIt.init(); + +// warm up worker cache +transpile(''); const readFile = promisify(fs.readFile); @@ -62,12 +67,7 @@ async function onGET({req, res, menuName}) { if (e) return sendDefaultMenu(res); - const [parseError, result] = tryCatch(putout, source, { - plugins: [ - 'convert-esm-to-commonjs', - 'strict-mode', - ], - }); + const [parseError, result] = await transpile(source); if (parseError) return res @@ -92,3 +92,11 @@ function sendDefaultMenu(res) { }); } +function transpile(source) { + return tryToCatch(putout, source, { + plugins: [ + 'convert-esm-to-commonjs', + 'strict-mode', + ], + }); +} diff --git a/server/user-menu.spec.js b/server/user-menu.spec.js index 0f2f0a3b..2400e404 100644 --- a/server/user-menu.spec.js +++ b/server/user-menu.spec.js @@ -5,6 +5,7 @@ const {join} = require('path'); const test = require('supertape'); const serveOnce = require('serve-once'); +const threadIt = require('thread-it'); const userMenu = require('./user-menu'); const {request} = serveOnce(userMenu); @@ -21,6 +22,8 @@ test('cloudcmd: user menu', async (t) => { options, }); + threadIt.terminate(); + t.equal(userMenuFile, body, 'should equal'); t.end(); }); From eee2cb1b10dc23695eff301fe74d75fd610a9a65 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Fri, 16 Aug 2019 15:22:21 +0300 Subject: [PATCH 0132/1728] docs(help) rm CLOUDCMD_USER_MENU: no longer supported --- HELP.md | 1 - 1 file changed, 1 deletion(-) diff --git a/HELP.md b/HELP.md index 3d5eeaa4..e7e385c7 100644 --- a/HELP.md +++ b/HELP.md @@ -459,7 +459,6 @@ Some config options can be overridden with environment variables, such as: - `CLOUDCMD_IMPORT_TOKEN` - authorization token used to connect to export server - `CLOUDCMD_IMPORT_URL` - url of an import server - `CLOUDCMD_IMPORT_LISTEN`- enable listen on config updates from import server -- `CLOUDCMD_USER_MENU`- enable `user menu` ### User Menu From 7d5b3463ccf8055e28e6b20b37a60d81983a2ce5 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Fri, 16 Aug 2019 17:37:02 +0300 Subject: [PATCH 0133/1728] refactor(client) callbacks -> async --- client/client.js | 57 +++++------ client/dom/buffer.js | 82 ++++++++-------- client/dom/current-file.js | 7 +- client/dom/index.js | 152 +++++++++++++----------------- client/dom/storage.js | 69 +++----------- client/key/index.js | 10 +- client/modules/operation/index.js | 40 ++++---- common/try-to-promise-all.js | 14 +++ common/try-to-promise-all.spec.js | 29 ++++++ 9 files changed, 224 insertions(+), 236 deletions(-) create mode 100644 common/try-to-promise-all.js create mode 100644 common/try-to-promise-all.spec.js diff --git a/client/client.js b/client/client.js index dacecc3b..f411cd39 100644 --- a/client/client.js +++ b/client/client.js @@ -19,18 +19,17 @@ const {unregisterSW} = require('./sw/register'); const jonny = require('jonny/legacy'); const currify = require('currify/legacy'); -const bind = (f, ...a) => () => f(...a); -const noop = () => {}; const noJS = (a) => a.replace(/.js$/, ''); +const loadCSS = promisify(load.css); +const loadJS = promisify(load.js); + const { apiURL, formatMsg, buildFromJSON, } = require('../common/cloudfunc'); -const callbackify = require('../common/callbackify'); - const loadModule = require('./load-module'); inherits(CloudCmdProto, Emitify); @@ -137,19 +136,7 @@ function CloudCmdProto(DOM) { * выполняет весь функционал по * инициализации */ - this.init = (prefix, config) => { - const func = bind(exec.series, [ - initModules, - baseInit, - loadStyle, - exec.with(CloudCmd.route, location.hash), - ], noop); - - const funcBefore = (callback) => { - const src = prefix + CloudCmd.DIRCLIENT_MODULES + 'polyfill.js'; - load.js(src, callback); - }; - + this.init = async (prefix, config) => { CloudCmd.prefix = prefix; CloudCmd.prefixURL = `${prefix}${apiURL}`; CloudCmd.prefixSocket = config.prefixSocket; @@ -171,14 +158,21 @@ function CloudCmdProto(DOM) { if (config.oneFilePanel) CloudCmd.MIN_ONE_PANEL_WIDTH = Infinity; - exec.if(document.body.scrollIntoViewIfNeeded, func, funcBefore); + if (!document.body.scrollIntoViewIfNeeded) + await loadJS(prefix + CloudCmd.DIRCLIENT_MODULES + 'polyfill.js'); + + await initModules(); + await baseInit(); + await loadStyle(); + + CloudCmd.route(location.hash); }; - function loadStyle(callback) { + async function loadStyle() { const {prefix} = CloudCmd; const name = prefix + '/dist/cloudcmd.common.css'; - load.css(name, callback); + await loadCSS(name); } this.route = (path) => { @@ -203,12 +197,12 @@ function CloudCmdProto(DOM) { CloudCmd.execFromModule(module, 'show'); }; - this.logOut = () => { + this.logOut = async () => { const url = CloudCmd.prefix + '/logout'; const error = () => document.location.reload(); const {prefix} = CloudCmd; - DOM.Storage.clear(); + await DOM.Storage.clear(); unregisterSW(prefix); DOM.load.ajax({ url, @@ -216,7 +210,7 @@ function CloudCmdProto(DOM) { }); }; - const initModules = callbackify(async () => { + const initModules = async () => { exec.if(CloudCmd.Key, () => { Key = new CloudCmd.Key(); CloudCmd.Key = Key; @@ -253,9 +247,9 @@ function CloudCmdProto(DOM) { for (const module of modules.local) { load(null, module, doBefore[module]); } - }); + }; - function baseInit(callback) { + async function baseInit() { const files = DOM.getFiles(); CloudCmd.on('current-file', DOM.updateCurrentInfo); @@ -279,15 +273,12 @@ function CloudCmdProto(DOM) { Listeners.initKeysPanel(); if (!CloudCmd.config('dirStorage')) - return callback(); + return; - Storage.get(dirPath, (error, data) => { - if (!data) { - data = getJSONfromFileTable(); - Storage.set(dirPath, data); - } - callback(); - }); + const data = await Storage.get(dirPath); + + if (!data) + await Storage.set(dirPath, getJSONfromFileTable()); } function getPanels() { diff --git a/client/dom/buffer.js b/client/dom/buffer.js index 6d7f05e8..d99429e5 100644 --- a/client/dom/buffer.js +++ b/client/dom/buffer.js @@ -3,8 +3,8 @@ /* global CloudCmd */ const jonny = require('jonny/legacy'); -const exec = require('execon'); +const tryToPromiseAll = require('../../common/try-to-promise-all'); const Storage = require('./storage'); const DOM = require('./'); @@ -58,7 +58,19 @@ function BufferProto() { showMessage('Buffer disabled in config!'); } - function copy() { + async function readBuffer() { + const [e, result] = await tryToPromiseAll([ + Storage.get(COPY), + Storage.get(CUT), + ]); + + return [ + e, + ...result, + ]; + } + + async function copy() { const names = getNames(); const from = Info.dirPath; @@ -67,14 +79,14 @@ function BufferProto() { if (!names.length) return; - Storage.remove(CUT) - .set(COPY, { - from, - names, - }); + await Storage.remove(CUT); + await Storage.set(COPY, { + from, + names, + }); } - function cut() { + async function cut() { const names = getNames(); const from = Info.dirPath; @@ -85,11 +97,10 @@ function BufferProto() { addCutClass(); - Storage - .set(CUT, { - from, - names, - }); + await Storage.set(CUT, { + from, + names, + }); } function clear() { @@ -99,33 +110,28 @@ function BufferProto() { rmCutClass(); } - function paste() { - const copy = Storage.get.bind(Storage, COPY); - const cut = Storage.get.bind(Storage, CUT); + async function paste() { + const [error, cp, ct] = await readBuffer(); - exec.parallel([copy, cut], (error, cp, ct) => { - const opStr = cp ? 'copy' : 'move'; - const opData = cp || ct; - const {Operation} = CloudCmd; - const msg = 'Path is same!'; - const path = Info.dirPath; - - if (!error && !cp && !ct) - error = 'Buffer is empty!'; - - if (error) - return showMessage(error); - - const data = jonny.parse(opData); - data.to = path; - - if (data.from === path) - return showMessage(msg); - - Operation.show(opStr, data); - clear(); - }); + if (error || !cp && !ct) + return showMessage(error || 'Buffer is empty!'); + + const opStr = cp ? 'copy' : 'move'; + const opData = cp || ct; + const {Operation} = CloudCmd; + const msg = 'Path is same!'; + const path = Info.dirPath; + + const data = jonny.parse(opData); + data.to = path; + + if (data.from === path) + return showMessage(msg); + + Operation.show(opStr, data); + clear(); } return Buffer; } + diff --git a/client/dom/current-file.js b/client/dom/current-file.js index b319db57..568297a0 100644 --- a/client/dom/current-file.js +++ b/client/dom/current-file.js @@ -168,7 +168,6 @@ function unsetCurrentFile(currentFile) { */ module.exports.setCurrentFile = (currentFile, options) => { const o = options; - const CENTER = true; const currentFileWas = DOM.getCurrentFile(); if (!currentFile) @@ -203,6 +202,7 @@ module.exports.setCurrentFile = (currentFile, options) => { } /* scrolling to current file */ + const CENTER = true; DOM.scrollIntoViewIfNeeded(currentFile, CENTER); CloudCmd.emit('current-file', currentFile); @@ -212,6 +212,11 @@ module.exports.setCurrentFile = (currentFile, options) => { return DOM; }; +this.setCurrentByName = (name) => { + const current = DOM.getCurrentByName(name); + return DOM.setCurrentFile(current); +}; + /* * set current file by position * diff --git a/client/dom/index.js b/client/dom/index.js index ab54010a..73f49317 100644 --- a/client/dom/index.js +++ b/client/dom/index.js @@ -5,6 +5,7 @@ const itype = require('itype/legacy'); const exec = require('execon'); const jonny = require('jonny/legacy'); +const tryToPromiseAll = require('../../common/try-to-promise-all'); const Util = require('../../common/util'); const callbackify = require('../../common/callbackify'); @@ -26,15 +27,6 @@ const DOM = { ...new CmdProto(), }; -const read = callbackify(async (...args) => { - const [e, data] = await RESTful.read(...args); - - if (e) - throw e; - - return data; -}); - DOM.Images = Images; DOM.load = load; DOM.Files = Files; @@ -262,12 +254,13 @@ function CmdProto() { * @callback * @currentFile */ - this.loadCurrentHash = (callback, currentFile) => { + this.loadCurrentHash = async (currentFile) => { const current = currentFile || DOM.getCurrentFile(); const query = '?hash'; const link = DOM.getCurrentPath(current); - read(link + query, callback); + const [, data] = await RESTful.read(link + query); + return data; }; /** @@ -275,12 +268,13 @@ function CmdProto() { * @callback * @currentFile */ - this.loadCurrentTime = (callback, currentFile) => { + this.loadCurrentTime = async (currentFile) => { const current = currentFile || DOM.getCurrentFile(); const query = '?time'; const link = DOM.getCurrentPath(current); - read(link + query, callback); + const [, data] = await RESTful.read(link + query); + return data; }; /** @@ -314,55 +308,57 @@ function CmdProto() { return owner.textContent; }; + const mixArgs = (f) => (a, b) => f(b, a); + /** * unified way to get current file content * * @param callback * @param currentFile */ - this.getCurrentData = (callback, currentFile) => { - let hash; + this.getCurrentData = callbackify(mixArgs(async (callback, currentFile) => { const {Dialog} = DOM; const Info = DOM.CurrentInfo; const current = currentFile || DOM.getCurrentFile(); const path = DOM.getCurrentPath(current); const isDir = DOM.isCurrentIsDir(current); - const func = (error, data) => { - const ONE_MEGABYTE = 1024 * 1024 * 1024; - - if (!error) { - if (itype.object(data)) - data = jonny.stringify(data); - - const {length} = data; - - if (hash && length < ONE_MEGABYTE) - DOM.saveDataToStorage(path, data, hash); - } - - callback(error, data); - }; - if (Info.name === '..') { Dialog.alert.noFiles(); return callback(Error('No files selected!')); } - if (isDir) - return read(path, func); + if (isDir) { + const [e, data] = await RESTful.read(path); + + if (e) + throw e; + + return data; + } - DOM.checkStorageHash(path, (error, equal, hashNew) => { - if (error) - return callback(error); - - if (equal) - return DOM.getDataFromStorage(path, callback); - - hash = hashNew; - read(path, func); - }); - }; + const [hashNew, hash] = await DOM.checkStorageHash(path); + + if (hash === hashNew) + return await DOM.getDataFromStorage(path); + + let [e, data] = await RESTful.read(path); + + if (e) + return; + + const ONE_MEGABYTE = 1024 * 1024 * 1024; + + if (itype.object(data)) + data = jonny.stringify(data); + + const {length} = data; + + if (hash && length < ONE_MEGABYTE) + await DOM.saveDataToStorage(path, data, hashNew); + + return data; + })); /** * unified way to get RefreshButton @@ -374,11 +370,6 @@ function CmdProto() { return refresh; }; - this.setCurrentByName = (name) => { - const current = DOM.getCurrentByName(name); - return DOM.setCurrentFile(current); - }; - /** * select current file * @param currentFile @@ -530,28 +521,21 @@ function CmdProto() { /** * check storage hash */ - this.checkStorageHash = (name, callback) => { - const {parallel} = exec; + this.checkStorageHash = async (name) => { const nameHash = name + '-hash'; - const getStoreHash = exec.with(Storage.get, nameHash); if (typeof name !== 'string') throw Error('name should be a string!'); - if (typeof callback !== 'function') - throw Error('callback should be a function!'); + const [error, loadHash, storeHash] = await tryToPromiseAll([ + DOM.loadCurrentHash(), + Storage.get(nameHash), + ]); - parallel([DOM.loadCurrentHash, getStoreHash], (error, loadHash, storeHash) => { - let equal; - const isContain = /error/.test(loadHash); - - if (isContain) - error = loadHash; - else if (loadHash === storeHash) - equal = true; - - callback(error, equal, loadHash); - }); + if (error) + throw error; + + return [loadHash, storeHash]; }; /** @@ -562,25 +546,21 @@ function CmdProto() { * @param hash * @param callback */ - this.saveDataToStorage = function(name, data, hash, callback) { + this.saveDataToStorage = async (name, data, hash) => { const isDir = DOM.isCurrentIsDir(); + + if (isDir) + return; + + hash = hash || await DOM.loadCurrentHash(); + const nameHash = name + '-hash'; const nameData = name + '-data'; - if (isDir) - return exec(callback); + await Storage.set(nameHash, hash); + await Storage.set(nameData, data); - exec.if(hash, () => { - Storage.set(nameHash, hash); - Storage.set(nameData, data); - - exec(callback, hash); - }, (callback) => { - DOM.loadCurrentHash((error, loadHash) => { - hash = loadHash; - callback(); - }); - }); + return hash; }; /** @@ -590,7 +570,7 @@ function CmdProto() { * @param data * @param callback */ - this.getDataFromStorage = (name, callback) => { + this.getDataFromStorage = callbackify(async (name, callback) => { const nameHash = name + '-hash'; const nameData = name + '-data'; const isDir = DOM.isCurrentIsDir(); @@ -598,11 +578,13 @@ function CmdProto() { if (isDir) return exec(callback); - exec.parallel([ - exec.with(Storage.get, nameData), - exec.with(Storage.get, nameHash), - ], callback); - }; + const result = Promise.all([ + await Storage.get(nameData), + await Storage.get(nameHash), + ]); + + return result; + }); this.getFM = () => { return DOM.getPanel().parentElement; diff --git a/client/dom/storage.js b/client/dom/storage.js index c1a5fbd4..628bc9bd 100644 --- a/client/dom/storage.js +++ b/client/dom/storage.js @@ -1,20 +1,22 @@ 'use strict'; -const itype = require('itype/legacy'); -const jonny = require('jonny/legacy'); -const exec = require('execon'); -const tryCatch = require('try-catch'); -const setItem = localStorage.setItem.bind(localStorage); - -/** remove element */ -module.exports.remove = (item, callback) => { - localStorage.removeItem(item); - exec(callback, null); - - return module.exports; +module.exports.set = async (name, data) => { + localStorage.setItem(name, data); }; -module.exports.removeMatch = (string, callback) => { +module.exports.get = async (name) => { + return localStorage.getItem(name); +}; + +module.exports.clear = async () => { + localStorage.clear(); +}; + +module.exports.remove = async(item) => { + localStorage.removeItem(item); +}; + +module.exports.removeMatch = (string) => { const reg = RegExp('^' + string + '.*$'); const test = (a) => reg.test(a); const remove = (a) => localStorage.removeItem(a); @@ -22,46 +24,5 @@ module.exports.removeMatch = (string, callback) => { Object.keys(localStorage) .filter(test) .forEach(remove); - - exec(callback); - - return module.exports; -}; - -/** если доступен localStorage и - * в нём есть нужная нам директория - - * записываем данные в него - */ -module.exports.set = (name, data, callback) => { - let str; - let error; - - if (itype.object(data)) - str = jonny.stringify(data); - - if (name) - [error] = tryCatch(setItem, name, str || data); - - exec(callback, error); - - return module.exports; -}; - -/** Если доступен Storage принимаем из него данные*/ -module.exports.get = (name, callback) => { - const ret = localStorage.getItem(name); - - exec(callback, null, ret); - - return module.exports; -}; - -/** функция чистит весь кэш для всех каталогов*/ -module.exports.clear = (callback) => { - localStorage.clear(); - - exec(callback); - - return module.exports; }; diff --git a/client/key/index.js b/client/key/index.js index e35ad9de..906ac963 100644 --- a/client/key/index.js +++ b/client/key/index.js @@ -6,7 +6,6 @@ const Info = DOM.CurrentInfo; const exec = require('execon'); const clipboard = require('@cloudcmd/clipboard'); -const wraptile = require('wraptile/legacy'); const Events = require('../dom/events'); const Buffer = require('../dom/buffer'); @@ -56,7 +55,7 @@ function KeyProto() { return fromCharCode(event.keyIdentifier); } - function listener(event) { + async function listener(event) { const {keyCode} = event; const alt = event.altKey; @@ -85,7 +84,7 @@ function KeyProto() { return setCurrentByChar(char, Chars); Chars([]); - switchKey(event); + await switchKey(event); if (keyCode >= KEY.F1 && keyCode <= KEY.F10) return; @@ -115,7 +114,7 @@ function KeyProto() { return char; } - function switchKey(event) { + async function switchKey(event) { let i; let isSelected; let prev; @@ -483,7 +482,8 @@ function KeyProto() { case Key.D: if (ctrlMeta) { CloudCmd.log('clearing storage...'); - DOM.Storage.clear(wraptile(CloudCmd.log, 'storage cleared')); + await DOM.Storage.clear(); + CloudCmd.log('storage cleared'); event.preventDefault(); } break; diff --git a/client/modules/operation/index.js b/client/modules/operation/index.js index 82a0e75d..97aab7f8 100644 --- a/client/modules/operation/index.js +++ b/client/modules/operation/index.js @@ -412,26 +412,26 @@ async function _processFiles(options, data) { names, }; - operation(files, () => { - DOM.Storage.remove(from, () => { - const { - panel, - panelPassive, - } = Info; - - const setCurrent = () => { - const currentName = name || data.names[0]; - DOM.setCurrentByName(currentName); - }; - - if (!Info.isOnePanel) - CloudCmd.refresh({ - panel: panelPassive, - noCurrent: true, - }); - - CloudCmd.refresh({panel}, setCurrent); - }); + operation(files, async () => { + await DOM.Storage.remove(from); + + const { + panel, + panelPassive, + } = Info; + + const setCurrent = () => { + const currentName = name || data.names[0]; + DOM.setCurrentByName(currentName); + }; + + if (!Info.isOnePanel) + CloudCmd.refresh({ + panel: panelPassive, + noCurrent: true, + }); + + CloudCmd.refresh({panel}, setCurrent); }); } } diff --git a/common/try-to-promise-all.js b/common/try-to-promise-all.js new file mode 100644 index 00000000..80000fa2 --- /dev/null +++ b/common/try-to-promise-all.js @@ -0,0 +1,14 @@ +'use strict'; + +const tryToCatch = require('try-to-catch/legacy'); +const all = Promise.all.bind(Promise); + +module.exports = async (a) => { + const [e, result = []] = await tryToCatch(all, a); + + return [ + e, + ...result, + ]; +}; + diff --git a/common/try-to-promise-all.spec.js b/common/try-to-promise-all.spec.js new file mode 100644 index 00000000..628bc931 --- /dev/null +++ b/common/try-to-promise-all.spec.js @@ -0,0 +1,29 @@ +'use strict'; + +const test = require('supertape'); +const tryToPromiseAll = require('./try-to-promise-all'); + +const resolve = Promise.resolve.bind(Promise); +const reject = Promise.reject.bind(Promise); + +test('try-to-promise-all', async (t) => { + const [, ...result] = await tryToPromiseAll([ + resolve('a'), + resolve('b'), + ]); + + const expected = ['a', 'b']; + + t.deepEqual(result, expected); + t.end(); +}); + +test('try-to-promise-all: error', async (t) => { + const [e] = await tryToPromiseAll([ + reject('a'), + ]); + + t.equal(e, 'a'); + t.end(); +}); + From 63be7c87433acf537ce0aa3f7eee7b0e6d622486 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Fri, 16 Aug 2019 18:19:22 +0300 Subject: [PATCH 0134/1728] feature(madrun) disable web workers, while testing --- madrun.js | 8 +++++++- package.json | 2 +- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/madrun.js b/madrun.js index d6c23998..f1ce2c66 100644 --- a/madrun.js +++ b/madrun.js @@ -36,7 +36,13 @@ module.exports = { 'spell': () => 'yaspeller .', 'fix:lint': () => run(['lint', 'lint:css'], '--fix'), 'lint:progress': () => run('lint', '-f progress'), - 'test': () => `tape 'test/**/*.js' '{client,static,common,server}/**/*.spec.js'`, + 'test': () => { + const env = 'THREAD_IT_COUNT=0'; + const cmd = 'tape'; + const names = `'test/**/*.js' '{client,static,common,server}/**/*.spec.js'`; + + return `${env} ${cmd} ${names}`; + }, 'test:client': () => `tape 'test/client/**/*.js`, 'test:server': () => `tape 'test/**/*.js' 'server/**/*.spec.js' 'common/**/*.spec.js'`, 'wisdom': () => run(['lint:all', 'build', 'test']), diff --git a/package.json b/package.json index 4e3ec8f2..d920bb5d 100644 --- a/package.json +++ b/package.json @@ -154,7 +154,7 @@ "socket.io-client": "^2.1.1", "squad": "^3.0.0", "table": "^5.0.2", - "thread-it": "^1.0.1", + "thread-it": "^1.1.0", "try-catch": "^2.0.0", "try-to-catch": "^1.0.2", "tryrequire": "^2.0.1", From 98a9801644c857b619b2bb6edf240fb790639986 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Fri, 16 Aug 2019 18:25:13 +0300 Subject: [PATCH 0135/1728] feature(cloudcmd) add ability to remember position of current file on reload --- client/client.js | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/client/client.js b/client/client.js index f411cd39..503b4928 100644 --- a/client/client.js +++ b/client/client.js @@ -249,14 +249,22 @@ function CloudCmdProto(DOM) { } }; + async function saveCurrentName(currentName) { + await Storage.set('current-name', currentName); + } + async function baseInit() { const files = DOM.getFiles(); CloudCmd.on('current-file', DOM.updateCurrentInfo); + CloudCmd.on('current-name', saveCurrentName); + + const name = await Storage.get('current-name'); + const currentFile = name && DOM.getCurrentByName(name) || files[0]; /* выделяем строку с первым файлом */ if (files) - DOM.setCurrentFile(files[0], { + DOM.setCurrentFile(currentFile, { // when hash is present // it should be handled with this.route // overwre otherwise @@ -361,7 +369,6 @@ function CloudCmdProto(DOM) { if (!newObj) return; - /* eslint require-atomic-updates:0 */ options.sort = sort; options.order = order; From 4189d2096162a61f3a810defbc98fe9add5683db Mon Sep 17 00:00:00 2001 From: coderaiser Date: Fri, 16 Aug 2019 18:29:28 +0300 Subject: [PATCH 0136/1728] chore(package) v13.1.0 --- ChangeLog | 14 ++++++++++++++ HELP.md | 3 ++- README.md | 2 +- package.json | 2 +- 4 files changed, 18 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index c4615e5a..269c8dc3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,17 @@ +2019.08.16, v13.1.0 + +fix: +- (user-menu) hide load on error +- (key) keys block + +feature: +- (cloudcmd) add ability to remember position of current file on reload +- (madrun) disable web workers, while testing +- (user-menu) speed up user menu parsing with help of worker threads +- (user-menu) add ability to used EcmaScript Modules, improve error handling +- (server) add compress: speed up client side load + + 2019.08.14, v13.0.1 fix: diff --git a/HELP.md b/HELP.md index e7e385c7..6b3004cb 100644 --- a/HELP.md +++ b/HELP.md @@ -1,4 +1,4 @@ -# Cloud Commander v13.0.1 +# Cloud Commander v13.1.0 ### [Main][MainURL] [Blog][BlogURL] Live(![Heroku][Heroku_LIVE_IMG] [Heroku][HerokuURL], ![Now][NOW_LIVE_IMG] [Now][NowURL]) @@ -951,6 +951,7 @@ There are a lot of ways to be involved in `Cloud Commander` development: Version history --------------- +- *2019.08.16*, **[v13.1.0](//github.com/coderaiser/cloudcmd/releases/tag/v13.1.0)** - *2019.08.14*, **[v13.0.1](//github.com/coderaiser/cloudcmd/releases/tag/v13.0.1)** - *2019.08.14*, **[v13.0.0](//github.com/coderaiser/cloudcmd/releases/tag/v13.0.0)** - *2019.08.02*, **[v12.6.3](//github.com/coderaiser/cloudcmd/releases/tag/v12.6.3)** diff --git a/README.md b/README.md index 1b3041f7..fd53fc39 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Cloud Commander v13.0.1 [![Build Status][BuildStatusIMGURL]][BuildStatusURL] [![Now status][BuildAppveyorIMGURL]][BuildAppveyorURL] [![Codacy][CodacyIMG]][CodacyURL] [![Gitter][GitterIMGURL]][GitterURL] [![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fcoderaiser%2Fcloudcmd.svg?type=shield)](https://app.fossa.io/projects/git%2Bgithub.com%2Fcoderaiser%2Fcloudcmd?ref=badge_shield) +# Cloud Commander v13.1.0 [![Build Status][BuildStatusIMGURL]][BuildStatusURL] [![Now status][BuildAppveyorIMGURL]][BuildAppveyorURL] [![Codacy][CodacyIMG]][CodacyURL] [![Gitter][GitterIMGURL]][GitterURL] [![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fcoderaiser%2Fcloudcmd.svg?type=shield)](https://app.fossa.io/projects/git%2Bgithub.com%2Fcoderaiser%2Fcloudcmd?ref=badge_shield) ### [Main][MainURL] [Blog][BlogURL] Live([Heroku][HerokuURL], [Now][NowURL]) diff --git a/package.json b/package.json index d920bb5d..652376c8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "cloudcmd", - "version": "13.0.1", + "version": "13.1.0", "author": "coderaiser (https://github.com/coderaiser)", "description": "File manager for the web with console and editor", "homepage": "http://cloudcmd.io", From cc76eb9d2b7f530b1db74ff2846351dd310ae07c Mon Sep 17 00:00:00 2001 From: coderaiser Date: Mon, 19 Aug 2019 20:01:54 +0300 Subject: [PATCH 0137/1728] feature(package) eslint-plugin-putout v2.0.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 652376c8..c9231ab1 100644 --- a/package.json +++ b/package.json @@ -180,7 +180,7 @@ "emitify": "^3.0.2", "eslint": "^6.0.0-alpha", "eslint-plugin-node": "^9.0.1", - "eslint-plugin-putout": "^1.0.1", + "eslint-plugin-putout": "^2.0.0", "extract-text-webpack-plugin": "^4.0.0-alpha.0", "fast-async": "^7.0.6", "gritty": "^4.7.0", From b8592d35c035c1f503d8c97aa0ccc0894ca8c0f0 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Tue, 20 Aug 2019 18:47:11 +0300 Subject: [PATCH 0138/1728] fix(dom) getCurrentData --- client/dom/index.js | 26 +------------------------- 1 file changed, 1 insertion(+), 25 deletions(-) diff --git a/client/dom/index.js b/client/dom/index.js index 73f49317..6f506987 100644 --- a/client/dom/index.js +++ b/client/dom/index.js @@ -3,7 +3,6 @@ 'use strict'; const itype = require('itype/legacy'); -const exec = require('execon'); const jonny = require('jonny/legacy'); const tryToPromiseAll = require('../../common/try-to-promise-all'); @@ -340,7 +339,7 @@ function CmdProto() { const [hashNew, hash] = await DOM.checkStorageHash(path); if (hash === hashNew) - return await DOM.getDataFromStorage(path); + return await Storage.get(`${path}-data`); let [e, data] = await RESTful.read(path); @@ -563,29 +562,6 @@ function CmdProto() { return hash; }; - /** - * save data to storage - * - * @param name - * @param data - * @param callback - */ - this.getDataFromStorage = callbackify(async (name, callback) => { - const nameHash = name + '-hash'; - const nameData = name + '-data'; - const isDir = DOM.isCurrentIsDir(); - - if (isDir) - return exec(callback); - - const result = Promise.all([ - await Storage.get(nameData), - await Storage.get(nameHash), - ]); - - return result; - }); - this.getFM = () => { return DOM.getPanel().parentElement; }; From 64e6b8387a42eaba7e20969336a1eaa40efc4ea4 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Tue, 20 Aug 2019 22:29:28 +0300 Subject: [PATCH 0139/1728] feature(user-menu) improve error handling --- client/modules/user-menu/index.js | 46 ++++++++++++++++---- client/modules/user-menu/parse-error.js | 29 ++++++++++++ client/modules/user-menu/parse-error.spec.js | 32 ++++++++++++++ package.json | 1 + server/user-menu.js | 15 ++++--- 5 files changed, 109 insertions(+), 14 deletions(-) create mode 100644 client/modules/user-menu/parse-error.js create mode 100644 client/modules/user-menu/parse-error.spec.js diff --git a/client/modules/user-menu/index.js b/client/modules/user-menu/index.js index 58f3ff1c..27e48baa 100644 --- a/client/modules/user-menu/index.js +++ b/client/modules/user-menu/index.js @@ -7,10 +7,13 @@ require('../../../css/user-menu.css'); const currify = require('currify/legacy'); const wraptile = require('wraptile/legacy'); const {promisify} = require('es6-promisify'); +const fullstore = require('fullstore/legacy'); const load = require('load.js'); const createElement = require('@cloudcmd/create-element'); const tryCatch = require('try-catch'); const tryToCatch = require('try-to-catch/legacy'); +const parse = require('./parse-error'); +const {codeFrameColumns} = require('@babel/code-frame'); const Images = require('../../dom/images'); const Dialog = require('../../dom/dialog'); @@ -18,6 +21,7 @@ const getUserMenu = require('./get-user-menu'); const navigate = require('./navigate'); const loadCSS = promisify(load.css); +const sourceStore = fullstore(); const Name = 'UserMenu'; CloudCmd[Name] = module.exports; @@ -45,12 +49,15 @@ async function show() { const {dirPath} = CurrentInfo; const res = await fetch(`${CloudCmd.prefix}/api/v1/user-menu?dir=${dirPath}`); - const [error, userMenu] = tryCatch(getUserMenu, await res.text()); + const source = await res.text(); + const [error, userMenu] = tryCatch(getUserMenu, source); Images.hide(); if (error) - return Dialog.alert(`User menu error: ${error.message}`); + return Dialog.alert(getCodeFrame({error, source})); + + sourceStore(source); const options = Object .keys(userMenu) @@ -132,18 +139,41 @@ const onKeyDown = currify(async (keys, options, userMenu, e) => { const runUserMenu = async (value, options, userMenu) => { hide(); - const [e] = await tryToCatch(userMenu[value], { + const [error] = await tryToCatch(userMenu[value], { DOM, CloudCmd, tryToCatch, }); - if (!e) + if (!error) return; - if (e.name === 'Error') - return Dialog.alert(e.message); - - return Dialog.alert(e.stack); + const source = sourceStore(); + return Dialog.alert(getCodeFrame({ + error, + source, + })); }; +function getCodeFrame({error, source}) { + if (error.code === 'frame') + return error.message; + + const [line, column] = parse(error); + const start = { + line, + column, + }; + + const location = { + start, + }; + + const frame = codeFrameColumns(source, location, { + message: error.message, + highlightCode: false, + }); + + return `
${frame}
`; +} + diff --git a/client/modules/user-menu/parse-error.js b/client/modules/user-menu/parse-error.js new file mode 100644 index 00000000..46ca1020 --- /dev/null +++ b/client/modules/user-menu/parse-error.js @@ -0,0 +1,29 @@ +'use strict'; + +const isNumber = (a) => typeof a === 'number'; + +module.exports = (error) => { + const { + lineNumber, + columnNumber, + } = error; + + if (isNumber(lineNumber) && isNumber(columnNumber)) + return [ + lineNumber, + columnNumber, + ]; + + const before = error.stack.indexOf('>'); + const str = error.stack.slice(before + 1); + const after = str.indexOf(')'); + const newStr = str.slice(1, after); + + const [line, column] = newStr.split(':'); + + return [ + Number(line), + Number(column), + ]; +}; + diff --git a/client/modules/user-menu/parse-error.spec.js b/client/modules/user-menu/parse-error.spec.js new file mode 100644 index 00000000..ebd21553 --- /dev/null +++ b/client/modules/user-menu/parse-error.spec.js @@ -0,0 +1,32 @@ +'use strict'; + +const test = require('supertape'); +const parseError = require('./parse-error'); + +test('user-menu: parse-error', (t) => { + const result = parseError({ + lineNumber: 1, + columnNumber: 2, + }); + + const expected = [1, 2]; + + t.deepEqual(result, expected); + t.end(); +}); + +test('user-menu: parse-error', (t) => { + const stack = ` + ReferenceError: s is not defined + at eval (eval at module.exports (get-user-menu.js:NaN), :1:2) + at module.exports (get-user-menu.js:6) + at tryCatch (VM12611 try-catch.js:7) + at AsyncFunction.show (index.js:67) + `; + + const result = parseError({stack}); + const expected = [1, 2]; + + t.deepEqual(result, expected); + t.end(); +}); diff --git a/package.json b/package.json index c9231ab1..05c3b351 100644 --- a/package.json +++ b/package.json @@ -162,6 +162,7 @@ "writejson": "^2.0.0" }, "devDependencies": { + "@babel/code-frame": "^7.5.5", "@babel/core": "^7.0.0", "@babel/preset-env": "^7.0.0", "@cloudcmd/clipboard": "^1.0.2", diff --git a/server/user-menu.js b/server/user-menu.js index 318d9158..b297648c 100644 --- a/server/user-menu.js +++ b/server/user-menu.js @@ -72,13 +72,16 @@ async function onGET({req, res, menuName}) { if (parseError) return res .type('js') - .send(` - throw Error(\`
path: ${menuPath}\n\n${codeframe({
-    error: parseError,
-    source,
-    highlightCode: false,
-})}
+            .send(`const e = Error(\`
path: ${menuPath}\n\n${codeframe({
+                error: parseError,
+                source,
+                highlightCode: false,
+            })}
                 
\`); + + e.code = 'frame'; + + throw e; `); res From 511cceb9d96f64fff5ab45e294a5104570877cee Mon Sep 17 00:00:00 2001 From: coderaiser Date: Tue, 20 Aug 2019 22:58:37 +0300 Subject: [PATCH 0140/1728] fix(menu) autoplay on download in firefox --- client/modules/menu.js | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/client/modules/menu.js b/client/modules/menu.js index ff9b405c..ec1d136b 100644 --- a/client/modules/menu.js +++ b/client/modules/menu.js @@ -295,6 +295,8 @@ function download(type) { src, }); + mute(element); + const {body} = document; const removeChild = body.removeChild.bind(body, element); @@ -305,6 +307,21 @@ function download(type) { } } +// prevent firefox from auto play +function mute(element) { + element.contentWindow.addEventListener('load', () => { + const video = element.contentWindow + .document + .body + .querySelector('audio, video'); + + if (!video) + return; + + video.pause(); + }); +} + function getCurrentPosition() { const current = Info.element; const rect = current.getBoundingClientRect(); From 8ba1340e924e7ab642fe7e7322cc9ddb91544a5b Mon Sep 17 00:00:00 2001 From: coderaiser Date: Tue, 20 Aug 2019 23:02:42 +0300 Subject: [PATCH 0141/1728] chore(madrun) coverage --- madrun.js | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/madrun.js b/madrun.js index f1ce2c66..3246ce64 100644 --- a/madrun.js +++ b/madrun.js @@ -25,6 +25,8 @@ const names = [ const {putout} = predefined; +const env = 'THREAD_IT_COUNT=0'; + module.exports = { 'start': () => 'node bin/cloudcmd.js', 'start:dev': () => `NODE_ENV=development ${run('start')}`, @@ -36,13 +38,13 @@ module.exports = { 'spell': () => 'yaspeller .', 'fix:lint': () => run(['lint', 'lint:css'], '--fix'), 'lint:progress': () => run('lint', '-f progress'), - 'test': () => { - const env = 'THREAD_IT_COUNT=0'; + 'test:base': () => { const cmd = 'tape'; const names = `'test/**/*.js' '{client,static,common,server}/**/*.spec.js'`; - return `${env} ${cmd} ${names}`; + return `${cmd} ${names}`; }, + 'test': () => `${env} ${run('test:base')}`, 'test:client': () => `tape 'test/client/**/*.js`, 'test:server': () => `tape 'test/**/*.js' 'server/**/*.spec.js' 'common/**/*.spec.js'`, 'wisdom': () => run(['lint:all', 'build', 'test']), @@ -72,7 +74,7 @@ module.exports = { 'docker:rm:alpine': () => `docker rmi -f coderaiser/cloudcmd:${version}-alpine`, 'docker:rm:latest-alpine': () => 'docker rmi -f coderaiser/cloudcmd:latest-alpine', 'docker:rm-old': () => `${parallel('docker:rm:*')} || true`, - 'coverage': () => `nyc ${run('test')}`, + 'coverage': () => `${env} nyc ${run('test:base')}`, 'report': () => 'nyc report --reporter=text-lcov | coveralls', '6to5': () => 'webpack --progress', '6to5:client': () => run('6to5', '--mode production'), From 99e3f5d95e20f9881c9589bc9895fe4f85bc0a4f Mon Sep 17 00:00:00 2001 From: coderaiser Date: Tue, 20 Aug 2019 23:04:45 +0300 Subject: [PATCH 0142/1728] chore(package) v13.2.0 --- ChangeLog | 11 +++++++++++ HELP.md | 3 ++- README.md | 2 +- package.json | 2 +- 4 files changed, 15 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index 269c8dc3..db09e192 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +2019.08.20, v13.2.0 + +fix: +- (menu) autoplay on download in firefox +- (dom) getCurrentData + +feature: +- (user-menu) improve error handling +- (package) eslint-plugin-putout v2.0.0 + + 2019.08.16, v13.1.0 fix: diff --git a/HELP.md b/HELP.md index 6b3004cb..fb7eeb69 100644 --- a/HELP.md +++ b/HELP.md @@ -1,4 +1,4 @@ -# Cloud Commander v13.1.0 +# Cloud Commander v13.2.0 ### [Main][MainURL] [Blog][BlogURL] Live(![Heroku][Heroku_LIVE_IMG] [Heroku][HerokuURL], ![Now][NOW_LIVE_IMG] [Now][NowURL]) @@ -951,6 +951,7 @@ There are a lot of ways to be involved in `Cloud Commander` development: Version history --------------- +- *2019.08.20*, **[v13.2.0](//github.com/coderaiser/cloudcmd/releases/tag/v13.2.0)** - *2019.08.16*, **[v13.1.0](//github.com/coderaiser/cloudcmd/releases/tag/v13.1.0)** - *2019.08.14*, **[v13.0.1](//github.com/coderaiser/cloudcmd/releases/tag/v13.0.1)** - *2019.08.14*, **[v13.0.0](//github.com/coderaiser/cloudcmd/releases/tag/v13.0.0)** diff --git a/README.md b/README.md index fd53fc39..cfa0e6c3 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Cloud Commander v13.1.0 [![Build Status][BuildStatusIMGURL]][BuildStatusURL] [![Now status][BuildAppveyorIMGURL]][BuildAppveyorURL] [![Codacy][CodacyIMG]][CodacyURL] [![Gitter][GitterIMGURL]][GitterURL] [![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fcoderaiser%2Fcloudcmd.svg?type=shield)](https://app.fossa.io/projects/git%2Bgithub.com%2Fcoderaiser%2Fcloudcmd?ref=badge_shield) +# Cloud Commander v13.2.0 [![Build Status][BuildStatusIMGURL]][BuildStatusURL] [![Now status][BuildAppveyorIMGURL]][BuildAppveyorURL] [![Codacy][CodacyIMG]][CodacyURL] [![Gitter][GitterIMGURL]][GitterURL] [![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fcoderaiser%2Fcloudcmd.svg?type=shield)](https://app.fossa.io/projects/git%2Bgithub.com%2Fcoderaiser%2Fcloudcmd?ref=badge_shield) ### [Main][MainURL] [Blog][BlogURL] Live([Heroku][HerokuURL], [Now][NowURL]) diff --git a/package.json b/package.json index 05c3b351..07560fce 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "cloudcmd", - "version": "13.1.0", + "version": "13.2.0", "author": "coderaiser (https://github.com/coderaiser)", "description": "File manager for the web with console and editor", "homepage": "http://cloudcmd.io", From 98e284074ca27d4e119adb99b40ab5cb66b8a46d Mon Sep 17 00:00:00 2001 From: coderaiser Date: Tue, 20 Aug 2019 23:35:39 +0300 Subject: [PATCH 0143/1728] chore(parse-error) comment --- client/modules/user-menu/parse-error.js | 1 + 1 file changed, 1 insertion(+) diff --git a/client/modules/user-menu/parse-error.js b/client/modules/user-menu/parse-error.js index 46ca1020..190c4ff6 100644 --- a/client/modules/user-menu/parse-error.js +++ b/client/modules/user-menu/parse-error.js @@ -8,6 +8,7 @@ module.exports = (error) => { columnNumber, } = error; + // thank you firefox if (isNumber(lineNumber) && isNumber(columnNumber)) return [ lineNumber, From 57984fe2d6a660541779ea3b2a6d116c89995cfe Mon Sep 17 00:00:00 2001 From: coderaiser Date: Wed, 21 Aug 2019 14:53:50 +0300 Subject: [PATCH 0144/1728] feature(user-menu) rm path --- server/user-menu.js | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/server/user-menu.js b/server/user-menu.js index b297648c..c68a5313 100644 --- a/server/user-menu.js +++ b/server/user-menu.js @@ -72,23 +72,27 @@ async function onGET({req, res, menuName}) { if (parseError) return res .type('js') - .send(`const e = Error(\`
path: ${menuPath}\n\n${codeframe({
-                error: parseError,
-                source,
-                highlightCode: false,
-            })}
-                
\`); - - e.code = 'frame'; - - throw e; - `); + .send(getError(parseError, source)); res .type('js') .send(result.code); } +function getError(parseError, source) { + return ` + const e = Error(\`
${codeframe({
+        error: parseError,
+        source,
+        highlightCode: false,
+    })}
\`); + + e.code = 'frame'; + + throw e; + `; +} + function sendDefaultMenu(res) { res.sendFile(DEFAULT_MENU_PATH, { cacheControl: false, From 9abb48526b743932e7174028c17eb5593ae4bfe1 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Wed, 21 Aug 2019 19:34:40 +0300 Subject: [PATCH 0145/1728] chore(travis) rm allow_failures: node_js v12 --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 474e137f..2e3efa98 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,7 +10,6 @@ cache: matrix: allow_failures: - os: windows - - node_js: 12 os: - linux From f22829ef4f475d7c0ef49a50ffdd8b8ddf5fd4cf Mon Sep 17 00:00:00 2001 From: coderaiser Date: Wed, 21 Aug 2019 19:38:28 +0300 Subject: [PATCH 0146/1728] fix(user-menu) processing menu item run error --- client/modules/user-menu/index.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/client/modules/user-menu/index.js b/client/modules/user-menu/index.js index 27e48baa..77113153 100644 --- a/client/modules/user-menu/index.js +++ b/client/modules/user-menu/index.js @@ -156,7 +156,9 @@ const runUserMenu = async (value, options, userMenu) => { }; function getCodeFrame({error, source}) { - if (error.code === 'frame') + const {code} = error; + + if (!code || code === 'frame') return error.message; const [line, column] = parse(error); From 137673c5516bdc8c1127c94d82c111b37d326ff0 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Wed, 21 Aug 2019 19:43:13 +0300 Subject: [PATCH 0147/1728] chore(madrun) set lint:progress default lint --- madrun.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/madrun.js b/madrun.js index 3246ce64..e322f1f8 100644 --- a/madrun.js +++ b/madrun.js @@ -33,11 +33,12 @@ module.exports = { 'build:start': () => run(['build:client', 'start']), 'build:start:dev': () => run(['build:client:dev', 'start:dev']), 'lint:all': () => run(['lint', 'lint:css', 'spell']), - 'lint': () => putout(names), + 'lint:base': () => putout(names), 'lint:css': () => 'stylelint css/*.css', 'spell': () => 'yaspeller .', 'fix:lint': () => run(['lint', 'lint:css'], '--fix'), - 'lint:progress': () => run('lint', '-f progress'), + 'lint': () => run('lint:progress'), + 'lint:progress': () => run('lint:base', '-f progress'), 'test:base': () => { const cmd = 'tape'; const names = `'test/**/*.js' '{client,static,common,server}/**/*.spec.js'`; From 7e6b3c6ba5e17373dbe7adc6cd7cc405a060db09 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Wed, 21 Aug 2019 22:07:56 +0300 Subject: [PATCH 0148/1728] fix(key) chrome event double pass --- client/key/index.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/client/key/index.js b/client/key/index.js index 906ac963..a27bd0e1 100644 --- a/client/key/index.js +++ b/client/key/index.js @@ -58,6 +58,11 @@ function KeyProto() { async function listener(event) { const {keyCode} = event; + // strange chrome bug calles listener twice + // in second time event misses a lot fields + if (typeof event.altKey === 'undefined') + return; + const alt = event.altKey; const ctrl = event.ctrlKey; const shift = event.shiftKey; From 3ac7ee4b76c93f5b5a57b402523c97236ab1c8ae Mon Sep 17 00:00:00 2001 From: coderaiser Date: Thu, 22 Aug 2019 18:30:38 +0300 Subject: [PATCH 0149/1728] fix(buffer) copy, cut --- client/client.js | 14 ++++++++------ client/dom/buffer.js | 34 +++++++++++++++++----------------- client/dom/index.js | 8 +------- client/dom/storage.js | 14 ++++++++++++-- 4 files changed, 38 insertions(+), 32 deletions(-) diff --git a/client/client.js b/client/client.js index 503b4928..78da2d75 100644 --- a/client/client.js +++ b/client/client.js @@ -16,7 +16,6 @@ const isDev = process.env.NODE_ENV === 'development'; const Images = require('./dom/images'); const {unregisterSW} = require('./sw/register'); -const jonny = require('jonny/legacy'); const currify = require('currify/legacy'); const noJS = (a) => a.replace(/.js$/, ''); @@ -345,15 +344,18 @@ function CloudCmdProto(DOM) { * */ function ajaxLoad(path, options, panel, callback) { + const {Dialog, RESTful} = DOM; + const create = async (error, json) => { - const {RESTful} = DOM; + if (error) + return Dialog.alert(`Can't get from store: ${e.message}`); + const name = options.currentName || Info.name; - const obj = jonny.parse(json); const isRefresh = options.refresh; const {noCurrent} = options; if (!isRefresh && json) - return createFileTable(obj, panel, options, callback); + return createFileTable(json, panel, options, callback); const position = DOM.getPanelPosition(panel); const sort = CloudCmd.sort[position]; @@ -364,10 +366,10 @@ function CloudCmdProto(DOM) { order, }); - const [, newObj] = await RESTful.read(path + query, 'json'); + const [e, newObj] = await RESTful.read(path + query, 'json'); if (!newObj) - return; + return Dialog.alert(`Can't read: ${e.message}`); options.sort = sort; options.order = order; diff --git a/client/dom/buffer.js b/client/dom/buffer.js index d99429e5..f3df5981 100644 --- a/client/dom/buffer.js +++ b/client/dom/buffer.js @@ -2,8 +2,6 @@ /* global CloudCmd */ -const jonny = require('jonny/legacy'); - const tryToPromiseAll = require('../../common/try-to-promise-all'); const Storage = require('./storage'); const DOM = require('./'); @@ -59,14 +57,15 @@ function BufferProto() { } async function readBuffer() { - const [e, result] = await tryToPromiseAll([ + const [e, cp, ct] = await tryToPromiseAll([ Storage.get(COPY), Storage.get(CUT), ]); return [ e, - ...result, + cp, + ct, ]; } @@ -74,7 +73,7 @@ function BufferProto() { const names = getNames(); const from = Info.dirPath; - clear(); + await clear(); if (!names.length) return; @@ -90,7 +89,7 @@ function BufferProto() { const names = getNames(); const from = Info.dirPath; - clear(); + await clear(); if (!names.length) return; @@ -103,9 +102,9 @@ function BufferProto() { }); } - function clear() { - Storage.remove(COPY) - .remove(CUT); + async function clear() { + await Storage.remove(COPY); + await Storage.remove(CUT); rmCutClass(); } @@ -117,19 +116,20 @@ function BufferProto() { return showMessage(error || 'Buffer is empty!'); const opStr = cp ? 'copy' : 'move'; - const opData = cp || ct; + const data = cp || ct; const {Operation} = CloudCmd; const msg = 'Path is same!'; - const path = Info.dirPath; + const to = Info.dirPath; - const data = jonny.parse(opData); - data.to = path; - - if (data.from === path) + if (data.from === to) return showMessage(msg); - Operation.show(opStr, data); - clear(); + Operation.show(opStr, { + ...data, + to, + }); + + await clear(); } return Buffer; diff --git a/client/dom/index.js b/client/dom/index.js index 6f506987..44eca2e2 100644 --- a/client/dom/index.js +++ b/client/dom/index.js @@ -2,8 +2,6 @@ 'use strict'; -const itype = require('itype/legacy'); -const jonny = require('jonny/legacy'); const tryToPromiseAll = require('../../common/try-to-promise-all'); const Util = require('../../common/util'); @@ -341,16 +339,12 @@ function CmdProto() { if (hash === hashNew) return await Storage.get(`${path}-data`); - let [e, data] = await RESTful.read(path); + const [e, data] = await RESTful.read(path); if (e) return; const ONE_MEGABYTE = 1024 * 1024 * 1024; - - if (itype.object(data)) - data = jonny.stringify(data); - const {length} = data; if (hash && length < ONE_MEGABYTE) diff --git a/client/dom/storage.js b/client/dom/storage.js index 628bc9bd..c8d427cd 100644 --- a/client/dom/storage.js +++ b/client/dom/storage.js @@ -1,11 +1,21 @@ 'use strict'; +const tryCatch = require('try-catch'); + +const {parse, stringify} = JSON; +const isObj = (a) => typeof a === 'object'; + module.exports.set = async (name, data) => { - localStorage.setItem(name, data); + const primitive = !isObj(data) ? data : stringify(data); + + localStorage.setItem(name, primitive); }; module.exports.get = async (name) => { - return localStorage.getItem(name); + const data = localStorage.getItem(name); + const [, result = data] = tryCatch(parse, data); + + return result; }; module.exports.clear = async () => { From a8793dbbc51f79811d302ea5bc8c4ad31ac9683d Mon Sep 17 00:00:00 2001 From: coderaiser Date: Thu, 22 Aug 2019 18:48:56 +0300 Subject: [PATCH 0150/1728] refactor(dom) getRefreshButton: simplify --- client/dom/index.js | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/client/dom/index.js b/client/dom/index.js index 44eca2e2..9b9880a3 100644 --- a/client/dom/index.js +++ b/client/dom/index.js @@ -356,11 +356,8 @@ function CmdProto() { /** * unified way to get RefreshButton */ - this.getRefreshButton = (panel) => { - const currentPanel = panel || DOM.getPanel(); - const refresh = DOM.getByDataName('js-refresh', currentPanel); - - return refresh; + this.getRefreshButton = (panel = DOM.getPanel()) => { + return DOM.getByDataName('js-refresh', panel); }; /** From 33c1fdf629fe0f64ecaddaed09ee10ceae3855ab Mon Sep 17 00:00:00 2001 From: coderaiser Date: Thu, 22 Aug 2019 19:06:35 +0300 Subject: [PATCH 0151/1728] chore(package) v13.2.1 --- ChangeLog | 11 +++++++++++ HELP.md | 3 ++- README.md | 2 +- package.json | 2 +- 4 files changed, 15 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index db09e192..2a43f98e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +2019.08.22, v13.2.1 + +fix: +- (buffer) copy, cut +- (key) chrome event double pass +- (user-menu) processing menu item run error + +feature: +- (user-menu) rm path + + 2019.08.20, v13.2.0 fix: diff --git a/HELP.md b/HELP.md index fb7eeb69..44ca253c 100644 --- a/HELP.md +++ b/HELP.md @@ -1,4 +1,4 @@ -# Cloud Commander v13.2.0 +# Cloud Commander v13.2.1 ### [Main][MainURL] [Blog][BlogURL] Live(![Heroku][Heroku_LIVE_IMG] [Heroku][HerokuURL], ![Now][NOW_LIVE_IMG] [Now][NowURL]) @@ -951,6 +951,7 @@ There are a lot of ways to be involved in `Cloud Commander` development: Version history --------------- +- *2019.08.22*, **[v13.2.1](//github.com/coderaiser/cloudcmd/releases/tag/v13.2.1)** - *2019.08.20*, **[v13.2.0](//github.com/coderaiser/cloudcmd/releases/tag/v13.2.0)** - *2019.08.16*, **[v13.1.0](//github.com/coderaiser/cloudcmd/releases/tag/v13.1.0)** - *2019.08.14*, **[v13.0.1](//github.com/coderaiser/cloudcmd/releases/tag/v13.0.1)** diff --git a/README.md b/README.md index cfa0e6c3..a33863bd 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Cloud Commander v13.2.0 [![Build Status][BuildStatusIMGURL]][BuildStatusURL] [![Now status][BuildAppveyorIMGURL]][BuildAppveyorURL] [![Codacy][CodacyIMG]][CodacyURL] [![Gitter][GitterIMGURL]][GitterURL] [![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fcoderaiser%2Fcloudcmd.svg?type=shield)](https://app.fossa.io/projects/git%2Bgithub.com%2Fcoderaiser%2Fcloudcmd?ref=badge_shield) +# Cloud Commander v13.2.1 [![Build Status][BuildStatusIMGURL]][BuildStatusURL] [![Now status][BuildAppveyorIMGURL]][BuildAppveyorURL] [![Codacy][CodacyIMG]][CodacyURL] [![Gitter][GitterIMGURL]][GitterURL] [![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fcoderaiser%2Fcloudcmd.svg?type=shield)](https://app.fossa.io/projects/git%2Bgithub.com%2Fcoderaiser%2Fcloudcmd?ref=badge_shield) ### [Main][MainURL] [Blog][BlogURL] Live([Heroku][HerokuURL], [Now][NowURL]) diff --git a/package.json b/package.json index 07560fce..48a6761e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "cloudcmd", - "version": "13.2.0", + "version": "13.2.1", "author": "coderaiser (https://github.com/coderaiser)", "description": "File manager for the web with console and editor", "homepage": "http://cloudcmd.io", From ca083963e924d31a11c18deb377b4cd38bd1b6c7 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Fri, 23 Aug 2019 13:17:00 +0300 Subject: [PATCH 0152/1728] fix(vim) find --- client/key/vim/index.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/client/key/vim/index.js b/client/key/vim/index.js index 7e66d37b..bdc9e698 100644 --- a/client/key/vim/index.js +++ b/client/key/vim/index.js @@ -4,6 +4,7 @@ const KEY = require('../key'); const Info = DOM.CurrentInfo; + const {Dialog} = DOM; const fullstore = require('fullstore/legacy'); @@ -30,7 +31,7 @@ const rmFirst = (a) => { .join(''); }; -module.exports = (key, event) => { +module.exports = async (key, event) => { const current = Info.element; const {keyCode} = event; const prevStore = store(); @@ -115,8 +116,9 @@ module.exports = (key, event) => { if (key === '/') { event.preventDefault(); - Dialog.prompt('Find', '', {cancel: false}) - .then(find); + const [, value] = await Dialog.prompt('Find', ''); + + value && find(value); return end(); } From 4b3afb522397ce412365d13f45f6f9119b070492 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Fri, 23 Aug 2019 13:22:58 +0300 Subject: [PATCH 0153/1728] refactor(edit-names) Dialog -> smalltalk --- client/modules/edit-names.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/client/modules/edit-names.js b/client/modules/edit-names.js index 90bfc59a..80020ec1 100644 --- a/client/modules/edit-names.js +++ b/client/modules/edit-names.js @@ -215,7 +215,8 @@ function isChanged() { if (!editor.isChanged()) return; - Dialog.confirm(msg, {cancel: false}) + smalltalk + .confirm(msg, {cancel: false}) .then(applyNames); } From a29b6d172a5ee6c6c2c69094df45f80e4cd33c22 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Fri, 23 Aug 2019 13:30:55 +0300 Subject: [PATCH 0154/1728] fix(edit-names) hide --- client/modules/edit-names.js | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/client/modules/edit-names.js b/client/modules/edit-names.js index 80020ec1..bd1d00b4 100644 --- a/client/modules/edit-names.js +++ b/client/modules/edit-names.js @@ -20,7 +20,6 @@ const rename = currify(_rename); let Menu; -const EditNames = exec.bind(); const ConfigView = { beforeClose: () => { exec.ifExist(Menu, 'hide'); @@ -67,7 +66,7 @@ function keyListener(event) { const {Key} = CloudCmd; if (ctrlMeta && event.keyCode === Key.S) - EditNames.hide(); + hide(); else if (ctrlMeta && event.keyCode === Key.P) smalltalk @@ -88,9 +87,11 @@ function getActiveNames() { return DOM.getFilenames(DOM.getActiveFiles()); } -module.exports.hide = () => { +module.exports.hide = hide; + +function hide() { CloudCmd.Edit.hide(); -}; +} function setListeners() { const element = CloudCmd.Edit.getElement(); @@ -175,7 +176,7 @@ function setMenu(event) { const menuData = { 'Save Ctrl+S' : () => { applyNames(); - EditNames.hide(); + hide(); }, 'Go To Line Ctrl+G' : () => { editor.goToLine(); @@ -196,7 +197,7 @@ function setMenu(event) { editor.selectAll(); }, 'Close Esc' : () => { - EditNames.hide(); + hide(); }, }; From 560dd8fddc7e048b84e1e95226738a179970cced Mon Sep 17 00:00:00 2001 From: coderaiser Date: Fri, 23 Aug 2019 14:05:38 +0300 Subject: [PATCH 0155/1728] refactor(edit-names) smalltalk -> Dialog --- client/modules/edit-names.js | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/client/modules/edit-names.js b/client/modules/edit-names.js index bd1d00b4..95da1739 100644 --- a/client/modules/edit-names.js +++ b/client/modules/edit-names.js @@ -4,7 +4,6 @@ CloudCmd.EditNames = exports; -const smalltalk = require('smalltalk'); const currify = require('currify/legacy'); const exec = require('execon'); const supermenu = require('supermenu'); @@ -59,7 +58,7 @@ module.exports.show = (options) => { return CloudCmd.Edit; }; -function keyListener(event) { +async function keyListener(event) { const ctrl = event.ctrlKey; const meta = event.metaKey; const ctrlMeta = ctrl || meta; @@ -68,10 +67,10 @@ function keyListener(event) { if (ctrlMeta && event.keyCode === Key.S) hide(); - else if (ctrlMeta && event.keyCode === Key.P) - smalltalk - .prompt('Apply pattern:', '[n][e]', {cancel: false}) - .then(applyPattern); + else if (ctrlMeta && event.keyCode === Key.P) { + const [, pattern] = await Dialog.prompt('Apply pattern:', '[n][e]'); + pattern && applyPattern(pattern); + } event.preventDefault(); } @@ -209,15 +208,14 @@ function setMenu(event) { module.exports.isChanged = isChanged; -function isChanged() { +async function isChanged() { const editor = CloudCmd.Edit.getEditor(); const msg = 'Apply new names?'; if (!editor.isChanged()) return; - smalltalk - .confirm(msg, {cancel: false}) - .then(applyNames); + const [, names] = await Dialog.confirm(msg); + names && applyNames(names); } From e46d104cc713edae9150dd1a1a16f4a7fcb868eb Mon Sep 17 00:00:00 2001 From: coderaiser Date: Fri, 23 Aug 2019 14:37:18 +0300 Subject: [PATCH 0156/1728] feature(markdown) move out parse to worker --- .../fixture}/markdown.html | 0 .../markdown => markdown/fixture}/markdown.md | 0 server/{markdown.js => markdown/index.js} | 23 +++++++++---------- .../index.spec.js} | 6 ++--- server/markdown/worker.js | 4 ++++ 5 files changed, 18 insertions(+), 15 deletions(-) rename server/{fixture/markdown => markdown/fixture}/markdown.html (100%) rename server/{fixture/markdown => markdown/fixture}/markdown.md (100%) rename server/{markdown.js => markdown/index.js} (81%) rename server/{markdown.spec.js => markdown/index.spec.js} (94%) create mode 100644 server/markdown/worker.js diff --git a/server/fixture/markdown/markdown.html b/server/markdown/fixture/markdown.html similarity index 100% rename from server/fixture/markdown/markdown.html rename to server/markdown/fixture/markdown.html diff --git a/server/fixture/markdown/markdown.md b/server/markdown/fixture/markdown.md similarity index 100% rename from server/fixture/markdown/markdown.md rename to server/markdown/fixture/markdown.md diff --git a/server/markdown.js b/server/markdown/index.js similarity index 81% rename from server/markdown.js rename to server/markdown/index.js index 5982701f..1f913ccd 100644 --- a/server/markdown.js +++ b/server/markdown/index.js @@ -1,7 +1,7 @@ 'use strict'; -const DIR_ROOT = __dirname + '/../'; const fs = require('fs'); +const {join} = require('path'); const { callbackify, promisify, @@ -9,11 +9,19 @@ const { const pullout = require('pullout'); const ponse = require('ponse'); -const markdown = require('markdown-it')(); +const threadIt = require('thread-it'); const readFile = promisify(fs.readFile); +const parse = threadIt(join(__dirname, 'worker')); -const root = require('./root'); +const root = require('../root'); + +threadIt.init(); + +// warm up +parse(''); + +const DIR_ROOT = __dirname + '/../../'; module.exports = callbackify(async (name, rootDir, request) => { check(name, request); @@ -48,18 +56,9 @@ async function onGET(request, name, root) { async function onPUT(request) { const data = await pullout(request); - return parse(data); } -const parse = promisify((data, callback) => { - process.nextTick(() => { - const md = markdown.render(data); - - callback(null, md); - }); -}); - function check(name, request) { if (typeof name !== 'string') throw Error('name should be string!'); diff --git a/server/markdown.spec.js b/server/markdown/index.spec.js similarity index 94% rename from server/markdown.spec.js rename to server/markdown/index.spec.js index 05510a65..3e6859d1 100644 --- a/server/markdown.spec.js +++ b/server/markdown/index.spec.js @@ -7,11 +7,11 @@ const {promisify} = require('util'); const tryToCatch = require('try-to-catch'); -const markdown = require('./markdown'); +const markdown = require('.'); const _markdown = promisify(markdown); -const fixtureDir = path.join(__dirname, 'fixture', 'markdown'); -const cloudcmd = require('..'); +const fixtureDir = path.join(__dirname, 'fixture'); +const cloudcmd = require('../..'); const config = { auth: false, }; diff --git a/server/markdown/worker.js b/server/markdown/worker.js new file mode 100644 index 00000000..ae2a95fd --- /dev/null +++ b/server/markdown/worker.js @@ -0,0 +1,4 @@ +'use strict'; + +const markdownIt = require('markdown-it')(); +module.exports = (a) => markdownIt.render(a); From 857fe1d95009c2376bc255a1391f4b42a7d7251b Mon Sep 17 00:00:00 2001 From: coderaiser Date: Fri, 23 Aug 2019 15:20:51 +0300 Subject: [PATCH 0157/1728] fix(user-menu) putout path --- server/user-menu.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/user-menu.js b/server/user-menu.js index c68a5313..0558550b 100644 --- a/server/user-menu.js +++ b/server/user-menu.js @@ -11,7 +11,7 @@ const currify = require('currify'); const findUp = require('find-up'); const threadIt = require('thread-it'); const {codeframe} = require('putout'); -const putout = threadIt('putout'); +const putout = threadIt(require.resolve('putout')); threadIt.init(); From 18111aa74473d6d5fc7c8c1aedcea5f4250081ab Mon Sep 17 00:00:00 2001 From: coderaiser Date: Fri, 23 Aug 2019 21:18:25 +0300 Subject: [PATCH 0158/1728] fix(client) rm additional dialog --- client/client.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/client.js b/client/client.js index 78da2d75..a963dc2c 100644 --- a/client/client.js +++ b/client/client.js @@ -366,10 +366,10 @@ function CloudCmdProto(DOM) { order, }); - const [e, newObj] = await RESTful.read(path + query, 'json'); + const [, newObj] = await RESTful.read(path + query, 'json'); if (!newObj) - return Dialog.alert(`Can't read: ${e.message}`); + return; // that's OK, error handled by RESTful options.sort = sort; options.order = order; From 139a91b094cddc598b073d16e0fbc917252dff26 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Mon, 26 Aug 2019 21:58:40 +0300 Subject: [PATCH 0159/1728] feature(menu) rm mute: has no sense with new ponse headers --- client/modules/menu.js | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/client/modules/menu.js b/client/modules/menu.js index ec1d136b..ff9b405c 100644 --- a/client/modules/menu.js +++ b/client/modules/menu.js @@ -295,8 +295,6 @@ function download(type) { src, }); - mute(element); - const {body} = document; const removeChild = body.removeChild.bind(body, element); @@ -307,21 +305,6 @@ function download(type) { } } -// prevent firefox from auto play -function mute(element) { - element.contentWindow.addEventListener('load', () => { - const video = element.contentWindow - .document - .body - .querySelector('audio, video'); - - if (!video) - return; - - video.pause(); - }); -} - function getCurrentPosition() { const current = Info.element; const rect = current.getBoundingClientRect(); From 32628ec43f6f941f60dfcb6372975ec008107822 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Tue, 27 Aug 2019 18:54:43 +0300 Subject: [PATCH 0160/1728] feature(package) es6-promisify v6.0.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 48a6761e..5af12d8f 100644 --- a/package.json +++ b/package.json @@ -120,7 +120,7 @@ "deepword": "^6.0.0", "dword": "^11.0.0", "edward": "^11.0.0", - "es6-promisify": "^6.0.1", + "es6-promisify": "^6.0.2", "execon": "^1.2.0", "express": "^4.13.0", "files-io": "^3.0.0", From 089bdc64a0395e435be2f2fb34a3c69652784a1d Mon Sep 17 00:00:00 2001 From: coderaiser Date: Tue, 27 Aug 2019 21:29:09 +0300 Subject: [PATCH 0161/1728] feature(client) remove legacy suffix, use modules as is --- client/client.js | 10 +++++----- client/cloudcmd.js | 2 +- client/dom/dialog.js | 2 +- client/dom/dom-tree.js | 2 +- client/dom/events/index.js | 2 +- client/dom/files.js | 4 ++-- client/dom/io.js | 2 +- client/dom/load-remote.js | 6 +++--- client/dom/load.js | 6 +++--- client/dom/rest.js | 2 +- client/dom/upload-files.js | 2 +- client/key/index.js | 2 +- client/key/vim/find.js | 4 ++-- client/key/vim/index.js | 2 +- client/listeners/index.js | 6 +++--- client/load-module.js | 2 +- client/modules/cloud.js | 2 +- client/modules/config/index.js | 10 +++++----- client/modules/config/input.js | 2 +- client/modules/edit-file.js | 4 ++-- client/modules/edit-names.js | 2 +- client/modules/edit.js | 2 +- client/modules/konsole.js | 4 ++-- client/modules/markdown.js | 2 +- client/modules/menu.js | 2 +- client/modules/operation/get-next-current-name.js | 2 +- client/modules/operation/index.js | 4 ++-- client/modules/operation/set-listeners.js | 4 ++-- client/modules/terminal-run.js | 4 ++-- client/modules/terminal.js | 2 +- client/modules/user-menu/index.js | 8 ++++---- client/modules/view.js | 8 ++++---- client/sw/sw.js | 4 ++-- common/cloudfunc.js | 6 +++--- common/try-to-promise-all.js | 2 +- 35 files changed, 65 insertions(+), 65 deletions(-) diff --git a/client/client.js b/client/client.js index a963dc2c..1a228e98 100644 --- a/client/client.js +++ b/client/client.js @@ -2,13 +2,13 @@ /* global DOM */ -const Emitify = require('emitify/legacy'); +const Emitify = require('emitify'); const inherits = require('inherits'); -const rendy = require('rendy/legacy'); +const rendy = require('rendy'); const exec = require('execon'); const load = require('load.js'); const {promisify} = require('es6-promisify'); -const tryToCatch = require('try-to-catch/legacy'); +const tryToCatch = require('try-to-catch'); const pascalCase = require('just-pascal-case'); const isDev = process.env.NODE_ENV === 'development'; @@ -16,7 +16,7 @@ const isDev = process.env.NODE_ENV === 'development'; const Images = require('./dom/images'); const {unregisterSW} = require('./sw/register'); -const currify = require('currify/legacy'); +const currify = require('currify'); const noJS = (a) => a.replace(/.js$/, ''); @@ -348,7 +348,7 @@ function CloudCmdProto(DOM) { const create = async (error, json) => { if (error) - return Dialog.alert(`Can't get from store: ${e.message}`); + return Dialog.alert(`Can't get from store: ${error.message}`); const name = options.currentName || Info.name; const isRefresh = options.refresh; diff --git a/client/cloudcmd.js b/client/cloudcmd.js index 667d3f55..f90ef712 100644 --- a/client/cloudcmd.js +++ b/client/cloudcmd.js @@ -6,7 +6,7 @@ require('../css/columns/name-size-date.css'); require('../css/columns/name-size.css'); const {promisify} = require('es6-promisify'); -const wraptile = require('wraptile/legacy'); +const wraptile = require('wraptile'); const load = require('load.js'); const isDev = process.env.NODE_ENV === 'development'; diff --git a/client/dom/dialog.js b/client/dom/dialog.js index 6133d25d..3fcf7fb6 100644 --- a/client/dom/dialog.js +++ b/client/dom/dialog.js @@ -1,6 +1,6 @@ 'use strict'; -const tryToCatch = require('try-to-catch/legacy'); +const tryToCatch = require('try-to-catch'); const { alert, diff --git a/client/dom/dom-tree.js b/client/dom/dom-tree.js index dcbff43b..3bef0e4f 100644 --- a/client/dom/dom-tree.js +++ b/client/dom/dom-tree.js @@ -1,6 +1,6 @@ 'use strict'; -const currify = require('currify/legacy'); +const currify = require('currify'); const DOM = module.exports; diff --git a/client/dom/events/index.js b/client/dom/events/index.js index 57267f9a..1fb4dac2 100644 --- a/client/dom/events/index.js +++ b/client/dom/events/index.js @@ -1,6 +1,6 @@ 'use strict'; -const itype = require('itype/legacy'); +const itype = require('itype'); const EventStore = require('./event-store'); module.exports = new EventsProto(); diff --git a/client/dom/files.js b/client/dom/files.js index c64f2a47..7955b128 100644 --- a/client/dom/files.js +++ b/client/dom/files.js @@ -2,8 +2,8 @@ 'use strict'; -const itype = require('itype/legacy'); -const currify = require('currify/legacy'); +const itype = require('itype'); +const currify = require('currify'); const {promisify} = require('es6-promisify'); const load = require('./load'); diff --git a/client/dom/io.js b/client/dom/io.js index 24abe841..8bd1ffa8 100644 --- a/client/dom/io.js +++ b/client/dom/io.js @@ -2,7 +2,7 @@ /* global CloudCmd*/ -const itype = require('itype/legacy'); +const itype = require('itype'); const {promisify} = require('es6-promisify'); const {FS} = require('../../common/cloudfunc'); diff --git a/client/dom/load-remote.js b/client/dom/load-remote.js index 23069e0a..52e66934 100644 --- a/client/dom/load-remote.js +++ b/client/dom/load-remote.js @@ -3,9 +3,9 @@ /* global CloudCmd */ const exec = require('execon'); -const rendy = require('rendy/legacy'); -const itype = require('itype/legacy'); -const wraptile = require('wraptile/legacy'); +const rendy = require('rendy'); +const itype = require('itype'); +const wraptile = require('wraptile'); const load = require('load.js'); const {findObjByNameInArr} = require('../../common/util'); diff --git a/client/dom/load.js b/client/dom/load.js index 5596a384..9ba976fc 100644 --- a/client/dom/load.js +++ b/client/dom/load.js @@ -1,8 +1,8 @@ 'use strict'; -const itype = require('itype/legacy'); -const jonny = require('jonny/legacy'); -const Emitify = require('emitify/legacy'); +const itype = require('itype'); +const jonny = require('jonny'); +const Emitify = require('emitify'); const exec = require('execon'); const Images = require('./images'); diff --git a/client/dom/rest.js b/client/dom/rest.js index 3a9d2f62..53fe28d8 100644 --- a/client/dom/rest.js +++ b/client/dom/rest.js @@ -1,6 +1,6 @@ 'use strict'; -const tryToCatch = require('try-to-catch/legacy'); +const tryToCatch = require('try-to-catch'); const {encode} = require('../../common/entity'); diff --git a/client/dom/upload-files.js b/client/dom/upload-files.js index f4f9dc62..414be578 100644 --- a/client/dom/upload-files.js +++ b/client/dom/upload-files.js @@ -3,7 +3,7 @@ /* global CloudCmd */ const {eachSeries} = require('execon'); -const wraptile = require('wraptile/legacy'); +const wraptile = require('wraptile'); const load = require('./load'); const Images = require('./images'); diff --git a/client/key/index.js b/client/key/index.js index a27bd0e1..ca1801c0 100644 --- a/client/key/index.js +++ b/client/key/index.js @@ -12,7 +12,7 @@ const Buffer = require('../dom/buffer'); const KEY = require('./key'); const vim = require('./vim'); const setCurrentByChar = require('./set-current-by-char'); -const fullstore = require('fullstore/legacy'); +const fullstore = require('fullstore'); const Chars = fullstore(); Chars([]); diff --git a/client/key/vim/find.js b/client/key/vim/find.js index 29a2a85f..a8573df7 100644 --- a/client/key/vim/find.js +++ b/client/key/vim/find.js @@ -2,8 +2,8 @@ /* global DOM */ -const fullstore = require('fullstore/legacy'); -const limier = require('limier/legacy'); +const fullstore = require('fullstore'); +const limier = require('limier'); const Info = DOM.CurrentInfo; const searchStore = fullstore([]); diff --git a/client/key/vim/index.js b/client/key/vim/index.js index bdc9e698..65751d23 100644 --- a/client/key/vim/index.js +++ b/client/key/vim/index.js @@ -7,7 +7,7 @@ const Info = DOM.CurrentInfo; const {Dialog} = DOM; -const fullstore = require('fullstore/legacy'); +const fullstore = require('fullstore'); const store = fullstore(''); const visual = fullstore(false); const { diff --git a/client/listeners/index.js b/client/listeners/index.js index c523232d..a82b8a20 100644 --- a/client/listeners/index.js +++ b/client/listeners/index.js @@ -3,9 +3,9 @@ 'use strict'; const exec = require('execon'); -const itype = require('itype/legacy'); -const currify = require('currify/legacy'); -const tryToCatch = require('try-to-catch/legacy'); +const itype = require('itype'); +const currify = require('currify'); +const tryToCatch = require('try-to-catch'); const clipboard = require('@cloudcmd/clipboard'); const getRange = require('./get-range'); diff --git a/client/load-module.js b/client/load-module.js index dffcf3f3..a60638b7 100644 --- a/client/load-module.js +++ b/client/load-module.js @@ -3,7 +3,7 @@ /* global CloudCmd */ const exec = require('execon'); -const tryToCatch = require('try-to-catch/legacy'); +const tryToCatch = require('try-to-catch'); const {promisify} = require('es6-promisify'); const loadJS = promisify(require('load.js').js); diff --git a/client/modules/cloud.js b/client/modules/cloud.js index 214d1325..af019f05 100644 --- a/client/modules/cloud.js +++ b/client/modules/cloud.js @@ -3,7 +3,7 @@ 'use strict'; const exec = require('execon'); -const currify = require('currify/legacy'); +const currify = require('currify'); const {promisify} = require('es6-promisify'); const loadJS = promisify(require('load.js').js); diff --git a/client/modules/config/index.js b/client/modules/config/index.js index 5db8ee06..75ec79b5 100644 --- a/client/modules/config/index.js +++ b/client/modules/config/index.js @@ -4,12 +4,12 @@ require('../../../css/config.css'); -const rendy = require('rendy/legacy'); -const currify = require('currify/legacy'); -const wraptile = require('wraptile/legacy'); -const squad = require('squad/legacy'); +const rendy = require('rendy'); +const currify = require('currify'); +const wraptile = require('wraptile'); +const squad = require('squad'); const {promisify} = require('es6-promisify'); -const tryToCatch = require('try-to-catch/legacy'); +const tryToCatch = require('try-to-catch'); const load = require('load.js'); const createElement = require('@cloudcmd/create-element'); diff --git a/client/modules/config/input.js b/client/modules/config/input.js index 7eea66b8..013908d2 100644 --- a/client/modules/config/input.js +++ b/client/modules/config/input.js @@ -1,6 +1,6 @@ 'use strict'; -const currify = require('currify/legacy'); +const currify = require('currify'); const isType = currify((type, object, name) => { return typeof object[name] === type; diff --git a/client/modules/edit-file.js b/client/modules/edit-file.js index 941b88d1..3fa55c14 100644 --- a/client/modules/edit-file.js +++ b/client/modules/edit-file.js @@ -4,8 +4,8 @@ CloudCmd.EditFile = exports; -const Format = require('format-io/legacy'); -const fullstore = require('fullstore/legacy'); +const Format = require('format-io'); +const fullstore = require('fullstore'); const exec = require('execon'); const supermenu = require('supermenu'); diff --git a/client/modules/edit-names.js b/client/modules/edit-names.js index 95da1739..06c0e29e 100644 --- a/client/modules/edit-names.js +++ b/client/modules/edit-names.js @@ -4,7 +4,7 @@ CloudCmd.EditNames = exports; -const currify = require('currify/legacy'); +const currify = require('currify'); const exec = require('execon'); const supermenu = require('supermenu'); const multiRename = require('multi-rename'); diff --git a/client/modules/edit.js b/client/modules/edit.js index e3e75d81..3f89d39b 100644 --- a/client/modules/edit.js +++ b/client/modules/edit.js @@ -3,7 +3,7 @@ 'use strict'; const {promisify} = require('es6-promisify'); -const tryToCatch = require('try-to-catch/legacy'); +const tryToCatch = require('try-to-catch'); const createElement = require('@cloudcmd/create-element'); const load = require('load.js'); const loadJS = promisify(load.js); diff --git a/client/modules/konsole.js b/client/modules/konsole.js index 86b8c9c2..5c973f84 100644 --- a/client/modules/konsole.js +++ b/client/modules/konsole.js @@ -9,8 +9,8 @@ CloudCmd.Konsole = exports; const exec = require('execon'); const {promisify} = require('es6-promisify'); -const currify = require('currify/legacy'); -const tryToCatch = require('try-to-catch/legacy'); +const currify = require('currify'); +const tryToCatch = require('try-to-catch'); const loadJS = promisify(require('load.js').js); const createElement = require('@cloudcmd/create-element'); diff --git a/client/modules/markdown.js b/client/modules/markdown.js index a25539df..523814c7 100644 --- a/client/modules/markdown.js +++ b/client/modules/markdown.js @@ -3,7 +3,7 @@ /* global CloudCmd */ const {promisify} = require('es6-promisify'); -const tryToCatch = require('try-to-catch/legacy'); +const tryToCatch = require('try-to-catch'); CloudCmd.Markdown = exports; diff --git a/client/modules/menu.js b/client/modules/menu.js index ff9b405c..439e48cb 100644 --- a/client/modules/menu.js +++ b/client/modules/menu.js @@ -3,7 +3,7 @@ 'use strict'; const exec = require('execon'); -const wrap = require('wraptile/legacy'); +const wrap = require('wraptile'); const supermenu = require('supermenu'); const createElement = require('@cloudcmd/create-element'); diff --git a/client/modules/operation/get-next-current-name.js b/client/modules/operation/get-next-current-name.js index c10e2129..a27e9daa 100644 --- a/client/modules/operation/get-next-current-name.js +++ b/client/modules/operation/get-next-current-name.js @@ -1,6 +1,6 @@ 'use strict'; -const currify = require('currify/legacy'); +const currify = require('currify'); const not = currify((array, value) => !~array.indexOf(value)); const notOneOf = currify((a, b) => a.filter(not(b))); diff --git a/client/modules/operation/index.js b/client/modules/operation/index.js index 97aab7f8..09a15a99 100644 --- a/client/modules/operation/index.js +++ b/client/modules/operation/index.js @@ -5,8 +5,8 @@ 'use strict'; -const currify = require('currify/legacy'); -const wraptile = require('wraptile/legacy'); +const currify = require('currify'); +const wraptile = require('wraptile'); const {promisify} = require('es6-promisify'); const exec = require('execon'); const loadJS = require('load.js').js; diff --git a/client/modules/operation/set-listeners.js b/client/modules/operation/set-listeners.js index 70eb69df..df83d243 100644 --- a/client/modules/operation/set-listeners.js +++ b/client/modules/operation/set-listeners.js @@ -7,8 +7,8 @@ const { Images, } = DOM; -const forEachKey = require('for-each-key/legacy'); -const wraptile = require('wraptile/legacy'); +const forEachKey = require('for-each-key'); +const wraptile = require('wraptile'); const format = require('./format'); diff --git a/client/modules/terminal-run.js b/client/modules/terminal-run.js index 72d8a5fb..eaadfe5f 100644 --- a/client/modules/terminal-run.js +++ b/client/modules/terminal-run.js @@ -3,8 +3,8 @@ /* global CloudCmd, gritty */ const {promisify} = require('es6-promisify'); -const tryToCatch = require('try-to-catch/legacy'); -const fullstore = require('fullstore/legacy'); +const tryToCatch = require('try-to-catch'); +const fullstore = require('fullstore'); require('../../css/terminal.css'); diff --git a/client/modules/terminal.js b/client/modules/terminal.js index ee33f4ae..20a85392 100644 --- a/client/modules/terminal.js +++ b/client/modules/terminal.js @@ -3,7 +3,7 @@ /* global CloudCmd, gritty */ const {promisify} = require('es6-promisify'); -const tryToCatch = require('try-to-catch/legacy'); +const tryToCatch = require('try-to-catch'); require('../../css/terminal.css'); diff --git a/client/modules/user-menu/index.js b/client/modules/user-menu/index.js index 77113153..27f61ad9 100644 --- a/client/modules/user-menu/index.js +++ b/client/modules/user-menu/index.js @@ -4,14 +4,14 @@ require('../../../css/user-menu.css'); -const currify = require('currify/legacy'); -const wraptile = require('wraptile/legacy'); +const currify = require('currify'); +const wraptile = require('wraptile'); const {promisify} = require('es6-promisify'); -const fullstore = require('fullstore/legacy'); +const fullstore = require('fullstore'); const load = require('load.js'); const createElement = require('@cloudcmd/create-element'); const tryCatch = require('try-catch'); -const tryToCatch = require('try-to-catch/legacy'); +const tryToCatch = require('try-to-catch'); const parse = require('./parse-error'); const {codeFrameColumns} = require('@babel/code-frame'); diff --git a/client/modules/view.js b/client/modules/view.js index 75043da8..f254da0f 100644 --- a/client/modules/view.js +++ b/client/modules/view.js @@ -4,12 +4,12 @@ require('../../css/view.css'); -const itype = require('itype/legacy'); -const rendy = require('rendy/legacy'); +const itype = require('itype'); +const rendy = require('rendy'); const exec = require('execon'); -const currify = require('currify/legacy'); +const currify = require('currify'); const {promisify} = require('es6-promisify'); -const tryToCatch = require('try-to-catch/legacy'); +const tryToCatch = require('try-to-catch'); const modal = require('@cloudcmd/modal'); const createElement = require('@cloudcmd/create-element'); diff --git a/client/sw/sw.js b/client/sw/sw.js index 32503911..3c849bd8 100644 --- a/client/sw/sw.js +++ b/client/sw/sw.js @@ -1,8 +1,8 @@ 'use strict'; const codegen = require('codegen.macro'); -const tryToCatch = require('try-to-catch/legacy'); -const currify = require('currify/legacy'); +const tryToCatch = require('try-to-catch'); +const currify = require('currify'); const isDev = process.env.NODE_ENV === 'development'; diff --git a/common/cloudfunc.js b/common/cloudfunc.js index 95df933b..81124e2a 100644 --- a/common/cloudfunc.js +++ b/common/cloudfunc.js @@ -1,8 +1,8 @@ 'use strict'; -const rendy = require('rendy/legacy'); -const currify = require('currify/legacy'); -const store = require('fullstore/legacy'); +const rendy = require('rendy'); +const currify = require('currify'); +const store = require('fullstore'); const {encode} = require('./entity'); const btoa = require('./btoa'); diff --git a/common/try-to-promise-all.js b/common/try-to-promise-all.js index 80000fa2..c8a54eab 100644 --- a/common/try-to-promise-all.js +++ b/common/try-to-promise-all.js @@ -1,6 +1,6 @@ 'use strict'; -const tryToCatch = require('try-to-catch/legacy'); +const tryToCatch = require('try-to-catch'); const all = Promise.all.bind(Promise); module.exports = async (a) => { From 950028af9290d71b10afcfd83f3fa644708e4bd8 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Tue, 27 Aug 2019 21:22:58 +0300 Subject: [PATCH 0162/1728] feature(cloudcmd) decrease bundle size: disable convertion to es5 cloudcmd.common.js: 155K -> 141K cloudcmd.js: 26K -> 20K --- .babelrc | 12 +----------- .browserslistrc | 5 +++++ package.json | 1 - 3 files changed, 6 insertions(+), 12 deletions(-) create mode 100644 .browserslistrc diff --git a/.babelrc b/.babelrc index b6260752..5fcb804f 100644 --- a/.babelrc +++ b/.babelrc @@ -1,18 +1,8 @@ { "presets": [ - ["@babel/preset-env", { - "exclude": [ - "transform-regenerator" - ] - }], + "@babel/preset-env" ], "plugins": [ - ["module:fast-async", { - "compiler": { - "generators": false, - "runtimePatter": ".js" - } - }], "module:babel-plugin-macros", ] } diff --git a/.browserslistrc b/.browserslistrc new file mode 100644 index 00000000..36cf4ddd --- /dev/null +++ b/.browserslistrc @@ -0,0 +1,5 @@ +last 2 Chrome versions +last 2 Safari versions +Firefox ESR +maintained node versions +not dead diff --git a/package.json b/package.json index 5af12d8f..d2bdbde5 100644 --- a/package.json +++ b/package.json @@ -183,7 +183,6 @@ "eslint-plugin-node": "^9.0.1", "eslint-plugin-putout": "^2.0.0", "extract-text-webpack-plugin": "^4.0.0-alpha.0", - "fast-async": "^7.0.6", "gritty": "^4.7.0", "gunzip-maybe": "^1.3.1", "html-looks-like": "^1.0.2", From c495db4bc672f9167ea87cc3904f9eb69711e508 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Wed, 28 Aug 2019 14:30:41 +0300 Subject: [PATCH 0163/1728] chore(package) v13.3.0 --- ChangeLog | 17 +++++++++++++++++ HELP.md | 3 ++- README.md | 2 +- package.json | 2 +- 4 files changed, 21 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index 2a43f98e..c52cf9b1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,20 @@ +2019.08.28, v13.3.0 + +fix: +- feature(client) remove legacy suffix, use modules as is +- (client) rm additional dialog +- (user-menu) putout path +- (edit-names) hide +- (vim) find + +feature: +- (cloudcmd) decrease bundle size: disable convertion to es5 +- (client) remove legacy suffix, use modules as is +- (package) es6-promisify v6.0.2 +- (menu) rm mute: has no sense with new ponse headers +- (markdown) move out parse to worker + + 2019.08.22, v13.2.1 fix: diff --git a/HELP.md b/HELP.md index 44ca253c..8abef604 100644 --- a/HELP.md +++ b/HELP.md @@ -1,4 +1,4 @@ -# Cloud Commander v13.2.1 +# Cloud Commander v13.3.0 ### [Main][MainURL] [Blog][BlogURL] Live(![Heroku][Heroku_LIVE_IMG] [Heroku][HerokuURL], ![Now][NOW_LIVE_IMG] [Now][NowURL]) @@ -951,6 +951,7 @@ There are a lot of ways to be involved in `Cloud Commander` development: Version history --------------- +- *2019.08.28*, **[v13.3.0](//github.com/coderaiser/cloudcmd/releases/tag/v13.3.0)** - *2019.08.22*, **[v13.2.1](//github.com/coderaiser/cloudcmd/releases/tag/v13.2.1)** - *2019.08.20*, **[v13.2.0](//github.com/coderaiser/cloudcmd/releases/tag/v13.2.0)** - *2019.08.16*, **[v13.1.0](//github.com/coderaiser/cloudcmd/releases/tag/v13.1.0)** diff --git a/README.md b/README.md index a33863bd..0a39b052 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Cloud Commander v13.2.1 [![Build Status][BuildStatusIMGURL]][BuildStatusURL] [![Now status][BuildAppveyorIMGURL]][BuildAppveyorURL] [![Codacy][CodacyIMG]][CodacyURL] [![Gitter][GitterIMGURL]][GitterURL] [![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fcoderaiser%2Fcloudcmd.svg?type=shield)](https://app.fossa.io/projects/git%2Bgithub.com%2Fcoderaiser%2Fcloudcmd?ref=badge_shield) +# Cloud Commander v13.3.0 [![Build Status][BuildStatusIMGURL]][BuildStatusURL] [![Now status][BuildAppveyorIMGURL]][BuildAppveyorURL] [![Codacy][CodacyIMG]][CodacyURL] [![Gitter][GitterIMGURL]][GitterURL] [![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fcoderaiser%2Fcloudcmd.svg?type=shield)](https://app.fossa.io/projects/git%2Bgithub.com%2Fcoderaiser%2Fcloudcmd?ref=badge_shield) ### [Main][MainURL] [Blog][BlogURL] Live([Heroku][HerokuURL], [Now][NowURL]) diff --git a/package.json b/package.json index d2bdbde5..4acb1e36 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "cloudcmd", - "version": "13.2.1", + "version": "13.3.0", "author": "coderaiser (https://github.com/coderaiser)", "description": "File manager for the web with console and editor", "homepage": "http://cloudcmd.io", From 1f07a199dbc33a6c2af24e992f4f68bf975f03da Mon Sep 17 00:00:00 2001 From: coderaiser Date: Fri, 30 Aug 2019 13:07:56 +0300 Subject: [PATCH 0164/1728] feature(package) madrun v3.0.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 4acb1e36..9b2ff802 100644 --- a/package.json +++ b/package.json @@ -191,7 +191,7 @@ "just-pascal-case": "^1.1.0", "limier": "^2.0.0", "load.js": "^2.0.0", - "madrun": "^2.0.0", + "madrun": "^3.0.1", "memfs": "^2.9.0", "minor": "^1.2.2", "mkdirp": "^0.5.1", From dda32c3a40dfa3075bfb4a3a204ac1a1cdaa2cb8 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Tue, 3 Sep 2019 18:46:12 +0300 Subject: [PATCH 0165/1728] feature(view) add support of pdf --- client/modules/view.js | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/client/modules/view.js b/client/modules/view.js index f254da0f..ab7b5890 100644 --- a/client/modules/view.js +++ b/client/modules/view.js @@ -123,9 +123,33 @@ async function show(data, options) { case 'media': return viewMedia(path); + + case 'pdf': + return viewPDF(path); } } +async function viewPDF(src) { + const element = createElement('iframe', { + src, + width: '100%', + height: '100%', + }); + + element.addEventListener('load', () => { + element.contentWindow.addEventListener('keydown', listener); + }); + + const options = { + ...Config, + }; + + if (CloudCmd.config('showFileName')) + options.title = Info.name; + + modal.open(element, options); +} + async function viewMedia(path) { const [e, element] = await getMediaElement(path); @@ -259,7 +283,12 @@ function isVideo(name) { return /\.(mp4|avi)$/i.test(name); } +const isPDF = (name) => /\.(pdf)$/i.test(name); + function getType(name) { + if (isPDF(name)) + return 'pdf'; + if (isImage(name)) return 'image'; From 6879c17edd4166897663e50d5115032f3fe6d237 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Tue, 3 Sep 2019 18:48:08 +0300 Subject: [PATCH 0166/1728] chore(package) v13.4.0 --- ChangeLog | 7 +++++++ HELP.md | 3 ++- README.md | 2 +- package.json | 2 +- 4 files changed, 11 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index c52cf9b1..9dfe3746 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2019.09.03, v13.4.0 + +feature: +- (view) add support of pdf +- (package) madrun v3.0.1 + + 2019.08.28, v13.3.0 fix: diff --git a/HELP.md b/HELP.md index 8abef604..c45a7532 100644 --- a/HELP.md +++ b/HELP.md @@ -1,4 +1,4 @@ -# Cloud Commander v13.3.0 +# Cloud Commander v13.4.0 ### [Main][MainURL] [Blog][BlogURL] Live(![Heroku][Heroku_LIVE_IMG] [Heroku][HerokuURL], ![Now][NOW_LIVE_IMG] [Now][NowURL]) @@ -951,6 +951,7 @@ There are a lot of ways to be involved in `Cloud Commander` development: Version history --------------- +- *2019.09.03*, **[v13.4.0](//github.com/coderaiser/cloudcmd/releases/tag/v13.4.0)** - *2019.08.28*, **[v13.3.0](//github.com/coderaiser/cloudcmd/releases/tag/v13.3.0)** - *2019.08.22*, **[v13.2.1](//github.com/coderaiser/cloudcmd/releases/tag/v13.2.1)** - *2019.08.20*, **[v13.2.0](//github.com/coderaiser/cloudcmd/releases/tag/v13.2.0)** diff --git a/README.md b/README.md index 0a39b052..e2c33b41 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Cloud Commander v13.3.0 [![Build Status][BuildStatusIMGURL]][BuildStatusURL] [![Now status][BuildAppveyorIMGURL]][BuildAppveyorURL] [![Codacy][CodacyIMG]][CodacyURL] [![Gitter][GitterIMGURL]][GitterURL] [![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fcoderaiser%2Fcloudcmd.svg?type=shield)](https://app.fossa.io/projects/git%2Bgithub.com%2Fcoderaiser%2Fcloudcmd?ref=badge_shield) +# Cloud Commander v13.4.0 [![Build Status][BuildStatusIMGURL]][BuildStatusURL] [![Now status][BuildAppveyorIMGURL]][BuildAppveyorURL] [![Codacy][CodacyIMG]][CodacyURL] [![Gitter][GitterIMGURL]][GitterURL] [![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fcoderaiser%2Fcloudcmd.svg?type=shield)](https://app.fossa.io/projects/git%2Bgithub.com%2Fcoderaiser%2Fcloudcmd?ref=badge_shield) ### [Main][MainURL] [Blog][BlogURL] Live([Heroku][HerokuURL], [Now][NowURL]) diff --git a/package.json b/package.json index 9b2ff802..2ea38cfd 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "cloudcmd", - "version": "13.3.0", + "version": "13.4.0", "author": "coderaiser (https://github.com/coderaiser)", "description": "File manager for the web with console and editor", "homepage": "http://cloudcmd.io", From 68cda2cd46c150b686b91694bb1c6628428cc3d5 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Wed, 4 Sep 2019 16:21:29 +0300 Subject: [PATCH 0167/1728] feature(package) restafary v7.0.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2ea38cfd..a852a753 100644 --- a/package.json +++ b/package.json @@ -147,7 +147,7 @@ "pullout": "^3.0.0", "putout": "^5.5.0", "rendy": "^2.0.0", - "restafary": "^6.0.0", + "restafary": "^7.0.0", "restbox": "^1.0.1", "shortdate": "^1.2.0", "socket.io": "^2.0.3", From b543965f357415ed6ea45e02adedddbd3b153c38 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Fri, 6 Sep 2019 17:32:20 +0300 Subject: [PATCH 0168/1728] feature(package) eslint-plugin-node v10.0.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a852a753..7a9154ee 100644 --- a/package.json +++ b/package.json @@ -180,7 +180,7 @@ "domtokenlist-shim": "^1.2.0", "emitify": "^3.0.2", "eslint": "^6.0.0-alpha", - "eslint-plugin-node": "^9.0.1", + "eslint-plugin-node": "^10.0.0", "eslint-plugin-putout": "^2.0.0", "extract-text-webpack-plugin": "^4.0.0-alpha.0", "gritty": "^4.7.0", From 3fff765adfb166d0442efd2c7789dbc8f111b182 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Fri, 6 Sep 2019 17:34:53 +0300 Subject: [PATCH 0169/1728] feature(package) rendy v3.0.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 7a9154ee..db30e79e 100644 --- a/package.json +++ b/package.json @@ -146,7 +146,7 @@ "ponse": "^3.0.0", "pullout": "^3.0.0", "putout": "^5.5.0", - "rendy": "^2.0.0", + "rendy": "^3.0.0", "restafary": "^7.0.0", "restbox": "^1.0.1", "shortdate": "^1.2.0", From 7e29a2f4eef863ec1585b37a4a2ca0f7a2b90358 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Sat, 7 Sep 2019 15:49:31 +0300 Subject: [PATCH 0170/1728] feature(package) wraptile v3.0.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index db30e79e..38a905a9 100644 --- a/package.json +++ b/package.json @@ -158,7 +158,7 @@ "try-catch": "^2.0.0", "try-to-catch": "^1.0.2", "tryrequire": "^2.0.1", - "wraptile": "^2.0.0", + "wraptile": "^3.0.0", "writejson": "^2.0.0" }, "devDependencies": { From 9876611eefaa4cd9ebf06062e28c080676de4de2 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Mon, 9 Sep 2019 19:17:40 +0300 Subject: [PATCH 0171/1728] feature(package) fullstore v2.0.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 38a905a9..9a57b19b 100644 --- a/package.json +++ b/package.json @@ -128,7 +128,7 @@ "flop": "^6.0.0", "for-each-key": "^1.0.1", "format-io": "^1.0.0", - "fullstore": "^1.0.0", + "fullstore": "^2.0.2", "http-auth": "^3.2.3", "inly": "^3.0.0", "jaguar": "^5.0.0", From 2291e35358870b7ae05b9e808e774bfa8752a3fd Mon Sep 17 00:00:00 2001 From: coderaiser Date: Wed, 11 Sep 2019 12:15:18 +0300 Subject: [PATCH 0172/1728] feature(package) rm version-io --- package.json | 1 - 1 file changed, 1 deletion(-) diff --git a/package.json b/package.json index 9a57b19b..59cc46b2 100644 --- a/package.json +++ b/package.json @@ -218,7 +218,6 @@ "tar-stream": "^2.0.0", "unionfs": "^4.0.0", "url-loader": "^2.0.0", - "version-io": "^2.0.1", "webpack": "^4.0.0", "webpack-cli": "^3.0.1", "webpack-merge": "^4.1.2", From 7a2ebe7f13598f52df9270b27c96b30af4fc5eb0 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Wed, 11 Sep 2019 12:15:23 +0300 Subject: [PATCH 0173/1728] feature(package) markdown-it v10.0.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 59cc46b2..a8475936 100644 --- a/package.json +++ b/package.json @@ -134,7 +134,7 @@ "jaguar": "^5.0.0", "jju": "^1.3.0", "jonny": "^2.0.3", - "markdown-it": "^9.0.0", + "markdown-it": "^10.0.0", "mellow": "^2.0.0", "minimist": "^1.2.0", "nomine": "^3.0.0", From e0e1a2480d8faee5b5900e67e8eda93288c99298 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Mon, 16 Sep 2019 17:42:21 +0300 Subject: [PATCH 0174/1728] feature(package) stylelint v11.0.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a8475936..26b9f1a1 100644 --- a/package.json +++ b/package.json @@ -211,7 +211,7 @@ "serviceworker-webpack-plugin": "^1.0.1", "smalltalk": "^3.4.0", "style-loader": "^1.0.0", - "stylelint": "^10.0.0", + "stylelint": "^11.0.0", "stylelint-config-standard": "^18.0.0", "supermenu": "^2.1.2", "supertape": "^1.0.3", From ba78be247e7375f520d86baf9850e45fd3b806b3 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Mon, 16 Sep 2019 17:42:28 +0300 Subject: [PATCH 0175/1728] feature(package) stylelint-config-standard v19.0.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 26b9f1a1..4180e703 100644 --- a/package.json +++ b/package.json @@ -212,7 +212,7 @@ "smalltalk": "^3.4.0", "style-loader": "^1.0.0", "stylelint": "^11.0.0", - "stylelint-config-standard": "^18.0.0", + "stylelint-config-standard": "^19.0.0", "supermenu": "^2.1.2", "supertape": "^1.0.3", "tar-stream": "^2.0.0", From a52b0b4115986eef101398ca36f74193dd77ae96 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Mon, 16 Sep 2019 17:48:42 +0300 Subject: [PATCH 0176/1728] chore(cloudcmd) lint --- client/cloudcmd.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/cloudcmd.js b/client/cloudcmd.js index f90ef712..53ef2391 100644 --- a/client/cloudcmd.js +++ b/client/cloudcmd.js @@ -17,7 +17,7 @@ const { } = require('./sw/register'); // prevent additional loading of emitify -window.Emitify = require('emitify/legacy'); +window.Emitify = require('emitify'); module.exports = window.CloudCmd = (config) => { window.Util = require('../common/util'); From 0ac1724f05804cad5c0eeced7bdca8eb0a58f488 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Mon, 16 Sep 2019 19:04:58 +0300 Subject: [PATCH 0177/1728] feature(package) putout v6.0.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 4180e703..3335270f 100644 --- a/package.json +++ b/package.json @@ -145,7 +145,7 @@ "package-json": "^6.0.0", "ponse": "^3.0.0", "pullout": "^3.0.0", - "putout": "^5.5.0", + "putout": "^6.0.0", "rendy": "^3.0.0", "restafary": "^7.0.0", "restbox": "^1.0.1", From e2687af6ef6385972d2ca158ce55b0add0453307 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Wed, 18 Sep 2019 16:39:04 +0300 Subject: [PATCH 0178/1728] feature(package) @cloudcmd/modal v2.0.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 3335270f..0d425eb4 100644 --- a/package.json +++ b/package.json @@ -167,7 +167,7 @@ "@babel/preset-env": "^7.0.0", "@cloudcmd/clipboard": "^1.0.2", "@cloudcmd/create-element": "^1.0.0", - "@cloudcmd/modal": "^1.0.0", + "@cloudcmd/modal": "^2.0.0", "@cloudcmd/olark": "^2.0.1", "@cloudcmd/stub": "^2.0.0", "auto-globals": "^1.7.0", From 5b14794690bff09319d2a6e1d26b86b23dac5b48 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Wed, 18 Sep 2019 16:46:23 +0300 Subject: [PATCH 0179/1728] feature(package) smalltalk v4.0.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 0d425eb4..66b35f0a 100644 --- a/package.json +++ b/package.json @@ -209,7 +209,7 @@ "scroll-into-view-if-needed": "^2.2.5", "serve-once": "^1.5.0", "serviceworker-webpack-plugin": "^1.0.1", - "smalltalk": "^3.4.0", + "smalltalk": "^4.0.0", "style-loader": "^1.0.0", "stylelint": "^11.0.0", "stylelint-config-standard": "^19.0.0", From be8c584e849d3dede7780b59c48fcc6d9768ea79 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Wed, 18 Sep 2019 16:50:36 +0300 Subject: [PATCH 0180/1728] feature(package) supermenu v3.0.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 66b35f0a..3dab9590 100644 --- a/package.json +++ b/package.json @@ -213,7 +213,7 @@ "style-loader": "^1.0.0", "stylelint": "^11.0.0", "stylelint-config-standard": "^19.0.0", - "supermenu": "^2.1.2", + "supermenu": "^3.0.0", "supertape": "^1.0.3", "tar-stream": "^2.0.0", "unionfs": "^4.0.0", From 2157bbf05f1477561e5ef8358c679ad47700c0b4 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Wed, 18 Sep 2019 17:17:39 +0300 Subject: [PATCH 0181/1728] feature(package) @cloudcmd/create-element v2.0.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 3dab9590..da8dc640 100644 --- a/package.json +++ b/package.json @@ -166,7 +166,7 @@ "@babel/core": "^7.0.0", "@babel/preset-env": "^7.0.0", "@cloudcmd/clipboard": "^1.0.2", - "@cloudcmd/create-element": "^1.0.0", + "@cloudcmd/create-element": "^2.0.0", "@cloudcmd/modal": "^2.0.0", "@cloudcmd/olark": "^2.0.1", "@cloudcmd/stub": "^2.0.0", From 83cf1b6990ae45375924f4d1242acde74cf6aa86 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Wed, 18 Sep 2019 17:03:36 +0300 Subject: [PATCH 0182/1728] feature(package) load.js v3.0.0 --- client/client.js | 7 ++----- client/cloudcmd.js | 6 ++---- client/dom/load-remote.js | 30 ++++++++++-------------------- client/load-module.js | 3 +-- client/modules/cloud.js | 5 ++--- client/modules/config/index.js | 2 +- client/modules/edit.js | 2 +- client/modules/konsole.js | 3 +-- client/modules/operation/index.js | 28 +++++++++++++--------------- client/modules/terminal-run.js | 4 +--- client/modules/terminal.js | 5 +---- client/modules/user-menu/index.js | 3 +-- client/modules/view.js | 3 +-- package.json | 2 +- 14 files changed, 38 insertions(+), 65 deletions(-) diff --git a/client/client.js b/client/client.js index 1a228e98..aaf0abf1 100644 --- a/client/client.js +++ b/client/client.js @@ -20,9 +20,6 @@ const currify = require('currify'); const noJS = (a) => a.replace(/.js$/, ''); -const loadCSS = promisify(load.css); -const loadJS = promisify(load.js); - const { apiURL, formatMsg, @@ -158,7 +155,7 @@ function CloudCmdProto(DOM) { CloudCmd.MIN_ONE_PANEL_WIDTH = Infinity; if (!document.body.scrollIntoViewIfNeeded) - await loadJS(prefix + CloudCmd.DIRCLIENT_MODULES + 'polyfill.js'); + await load.js(prefix + CloudCmd.DIRCLIENT_MODULES + 'polyfill.js'); await initModules(); await baseInit(); @@ -171,7 +168,7 @@ function CloudCmdProto(DOM) { const {prefix} = CloudCmd; const name = prefix + '/dist/cloudcmd.common.css'; - await loadCSS(name); + await load.css(name); } this.route = (path) => { diff --git a/client/cloudcmd.js b/client/cloudcmd.js index 53ef2391..a1bcdacb 100644 --- a/client/cloudcmd.js +++ b/client/cloudcmd.js @@ -5,7 +5,6 @@ require('../css/nojs.css'); require('../css/columns/name-size-date.css'); require('../css/columns/name-size.css'); -const {promisify} = require('es6-promisify'); const wraptile = require('wraptile'); const load = require('load.js'); @@ -55,10 +54,9 @@ const onUpdateFound = wraptile(async (config) => { const {DOM} = window; const prefix = getPrefix(config.prefix); - const js = promisify(load.js); - await js(`${prefix}/dist/cloudcmd.common.js`); - await js(`${prefix}/dist/cloudcmd.js`); + await load.js(`${prefix}/dist/cloudcmd.common.js`); + await load.js(`${prefix}/dist/cloudcmd.js`); console.log('cloudcmd: sw: updated'); diff --git a/client/dom/load-remote.js b/client/dom/load-remote.js index 52e66934..b4e0aa22 100644 --- a/client/dom/load-remote.js +++ b/client/dom/load-remote.js @@ -2,16 +2,14 @@ /* global CloudCmd */ -const exec = require('execon'); const rendy = require('rendy'); const itype = require('itype'); -const wraptile = require('wraptile'); const load = require('load.js'); +const tryToCatch = require('try-to-catch'); const {findObjByNameInArr} = require('../../common/util'); const Files = require('./files'); -const parallel = wraptile(load.parallel); module.exports = (name, options, callback = options) => { const {prefix, config} = CloudCmd; @@ -20,7 +18,7 @@ module.exports = (name, options, callback = options) => { if (o.name && window[o.name]) return callback(); - Files.get('modules').then((modules) => { + Files.get('modules').then(async (modules) => { const online = config('online') && navigator.onLine; const module = findObjByNameInArr(modules.remote, name); @@ -48,23 +46,15 @@ module.exports = (name, options, callback = options) => { }); }); - const on = funcON(localURL, remoteURL, callback); - const off = funcOFF(localURL, callback); + if (online) { + const [e] = await tryToCatch(load.parallel, remoteURL); + + if (!e) + return callback(); + } - exec.if(online, on, off); + const [e] = await tryToCatch(load.parallel, localURL); + callback(e); }); }; -function funcOFF(local, callback) { - return parallel(local, callback); -} - -function funcON (local, remote,callback) { - return parallel(remote, (error) => { - if (error) - return funcOFF(); - - callback(); - }); -} - diff --git a/client/load-module.js b/client/load-module.js index a60638b7..5111259c 100644 --- a/client/load-module.js +++ b/client/load-module.js @@ -4,8 +4,7 @@ const exec = require('execon'); const tryToCatch = require('try-to-catch'); -const {promisify} = require('es6-promisify'); -const loadJS = promisify(require('load.js').js); +const loadJS = require('load.js').js; const pascalCase = require('just-pascal-case'); const noJS = (a) => a.replace(/.js$/, ''); diff --git a/client/modules/cloud.js b/client/modules/cloud.js index af019f05..59c203c9 100644 --- a/client/modules/cloud.js +++ b/client/modules/cloud.js @@ -4,8 +4,7 @@ const exec = require('execon'); const currify = require('currify'); -const {promisify} = require('es6-promisify'); -const loadJS = promisify(require('load.js').js); +const load = require('load.js'); const {log} = CloudCmd; @@ -62,7 +61,7 @@ async function loadFiles() { return Promise.all([ Files.get('modules'), - loadJS(js), + load.js(js), ]); } diff --git a/client/modules/config/index.js b/client/modules/config/index.js index 75ec79b5..014ea2fe 100644 --- a/client/modules/config/index.js +++ b/client/modules/config/index.js @@ -44,7 +44,7 @@ const Config = {}; let Template; -const loadCSS = promisify(load.css); +const loadCSS = load.css; module.exports.init = async () => { if (!CloudCmd.config('configDialog')) diff --git a/client/modules/edit.js b/client/modules/edit.js index 3f89d39b..1807145b 100644 --- a/client/modules/edit.js +++ b/client/modules/edit.js @@ -6,7 +6,7 @@ const {promisify} = require('es6-promisify'); const tryToCatch = require('try-to-catch'); const createElement = require('@cloudcmd/create-element'); const load = require('load.js'); -const loadJS = promisify(load.js); +const loadJS = load.js; const {MAX_FILE_SIZE: maxSize} = require('../../common/cloudfunc'); const {time, timeEnd} = require('../../common/util'); diff --git a/client/modules/konsole.js b/client/modules/konsole.js index 5c973f84..e1fda7d5 100644 --- a/client/modules/konsole.js +++ b/client/modules/konsole.js @@ -8,10 +8,9 @@ CloudCmd.Konsole = exports; const exec = require('execon'); -const {promisify} = require('es6-promisify'); const currify = require('currify'); const tryToCatch = require('try-to-catch'); -const loadJS = promisify(require('load.js').js); +const loadJS = require('load.js').js; const createElement = require('@cloudcmd/create-element'); const Images = require('../dom/images'); diff --git a/client/modules/operation/index.js b/client/modules/operation/index.js index 09a15a99..fff15efb 100644 --- a/client/modules/operation/index.js +++ b/client/modules/operation/index.js @@ -9,7 +9,8 @@ const currify = require('currify'); const wraptile = require('wraptile'); const {promisify} = require('es6-promisify'); const exec = require('execon'); -const loadJS = require('load.js').js; +const load = require('load.js'); +const tryToCatch = require('try-to-catch'); const {encode} = require('../../../common/entity'); const callbackify = require('../../../common/callbackify'); @@ -60,7 +61,7 @@ module.exports.init = promisify((callback) => { exec.series([ DOM.loadSocket, - (callback) => { + async (callback) => { if (!config('progress') || config('dropbox')) return callback(); @@ -68,7 +69,9 @@ module.exports.init = promisify((callback) => { prefix, prefixSocket, } = CloudCmd; - load(initOperations(prefix, prefixSocket, callback)); + + await tryToCatch(loadAll, initOperations(prefix, prefixSocket)); + callback(); }, (callback) => { Loaded = true; @@ -514,21 +517,16 @@ async function prompt(msg, to, names) { return Dialog.prompt(msg, to); } -function load(callback) { +async function loadAll() { const {prefix} = CloudCmd; const file = `${prefix}/fileop/fileop.js`; - loadJS(file, (error) => { - if (error) { - Dialog.alert(error.message); - return exec(callback); - } - - Loaded = true; - Util.timeEnd(Name + ' load'); - exec(callback); - }); + const [error] = await tryToCatch(load.js, file); - Util.time(Name + ' load'); + if (error) + Dialog.alert(error.message); + + Loaded = true; + Util.timeEnd(Name + ' load'); } diff --git a/client/modules/terminal-run.js b/client/modules/terminal-run.js index eaadfe5f..5e0334ba 100644 --- a/client/modules/terminal-run.js +++ b/client/modules/terminal-run.js @@ -13,8 +13,6 @@ const load = require('load.js'); const DOM = require('../dom'); const Images = require('../dom/images'); -const loadParallel = promisify(load.parallel); - const {Dialog} = DOM; const { Key, @@ -36,7 +34,7 @@ const loadAll = async () => { const js = `${prefixGritty}/gritty.js`; const css = `${prefix}/dist/terminal.css`; - const [e] = await tryToCatch(loadParallel, [js, css]); + const [e] = await tryToCatch(load.parallel, [js, css]); if (e) { const src = e.target.src.replace(window.location.href, ''); diff --git a/client/modules/terminal.js b/client/modules/terminal.js index 20a85392..6ddc632c 100644 --- a/client/modules/terminal.js +++ b/client/modules/terminal.js @@ -1,8 +1,5 @@ 'use strict'; -/* global CloudCmd, gritty */ - -const {promisify} = require('es6-promisify'); const tryToCatch = require('try-to-catch'); require('../../css/terminal.css'); @@ -12,7 +9,7 @@ const load = require('load.js'); const DOM = require('../dom'); const Images = require('../dom/images'); -const loadParallel = promisify(load.parallel); +const loadParallel = load.parallel; const {Dialog} = DOM; const { diff --git a/client/modules/user-menu/index.js b/client/modules/user-menu/index.js index 27f61ad9..770762fc 100644 --- a/client/modules/user-menu/index.js +++ b/client/modules/user-menu/index.js @@ -6,7 +6,6 @@ require('../../../css/user-menu.css'); const currify = require('currify'); const wraptile = require('wraptile'); -const {promisify} = require('es6-promisify'); const fullstore = require('fullstore'); const load = require('load.js'); const createElement = require('@cloudcmd/create-element'); @@ -20,7 +19,7 @@ const Dialog = require('../../dom/dialog'); const getUserMenu = require('./get-user-menu'); const navigate = require('./navigate'); -const loadCSS = promisify(load.css); +const loadCSS = load.css; const sourceStore = fullstore(); const Name = 'UserMenu'; diff --git a/client/modules/view.js b/client/modules/view.js index ab7b5890..c5f6743d 100644 --- a/client/modules/view.js +++ b/client/modules/view.js @@ -8,7 +8,6 @@ const itype = require('itype'); const rendy = require('rendy'); const exec = require('execon'); const currify = require('currify'); -const {promisify} = require('es6-promisify'); const tryToCatch = require('try-to-catch'); const modal = require('@cloudcmd/modal'); @@ -31,7 +30,7 @@ const lifo = currify((fn, el, cb, name) => fn(name, el, cb)); const addEvent = lifo(Events.add); const getRegExp = (ext) => RegExp(`\\.${ext}$`, 'i'); -const loadCSS = promisify(load.css); +const loadCSS = load.css; module.exports.show = show; module.exports.hide = hide; diff --git a/package.json b/package.json index da8dc640..b4876a14 100644 --- a/package.json +++ b/package.json @@ -190,7 +190,7 @@ "inherits": "^2.0.3", "just-pascal-case": "^1.1.0", "limier": "^2.0.0", - "load.js": "^2.0.0", + "load.js": "^3.0.0", "madrun": "^3.0.1", "memfs": "^2.9.0", "minor": "^1.2.2", From 160114a36469e19c420b8da76ff9586a41112c93 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Wed, 18 Sep 2019 23:16:22 +0300 Subject: [PATCH 0183/1728] chore(terminal) lint --- client/modules/terminal.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/client/modules/terminal.js b/client/modules/terminal.js index 6ddc632c..bd481854 100644 --- a/client/modules/terminal.js +++ b/client/modules/terminal.js @@ -1,5 +1,8 @@ 'use strict'; +/* global CloudCmd */ +/* global gritty */ + const tryToCatch = require('try-to-catch'); require('../../css/terminal.css'); From b35c692e3b09121152b62e6c0c1fa0c94160ae29 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Thu, 19 Sep 2019 21:40:57 +0300 Subject: [PATCH 0184/1728] feature(package) limier v2.0.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b4876a14..a49fb889 100644 --- a/package.json +++ b/package.json @@ -189,7 +189,7 @@ "html-webpack-plugin": "^3.0.7", "inherits": "^2.0.3", "just-pascal-case": "^1.1.0", - "limier": "^2.0.0", + "limier": "^2.0.1", "load.js": "^3.0.0", "madrun": "^3.0.1", "memfs": "^2.9.0", From f17af9a920343928e5afd033ab307806a2952ff2 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Thu, 19 Sep 2019 21:45:36 +0300 Subject: [PATCH 0185/1728] feature(package) currify v4.0.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a49fb889..9a568cb3 100644 --- a/package.json +++ b/package.json @@ -115,7 +115,7 @@ "console-io": "^10.0.0", "copymitter": "^4.0.2", "criton": "^2.0.0", - "currify": "^3.0.0", + "currify": "^4.0.0", "deepmerge": "^4.0.0", "deepword": "^6.0.0", "dword": "^11.0.0", From 8210c4f05df0b3b9bea423f65b2262687bf9e24c Mon Sep 17 00:00:00 2001 From: coderaiser Date: Thu, 19 Sep 2019 21:57:34 +0300 Subject: [PATCH 0186/1728] feature(package) limier v3.0.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 9a568cb3..91d3d2f6 100644 --- a/package.json +++ b/package.json @@ -189,7 +189,7 @@ "html-webpack-plugin": "^3.0.7", "inherits": "^2.0.3", "just-pascal-case": "^1.1.0", - "limier": "^2.0.1", + "limier": "^3.0.0", "load.js": "^3.0.0", "madrun": "^3.0.1", "memfs": "^2.9.0", From 68d186e686f3bafdc2a0daa583224de50eb5b339 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Fri, 20 Sep 2019 14:05:00 +0300 Subject: [PATCH 0187/1728] feature(package) format-io v2.0.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 91d3d2f6..23fa9216 100644 --- a/package.json +++ b/package.json @@ -127,7 +127,7 @@ "find-up": "^4.0.0", "flop": "^6.0.0", "for-each-key": "^1.0.1", - "format-io": "^1.0.0", + "format-io": "^2.0.0", "fullstore": "^2.0.2", "http-auth": "^3.2.3", "inly": "^3.0.0", From 4fd5b3883234f077e3c57dab5e10be8b77245f92 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Fri, 20 Sep 2019 14:30:25 +0300 Subject: [PATCH 0188/1728] feature(package) @cloudcmd/olark v3.0.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 23fa9216..8ad7cf6a 100644 --- a/package.json +++ b/package.json @@ -168,7 +168,7 @@ "@cloudcmd/clipboard": "^1.0.2", "@cloudcmd/create-element": "^2.0.0", "@cloudcmd/modal": "^2.0.0", - "@cloudcmd/olark": "^2.0.1", + "@cloudcmd/olark": "^3.0.0", "@cloudcmd/stub": "^2.0.0", "auto-globals": "^1.7.0", "babel-loader": "^8.0.0", From 8c318fce0e87a75c00f9a92d67184725ad9a80bc Mon Sep 17 00:00:00 2001 From: coderaiser Date: Fri, 20 Sep 2019 17:12:52 +0300 Subject: [PATCH 0189/1728] chore(package) v13.4.1 --- ChangeLog | 25 +++++++++++++++++++++++++ HELP.md | 3 ++- README.md | 2 +- package.json | 2 +- 4 files changed, 29 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index 9dfe3746..c18f42f7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,28 @@ +2019.09.20, v13.4.1 + +feature: +- (package) @cloudcmd/olark v3.0.0 +- (package) format-io v2.0.0 +- (package) limier v3.0.0 +- (package) currify v4.0.0 +- (package) limier v2.0.1 +- (package) load.js v3.0.0 +- (package) @cloudcmd/create-element v2.0.0 +- (package) supermenu v3.0.0 +- (package) smalltalk v4.0.0 +- (package) @cloudcmd/modal v2.0.0 +- (package) putout v6.0.0 +- (package) stylelint-config-standard v19.0.0 +- (package) stylelint v11.0.0 +- (package) markdown-it v10.0.0 +- (package) rm version-io +- (package) fullstore v2.0.2 +- (package) wraptile v3.0.0 +- (package) rendy v3.0.0 +- (package) eslint-plugin-node v10.0.0 +- (package) restafary v7.0.0 + + 2019.09.03, v13.4.0 feature: diff --git a/HELP.md b/HELP.md index c45a7532..27ccc30a 100644 --- a/HELP.md +++ b/HELP.md @@ -1,4 +1,4 @@ -# Cloud Commander v13.4.0 +# Cloud Commander v13.4.1 ### [Main][MainURL] [Blog][BlogURL] Live(![Heroku][Heroku_LIVE_IMG] [Heroku][HerokuURL], ![Now][NOW_LIVE_IMG] [Now][NowURL]) @@ -951,6 +951,7 @@ There are a lot of ways to be involved in `Cloud Commander` development: Version history --------------- +- *2019.09.20*, **[v13.4.1](//github.com/coderaiser/cloudcmd/releases/tag/v13.4.1)** - *2019.09.03*, **[v13.4.0](//github.com/coderaiser/cloudcmd/releases/tag/v13.4.0)** - *2019.08.28*, **[v13.3.0](//github.com/coderaiser/cloudcmd/releases/tag/v13.3.0)** - *2019.08.22*, **[v13.2.1](//github.com/coderaiser/cloudcmd/releases/tag/v13.2.1)** diff --git a/README.md b/README.md index e2c33b41..c8ee6e21 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Cloud Commander v13.4.0 [![Build Status][BuildStatusIMGURL]][BuildStatusURL] [![Now status][BuildAppveyorIMGURL]][BuildAppveyorURL] [![Codacy][CodacyIMG]][CodacyURL] [![Gitter][GitterIMGURL]][GitterURL] [![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fcoderaiser%2Fcloudcmd.svg?type=shield)](https://app.fossa.io/projects/git%2Bgithub.com%2Fcoderaiser%2Fcloudcmd?ref=badge_shield) +# Cloud Commander v13.4.1 [![Build Status][BuildStatusIMGURL]][BuildStatusURL] [![Now status][BuildAppveyorIMGURL]][BuildAppveyorURL] [![Codacy][CodacyIMG]][CodacyURL] [![Gitter][GitterIMGURL]][GitterURL] [![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fcoderaiser%2Fcloudcmd.svg?type=shield)](https://app.fossa.io/projects/git%2Bgithub.com%2Fcoderaiser%2Fcloudcmd?ref=badge_shield) ### [Main][MainURL] [Blog][BlogURL] Live([Heroku][HerokuURL], [Now][NowURL]) diff --git a/package.json b/package.json index 8ad7cf6a..c2ac65b8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "cloudcmd", - "version": "13.4.0", + "version": "13.4.1", "author": "coderaiser (https://github.com/coderaiser)", "description": "File manager for the web with console and editor", "homepage": "http://cloudcmd.io", From 715fe59ee58229b49ea41900798d009ff3aed38b Mon Sep 17 00:00:00 2001 From: coderaiser Date: Fri, 20 Sep 2019 17:16:08 +0300 Subject: [PATCH 0190/1728] docs(help) group rename link --- HELP.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/HELP.md b/HELP.md index 27ccc30a..0b64b2c8 100644 --- a/HELP.md +++ b/HELP.md @@ -189,7 +189,7 @@ Hot keys | `Ctrl + R` | refresh | `Ctrl + D` | clear local storage | `Ctrl + A` | select all files in a panel -| `Ctrl + M` | [rename selected files](https://github.com/coderaiser/cloudcmd/releases/tag/v12.0.0) in editor +| `Ctrl + M` | [rename selected files](https://github.com/coderaiser/cloudcmd/releases/tag/v12.1.0) in editor | `Shift + Ctrl + M` | rename selected files in vim mode of editor | `Ctrl + U` | swap panels | `Ctrl + F3` | sort by name From cd5188c71e2bab635b9855c78a886be4307dc4f5 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Sat, 21 Sep 2019 16:42:58 +0300 Subject: [PATCH 0191/1728] fix(terminal) on -> onKey --- client/modules/terminal-run.js | 4 +++- client/modules/terminal.js | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/client/modules/terminal-run.js b/client/modules/terminal-run.js index 5e0334ba..ca31389f 100644 --- a/client/modules/terminal-run.js +++ b/client/modules/terminal-run.js @@ -121,7 +121,9 @@ function create(createOptions) { Socket = socket; Terminal = terminal; - Terminal.on('key', (char, {keyCode, shiftKey}) => { + Terminal.onKey(({domEvent}) => { + const {keyCode, shiftKey} = domEvent; + if (commandExit) hide(); diff --git a/client/modules/terminal.js b/client/modules/terminal.js index bd481854..753fbc67 100644 --- a/client/modules/terminal.js +++ b/client/modules/terminal.js @@ -91,7 +91,9 @@ function create() { Socket = socket; Terminal = terminal; - Terminal.on('key', (char, {keyCode, shiftKey}) => { + Terminal.onKey(({domEvent}) => { + const {keyCode, shiftKey} = domEvent; + if (shiftKey && keyCode === Key.ESC) { hide(); } From e0df785ecee83ceedc11503f21a4dd2c2cfc6c0e Mon Sep 17 00:00:00 2001 From: coderaiser Date: Sat, 21 Sep 2019 16:47:59 +0300 Subject: [PATCH 0192/1728] chore(package) v13.4.2 --- ChangeLog | 6 ++++++ HELP.md | 3 ++- README.md | 2 +- package.json | 2 +- 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index c18f42f7..33e2acc7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2019.09.21, v13.4.2 + +fix: +- (terminal) on -> onKey + + 2019.09.20, v13.4.1 feature: diff --git a/HELP.md b/HELP.md index 0b64b2c8..44478adf 100644 --- a/HELP.md +++ b/HELP.md @@ -1,4 +1,4 @@ -# Cloud Commander v13.4.1 +# Cloud Commander v13.4.2 ### [Main][MainURL] [Blog][BlogURL] Live(![Heroku][Heroku_LIVE_IMG] [Heroku][HerokuURL], ![Now][NOW_LIVE_IMG] [Now][NowURL]) @@ -951,6 +951,7 @@ There are a lot of ways to be involved in `Cloud Commander` development: Version history --------------- +- *2019.09.21*, **[v13.4.2](//github.com/coderaiser/cloudcmd/releases/tag/v13.4.2)** - *2019.09.20*, **[v13.4.1](//github.com/coderaiser/cloudcmd/releases/tag/v13.4.1)** - *2019.09.03*, **[v13.4.0](//github.com/coderaiser/cloudcmd/releases/tag/v13.4.0)** - *2019.08.28*, **[v13.3.0](//github.com/coderaiser/cloudcmd/releases/tag/v13.3.0)** diff --git a/README.md b/README.md index c8ee6e21..6bbde6c9 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Cloud Commander v13.4.1 [![Build Status][BuildStatusIMGURL]][BuildStatusURL] [![Now status][BuildAppveyorIMGURL]][BuildAppveyorURL] [![Codacy][CodacyIMG]][CodacyURL] [![Gitter][GitterIMGURL]][GitterURL] [![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fcoderaiser%2Fcloudcmd.svg?type=shield)](https://app.fossa.io/projects/git%2Bgithub.com%2Fcoderaiser%2Fcloudcmd?ref=badge_shield) +# Cloud Commander v13.4.2 [![Build Status][BuildStatusIMGURL]][BuildStatusURL] [![Now status][BuildAppveyorIMGURL]][BuildAppveyorURL] [![Codacy][CodacyIMG]][CodacyURL] [![Gitter][GitterIMGURL]][GitterURL] [![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fcoderaiser%2Fcloudcmd.svg?type=shield)](https://app.fossa.io/projects/git%2Bgithub.com%2Fcoderaiser%2Fcloudcmd?ref=badge_shield) ### [Main][MainURL] [Blog][BlogURL] Live([Heroku][HerokuURL], [Now][NowURL]) diff --git a/package.json b/package.json index c2ac65b8..7447143a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "cloudcmd", - "version": "13.4.1", + "version": "13.4.2", "author": "coderaiser (https://github.com/coderaiser)", "description": "File manager for the web with console and editor", "homepage": "http://cloudcmd.io", From 6e4bedca2df465dbaaf775020a6de6b024624c40 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Wed, 21 Aug 2019 21:44:39 +0300 Subject: [PATCH 0193/1728] feature(cloudcmd) remove --progress option, make always enabled --- HELP.md | 3 --- bin/cloudcmd.js | 3 --- client/modules/operation/index.js | 2 +- json/config.json | 1 - json/help.json | 2 -- man/cloudcmd.1 | 2 -- tmpl/config.hbs | 6 ------ 7 files changed, 1 insertion(+), 18 deletions(-) diff --git a/HELP.md b/HELP.md index 44478adf..e88a4f07 100644 --- a/HELP.md +++ b/HELP.md @@ -82,7 +82,6 @@ Cloud Commander supports the following command-line parameters: | `--prefix` | set url prefix | `--prefix-socket` | set prefix for url connection | `--port` | set port number -| `--progress` | show progress of file operations | `--confirm-copy` | confirm copy | `--confirm-move` | confirm move | `--open` | open web browser when server starts @@ -117,7 +116,6 @@ Cloud Commander supports the following command-line parameters: | `--no-name` | set default tab name in web browser | `--no-keys-panel` | hide keys panel | `--no-one-file-panel` | show two file panels -| `--no-progress` | do not show progress of file operations | `--no-confirm-copy` | do not confirm copy | `--no-confirm-move` | do not confirm move | `--no-config-dialog` | disable config dialog @@ -398,7 +396,6 @@ Here's a description of all options: "root" : "/", // root directory "prefix" : "", // url prefix "prefixSocket" : "", // prefix for socket connection - "progress" : true, // show progress of file operations "confirmCopy" : true, // confirm copy "confirmMove" : true, // confirm move "showConfig" : false, // show config at startup diff --git a/bin/cloudcmd.js b/bin/cloudcmd.js index cf887908..a72f2241 100755 --- a/bin/cloudcmd.js +++ b/bin/cloudcmd.js @@ -59,7 +59,6 @@ const args = require('minimist')(argv.slice(2), { 'server', 'online', 'open', - 'progress', 'config-dialog', 'config-auth', 'console', @@ -94,7 +93,6 @@ const args = require('minimist')(argv.slice(2), { 'username' : env('username') || config('username'), 'root' : choose(env('root'), config('root')), 'prefix' : config('prefix'), - 'progress' : config('progress'), 'console' : choose(env.bool('console'), config('console')), 'contact' : choose(env.bool('contact'), config('contact')), 'terminal' : choose(env.bool('terminal'), config('terminal')), @@ -159,7 +157,6 @@ function main() { config('online', args.online); config('open', args.open); config('username', args.username); - config('progress', args.progress); config('console', args.console); config('syncConsolePath', args['sync-console-path']); config('showFileName', args['show-file-name']); diff --git a/client/modules/operation/index.js b/client/modules/operation/index.js index fff15efb..61bdec90 100644 --- a/client/modules/operation/index.js +++ b/client/modules/operation/index.js @@ -62,7 +62,7 @@ module.exports.init = promisify((callback) => { exec.series([ DOM.loadSocket, async (callback) => { - if (!config('progress') || config('dropbox')) + if (config('dropbox')) return callback(); const { diff --git a/json/config.json b/json/config.json index eec170c8..54e78bfe 100644 --- a/json/config.json +++ b/json/config.json @@ -18,7 +18,6 @@ "root": "/", "prefix": "", "prefixSocket": "", - "progress": true, "contact": true, "confirmCopy": true, "confirmMove": true, diff --git a/json/help.json b/json/help.json index e9455868..84c6dbf9 100644 --- a/json/help.json +++ b/json/help.json @@ -15,7 +15,6 @@ "--prefix ": "set url prefix", "--prefix-socket ": "set prefix for socket connection", "--port ": "set port number", - "--progress ": "show progress of file operations", "--confirm-copy ": "confirm copy", "--confirm-move ": "confirm move", "--open ": "open web browser when server started", @@ -51,7 +50,6 @@ "--no-one-file-panel ": "show two file panels", "--no-keys-panel ": "hide keys panel", "--no-one-file-panel ": "show two file panels", - "--no-progress ": "do not show progress of file operations", "--no-confirm-copy ": "do not confirm copy", "--no-confirm-move ": "do not confirm move", "--no-config-dialog ": "disable config dialog", diff --git a/man/cloudcmd.1 b/man/cloudcmd.1 index 9db5e7d1..781e01e1 100644 --- a/man/cloudcmd.1 +++ b/man/cloudcmd.1 @@ -38,7 +38,6 @@ programs in browser from any computer, mobile or tablet device. --prefix set url prefix --prefix-socket set prefix for socket connection --port set port number - --progress show progress of file operations --confirm-copy confirm copy --confirm-move confirm move --open open web browser when server started @@ -73,7 +72,6 @@ programs in browser from any computer, mobile or tablet device. --no-name set default tab name in web browser --no-one-file-panel show two file panels --no-keys-panel hide keys panel - --no-progress do not show progress of file operations --no-confirm-copy do not confirm copy --no-confirm-move do not confirm move --no-contact disable contact diff --git a/tmpl/config.hbs b/tmpl/config.hbs index 742c2b24..b7a3e757 100644 --- a/tmpl/config.hbs +++ b/tmpl/config.hbs @@ -146,12 +146,6 @@ Confirm Move - -
  • -
    • +