diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml index 6e69991e..93b856e8 100644 --- a/.github/FUNDING.yml +++ b/.github/FUNDING.yml @@ -1,10 +1,4 @@ -# These are supported funding model platforms - github: coderaiser patreon: coderaiser open_collective: cloudcmd ko_fi: coderaiser -#issuehunt: # Replace with a single IssueHunt username -#otechie: # Replace with a single Otechie username -#lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry -#liberapay: ~1758956 diff --git a/.github/workflows/nodejs.yml b/.github/workflows/nodejs.yml index 7914ba68..95e1fd6e 100644 --- a/.github/workflows/nodejs.yml +++ b/.github/workflows/nodejs.yml @@ -48,6 +48,6 @@ jobs: - name: Coverage run: redrun coverage coverage:report - name: Coveralls - uses: coverallsapp/github-action@master + uses: coverallsapp/github-action@v2 with: github-token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.putout.json b/.putout.json index ef357bf1..c746c016 100644 --- a/.putout.json +++ b/.putout.json @@ -1,7 +1,5 @@ { - "plugins": [ - "cloudcmd" - ], + "plugins": ["cloudcmd"], "ignore": [ "html", "fixture*", diff --git a/.webpack/css.js b/.webpack/css.js index 1d31bad9..9eea5ce9 100644 --- a/.webpack/css.js +++ b/.webpack/css.js @@ -37,11 +37,8 @@ const plugins = clean([ const rules = [{ test: /\.css$/, exclude: /css\/(nojs|view|config|terminal|user-menu|columns.*)\.css/, - use: extractMain.extract([ - 'css-loader', - ]), -}, -...cssPlugins.map(extract), { + use: extractMain.extract(['css-loader']), +}, ...cssPlugins.map(extract), { test: /\.(png|gif|svg|woff|woff2|eot|ttf)$/, use: { loader: 'url-loader', @@ -63,7 +60,8 @@ function getCSSList(dir) { const addDir = (name) => `${dir}/${name}`; const rootDir = join(__dirname, '..'); - return fs.readdirSync(`${rootDir}/css/${dir}`) + return fs + .readdirSync(`${rootDir}/css/${dir}`) .map(base) .map(addDir); } @@ -73,9 +71,6 @@ function extract(extractPlugin) { return { test: RegExp(`css/${filename}`), - use: extractPlugin.extract([ - 'css-loader', - ]), + use: extractPlugin.extract(['css-loader']), }; } - diff --git a/.webpack/html.js b/.webpack/html.js index 6a066e53..b684acb2 100644 --- a/.webpack/html.js +++ b/.webpack/html.js @@ -19,25 +19,24 @@ module.exports = { function getMinifyHtmlOptions() { return { - removeComments: true, - removeCommentsFromCDATA: true, - removeCDATASectionsFromCDATA: true, - collapseWhitespace: true, - collapseBooleanAttributes: true, - removeAttributeQuotes: true, - removeRedundantAttributes: true, - useShortDoctype: true, - removeEmptyAttributes: true, + removeComments: true, + removeCommentsFromCDATA: true, + removeCDATASectionsFromCDATA: true, + collapseWhitespace: true, + collapseBooleanAttributes: true, + removeAttributeQuotes: true, + removeRedundantAttributes: true, + useShortDoctype: true, + removeEmptyAttributes: true, /* оставляем, поскольку у нас * в элемент fm генерируеться * таблица файлов */ - removeEmptyElements: false, - removeOptionalTags: true, - removeScriptTypeAttributes: true, - removeStyleLinkTypeAttributes: true, + removeEmptyElements: false, + removeOptionalTags: true, + removeScriptTypeAttributes: true, + removeStyleLinkTypeAttributes: true, - minifyJS: true, + minifyJS: true, }; } - diff --git a/.webpack/js.js b/.webpack/js.js index 18d14262..068d3891 100644 --- a/.webpack/js.js +++ b/.webpack/js.js @@ -44,18 +44,17 @@ const rules = clean([ exclude: /node_modules/, loader: 'babel-loader', options, - }]); + }, +]); const plugins = [ new EnvironmentPlugin({ NODE_ENV, }), - new ServiceWorkerWebpackPlugin({ entry: join(__dirname, '..', 'client', 'sw', 'sw.js'), excludes: ['*'], }), - new WebpackBar(), ]; @@ -102,9 +101,7 @@ module.exports = { devtoolModuleFilenameTemplate, publicPath: '/dist/', }, - externals: [ - externals, - ], + externals: [externals], module: { rules, noParse, @@ -132,4 +129,3 @@ function devtoolModuleFilenameTemplate(info) { const resource = info.absoluteResourcePath.replace(rootDir + sep, ''); return `file://cloudcmd/${resource}`; } - diff --git a/HELP.md b/HELP.md index 4cd6eacb..07449236 100644 --- a/HELP.md +++ b/HELP.md @@ -374,50 +374,50 @@ Here's a description of all options: ```json { - "name" : "", // set tab name in web browser - "auth" : false, // enable http authentication - "username" : "root", // username for authentication - "password" : "toor", // password hash for authentication - "algo" : "sha512WithRSAEncryption", // cryptographic algorithm - "editor" : "edward", // default, could be "dword" or "edward" - "packer" : "tar", // default, could be "tar" or "zip" - "diff" : true, // when save - send patch, not whole file - "zip" : true, // zip text before send / unzip before save - "buffer" : true, // buffer for copying files - "dirStorage" : true, // store directory listing - "online" : false, // do not load js files from cdn - "open" : true, // open web browser when server started - "oneFilePanel" : false, // show one file panel - "keysPanel" : true, // show classic panel with buttons of keys - "port" : 8000, // http port - "ip" : null, // ip or null(default) - "root" : "/", // root directory - "prefix" : "", // url prefix - "prefixSocket" : "", // prefix for socket connection - "confirmCopy" : true, // confirm copy - "confirmMove" : true, // confirm move - "showConfig" : false, // show config at startup - "showFileName" : false, // do not show file name in view and edit - "contact" : true, // enable contact - "configDialog" : true, // enable config dialog - "configAuth" : true, // enable auth change in config dialog - "console" : true, // enable console - "syncConsolePath" : false, // do not sync console path - "terminal" : false, // disable terminal - "terminalPath" : "", // path of a terminal - "terminalCommand" : "", // set command to run in terminal - "terminalAutoRestart" : true, // restart command on exit - "vim" : false, // disable vim hot keys - "columns" : "name-size-date-owner-mode", // set visible columns - "export" : false, // enable export of config through a server - "exportToken" : "root", // token used by export server - "import" : false, // enable import of config - "import-url" : "http://localhost:8000", // url of an export server - "importToken" : "root", // token used to connect to export server - "importListen" : false, // listen on config updates - "dropbox" : false, // disable dropbox integration - "dropboxToken" : "", // unset dropbox token - "log" : true // logging + "name": "", // set tab name in web browser + "auth": false, // enable http authentication + "username": "root", // username for authentication + "password": "toor", // password hash for authentication + "algo": "sha512WithRSAEncryption", // cryptographic algorithm + "editor": "edward", // default, could be "dword" or "edward" + "packer": "tar", // default, could be "tar" or "zip" + "diff": true, // when save - send patch, not whole file + "zip": true, // zip text before send / unzip before save + "buffer": true, // buffer for copying files + "dirStorage": true, // store directory listing + "online": false, // do not load js files from cdn + "open": true, // open web browser when server started + "oneFilePanel": false, // show one file panel + "keysPanel": true, // show classic panel with buttons of keys + "port": 8000, // http port + "ip": null, // ip or null(default) + "root": "/", // root directory + "prefix": "", // url prefix + "prefixSocket": "", // prefix for socket connection + "confirmCopy": true, // confirm copy + "confirmMove": true, // confirm move + "showConfig": false, // show config at startup + "showFileName": false, // do not show file name in view and edit + "contact": true, // enable contact + "configDialog": true, // enable config dialog + "configAuth": true, // enable auth change in config dialog + "console": true, // enable console + "syncConsolePath": false, // do not sync console path + "terminal": false, // disable terminal + "terminalPath": "", // path of a terminal + "terminalCommand": "", // set command to run in terminal + "terminalAutoRestart": true, // restart command on exit + "vim": false, // disable vim hot keys + "columns": "name-size-date-owner-mode", // set visible columns + "export": false, // enable export of config through a server + "exportToken": "root", // token used by export server + "import": false, // enable import of config + "import-url": "http://localhost:8000", // url of an export server + "importToken": "root", // token used to connect to export server + "importListen": false, // listen on config updates + "dropbox": false, // disable dropbox integration + "dropboxToken": "", // unset dropbox token + "log": true // logging } ``` @@ -467,9 +467,7 @@ const RENAME_FILE = 'Rename file'; export default { '__settings': { - select: [ - RENAME_FILE, - ], + select: [RENAME_FILE], run: false, }, [`F2 - ${RENAME_FILE}`]: async ({DOM}) => { @@ -499,7 +497,9 @@ export default { const path = `${dirPath}.cloudcmd.menu.js`; const {prefix} = CloudCmd; - const data = await readDefaultMenu({prefix}); + const data = await readDefaultMenu({ + prefix, + }); await createDefaultMenu({ path, data, @@ -743,6 +743,7 @@ const socket2 = new Server(server, { }); const configManager1 = createConfigManager(); + configManager1('name', '1'); const configManager2 = createConfigManager(); @@ -765,8 +766,10 @@ If you want to enable authorization, you can pass credentials to Cloud Commander ```js import criton from 'criton'; -const algo = 'sha512WithRSAEncryption'; // default +const algo = 'sha512WithRSAEncryption'; + +// default // you can generate a hash dynamically const password = criton('root', algo); diff --git a/bin/cloudcmd.mjs b/bin/cloudcmd.mjs index 387f2fa1..d55c41d3 100755 --- a/bin/cloudcmd.mjs +++ b/bin/cloudcmd.mjs @@ -5,13 +5,11 @@ import {promisify} from 'util'; import tryToCatch from 'try-to-catch'; import {createSimport} from 'simport'; import parse from 'yargs-parser'; - import exit from '../server/exit.js'; import { createConfig, configPath, } from '../server/config.js'; - import env from '../server/env.js'; import prefixer from '../server/prefixer.js'; @@ -26,7 +24,7 @@ const simport = createSimport(import.meta.url); const choose = (a, b) => { if (a === undefined) return b; - + return a; }; @@ -39,7 +37,7 @@ const DIR_SERVER = '../server/'; const maybeRoot = (a) => { if (a === '.') return process.cwd(); - + return a; }; @@ -100,29 +98,29 @@ const yargsOptions = { 'dropbox', ], 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' : choose(env('prefix'), config('prefix')), - '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': choose(env('prefix'), config('prefix')), + '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')), @@ -348,4 +346,3 @@ async function showUpdateInfo(version) { console.log('%s %s', latest, current); } - diff --git a/bin/release.mjs b/bin/release.mjs index bceb2c9f..08254685 100755 --- a/bin/release.mjs +++ b/bin/release.mjs @@ -1,7 +1,6 @@ #!/usr/bin/env node import {promisify} from 'util'; - import tryToCatch from 'try-to-catch'; import {createSimport} from 'simport'; import minor from 'minor'; @@ -20,8 +19,9 @@ async function main() { const history = '## Version history\n\n'; const link = '//github.com/coderaiser/cloudcmd/releases/tag/'; const template = '- *{{ date }}*, ' + - '**[v{{ version }}]' + - '(' + link + 'v{{ version }})**\n'; + '**[v{{ version }}]' + + '(' + link + + 'v{{ version }})**\n'; const {version} = Info; @@ -34,8 +34,8 @@ async function main() { await replaceVersion('HELP.md', version, versionNew); const historyNew = history + rendy(template, { - date : shortdate(), - version : versionNew, + date: shortdate(), + version: versionNew, }); await replaceVersion('HELP.md', history, historyNew); @@ -68,7 +68,6 @@ async function cl() { function getVersionNew(last, match) { if (match) return minor(match, Info.version); - + return last.substr(3); } - diff --git a/client/client.js b/client/client.js index 6f909207..cdf33629 100644 --- a/client/client.js +++ b/client/client.js @@ -1,7 +1,6 @@ 'use strict'; /* global DOM */ - const Emitify = require('emitify'); const inherits = require('inherits'); const rendy = require('rendy'); @@ -16,6 +15,7 @@ const Images = require('./dom/images'); const {unregisterSW} = require('./sw/register'); const getJsonFromFileTable = require('./get-json-from-file-table'); const Key = require('./key'); + const { apiURL, formatMsg, @@ -39,58 +39,60 @@ load.addErrorListener((e, src) => { function CloudCmdProto(DOM) { let Listeners; - + Emitify.call(this); - + const CloudCmd = this; const Info = DOM.CurrentInfo; - - const { - Storage, - Files, - } = DOM; - + + const {Storage, Files} = DOM; + this.log = (...a) => { if (!isDev) return; - + console.log(...a); }; this.prefix = ''; this.prefixSocket = ''; this.prefixURL = ''; - + this.MIN_ONE_PANEL_WIDTH = 1155; this.HOST = location.origin || location.protocol + '//' + location.host; - + this.TITLE = 'Cloud Commander'; - + this.sort = { left: 'name', right: 'name', }; - + this.order = { left: 'asc', right: 'asc', }; - - this.changeDir = async (path, {isRefresh, panel, history = true, noCurrent, currentName} = {}) => { + + this.changeDir = async (path, { + isRefresh, + panel, + history = true, + noCurrent, + currentName, + } = {}) => { const refresh = isRefresh; let panelChanged; - + if (!noCurrent && panel && panel !== Info.panel) { DOM.changePanel(); panelChanged = true; } - + let imgPosition; - + if (panelChanged || refresh || !history) imgPosition = 'top'; - + Images.show.load(imgPosition, panel); - /* загружаем содержимое каталога */ await ajaxLoad(addSlashToEnd(path), { refresh, @@ -111,7 +113,7 @@ function CloudCmdProto(DOM) { CloudCmd.prefixSocket = config.prefixSocket; CloudCmd.DIR_DIST = `${prefix}/dist`; CloudCmd.DIR_MODULES = `${this.DIR_DIST}/modules`; - + CloudCmd.config = (key) => config[key]; CloudCmd.config.if = currify((key, fn, a) => config[key] && fn(a)); CloudCmd._config = (key, value) => { @@ -119,61 +121,60 @@ function CloudCmdProto(DOM) { * should be called from config.js only * after successful update on server */ - if (key === 'password') return; - + config[key] = value; }; - + if (config.oneFilePanel) CloudCmd.MIN_ONE_PANEL_WIDTH = Infinity; - + if (!document.body.scrollIntoViewIfNeeded) await load.js(`${CloudCmd.DIR_MODULES}/polyfill.js`); - + await initModules(); await baseInit(); await loadStyle(); - + CloudCmd.route(location.hash); }; - + async function loadStyle() { const {prefix} = CloudCmd; const name = `${prefix}/dist/cloudcmd.common.css`; - + await load.css(name); } this.route = (path) => { const query = path.split('/'); - + if (!path) return; - + const [kebabModule] = query; const module = noJS(pascalCase(kebabModule.slice(1))); - + const file = query[1]; const current = DOM.getCurrentByName(file); - + if (file && !current) { const msg = formatMsg('set current file', file, 'error'); CloudCmd.log(msg); - + return; } - + DOM.setCurrentFile(current); CloudCmd.execFromModule(module, 'show'); }; - + this.logOut = async () => { const url = CloudCmd.prefix + '/logout'; const error = () => document.location.reload(); const {prefix} = CloudCmd; - + await DOM.Storage.clear(); unregisterSW(prefix); DOM.load.ajax({ @@ -181,19 +182,19 @@ function CloudCmdProto(DOM) { error, }); }; - + const initModules = async () => { CloudCmd.Key = Key; CloudCmd.Key.bind(); - + 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, @@ -201,28 +202,28 @@ function CloudCmdProto(DOM) { dobefore, }); }; - + if (!modules) return; - + for (const module of modules.local) { load(null, module, doBefore[module]); } }; - + 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(currentFile, { @@ -231,31 +232,32 @@ function CloudCmdProto(DOM) { // overwre otherwise history: !location.hash, }); - + const dirPath = DOM.getCurrentDirPath(); + Listeners = CloudCmd.Listeners; Listeners.init(); - + const panels = getPanels(); panels.forEach(Listeners.setOnPanel); - + Listeners.initKeysPanel(); - + if (!CloudCmd.config('dirStorage')) return; - + const data = await Storage.get(dirPath); - + if (!data) await Storage.setJson(dirPath, getJsonFromFileTable()); } function getPanels() { const panels = ['left']; - + if (CloudCmd.config('oneFilePanel')) return panels; - + return [ ...panels, 'right', @@ -264,23 +266,20 @@ function CloudCmdProto(DOM) { this.execFromModule = async (moduleName, funcName, ...args) => { await CloudCmd[moduleName](); - + const func = CloudCmd[moduleName][funcName]; func(...args); }; - + this.refresh = async (options = {}) => { - const { - panel = Info.panel, - currentName, - } = options; - + const {panel = Info.panel, currentName} = options; + const path = DOM.getCurrentDirPath(panel); - + const isRefresh = true; const history = false; const noCurrent = options ? options.noCurrent : false; - + await CloudCmd.changeDir(path, { isRefresh, history, @@ -302,46 +301,43 @@ function CloudCmdProto(DOM) { */ async function ajaxLoad(path, options = {}, panel) { const {RESTful} = DOM; - + CloudCmd.log(`reading dir: "${path}";`); - + const dirStorage = CloudCmd.config('dirStorage'); const json = dirStorage && await Storage.getJson(path); - + const name = options.currentName || Info.name; - const { - noCurrent, - refresh, - } = options; - + const {noCurrent, refresh} = options; + if (!refresh && json) return await createFileTable(json, panel, options); - + const position = DOM.getPanelPosition(panel); const sort = CloudCmd.sort[position]; const order = CloudCmd.order[position]; - + const query = rendy('?sort={{ sort }}&order={{ order }}', { sort, order, }); - + const [, newObj] = await RESTful.read(path + query, 'json'); - + if (!newObj) - return; // that's OK, error handled by RESTful - + // that's OK, error handled by RESTful + return; options.sort = sort; options.order = order; - + await createFileTable(newObj, panel, options); - + if (refresh && !noCurrent) DOM.setCurrentByName(name); - + if (!CloudCmd.config('dirStorage')) return; - + Storage.setJson(path, newObj); } @@ -353,69 +349,60 @@ function CloudCmdProto(DOM) { * @param callback */ async function createFileTable(data, panelParam, options) { - const { - history, - noCurrent, - } = options; - + const {history, noCurrent} = options; + const names = [ 'file', 'path', 'link', 'pathLink', ]; - - const [ - error, - [file, path, link, pathLink], - ] = await tryToCatch(Files.get, names); - + + const [error, [file, path, link, pathLink]] = 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 {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, + sort: options.sort, + order: options.order, data, - id : panel.id, + id: panel.id, prefix, - template : { + template: { file, path, pathLink, link, }, }); - + 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); } } @@ -427,20 +414,19 @@ function CloudCmdProto(DOM) { parentDirPath, panel, } = Info; - + if (dirPath === parentDirPath) return; - + const path = parentDirPath; - + await CloudCmd.changeDir(path); - + const current = DOM.getCurrentByName(dir); const [first] = DOM.getFiles(panel); - + DOM.setCurrentFile(current || first, { history, }); }; } - diff --git a/client/cloudcmd.js b/client/cloudcmd.js index 58363958..09dd202f 100644 --- a/client/cloudcmd.js +++ b/client/cloudcmd.js @@ -8,10 +8,7 @@ require('../css/columns/name-size.css'); const wraptile = require('wraptile'); const load = require('load.js'); -const { - registerSW, - listenSW, -} = require('./sw/register'); +const {registerSW, listenSW} = require('./sw/register'); const isDev = process.env.NODE_ENV === 'development'; @@ -65,4 +62,3 @@ async function register(config) { listenSW(sw, 'updatefound', onUpdateFound(config)); } - diff --git a/client/dom/buffer.js b/client/dom/buffer.js index 1c81d473..189f6423 100644 --- a/client/dom/buffer.js +++ b/client/dom/buffer.js @@ -1,7 +1,6 @@ 'use strict'; /* global CloudCmd */ - const tryToPromiseAll = require('../../common/try-to-promise-all'); const Storage = require('./storage'); const DOM = require('./'); @@ -13,24 +12,25 @@ function BufferProto() { const CLASS = 'cut-file'; const COPY = 'copy'; const CUT = 'cut'; + const Buffer = { - cut : callIfEnabled.bind(null, cut), - copy : callIfEnabled.bind(null, copy), - clear : callIfEnabled.bind(null, clear), - paste : callIfEnabled.bind(null, paste), + cut: callIfEnabled.bind(null, cut), + copy: callIfEnabled.bind(null, copy), + clear: callIfEnabled.bind(null, clear), + paste: callIfEnabled.bind(null, paste), }; function showMessage(msg) { DOM.Dialog.alert(msg); } - + function getNames() { const files = DOM.getActiveFiles(); const names = DOM.getFilenames(files); return names; } - + function addCutClass() { const files = DOM.getActiveFiles(); @@ -38,7 +38,7 @@ function BufferProto() { element.classList.add(CLASS); } } - + function rmCutClass() { const files = DOM.getByClassAll(CLASS); @@ -46,7 +46,7 @@ function BufferProto() { element.classList.remove(CLASS); } } - + function callIfEnabled(callback) { const is = CloudCmd.config('buffer'); @@ -55,7 +55,7 @@ function BufferProto() { showMessage('Buffer disabled in config!'); } - + async function readBuffer() { const [e, cp, ct] = await tryToPromiseAll([ Storage.getJson(COPY), @@ -68,7 +68,7 @@ function BufferProto() { ct, ]; } - + async function copy() { const names = getNames(); const from = Info.dirPath; @@ -84,7 +84,7 @@ function BufferProto() { names, }); } - + async function cut() { const names = getNames(); const from = Info.dirPath; @@ -101,14 +101,14 @@ function BufferProto() { names, }); } - + async function clear() { await Storage.remove(COPY); await Storage.remove(CUT); rmCutClass(); } - + async function paste() { const [error, cp, ct] = await readBuffer(); @@ -131,7 +131,6 @@ function BufferProto() { await clear(); } - + return Buffer; } - diff --git a/client/dom/current-file.js b/client/dom/current-file.js index 2ded2c96..2ab0ab51 100644 --- a/client/dom/current-file.js +++ b/client/dom/current-file.js @@ -2,19 +2,12 @@ /* global DOM */ /* global CloudCmd */ - const {atob, btoa} = require('../../common/base64'); const createElement = require('@cloudcmd/create-element'); -const { - encode, - decode, -} = require('../../common/entity'); +const {encode, decode} = require('../../common/entity'); -const { - getTitle, - FS, -} = require('../../common/cloudfunc'); +const {getTitle, FS} = require('../../common/cloudfunc'); let Title; @@ -23,7 +16,6 @@ const encodeNBSP = (a) => a?.replace('\xa0', ' '); const decodeNBSP = (a) => a?.replace(' ', '\xa0'); module.exports._CURRENT_FILE = CURRENT_FILE; - /** * set name from current (or param) file * @@ -85,8 +77,8 @@ const parseHrefAttribute = (prefix, attribute) => { attribute = attribute.replace(RegExp('^' + prefix + FS), ''); return decode(decodeNBSP(attribute)); }; -module.exports._parseHrefAttribute = parseHrefAttribute; +module.exports._parseHrefAttribute = parseHrefAttribute; /** * get current direcotory path */ @@ -112,7 +104,8 @@ module.exports.getCurrentPath = (currentFile) => { * get current direcotory name */ module.exports.getCurrentDirName = () => { - const href = DOM.getCurrentDirPath() + const href = DOM + .getCurrentDirPath() .replace(/\/$/, ''); const substr = href.substr(href, href.lastIndexOf('/')); @@ -158,7 +151,6 @@ module.exports.getCurrentFile = () => { /** * get current file by name */ - module.exports.getCurrentByName = (name, panel = DOM.CurrentInfo.panel) => { const dataName = 'js-file-' + btoa(encodeURI(encodeNBSP(name))); return DOM.getByDataName(dataName, panel); @@ -205,7 +197,7 @@ module.exports.setCurrentFile = (currentFile, options) => { name, path, })); - + /* history could be present * but it should be false * to prevent default behavior @@ -274,7 +266,7 @@ module.exports.getCurrentByPosition = ({x, y}) => { module.exports.isCurrentFile = (currentFile) => { if (!currentFile) return false; - + return DOM.isContainClass(currentFile, CURRENT_FILE); }; @@ -283,7 +275,6 @@ module.exports.isCurrentFile = (currentFile) => { * * @param name */ - module.exports.setTitle = (name) => { if (!Title) Title = DOM.getByTag('title')[0] || createElement('title', { @@ -315,10 +306,10 @@ module.exports.isCurrentIsDir = (currentFile) => { module.exports.getCurrentType = (currentFile) => { const current = currentFile || DOM.getCurrentFile(); const el = DOM.getByDataName('js-type', current); - const type = el.className + const type = el + .className .split(' ') .pop(); return type; }; - diff --git a/client/dom/current-file.spec.js b/client/dom/current-file.spec.js index 2e816c3c..8f24f3c8 100644 --- a/client/dom/current-file.spec.js +++ b/client/dom/current-file.spec.js @@ -1,9 +1,7 @@ 'use strict'; -const { - test, - stub, -} = require('supertape'); +const {test, stub} = require('supertape'); + const {create} = require('auto-globals'); const wraptile = require('wraptile'); const currentFile = require('./current-file'); @@ -13,10 +11,7 @@ const returns = wraptile(id); const {_CURRENT_FILE} = currentFile; test('current-file: setCurrentName: setAttribute', (t) => { - const { - DOM, - CloudCmd, - } = global; + const {DOM, CloudCmd} = global; global.DOM = getDOM(); global.CloudCmd = getCloudCmd(); @@ -35,10 +30,7 @@ test('current-file: setCurrentName: setAttribute', (t) => { }); test('current-file: setCurrentName: setAttribute: cyrillic', (t) => { - const { - DOM, - CloudCmd, - } = global; + const {DOM, CloudCmd} = global; global.DOM = getDOM(); global.CloudCmd = getCloudCmd(); @@ -67,10 +59,7 @@ test('current-file: getCurrentName', (t) => { }); test('current-file: emit', (t) => { - const { - DOM, - CloudCmd, - } = global; + const {DOM, CloudCmd} = global; const emit = stub(); @@ -92,10 +81,7 @@ test('current-file: emit', (t) => { }); test('current-file: setCurrentName: return', (t) => { - const { - DOM, - CloudCmd, - } = global; + const {DOM, CloudCmd} = global; const link = {}; @@ -138,28 +124,22 @@ test('current-file: getParentDirPath: result', (t) => { }); test('current-file: isCurrentFile: no', (t) => { - const { - DOM, - CloudCmd, - } = global; - + const {DOM, CloudCmd} = global; + global.DOM = getDOM(); global.CloudCmd = getCloudCmd(); - + const result = currentFile.isCurrentFile(); - + global.DOM = DOM; global.CloudCmd = CloudCmd; - + t.notOk(result); t.end(); }); test('current-file: isCurrentFile', (t) => { - const { - DOM, - CloudCmd, - } = global; + const {DOM, CloudCmd} = global; const isContainClass = stub(); @@ -180,10 +160,7 @@ test('current-file: isCurrentFile', (t) => { }); test('current-file: getCurrentType', (t) => { - const { - DOM, - CloudCmd, - } = global; + const {DOM, CloudCmd} = global; global.DOM = getDOM(); global.CloudCmd = getCloudCmd(); @@ -206,10 +183,7 @@ test('current-file: getCurrentType', (t) => { }); test('current-file: isCurrentIsDir: getCurrentType', (t) => { - const { - DOM, - CloudCmd, - } = global; + const {DOM, CloudCmd} = global; global.DOM = getDOM(); global.CloudCmd = getCloudCmd(); @@ -228,10 +202,7 @@ test('current-file: isCurrentIsDir: getCurrentType', (t) => { }); test('current-file: isCurrentIsDir: directory', (t) => { - const { - DOM, - CloudCmd, - } = global; + const {DOM, CloudCmd} = global; global.DOM = getDOM({ getCurrentType: stub().returns('directory'), @@ -251,10 +222,7 @@ test('current-file: isCurrentIsDir: directory', (t) => { }); test('current-file: isCurrentIsDir: directory-link', (t) => { - const { - DOM, - CloudCmd, - } = global; + const {DOM, CloudCmd} = global; global.DOM = getDOM({ getCurrentType: stub().returns('directory-link'), @@ -274,10 +242,7 @@ test('current-file: isCurrentIsDir: directory-link', (t) => { }); test('current-file: isCurrentIsDir: file', (t) => { - const { - DOM, - CloudCmd, - } = global; + const {DOM, CloudCmd} = global; global.DOM = getDOM({ getCurrentType: stub().returns('file'), @@ -320,15 +285,7 @@ test('current-file: parseHrefAttribute', (t) => { t.end(); }); -function getDOM({ - link = {}, - getCurrentDirPath = stub(), - getCurrentDirName = stub(), - getByDataName = stub(), - isContainClass = stub(), - getCurrentType = stub(), - getCurrentPath = stub(), -} = {}) { +function getDOM({link = {}, getCurrentDirPath = stub(), getCurrentDirName = stub(), getByDataName = stub(), isContainClass = stub(), getCurrentType = stub(), getCurrentPath = stub()} = {}) { return { getCurrentDirPath, getCurrentDirName, @@ -342,4 +299,3 @@ function getDOM({ }, }; } - diff --git a/client/dom/dialog.js b/client/dom/dialog.js index 3fcf7fb6..f4751456 100644 --- a/client/dom/dialog.js +++ b/client/dom/dialog.js @@ -24,4 +24,3 @@ module.exports.alert.noFiles = () => { cancel: false, }); }; - diff --git a/client/dom/directory.js b/client/dom/directory.js index 8579b930..88802d40 100644 --- a/client/dom/directory.js +++ b/client/dom/directory.js @@ -1,7 +1,6 @@ 'use strict'; /* global CloudCmd */ - const philip = require('philip'); const Images = require('./images'); @@ -15,11 +14,12 @@ module.exports = (items) => { if (items.length) Images.show('top'); - const entries = Array.from(items).map((item) => item.webkitGetAsEntry()); + const entries = Array + .from(items) + .map((item) => item.webkitGetAsEntry()); const dirPath = getPathWhenRootEmpty(); - const path = dirPath - .replace(/\/$/, ''); + const path = dirPath.replace(/\/$/, ''); const progress = Dialog.progress('Uploading...'); @@ -74,4 +74,3 @@ function uploadFile(url, data) { function uploadDir(url) { return DOM.load.put(`${url}?dir`); } - diff --git a/client/dom/dom-tree.js b/client/dom/dom-tree.js index ffd6f5e2..5159cf8b 100644 --- a/client/dom/dom-tree.js +++ b/client/dom/dom-tree.js @@ -18,7 +18,10 @@ const isContainClass = (element, className) => { throw Error('className could not be empty!'); if (Array.isArray(className)) - return className.some(currify(isContainClass, element)); + return className.some(currify( + isContainClass, + element, + )); const {classList} = element; @@ -26,7 +29,6 @@ const isContainClass = (element, className) => { }; module.exports.isContainClass = isContainClass; - /** * Function search element by tag * @param tag - className @@ -79,4 +81,3 @@ module.exports.show = (element) => { element.classList.remove('hidden'); return DOM; }; - diff --git a/client/dom/dom-tree.spec.js b/client/dom/dom-tree.spec.js index 5c3e9a97..044e97b0 100644 --- a/client/dom/dom-tree.spec.js +++ b/client/dom/dom-tree.spec.js @@ -36,13 +36,8 @@ test('dom: isContainClass: contains: array', (t) => { const {contains} = el.classList; const className = 'hello'; - isContainClass(el, [ - 'world', - className, - 'hello', - ]); + isContainClass(el, ['world', className, 'hello']); t.calledWith(contains, [className], 'should call contains'); t.end(); }); - diff --git a/client/dom/events/event-store.js b/client/dom/events/event-store.js index ae08a7ee..ae9ad90a 100644 --- a/client/dom/events/event-store.js +++ b/client/dom/events/event-store.js @@ -15,4 +15,3 @@ module.exports.clear = () => { }; module.exports.get = () => list; - diff --git a/client/dom/events/event-store.spec.js b/client/dom/events/event-store.spec.js index 85e5959d..82e6752a 100644 --- a/client/dom/events/event-store.spec.js +++ b/client/dom/events/event-store.spec.js @@ -10,8 +10,13 @@ test('event-store: get', (t) => { eventStore.add(el, name, fn); const result = eventStore.get(); + const expected = [ - [el, name, fn], + [ + el, + name, + fn, + ], ]; t.deepEqual(result, expected); diff --git a/client/dom/events/index.js b/client/dom/events/index.js index 307768c3..d1fca862 100644 --- a/client/dom/events/index.js +++ b/client/dom/events/index.js @@ -11,7 +11,7 @@ function EventsProto() { const getEventOptions = (eventName) => { if (eventName !== 'touchstart') return false; - + return { passive: true, }; @@ -35,12 +35,7 @@ function EventsProto() { if (!type.endsWith('element')) throw Error(`unknown eventName: ${type}`); - parseArgs( - args[EVENT_NAME], - args[ELEMENT], - listener, - callback, - ); + parseArgs(args[EVENT_NAME], args[ELEMENT], listener, callback); break; case 'string': @@ -62,33 +57,25 @@ function EventsProto() { break; case 'array': + for (const name of eventName) { - parseArgs( - name, - element, - listener, - callback, - ); + parseArgs(name, element, listener, callback); } break; case 'object': + for (const name of Object.keys(eventName)) { const eventListener = eventName[name]; - parseArgs( - name, - element, - eventListener, - callback, - ); + parseArgs(name, element, eventListener, callback); } break; } } - + /** * safe add event listener * @@ -108,7 +95,7 @@ function EventsProto() { return Events; }; - + /** * safe add event listener * @@ -131,7 +118,7 @@ function EventsProto() { return Events; }; - + /** * safe remove event listener * @@ -148,7 +135,7 @@ function EventsProto() { return Events; }; - + /** * remove all added event listeners * @@ -162,7 +149,7 @@ function EventsProto() { EventStore.clear(); }; - + /** * safe add event keydown listener * @@ -170,11 +157,14 @@ function EventsProto() { */ this.addKey = function(...argsArr) { const name = 'keydown'; - const args = [name, ...argsArr]; + const args = [ + name, + ...argsArr, + ]; return Events.add(...args); }; - + /** * safe remove event click listener * @@ -182,11 +172,14 @@ function EventsProto() { */ this.rmKey = function(...argsArr) { const name = 'keydown'; - const args = [name, ...argsArr]; + const args = [ + name, + ...argsArr, + ]; return Events.remove(...args); }; - + /** * safe add event click listener * @@ -194,11 +187,14 @@ function EventsProto() { */ this.addClick = function(...argsArr) { const name = 'click'; - const args = [name, ...argsArr]; + const args = [ + name, + ...argsArr, + ]; return Events.add(...args); }; - + /** * safe remove event click listener * @@ -206,18 +202,24 @@ function EventsProto() { */ this.rmClick = function(...argsArr) { const name = 'click'; - const args = [name, ...argsArr]; + const args = [ + name, + ...argsArr, + ]; return Events.remove(...args); }; this.addContextMenu = function(...argsArr) { const name = 'contextmenu'; - const args = [name, ...argsArr]; + const args = [ + name, + ...argsArr, + ]; return Events.add(...args); }; - + /** * safe add event click listener * @@ -225,11 +227,14 @@ function EventsProto() { */ this.addError = function(...argsArr) { const name = 'error'; - const args = [name, ...argsArr]; + const args = [ + name, + ...argsArr, + ]; return Events.add(...args); }; - + /** * safe add load click listener * @@ -237,7 +242,10 @@ function EventsProto() { */ this.addLoad = function(...argsArr) { const name = 'load'; - const args = [name, ...argsArr]; + const args = [ + name, + ...argsArr, + ]; return Events.add(...args); }; @@ -247,4 +255,3 @@ function EventsProto() { throw Error('type could not be empty!'); } } - diff --git a/client/dom/files.js b/client/dom/files.js index 9fac8ee1..a7de8ff6 100644 --- a/client/dom/files.js +++ b/client/dom/files.js @@ -1,7 +1,6 @@ 'use strict'; /* global CloudCmd */ - const itype = require('itype'); const {promisify} = require('es6-promisify'); @@ -49,6 +48,7 @@ function getModule(name) { return getConfig(); const path = getPath(name, isHTML, isJSON); + return getSystemFile(path); } @@ -137,4 +137,3 @@ function getTimeoutOnce(time) { }, time); }; } - diff --git a/client/dom/images.js b/client/dom/images.js index 8c597ea3..382da9e8 100644 --- a/client/dom/images.js +++ b/client/dom/images.js @@ -15,7 +15,6 @@ function getLoadingType() { } module.exports.get = getElement; - /** * check SVG SMIL animation support */ @@ -69,7 +68,6 @@ module.exports.error = () => { module.exports.show = show; module.exports.show.load = show; module.exports.show.error = error; - /** * Function shows loading spinner * position = {top: true}; @@ -147,4 +145,3 @@ module.exports.clearProgress = () => { return Images; }; - diff --git a/client/dom/index.js b/client/dom/index.js index 54a2839e..bb58eac8 100644 --- a/client/dom/index.js +++ b/client/dom/index.js @@ -1,7 +1,6 @@ 'use strict'; /* global CloudCmd */ - const Util = require('../../common/util'); const Images = require('./images'); @@ -41,8 +40,8 @@ const selectByPattern = require('./select-by-pattern'); const SELECTED_FILE = 'selected-file'; const TabPanel = { - 'js-left' : null, - 'js-right' : null, + 'js-left': null, + 'js-right': null, }; module.exports.loadRemote = (name, options, callback) => { @@ -52,7 +51,7 @@ module.exports.loadRemote = (name, options, callback) => { module.exports.loadSocket = (callback) => { DOM.loadRemote('socket', { - name : 'io', + name: 'io', }, callback); return DOM; @@ -80,6 +79,7 @@ async function promptNew(typeName) { const {Dialog} = DOM; const dir = DOM.getCurrentDirPath(); const msg = `New ${typeName}` || 'File'; + const getName = () => { const name = DOM.getCurrentName(); @@ -111,11 +111,12 @@ async function promptNew(typeName) { * get current direcotory name */ module.exports.getCurrentDirName = () => { - const href = DOM.getCurrentDirPath() + const href = DOM + .getCurrentDirPath() .replace(/\/$/, ''); - const substr = href.substr(href, href.lastIndexOf('/')); - const ret = href.replace(`${substr}/`, '') || '/'; + const substr = href.substr(href, href.lastIndexOf('/')); + const ret = href.replace(`${substr}/`, '') || '/'; return ret; }; @@ -138,7 +139,9 @@ module.exports.getParentDirPath = (panel) => { * get not current direcotory path */ module.exports.getNotCurrentDirPath = () => { - const panel = DOM.getPanel({active: false}); + const panel = DOM.getPanel({ + active: false, + }); const path = DOM.getCurrentDirPath(panel); return path; @@ -162,7 +165,9 @@ module.exports.getSelectedFiles = () => { module.exports.unselectFiles = (files) => { files = files || DOM.getSelectedFiles(); - Array.from(files).forEach(DOM.toggleSelectedFile); + Array + .from(files) + .forEach(DOM.toggleSelectedFile); }; /** @@ -183,9 +188,7 @@ module.exports.getActiveFiles = () => { module.exports.getCurrentDate = (currentFile) => { const current = currentFile || DOM.getCurrentFile(); - const date = DOM - .getByDataName('js-date', current) - .textContent; + const date = DOM.getByDataName('js-date', current).textContent; return date; }; @@ -196,8 +199,10 @@ module.exports.getCurrentDate = (currentFile) => { */ module.exports.getCurrentSize = (currentFile) => { const current = currentFile || DOM.getCurrentFile(); + /* если это папка - возвращаем слово dir вместо размера*/ - const size = DOM.getByDataName('js-size', current) + const size = DOM + .getByDataName('js-size', current) .textContent .replace(/^<|>$/g, ''); @@ -237,6 +242,7 @@ module.exports.loadCurrentHash = async (currentFile) => { const link = DOM.getCurrentPath(current); const [, data] = await RESTful.read(link + query); + return data; }; @@ -285,7 +291,9 @@ module.exports.getCurrentData = async (currentFile) => { if (Info.name === '..') { Dialog.alert.noFiles(); - return [Error('No Files')]; + return [ + Error('No Files'), + ]; } if (isDir) @@ -294,7 +302,9 @@ module.exports.getCurrentData = async (currentFile) => { const [hashNew, hash] = await DOM.checkStorageHash(path); if (!hashNew) - return [Error(`Can't get hash of a file`)]; + return [ + Error(`Can't get hash of a file`), + ]; if (hash === hashNew) return [null, await Storage.get(`${path}-data`)]; @@ -302,7 +312,10 @@ module.exports.getCurrentData = async (currentFile) => { const [e, data] = await RESTful.read(path); if (e) - return [e, null]; + return [ + e, + null, + ]; const ONE_MEGABYTE = 1024 ** 2 * 1024; const {length} = data; @@ -353,13 +366,17 @@ module.exports.toggleSelectedFile = (currentFile) => { }; module.exports.toggleAllSelectedFiles = () => { - DOM.getAllFiles().map(DOM.toggleSelectedFile); + DOM + .getAllFiles() + .map(DOM.toggleSelectedFile); return Cmd; }; module.exports.selectAllFiles = () => { - DOM.getAllFiles().map(DOM.selectFile); + DOM + .getAllFiles() + .map(DOM.selectFile); return Cmd; }; @@ -372,7 +389,9 @@ module.exports.getAllFiles = () => { const from = (a) => a === '..' ? 1 : 0; const i = from(name); - return Array.from(files).slice(i); + return Array + .from(files) + .slice(i); }; /** @@ -418,7 +437,7 @@ module.exports.setHistory = (data, title, url) => { module.exports.isSelected = (selected) => { if (!selected) return false; - + return DOM.isContainClass(selected, SELECTED_FILE); }; @@ -550,7 +569,9 @@ module.exports.getFiles = (element) => { * shows panel right or left (or active) */ module.exports.showPanel = (active) => { - const panel = DOM.getPanel({active}); + const panel = DOM.getPanel({ + active, + }); if (!panel) return false; @@ -627,7 +648,6 @@ module.exports.deleteSelected = (selected) => { * @currentFile */ module.exports.renameCurrent = renameCurrent; - /** * unified way to scrollIntoViewIfNeeded * (native suporte by webkit only) @@ -702,7 +722,7 @@ module.exports.changePanel = () => { module.exports.getPackerExt = (type) => { if (type === 'zip') return '.zip'; - + return '.tar.gz'; }; @@ -711,10 +731,7 @@ module.exports.goToDirectory = async () => { const {Dialog} = DOM; const {dirPath} = CurrentInfo; - const [ - cancel, - path = dirPath, - ] = await Dialog.prompt(msg, dirPath); + const [cancel, path = dirPath] = await Dialog.prompt(msg, dirPath); if (cancel) return; @@ -731,7 +748,7 @@ module.exports.duplicatePanel = async () => { const getPath = (isDir) => { if (isDir) return Info.path; - + return Info.dirPath; }; @@ -790,26 +807,29 @@ module.exports.updateCurrentInfo = (currentFile) => { const filesPassive = DOM.getFiles(panelPassive); const name = DOM.getCurrentName(current); - info.dir = DOM.getCurrentDirName(); - info.dirPath = DOM.getCurrentDirPath(); - info.parentDirPath = DOM.getParentDirPath(); - info.element = current; - info.ext = Util.getExt(name); - info.files = Array.from(files.children); - info.filesPassive = Array.from(filesPassive); - info.first = files.firstChild; - info.getData = DOM.getCurrentData; - info.last = files.lastChild; - info.link = DOM.getCurrentLink(current); - info.mode = DOM.getCurrentMode(current); - info.name = name; - info.path = DOM.getCurrentPath(current); - info.panel = files.parentElement || DOM.getPanel(); - info.panelPassive = panelPassive; - info.size = DOM.getCurrentSize(current); - info.isDir = DOM.isCurrentIsDir(); - info.isSelected = DOM.isSelected(current); - info.panelPosition = DOM.getPanel().dataset.name.replace('js-', ''); - info.isOnePanel = info.panel.getAttribute('data-name') === - info.panelPassive.getAttribute('data-name'); + info.dir = DOM.getCurrentDirName(); + info.dirPath = DOM.getCurrentDirPath(); + info.parentDirPath = DOM.getParentDirPath(); + info.element = current; + info.ext = Util.getExt(name); + info.files = Array.from(files.children); + info.filesPassive = Array.from(filesPassive); + info.first = files.firstChild; + info.getData = DOM.getCurrentData; + info.last = files.lastChild; + info.link = DOM.getCurrentLink(current); + info.mode = DOM.getCurrentMode(current); + info.name = name; + info.path = DOM.getCurrentPath(current); + info.panel = files.parentElement || DOM.getPanel(); + info.panelPassive = panelPassive; + info.size = DOM.getCurrentSize(current); + info.isDir = DOM.isCurrentIsDir(); + info.isSelected = DOM.isSelected(current); + info.panelPosition = DOM + .getPanel() + .dataset + .name + .replace('js-', ''); + info.isOnePanel = info.panel.getAttribute('data-name') === info.panelPassive.getAttribute('data-name'); }; diff --git a/client/dom/index.spec.js b/client/dom/index.spec.js index 914862a4..0a0948b6 100644 --- a/client/dom/index.spec.js +++ b/client/dom/index.spec.js @@ -29,4 +29,3 @@ test('cloudcmd: client: dom: goToDirectory', async (t) => { t.calledWith(changeDir, [path]); t.end(); }); - diff --git a/client/dom/io/index.js b/client/dom/io/index.js index 79944724..577c357a 100644 --- a/client/dom/io/index.js +++ b/client/dom/io/index.js @@ -9,10 +9,10 @@ const imgPosition = { module.exports.delete = async (url, data) => { return await sendRequest({ - method : 'DELETE', - url : FS + url, + method: 'DELETE', + url: FS + url, data, - imgPosition : { + imgPosition: { top: Boolean(data), }, }); @@ -149,4 +149,3 @@ module.exports.Markdown = { }); }, }; - diff --git a/client/dom/io/index.spec.js b/client/dom/io/index.spec.js index 92c621f7..2212f91a 100644 --- a/client/dom/io/index.spec.js +++ b/client/dom/io/index.spec.js @@ -1,9 +1,7 @@ 'use strict'; -const { - test, - stub, -} = require('supertape'); +const {test, stub} = require('supertape'); + const mockRequire = require('mock-require'); const {reRequire, stopAll} = mockRequire; diff --git a/client/dom/io/send-request.js b/client/dom/io/send-request.js index f3307764..bc52d667 100644 --- a/client/dom/io/send-request.js +++ b/client/dom/io/send-request.js @@ -1,7 +1,6 @@ 'use strict'; /* global CloudCmd */ - const {promisify} = require('es6-promisify'); const Images = require('../images'); @@ -17,17 +16,14 @@ module.exports = promisify((params, callback) => { p.url = replaceHash(p.url); load.ajax({ - method : p.method, - url : p.url, - data : p.data, - dataType : p.dataType, - error : (jqXHR) => { + method: p.method, + url: p.url, + data: p.data, + dataType: p.dataType, + error: (jqXHR) => { const response = jqXHR.responseText; - const { - statusText, - status, - } = jqXHR; + const {statusText, status} = jqXHR; const text = status === 404 ? response : statusText; @@ -52,4 +48,3 @@ function replaceHash(url) { */ return url.replace(/#/g, '%23'); } - diff --git a/client/dom/io/send-request.spec.js b/client/dom/io/send-request.spec.js index 077ba4c7..e8d0449a 100644 --- a/client/dom/io/send-request.spec.js +++ b/client/dom/io/send-request.spec.js @@ -11,4 +11,3 @@ test('cloudcmd: client: io: replaceHash', (t) => { t.equal(result, expected); t.end(); }); - diff --git a/client/dom/load-remote.js b/client/dom/load-remote.js index eb295bb7..dac84a62 100644 --- a/client/dom/load-remote.js +++ b/client/dom/load-remote.js @@ -1,7 +1,6 @@ 'use strict'; /* global CloudCmd */ - const rendy = require('rendy'); const itype = require('itype'); const load = require('load.js'); @@ -18,41 +17,42 @@ module.exports = (name, options, callback = options) => { if (o.name && window[o.name]) return callback(); - Files.get('modules').then(async (modules) => { - const online = config('online') && navigator.onLine; - const module = findObjByNameInArr(modules.remote, name); + Files + .get('modules') + .then(async (modules) => { + const online = config('online') && navigator.onLine; + const module = findObjByNameInArr(modules.remote, name); - const isArray = itype.array(module.local); - const {version} = module; + const isArray = itype.array(module.local); + const {version} = module; - let remoteTmpls; - let local; + let remoteTmpls; + let local; - if (isArray) { - remoteTmpls = module.remote; - local = module.local; - } else { - remoteTmpls = [module.remote]; - local = [module.local]; - } + if (isArray) { + remoteTmpls = module.remote; + local = module.local; + } else { + remoteTmpls = [module.remote]; + local = [module.local]; + } - const localURL = local.map((url) => prefix + url); + const localURL = local.map((url) => prefix + url); - const remoteURL = remoteTmpls.map((tmpl) => { - return rendy(tmpl, { - version, + const remoteURL = remoteTmpls.map((tmpl) => { + return rendy(tmpl, { + version, + }); }); - }); - if (online) { - const [e] = await tryToCatch(load.parallel, remoteURL); + if (online) { + const [e] = await tryToCatch(load.parallel, remoteURL); - if (!e) - return callback(); - } + if (!e) + return callback(); + } - const [e] = await tryToCatch(load.parallel, localURL); - callback(e); - }); + const [e] = await tryToCatch(load.parallel, localURL); + callback(e); + }); }; - diff --git a/client/dom/load.js b/client/dom/load.js index f76cbe86..9148c1b8 100644 --- a/client/dom/load.js +++ b/client/dom/load.js @@ -7,7 +7,6 @@ const exec = require('execon'); const Images = require('./images'); module.exports.getIdBySrc = getIdBySrc; - /** * Function gets id by src * @param src @@ -25,6 +24,7 @@ function getIdBySrc(src) { const num = src.lastIndexOf('/') + 1; const sub = src.substr(src, num); + const id = src .replace(sub, '') .replace(/\./g, '-'); @@ -43,9 +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; + + const {headers = {}} = p; + const xhr = new XMLHttpRequest(); xhr.open(type, p.url, true); @@ -98,8 +98,7 @@ module.exports.put = (url, body) => { const emitter = Emitify(); const xhr = new XMLHttpRequest(); - url = encodeURI(url) - .replace(/#/g, '%23'); + url = encodeURI(url).replace(/#/g, '%23'); xhr.open('put', url, true); @@ -133,4 +132,3 @@ module.exports.put = (url, body) => { return emitter; }; - diff --git a/client/dom/operations/rename-current.js b/client/dom/operations/rename-current.js index aa01bf02..5b2e0ff7 100644 --- a/client/dom/operations/rename-current.js +++ b/client/dom/operations/rename-current.js @@ -1,12 +1,12 @@ 'use strict'; /* global CloudCmd */ - const capitalize = require('just-capitalize'); const Dialog = require('../dialog'); const Storage = require('../storage'); const RESTful = require('../rest'); + const { isCurrentFile, getCurrentName, @@ -60,4 +60,3 @@ module.exports = async (current) => { Storage.remove(dirPath); CloudCmd.refresh(); }; - diff --git a/client/dom/operations/rename-current.spec.js b/client/dom/operations/rename-current.spec.js index bc294e15..f39ff6bf 100644 --- a/client/dom/operations/rename-current.spec.js +++ b/client/dom/operations/rename-current.spec.js @@ -1,9 +1,7 @@ 'use strict'; -const { - test, - stub, -} = require('supertape'); +const {test, stub} = require('supertape'); + const mockRequire = require('mock-require'); const {reRequire, stopAll} = mockRequire; @@ -55,6 +53,7 @@ test('cloudcmd: client: dom: renameCurrent: file exist', async (t) => { await renameCurrent(); const expected = 'Directory "hello" already exists. Proceed?'; + global.CloudCmd = CloudCmd; stopAll(); @@ -98,4 +97,3 @@ const stubCurrentFile = (fns = {}) => { setCurrentName, }; }; - diff --git a/client/dom/rest.js b/client/dom/rest.js index 9ce9c302..9c638446 100644 --- a/client/dom/rest.js +++ b/client/dom/rest.js @@ -42,4 +42,3 @@ module.exports.Markdown = { read: handleError(IO.Markdown.read), render: handleError(IO.Markdown.render), }; - diff --git a/client/dom/select-by-pattern.js b/client/dom/select-by-pattern.js index eec89bb4..2f2cb22d 100644 --- a/client/dom/select-by-pattern.js +++ b/client/dom/select-by-pattern.js @@ -3,10 +3,7 @@ let SelectType = '*.*'; const {getRegExp} = require('../../common/util'); -const { - alert, - prompt, -} = require('./dialog'); +const {alert, prompt} = require('./dialog'); const DOM = require('.'); @@ -15,8 +12,6 @@ module.exports = async (msg, files) => { return; const allMsg = `Specify file type for ${msg} selection`; - - /* eslint require-atomic-updates: 0 */ const [cancel, type] = await prompt(allMsg, SelectType); if (cancel) @@ -48,4 +43,3 @@ module.exports = async (msg, files) => { if (!matches) alert('No matches found!'); }; - diff --git a/client/dom/storage.js b/client/dom/storage.js index d9eeb938..1fa6e8fe 100644 --- a/client/dom/storage.js +++ b/client/dom/storage.js @@ -26,4 +26,3 @@ module.exports.clear = () => { module.exports.remove = (item) => { localStorage.removeItem(item); }; - diff --git a/client/dom/storage.spec.js b/client/dom/storage.spec.js index d3b15e33..ff41af26 100644 --- a/client/dom/storage.spec.js +++ b/client/dom/storage.spec.js @@ -1,9 +1,7 @@ 'use strict'; -const { - test, - stub, -} = require('supertape'); +const {test, stub} = require('supertape'); + const storage = require('./storage'); const {stringify} = JSON; @@ -32,6 +30,7 @@ test('cloudcmd: client: storage: get', async (t) => { }; const result = await storage.get('hello'); + global.localStorage = localStorage; t.equal(result, 'world'); @@ -43,6 +42,7 @@ test('cloudcmd: client: storage: getJson', async (t) => { const expected = { hello: 'world', }; + const getItem = stub().returns(stringify(expected)); global.localStorage = { @@ -50,6 +50,7 @@ test('cloudcmd: client: storage: getJson', async (t) => { }; const result = await storage.getJson('hello'); + global.localStorage = localStorage; t.deepEqual(result, expected); @@ -105,4 +106,3 @@ test('cloudcmd: client: storage: clear', async (t) => { t.ok(clear.calledWith(), 'should call clear'); t.end(); }); - diff --git a/client/dom/upload-files.js b/client/dom/upload-files.js index e6e7ed79..61ccff5d 100644 --- a/client/dom/upload-files.js +++ b/client/dom/upload-files.js @@ -1,7 +1,6 @@ 'use strict'; /* global CloudCmd */ - const {eachSeries} = require('execon'); const wraptile = require('wraptile'); @@ -55,13 +54,14 @@ function _loadFile(dir, n, file, callback) { ++i; - load.put(api + path, file) + load + .put(api + path, file) .on('error', showError) .on('end', callback) .on('progress', (count) => { const max = step(n); const value = (i - 1) * max + percent(count, 100, max); - + Images.show.load('top'); Images.setProgress(Math.round(value)); }); @@ -70,4 +70,3 @@ function _loadFile(dir, n, file, callback) { function showError({message}) { alert(message); } - diff --git a/client/get-json-from-file-table.js b/client/get-json-from-file-table.js index 747cae9d..e6fbc872 100644 --- a/client/get-json-from-file-table.js +++ b/client/get-json-from-file-table.js @@ -1,7 +1,6 @@ 'use strict'; /* global DOM */ - const Info = DOM.CurrentInfo; /** @@ -46,4 +45,3 @@ module.exports = () => { return fileTable; }; - diff --git a/client/key/binder.js b/client/key/binder.js index 6765f931..2e858d76 100644 --- a/client/key/binder.js +++ b/client/key/binder.js @@ -15,4 +15,3 @@ module.exports.createBinder = () => { }, }; }; - diff --git a/client/key/index.js b/client/key/index.js index 3890121c..094d4e75 100644 --- a/client/key/index.js +++ b/client/key/index.js @@ -1,7 +1,6 @@ 'use strict'; /* global CloudCmd, DOM */ - const clipboard = require('@cloudcmd/clipboard'); const Buffer = require('../dom/buffer'); @@ -32,6 +31,7 @@ Chars([]); const {assign} = Object; const binder = createBinder(); + module.exports = assign(binder, KEY); module.exports.bind = () => { Events.addKey(listener, true); @@ -45,13 +45,13 @@ function getChar(event) { * event.keyIdentifier deprecated in chrome v51 * but event.key is absent in chrome <= v51 */ - const { key, shift, keyCode, keyIdentifier, } = event; + const char = key || fromCharCode(keyIdentifier); const symbol = getSymbol(shift, keyCode); @@ -136,6 +136,7 @@ async function switchKey(event) { changeDir, config, } = CloudCmd; + const {keyCode} = event; const alt = event.altKey; @@ -156,12 +157,14 @@ async function switchKey(event) { break; case KEY.INSERT: - DOM .toggleSelectedFile(current) + DOM + .toggleSelectedFile(current) .setCurrentFile(next); break; case KEY.INSERT_MAC: - DOM .toggleSelectedFile(current) + DOM + .toggleSelectedFile(current) .setCurrentFile(next); break; @@ -170,7 +173,7 @@ async function switchKey(event) { Operation.show('delete:silent'); else Operation.show('delete'); - + break; case KEY.ASTERISK: @@ -305,7 +308,7 @@ async function switchKey(event) { DOM.swapPanels(); event.preventDefault(); } - + break; /* navigation on file table: * @@ -403,7 +406,7 @@ async function switchKey(event) { await changeDir(path); else CloudCmd.View.show(); - + break; case KEY.BACKSPACE: @@ -414,7 +417,7 @@ async function switchKey(event) { case KEY.BACKSLASH: if (ctrlMeta) await changeDir('/'); - + break; case KEY.A: @@ -455,6 +458,7 @@ async function switchKey(event) { .catch(CloudCmd.log); break; + /** * обновляем страницу, * загружаем содержимое каталога @@ -468,31 +472,31 @@ async function switchKey(event) { CloudCmd.refresh(); event.preventDefault(); } - + break; case KEY.C: if (ctrlMeta) Buffer.copy(); - + break; case KEY.X: if (ctrlMeta) Buffer.cut(); - + break; case KEY.V: if (ctrlMeta) Buffer.paste(); - + break; case KEY.Z: if (ctrlMeta) Buffer.clear(); - + break; case KEY.COLON: @@ -508,8 +512,7 @@ async function switchKey(event) { CloudCmd.log('storage cleared'); event.preventDefault(); } - + break; } } - diff --git a/client/key/index.spec.js b/client/key/index.spec.js index 2dc3df06..b5a2a2c2 100644 --- a/client/key/index.spec.js +++ b/client/key/index.spec.js @@ -4,10 +4,8 @@ const autoGlobals = require('auto-globals'); const stub = require('@cloudcmd/stub'); const mockRequire = require('mock-require'); const {ESC} = require('./key'); -const { - getDOM, - getCloudCmd, -} = require('./vim/globals.fixture'); + +const {getDOM, getCloudCmd} = require('./vim/globals.fixture'); const {reRequire, stopAll} = mockRequire; @@ -66,4 +64,3 @@ test('cloudcmd: client: key: disable vim', async (t) => { t.calledWith(_config, ['vim']); t.end(); }); - diff --git a/client/key/key.js b/client/key/key.js index b160beef..d9696b9f 100644 --- a/client/key/key.js +++ b/client/key/key.js @@ -1,81 +1,81 @@ 'use strict'; module.exports = { - BACKSPACE : 8, - TAB : 9, - ENTER : 13, - CAPSLOCK : 20, - ESC : 27, + BACKSPACE: 8, + TAB: 9, + ENTER: 13, + CAPSLOCK: 20, + ESC: 27, - SPACE : 32, - PAGE_UP : 33, - PAGE_DOWN : 34, - END : 35, - HOME : 36, + SPACE: 32, + PAGE_UP: 33, + PAGE_DOWN: 34, + END: 35, + HOME: 36, - LEFT : 37, - UP : 38, - RIGHT : 39, - DOWN : 40, + LEFT: 37, + UP: 38, + RIGHT: 39, + DOWN: 40, - INSERT : 45, - DELETE : 46, + INSERT: 45, + DELETE: 46, - ZERO : 48, + ZERO: 48, - SEMICOLON : 52, + SEMICOLON: 52, - A : 65, + A: 65, - C : 67, - D : 68, + C: 67, + D: 68, - G : 71, + G: 71, - J : 74, - K : 75, + J: 74, + K: 75, - M : 77, + M: 77, - O : 79, - P : 80, - Q : 81, - R : 82, - S : 83, - T : 84, - U : 85, + O: 79, + P: 80, + Q: 81, + R: 82, + S: 83, + T: 84, + U: 85, - V : 86, + V: 86, - X : 88, + X: 88, - Z : 90, + Z: 90, - INSERT_MAC : 96, + INSERT_MAC: 96, - ASTERISK : 106, - PLUS : 107, - MINUS : 109, + ASTERISK: 106, + PLUS: 107, + MINUS: 109, - F1 : 112, - F2 : 113, - F3 : 114, - F4 : 115, - F5 : 116, - F6 : 117, - F7 : 118, - F8 : 119, - F9 : 120, - F10 : 121, + F1: 112, + F2: 113, + F3: 114, + F4: 115, + F5: 116, + F6: 117, + F7: 118, + F8: 119, + F9: 120, + F10: 121, - COLON : 186, - EQUAL : 187, - HYPHEN : 189, - DOT : 190, - SLASH : 191, - TRA : 192, /* Typewritten Reverse Apostrophe (`) */ - BACKSLASH : 220, + COLON: 186, + EQUAL: 187, + HYPHEN: 189, + DOT: 190, + SLASH: 191, + /* Typewritten Reverse Apostrophe (`) */ + TRA: 192, + BACKSLASH: 220, BRACKET_CLOSE: 221, }; - diff --git a/client/key/set-current-by-char.js b/client/key/set-current-by-char.js index c74876a4..f54881a3 100644 --- a/client/key/set-current-by-char.js +++ b/client/key/set-current-by-char.js @@ -31,6 +31,7 @@ module.exports = function setCurrentByChar(char, charStore) { const isTest = (a) => regExp.test(a); const isRoot = (a) => a === '..'; const not = (f) => (a) => !f(a); + const setCurrent = (name) => { const byName = DOM.getCurrentByName(name); @@ -57,4 +58,3 @@ module.exports = function setCurrentByChar(char, charStore) { charStore([char]); } }; - diff --git a/client/key/vim/find.js b/client/key/vim/find.js index a5f415d0..131ba267 100644 --- a/client/key/vim/find.js +++ b/client/key/vim/find.js @@ -37,14 +37,13 @@ module.exports._previous = previous; function next(index, length) { if (index === length - 1) return 0; - + return ++index; } function previous(index, length) { if (!index) return length - 1; - + return --index; } - diff --git a/client/key/vim/find.spec.js b/client/key/vim/find.spec.js index 3e3d6d3e..1b36216b 100644 --- a/client/key/vim/find.spec.js +++ b/client/key/vim/find.spec.js @@ -7,10 +7,7 @@ const {getDOM} = require('./globals.fixture'); global.DOM = getDOM(); -const { - _next, - _previous, -} = require(`${dir}find`); +const {_next, _previous} = require(`${dir}find`); test('cloudcmd: client: vim: _next', (t) => { const result = _next(1, 2); @@ -25,4 +22,3 @@ test('cloudcmd: client: vim: _previous', (t) => { t.equal(result, 1, 'should return 1'); t.end(); }); - diff --git a/client/key/vim/globals.fixture.js b/client/key/vim/globals.fixture.js index 9f2f63b4..3882e477 100644 --- a/client/key/vim/globals.fixture.js +++ b/client/key/vim/globals.fixture.js @@ -38,7 +38,7 @@ module.exports.getCloudCmd = () => { const show = () => {}; return { - Operation: { + Operation: { show, }, @@ -46,4 +46,3 @@ module.exports.getCloudCmd = () => { _config: noop, }; }; - diff --git a/client/key/vim/index.js b/client/key/vim/index.js index 290983d7..e79adb33 100644 --- a/client/key/vim/index.js +++ b/client/key/vim/index.js @@ -2,7 +2,6 @@ /* global CloudCmd */ /* global DOM */ - const vim = require('./vim'); const finder = require('./find'); @@ -16,43 +15,43 @@ module.exports = async (key, event) => { const getOperations = (event) => ({ escape: DOM.unselectFiles, - + remove: () => { CloudCmd.Operation.show('delete'); }, - + makeDirectory: () => { event.stopImmediatePropagation(); event.preventDefault(); DOM.promptNewDir(); }, - + makeFile: () => { event.stopImmediatePropagation(); event.preventDefault(); DOM.promptNewFile(); }, - + terminal: () => { CloudCmd.Terminal.show(); }, - + edit: () => { CloudCmd.EditFileVim.show(); }, - + copy: () => { DOM.Buffer.copy(); DOM.unselectFiles(); }, - + select: () => { const current = Info.element; DOM.toggleSelectedFile(current); }, - + paste: DOM.Buffer.paste, - + moveNext: ({count, isVisual, isDelete}) => { setCurrent('next', { count, @@ -60,7 +59,7 @@ const getOperations = (event) => ({ isDelete, }); }, - + movePrevious: ({count, isVisual, isDelete}) => { setCurrent('previous', { count, @@ -68,25 +67,25 @@ const getOperations = (event) => ({ isDelete, }); }, - + find: async () => { event.preventDefault(); const [, value] = await Dialog.prompt('Find', ''); - + if (!value) return; - + const names = Info.files.map(DOM.getCurrentName); const [result] = finder.find(value, names); - + DOM.setCurrentByName(result); }, - + findNext: () => { const name = finder.findNext(); DOM.setCurrentByName(name); }, - + findPrevious: () => { const name = finder.findPrevious(); DOM.setCurrentByName(name); @@ -97,34 +96,33 @@ module.exports.selectFile = selectFile; function selectFile(current) { const name = DOM.getCurrentName(current); - + if (name === '..') return; - + DOM.selectFile(current); } function setCurrent(sibling, {count, isVisual, isDelete}) { let current = Info.element; const select = isVisual ? selectFile : DOM.unselectFile; - + select(current); - + const position = `${sibling}Sibling`; - + for (let i = 0; i < count; i++) { const next = current[position]; - + if (!next) break; - + current = next; select(current); } - + DOM.setCurrentFile(current); - + if (isDelete) CloudCmd.Operation.show('delete'); } - diff --git a/client/key/vim/index.spec.js b/client/key/vim/index.spec.js index a28badcc..1e9c2632 100644 --- a/client/key/vim/index.spec.js +++ b/client/key/vim/index.spec.js @@ -2,20 +2,15 @@ const {join} = require('path'); -const { - test, - stub, -} = require('supertape'); +const {test, stub} = require('supertape'); + const mockRequire = require('mock-require'); const dir = '../'; const pathVim = join(dir, 'vim'); -const { - getDOM, - getCloudCmd, -} = require('./globals.fixture'); +const {getDOM, getCloudCmd} = require('./globals.fixture'); global.DOM = getDOM(); global.CloudCmd = getCloudCmd(); @@ -23,10 +18,7 @@ global.CloudCmd = getCloudCmd(); const vim = require(pathVim); const {assign} = Object; -const { - DOM, - CloudCmd, -} = global; +const {DOM, CloudCmd} = global; const {Buffer} = DOM; const pathFind = join(dir, 'vim', 'find'); @@ -34,14 +26,14 @@ const {reRequire, stopAll} = mockRequire; test('cloudcmd: client: key: set next file: no', (t) => { const element = {}; - + const setCurrentFile = stub(); - + global.DOM.CurrentInfo.element = element; global.DOM.setCurrentFile = setCurrentFile; - + vim('j', {}); - + t.calledWith(setCurrentFile, [element], 'should set next file'); t.end(); }); @@ -51,14 +43,14 @@ test('cloudcmd: client: key: set next file current: j', (t) => { const element = { nextSibling, }; - + const setCurrentFile = stub(); - + global.DOM.CurrentInfo.element = element; global.DOM.setCurrentFile = setCurrentFile; - + vim('j', {}); - + t.calledWith(setCurrentFile, [nextSibling], 'should set next file'); t.end(); }); @@ -68,16 +60,16 @@ test('cloudcmd: client: key: set next file current: mjj', (t) => { const element = { nextSibling, }; - + const setCurrentFile = stub(); - + global.DOM.CurrentInfo.element = element; global.DOM.setCurrentFile = setCurrentFile; - + vim('m', {}); vim('j', {}); vim('j', {}); - + t.calledWith(setCurrentFile, [nextSibling], 'should set next file'); t.end(); }); @@ -87,15 +79,15 @@ test('cloudcmd: client: key: set next file current: g', (t) => { const element = { nextSibling, }; - + const setCurrentFile = stub(); - + global.DOM.CurrentInfo.element = element; global.DOM.setCurrentFile = setCurrentFile; - + vim('g', {}); vim('j', {}); - + t.calledWith(setCurrentFile, [nextSibling], 'should ignore g'); t.end(); }); @@ -105,20 +97,21 @@ test('cloudcmd: client: key: set +2 file current', (t) => { const nextSibling = { nextSibling: last, }; + const element = { nextSibling, }; - + const setCurrentFile = stub(); - + global.DOM.CurrentInfo.element = element; global.DOM.setCurrentFile = setCurrentFile; - + const event = {}; - + vim('2', event); vim('j', event); - + t.calledWith(setCurrentFile, [last], 'should set next file'); t.end(); }); @@ -128,24 +121,25 @@ test('cloudcmd: client: key: select +2 files from current before delete', (t) => const nextSibling = { nextSibling: last, }; + const element = { nextSibling, }; - + const setCurrentFile = stub(); - + global.DOM.CurrentInfo.element = element; global.DOM.setCurrentFile = setCurrentFile; global.DOM.selectFile = stub(); global.DOM.getCurrentName = () => false; global.CloudCmd.Operation.show = stub(); - + const event = {}; - + vim('d', event); vim('2', event); vim('j', event); - + t.calledWith(setCurrentFile, [last], 'should set next file'); t.end(); }); @@ -155,25 +149,26 @@ test('cloudcmd: client: key: delete +2 files from current', (t) => { const nextSibling = { nextSibling: last, }; + const element = { nextSibling, }; - + const setCurrentFile = stub(); const show = stub(); - + global.DOM.CurrentInfo.element = element; global.DOM.setCurrentFile = setCurrentFile; global.DOM.selectFile = stub(); global.DOM.getCurrentName = () => false; global.CloudCmd.Operation.show = show; - + const event = {}; - + vim('d', event); vim('2', event); vim('j', event); - + t.calledWith(show, ['delete'], 'should call delete'); t.end(); }); @@ -183,87 +178,87 @@ test('cloudcmd: client: key: set previous file current', (t) => { const element = { previousSibling, }; - + const setCurrentFile = stub(); - + global.DOM.CurrentInfo.element = element; global.DOM.setCurrentFile = setCurrentFile; - + vim('k', {}); - + t.calledWith(setCurrentFile, [previousSibling], 'should set previous file'); t.end(); }); test('cloudcmd: client: key: copy: no', (t) => { const copy = stub(); - + Buffer.copy = copy; - + vim('y', {}); - + t.notOk(copy.called, 'should not copy files'); t.end(); }); test('cloudcmd: client: key: copy', (t) => { const copy = stub(); - + Buffer.copy = copy; - + vim('v', {}); vim('y', {}); - + t.ok(copy.calledWith(), 'should copy files'); t.end(); }); test('cloudcmd: client: key: copy: unselectFiles', (t) => { const unselectFiles = stub(); - + DOM.unselectFiles = unselectFiles; - + vim('v', {}); vim('y', {}); - + t.ok(unselectFiles.calledWith(), 'should unselect files'); t.end(); }); test('cloudcmd: client: key: paste', (t) => { const paste = stub(); - + Buffer.paste = paste; - + vim('p', {}); - + t.ok(paste.calledWith(), 'should paste files'); t.end(); }); test('cloudcmd: client: key: selectFile: ..', (t) => { const getCurrentName = stub(); - + DOM.selectFile = stub(); DOM.getCurrentName = () => '..'; - + const current = {}; vim.selectFile(current); - + t.notOk(getCurrentName.called, 'should not call selectFile'); t.end(); }); test('cloudcmd: client: key: selectFile', (t) => { const selectFile = stub(); - + DOM.selectFile = selectFile; DOM.getCurrentName = (a) => a.name; - + const current = {}; - + vim.selectFile(current); - + t.calledWith(selectFile, [current], 'should call selectFile'); t.end(); }); @@ -273,17 +268,18 @@ test('cloudcmd: client: key: set last file current: shift + g', (t) => { const nextSibling = { nextSibling: last, }; + const element = { nextSibling, }; - + const setCurrentFile = stub(); - + global.DOM.CurrentInfo.element = element; global.DOM.setCurrentFile = setCurrentFile; - + vim('G', {}); - + t.calledWith(setCurrentFile, [last], 'should set last file'); t.end(); }); @@ -293,17 +289,18 @@ test('cloudcmd: client: key: set last file current: $', (t) => { const nextSibling = { nextSibling: last, }; + const element = { nextSibling, }; - + const setCurrentFile = stub(); - + global.DOM.CurrentInfo.element = element; global.DOM.setCurrentFile = setCurrentFile; - + vim('$', {}); - + t.calledWith(setCurrentFile, [last], 'should set last file'); t.end(); }); @@ -313,19 +310,19 @@ test('cloudcmd: client: key: set first file current: gg', (t) => { const previousSibling = { previousSibling: first, }; - + const element = { previousSibling, }; - + const setCurrentFile = stub(); - + global.DOM.CurrentInfo.element = element; global.DOM.setCurrentFile = setCurrentFile; - + vim('g', {}); vim('g', {}); - + t.calledWith(setCurrentFile, [first], 'should set first file'); t.end(); }); @@ -335,46 +332,46 @@ test('cloudcmd: client: key: set first file current: ^', (t) => { const previousSibling = { previousSibling: first, }; - + const element = { previousSibling, }; - + const setCurrentFile = stub(); - + global.DOM.CurrentInfo.element = element; global.DOM.setCurrentFile = setCurrentFile; - + vim('^', {}); - + t.calledWith(setCurrentFile, [first], 'should set first file'); t.end(); }); test('cloudcmd: client: key: visual', (t) => { const element = {}; - + const toggleSelectedFile = stub(); - + global.DOM.CurrentInfo.element = element; global.DOM.toggleSelectedFile = toggleSelectedFile; - + vim('v', {}); - + t.calledWith(toggleSelectedFile, [element], 'should toggle selection'); t.end(); }); test('cloudcmd: client: key: ESC', (t) => { const element = {}; - + const unselectFiles = stub(); - + global.DOM.CurrentInfo.element = element; - global.DOM.unselectFiles = unselectFiles ; - + global.DOM.unselectFiles = unselectFiles; + vim('Escape'); - + t.ok(unselectFiles.calledWith(), 'should toggle selection'); t.end(); }); @@ -384,16 +381,16 @@ test('cloudcmd: client: key: Enter', (t) => { const element = { nextSibling, }; - + const setCurrentFile = stub(); - + DOM.CurrentInfo.element = element; DOM.setCurrentFile = setCurrentFile; - + vim('Enter'); - + vim('j'); - + t.calledWith(setCurrentFile, [nextSibling], 'should set next file'); t.end(); }); @@ -401,14 +398,14 @@ test('cloudcmd: client: key: Enter', (t) => { test('cloudcmd: client: key: /', (t) => { const preventDefault = stub(); const element = {}; - + DOM.CurrentInfo.element = element; DOM.getCurrentName = () => ''; - + vim('/', { preventDefault, }); - + t.calledWithNoArgs(preventDefault, 'should call preventDefault'); t.end(); }); @@ -417,94 +414,97 @@ test('cloudcmd: client: find', (t) => { assign(DOM.Dialog, { prompt: stub().returns([]), }); - + const setCurrentByName = stub(); - + assign(DOM, { setCurrentByName, }); - + const vim = reRequire(pathVim); + const event = { preventDefault: stub(), }; - + vim('/', event); - + stopAll(); - + t.notCalled(setCurrentByName); t.end(); }); test('cloudcmd: client: key: n', (t) => { const findNext = stub(); - + mockRequire(pathFind, { findNext, }); - + const vim = reRequire(pathVim); const event = {}; - + vim('n', event); - + stopAll(); - + t.ok(findNext.calledWith(), 'should call findNext'); t.end(); }); test('cloudcmd: client: key: N', (t) => { const findPrevious = stub(); - + mockRequire(pathFind, { findPrevious, }); - + const vim = reRequire(`${dir}vim`); const event = {}; - + vim('N', event); - + stopAll(); - + t.ok(findPrevious.calledWith(), 'should call findPrevious'); t.end(); }); test('cloudcmd: client: key: make directory', (t) => { const vim = reRequire(pathVim); - + assign(DOM, { promptNewDir: stub(), }); - + const event = { stopImmediatePropagation: stub(), preventDefault: stub(), }; + vim('m', event); vim('d', event); - + t.calledWithNoArgs(DOM.promptNewDir); t.end(); }); test('cloudcmd: client: key: make file', (t) => { const vim = reRequire(pathVim); - + assign(DOM, { promptNewFile: stub(), }); - + const event = { stopImmediatePropagation: stub(), preventDefault: stub(), }; + vim('m', event); vim('f', event); - + t.calledWithNoArgs(DOM.promptNewDir); t.end(); }); @@ -515,12 +515,12 @@ test('cloudcmd: client: vim: terminal', (t) => { show: stub(), }, }); - - const event = { - }; + + const event = {}; + vim('t', event); vim('t', event); - + t.calledWithNoArgs(CloudCmd.Terminal.show); t.end(); }); @@ -531,12 +531,11 @@ test('cloudcmd: client: vim: edit', (t) => { show: stub(), }, }); - - const event = { - }; + + const event = {}; + vim('e', event); - + t.calledWithNoArgs(CloudCmd.EditFileVim.show); t.end(); }); - diff --git a/client/key/vim/vim.js b/client/key/vim/vim.js index 89208a90..ef454442 100644 --- a/client/key/vim/vim.js +++ b/client/key/vim/vim.js @@ -25,6 +25,7 @@ module.exports = (key, operations) => { const prevStore = store(); const isVisual = visual(); const value = store(prevStore.concat(key)); + const { escape = noop, moveNext = noop, @@ -41,132 +42,129 @@ module.exports = (key, operations) => { terminal = noop, edit = noop, } = operations; - + if (key === 'Enter') return end(); - + if (key === 'Escape') { visual(false); escape(); - + return end(); } - + if (key === 'j' || key === 'w') { const { count, isDelete, isVisual, } = handleDelete(prevStore); - + !isNaN(count) && moveNext({ count, isVisual, isDelete, }); - + return end(); } - + if (key === 'k' || key === 'b') { const { count, isDelete, isVisual, } = handleDelete(prevStore); - + !isNaN(count) && movePrevious({ count, isVisual, isDelete, }); - + return end(); } - + if (value === 'gg' || key === '^') { - const { - isDelete, - isVisual, - } = handleDelete(prevStore); - + const {isDelete, isVisual} = handleDelete(prevStore); + movePrevious({ count: Infinity, isVisual, isDelete, }); - + return end(); } - + if (value === 'md') { makeDirectory(); return end(); } - + if (value === 'tt') { terminal(); return end(); } - + if (value === 'e') { edit(); return end(); } - + if (value === 'mf') { makeFile(); return end(); } - + if (key === 'd' && (visual() || prevStore === 'd')) { stopVisual(); remove(); - + return end(); } - + if (key === 'G' || key === '$') { moveNext({ count: Infinity, isVisual, }); - + return end(); } - + if (key === 'y') { if (!visual()) return end(); - + stopVisual(); copy(); - + return end(); } - + if (/^p$/i.test(key)) { paste(); return end(); } - + if (/^v$/i.test(key)) { visual(!visual()); select(); - + return end(); } - + if (key === '/') { find(); return end(); } - + if (key === 'n') { findNext(); return end(); } - + if (key === 'N') { findPrevious(); return end(); @@ -175,15 +173,15 @@ module.exports = (key, operations) => { function handleDelete(prevStore) { const isDelete = prevStore[0] === 'd'; - + if (isDelete) { visual(true); prevStore = rmFirst(prevStore); } - + const count = getNumber(prevStore); const isVisual = visual(); - + return { count, isDelete, @@ -194,10 +192,9 @@ function handleDelete(prevStore) { function getNumber(value) { if (!value) return 1; - + if (value === 'g') return 1; - + return parseInt(value); } - diff --git a/client/key/vim/vim.spec.js b/client/key/vim/vim.spec.js index 056b3c76..d0213369 100644 --- a/client/key/vim/vim.spec.js +++ b/client/key/vim/vim.spec.js @@ -1,9 +1,6 @@ 'use strict'; -const { - test, - stub, -} = require('supertape'); +const {test, stub} = require('supertape'); const vim = require('./vim'); @@ -64,4 +61,3 @@ test('vim: b', (t) => { t.calledWith(movePrevious, [expected], 'should call movePrevious'); t.end(); }); - diff --git a/client/listeners/get-index.js b/client/listeners/get-index.js index d7870608..4b31b249 100644 --- a/client/listeners/get-index.js +++ b/client/listeners/get-index.js @@ -8,4 +8,3 @@ module.exports = (array, item) => { return index; }; - diff --git a/client/listeners/get-range.js b/client/listeners/get-range.js index ef1ea0f8..b1d23c2c 100644 --- a/client/listeners/get-range.js +++ b/client/listeners/get-range.js @@ -9,4 +9,3 @@ module.exports = (indexFrom, indexTo, files) => { return [files[indexFrom]]; }; - diff --git a/client/listeners/index.js b/client/listeners/index.js index 054b3f7e..42595f3b 100644 --- a/client/listeners/index.js +++ b/client/listeners/index.js @@ -52,12 +52,10 @@ const execAll = currify((funcs, event) => { const Info = DOM.CurrentInfo; const {Events} = DOM; + const EventsFiles = { mousedown: exec.with(execIfNotUL, setCurrentFileByEvent), - click: execAll([ - onClick, - unselect, - ]), + click: execAll([onClick, unselect]), dragstart: exec.with(execIfNotUL, onDragStart), dblclick: exec.with(execIfNotUL, onDblClick), touchstart: exec.with(execIfNotUL, onTouch), @@ -79,8 +77,7 @@ function header() { if (parent.dataset.name !== 'js-fm-header') return; - const name = (el.dataset.name || '') - .replace('js-', ''); + const name = (el.dataset.name || '').replace('js-', ''); if (!/^(name|size|date)$/.test(name)) return; @@ -97,7 +94,7 @@ function header() { function getPath(el, path = []) { if (!el) return path; - + return getPath(el.parentElement, path.concat(el)); } @@ -124,19 +121,19 @@ module.exports.initKeysPanel = () => { }; const clickFuncs = { - 'f1' : CloudCmd.Help.show, - 'f2' : CloudCmd.UserMenu.show, - 'f3' : CloudCmd.View.show, - 'f4' : CloudCmd.EditFile.show, - 'f5' : operation('copy'), - 'f6' : operation('move'), - 'f7' : DOM.promptNewDir, - 'f8' : operation('delete'), - 'f9' : CloudCmd.Menu.show, - 'f10' : CloudCmd.Config.show, - '~' : CloudCmd.Konsole.show, - 'shift~' : CloudCmd.Terminal.show, - 'contact' : CloudCmd.Contact.show, + 'f1': CloudCmd.Help.show, + 'f2': CloudCmd.UserMenu.show, + 'f3': CloudCmd.View.show, + 'f4': CloudCmd.EditFile.show, + 'f5': operation('copy'), + 'f6': operation('move'), + 'f7': DOM.promptNewDir, + 'f8': operation('delete'), + 'f9': CloudCmd.Menu.show, + 'f10': CloudCmd.Config.show, + '~': CloudCmd.Konsole.show, + 'shift~': CloudCmd.Terminal.show, + 'contact': CloudCmd.Contact.show, }; exec(clickFuncs[id]); @@ -146,7 +143,7 @@ module.exports.initKeysPanel = () => { const getPanel = (side) => { if (!itype.string(side)) return side; - + return DOM.getByDataName(`js-${side}`); }; @@ -182,10 +179,8 @@ function decodePath(path) { const {prefix} = CloudCmd; const prefixReg = RegExp('^' + prefix + FS); - return decodeURI(path) - .replace(url, '') - .replace(prefixReg, '') - // browser doesn't replace % -> %25% do it for him + return decodeURI(path).replace(url, '') + .replace(prefixReg, '') // browser doesn't replace % -> %25% do it for him .replace('%%', '%25%') .replace(NBSP_REG, SPACE) || '/'; } @@ -219,8 +214,12 @@ async function onPathElementClick(panel, event) { } function copyPath(el) { - clipboard.writeText(el.parentElement.title) - .then(CloudCmd.log) + clipboard + .writeText(el + .parentElement + .title) + .then(CloudCmd + .log) .catch(CloudCmd.log); } @@ -308,12 +307,8 @@ function onDragStart(event) { link.href = prefixURL + '/pack' + Info.path + EXT; } - event.dataTransfer.setData( - 'DownloadURL', - 'application/octet-stream' + ':' + - name + ':' + - link, - ); + event.dataTransfer.setData('DownloadURL', 'application/octet-stream' + ':' + name + + ':' + link); } function getLIElement(element) { @@ -397,10 +392,7 @@ function dragndrop() { }; const onDrop = (event) => { - const { - files, - items, - } = event.dataTransfer; + const {files, items} = event.dataTransfer; const {length: filesCount} = files; @@ -410,7 +402,9 @@ function dragndrop() { return uploadFiles(files); const isFile = (item) => item.kind === 'file'; - const dirFiles = Array.from(items).filter(isFile); + const dirFiles = Array + .from(items) + .filter(isFile); if (dirFiles.length) return DOM.uploadDirectory(dirFiles); @@ -467,6 +461,7 @@ function pop() { return CloudCmd.route(location.hash); const history = false; + await CloudCmd.changeDir(path, { history, }); @@ -495,4 +490,3 @@ function resize() { DOM.changePanel(); }); } - diff --git a/client/load-module.js b/client/load-module.js index d49ade87..0ce0cc64 100644 --- a/client/load-module.js +++ b/client/load-module.js @@ -1,7 +1,6 @@ 'use strict'; /* global CloudCmd */ - const exec = require('execon'); const tryToCatch = require('try-to-catch'); const loadJS = require('load.js').js; @@ -16,45 +15,44 @@ const noJS = (a) => a.replace(/.js$/, ''); module.exports = function loadModule(params) { if (!params) return; - + const {path} = params; - + const name = path && noJS(pascalCase(path)); const doBefore = params.dobefore; - + if (CloudCmd[name]) return; - + CloudCmd[name] = async () => { exec(doBefore); - + const {DIR_MODULES} = CloudCmd; const pathFull = `${DIR_MODULES}/${path}.js`; - + await loadJS(pathFull); const newModule = async (f) => f && f(); const module = CloudCmd[name]; - + Object.assign(newModule, module); - + CloudCmd[name] = newModule; CloudCmd.log('init', name); - + await module.init(); - + return newModule; }; - + CloudCmd[name].show = async (...args) => { CloudCmd.log('show', name, args); const m = CloudCmd[name]; - + const [e, a] = await tryToCatch(m); - + if (e) return console.error(e); - + return await a.show(...args); }; }; - diff --git a/client/modules/cloud.js b/client/modules/cloud.js index 05c4dab5..81498c4b 100644 --- a/client/modules/cloud.js +++ b/client/modules/cloud.js @@ -15,6 +15,7 @@ const {log} = CloudCmd; const upload = currify(_upload); const Name = 'Cloud'; + CloudCmd[Name] = module.exports; module.exports.init = async () => { @@ -41,10 +42,7 @@ module.exports.saveFile = (callback) => { }; function _upload(callback, file) { - const { - url, - filename, - } = file; + const {url, filename} = file; const responseType = 'arraybuffer'; const success = exec.with(callback, filename); @@ -64,4 +62,3 @@ function loadFiles() { load.js(js), ]); } - diff --git a/client/modules/command-line.js b/client/modules/command-line.js index bf53ce99..a6cbf231 100644 --- a/client/modules/command-line.js +++ b/client/modules/command-line.js @@ -1,7 +1,6 @@ 'use strict'; /* global CloudCmd */ - CloudCmd.CommandLine = exports; const Dialog = require('../dom/dialog'); @@ -34,6 +33,4 @@ async function show() { } } -function hide() { -} - +function hide() {} diff --git a/client/modules/config/index.js b/client/modules/config/index.js index bf72c661..5c586c48 100644 --- a/client/modules/config/index.js +++ b/client/modules/config/index.js @@ -1,7 +1,6 @@ 'use strict'; /* global CloudCmd, DOM, io */ - require('../../../css/config.css'); const rendy = require('rendy'); @@ -22,6 +21,7 @@ const {getTitle} = require('../../../common/cloudfunc'); const {Dialog, setTitle} = DOM; const Name = 'Config'; + CloudCmd[Name] = module.exports; const loadSocket = promisify(DOM.loadSocket); @@ -64,10 +64,7 @@ module.exports.init = async () => { initSocket(); }; -const { - config, - Key, -} = CloudCmd; +const {config, Key} = CloudCmd; let Element; @@ -77,6 +74,7 @@ function getHost() { origin, protocol, } = location; + const href = origin || `${protocol}//${host}`; return href; @@ -84,10 +82,7 @@ function getHost() { function initSocket() { const href = getHost(); - const { - prefixSocket, - prefix, - } = CloudCmd; + const {prefixSocket, prefix} = CloudCmd; const ONE_MINUTE = 60 * 1000; @@ -156,7 +151,7 @@ async function fillTemplate() { const innerHTML = rendy(Template, obj); Element = createElement('form', { - className : 'config', + className: 'config', innerHTML, }); @@ -173,11 +168,13 @@ async function fillTemplate() { const getTarget = ({target}) => target; const handleChange = squad(onChange, getTarget); - Array.from(inputs) + Array + .from(inputs) .map(addKey(onKey)) .map(addChange(handleChange)); const autoSize = true; + CloudCmd.View.show(Element, { autoSize, afterShow, @@ -246,4 +243,3 @@ async function onKey({keyCode, target}) { return await onChange(target); } } - diff --git a/client/modules/config/input.js b/client/modules/config/input.js index adc44055..ca1c638d 100644 --- a/client/modules/config/input.js +++ b/client/modules/config/input.js @@ -11,8 +11,7 @@ module.exports.getElementByName = getElementByName; function getElementByName(selector, element) { const str = `[data-name="js-${selector}"]`; - return element - .querySelector(str); + return element.querySelector(str); } module.exports.getName = (element) => { @@ -40,7 +39,7 @@ module.exports.convert = (config) => { function setState(state) { if (state) return ' checked'; - + return ''; } @@ -74,4 +73,3 @@ module.exports.setValue = (name, value, element) => { break; } }; - diff --git a/client/modules/contact.js b/client/modules/contact.js index abcfd003..76a07d30 100644 --- a/client/modules/contact.js +++ b/client/modules/contact.js @@ -39,4 +39,3 @@ function onKey({keyCode}) { if (keyCode === Key.ESC) hide(); } - diff --git a/client/modules/edit-file-vim.js b/client/modules/edit-file-vim.js index c9b9c891..48cfd93e 100644 --- a/client/modules/edit-file-vim.js +++ b/client/modules/edit-file-vim.js @@ -1,7 +1,6 @@ 'use strict'; /* global CloudCmd */ - CloudCmd.EditFileVim = exports; const Events = require('../dom/events'); @@ -23,8 +22,7 @@ module.exports.init = async () => { module.exports.show = async () => { Events.addKey(listener); - const editFile = await CloudCmd.EditFile - .show(ConfigView); + const editFile = await CloudCmd.EditFile.show(ConfigView); editFile .getEditor() @@ -38,14 +36,10 @@ function hide() { } function listener(event) { - const { - keyCode, - shiftKey, - } = event; + const {keyCode, shiftKey} = event; if (shiftKey && keyCode === Key.ESC) { event.preventDefault(); hide(); } } - diff --git a/client/modules/edit-file.js b/client/modules/edit-file.js index 32616edb..5551a155 100644 --- a/client/modules/edit-file.js +++ b/client/modules/edit-file.js @@ -1,7 +1,6 @@ 'use strict'; /* global CloudCmd, DOM*/ - CloudCmd.EditFile = exports; const Format = require('format-io'); @@ -11,10 +10,7 @@ const supermenu = require('supermenu'); const Info = DOM.CurrentInfo; -const { - Dialog, - Images, -} = DOM; +const {Dialog, Images} = DOM; const {config} = CloudCmd; @@ -65,7 +61,8 @@ module.exports.show = async (options) => { Images.show.load(); - CloudCmd.Edit + CloudCmd + .Edit .getEditor() .setOption('keyMap', 'default'); @@ -81,7 +78,8 @@ module.exports.show = async (options) => { setMsgChanged(name); - CloudCmd.Edit + CloudCmd + .Edit .getEditor() .setValueFirst(path, data) .setModeForPath(name) @@ -133,7 +131,8 @@ function setMenu(event) { }, afterClick: () => { - CloudCmd.Edit + CloudCmd + .Edit .getEditor() .focus(); }, @@ -151,28 +150,28 @@ function getMenuData() { const editor = CloudCmd.Edit.getEditor(); return { - 'Save Ctrl+S' : () => { + 'Save Ctrl+S': () => { editor.save(); }, - 'Go To Line Ctrl+G' : () => { + 'Go To Line Ctrl+G': () => { editor.goToLine(); }, - 'Cut Ctrl+X' : () => { + 'Cut Ctrl+X': () => { editor.cutToClipboard(); }, - 'Copy Ctrl+C' : () => { + 'Copy Ctrl+C': () => { editor.copyToClipboard(); }, - 'Paste Ctrl+V' : () => { + 'Paste Ctrl+V': () => { editor.pasteFromClipboard(); }, - 'Delete Del' : () => { + 'Delete Del': () => { editor.remove('right'); }, - 'Select All Ctrl+A' : () => { + 'Select All Ctrl+A': () => { editor.selectAll(); }, - 'Close Esc' : hide, + 'Close Esc': hide, }; } @@ -196,4 +195,3 @@ async function isChanged() { editor.save(); } - diff --git a/client/modules/edit-names-vim.js b/client/modules/edit-names-vim.js index 66087294..540259e5 100644 --- a/client/modules/edit-names-vim.js +++ b/client/modules/edit-names-vim.js @@ -1,7 +1,6 @@ 'use strict'; /* global CloudCmd */ - CloudCmd.EditNamesVim = exports; const Events = require('../dom/events'); @@ -22,7 +21,8 @@ module.exports.init = async () => { module.exports.show = () => { Events.addKey(listener); - CloudCmd.EditNames + CloudCmd + .EditNames .show(ConfigView) .getEditor() .setKeyMap('vim'); @@ -35,14 +35,10 @@ function hide() { } function listener(event) { - const { - keyCode, - shiftKey, - } = event; + const {keyCode, shiftKey} = event; if (shiftKey && keyCode === Key.ESC) { event.preventDefault(); hide(); } } - diff --git a/client/modules/edit-names.js b/client/modules/edit-names.js index bce3038d..36a9c653 100644 --- a/client/modules/edit-names.js +++ b/client/modules/edit-names.js @@ -1,7 +1,6 @@ 'use strict'; /* global CloudCmd, DOM */ - CloudCmd.EditNames = exports; const currify = require('currify'); @@ -45,7 +44,8 @@ module.exports.show = (options) => { DOM.Events.addKey(keyListener); - CloudCmd.Edit + CloudCmd + .Edit .getEditor() .setValueFirst('edit-names', names) .setMode() @@ -65,7 +65,6 @@ async function keyListener(event) { if (ctrlMeta && event.keyCode === Key.S) hide(); - else if (ctrlMeta && event.keyCode === Key.P) { const [, pattern] = await Dialog.prompt('Apply pattern:', '[n][e]'); pattern && applyPattern(pattern); @@ -107,7 +106,8 @@ function applyNames() { const root = CloudCmd.config('root'); - Promise.resolve(root) + Promise + .resolve(root) .then(rename(dir, from, to)) .then(refresh(to, nameIndex)) .catch(alert); @@ -115,7 +115,9 @@ function applyNames() { function _refresh(to, nameIndex, res) { if (res.status === 404) - return res.text().then(reject); + return res + .text() + .then(reject); const currentName = to[nameIndex]; @@ -127,7 +129,7 @@ function _refresh(to, nameIndex, res) { function getDir(root, dir) { if (root === '/') return dir; - + return root + dir; } @@ -158,6 +160,7 @@ function setMenu(event) { return; const editor = CloudCmd.Edit.getEditor(); + const options = { beforeShow: (params) => { params.x -= 18; @@ -170,29 +173,29 @@ function setMenu(event) { }; const menuData = { - 'Save Ctrl+S' : () => { + 'Save Ctrl+S': () => { applyNames(); hide(); }, - 'Go To Line Ctrl+G' : () => { + 'Go To Line Ctrl+G': () => { editor.goToLine(); }, - 'Cut Ctrl+X' : () => { + 'Cut Ctrl+X': () => { editor.cutToClipboard(); }, - 'Copy Ctrl+C' : () => { + 'Copy Ctrl+C': () => { editor.copyToClipboard(); }, - 'Paste Ctrl+V' : () => { + 'Paste Ctrl+V': () => { editor.pasteFromClipboard(); }, - 'Delete Del' : () => { + 'Delete Del': () => { editor.remove('right'); }, - 'Select All Ctrl+A' : () => { + 'Select All Ctrl+A': () => { editor.selectAll(); }, - 'Close Esc' : hide, + 'Close Esc': hide, }; const element = CloudCmd.Edit.getElement(); @@ -215,4 +218,3 @@ async function isChanged() { const [, names] = await Dialog.confirm(msg); names && applyNames(); } - diff --git a/client/modules/edit.js b/client/modules/edit.js index 6807ca3b..ce8848af 100644 --- a/client/modules/edit.js +++ b/client/modules/edit.js @@ -33,7 +33,7 @@ const ConfigView = { module.exports.init = async () => { const element = create(); - + await CloudCmd.View(); await loadFiles(element); }; @@ -47,9 +47,9 @@ function create() { `, notAppend: true, }); - + Element = element; - + return element; } @@ -63,30 +63,29 @@ function initConfig(options = {}) { ...options, ...ConfigView, }; - + if (!options.afterShow) return config; - + checkFn('options.afterShow', options.afterShow); - + config.afterShow = () => { ConfigView.afterShow(); options.afterShow(); }; - + return config; } module.exports.show = (options) => { if (Loading) return; - + CloudCmd.View.show(Element, initConfig(options)); - - getEditor() - .setOptions({ - fontSize: 16, - }); + + getEditor().setOptions({ + fontSize: 16, + }); }; module.exports.getEditor = getEditor; @@ -106,11 +105,11 @@ const loadFiles = async (element) => { const socketPath = CloudCmd.prefix; const prefixSocket = `${CloudCmd.prefixSocket}/${EditorName}`; const url = `${prefix}/${EditorName}.js`; - + time(`${Name} load`); - + await loadJS(url); - + const word = promisify(window[EditorName]); const [ed] = await tryToCatch(word, element, { maxSize, @@ -118,9 +117,8 @@ const loadFiles = async (element) => { prefixSocket, socketPath, }); - + timeEnd(`${Name} load`); editor = ed; Loading = false; }; - diff --git a/client/modules/help.js b/client/modules/help.js index 5e859115..785bb32c 100644 --- a/client/modules/help.js +++ b/client/modules/help.js @@ -1,7 +1,6 @@ 'use strict'; /* global CloudCmd */ - CloudCmd.Help = exports; const Images = require('../dom/images'); @@ -17,15 +16,12 @@ function show() { const positionLoad = 'top'; const relative = true; - CloudCmd - .Markdown - .show('/HELP.md', { - positionLoad, - relative, - }); + CloudCmd.Markdown.show('/HELP.md', { + positionLoad, + relative, + }); } function hide() { CloudCmd.View.hide(); } - diff --git a/client/modules/konsole.js b/client/modules/konsole.js index 5c2ade00..41936486 100644 --- a/client/modules/konsole.js +++ b/client/modules/konsole.js @@ -4,7 +4,6 @@ /* global Util */ /* global DOM */ /* global Console */ - CloudCmd.Konsole = exports; const exec = require('execon'); @@ -14,10 +13,7 @@ const loadJS = require('load.js').js; const createElement = require('@cloudcmd/create-element'); const Images = require('../dom/images'); -const { - Dialog, - CurrentInfo:Info, -} = DOM; +const {Dialog, CurrentInfo: Info} = DOM; const rmLastSlash = (a) => a.replace(/\/$/, '') || '/'; @@ -147,4 +143,3 @@ const load = async () => { cancel: false, }); }; - diff --git a/client/modules/markdown.js b/client/modules/markdown.js index 759805c5..6c5c3282 100644 --- a/client/modules/markdown.js +++ b/client/modules/markdown.js @@ -1,7 +1,6 @@ 'use strict'; /* global CloudCmd */ - CloudCmd.Markdown = exports; const createElement = require('@cloudcmd/create-element'); @@ -22,10 +21,7 @@ module.exports.hide = () => { }; async function show(name, options = {}) { - const { - positionLoad, - relative, - } = options; + const {positionLoad, relative} = options; Images.show.load(positionLoad); @@ -41,6 +37,7 @@ async function show(name, options = {}) { }); const className = 'help'; + const div = createElement('div', { className, innerHTML, @@ -48,4 +45,3 @@ async function show(name, options = {}) { CloudCmd.View.show(div); } - diff --git a/client/modules/menu.js b/client/modules/menu.js index fa85dabc..69ea8a66 100644 --- a/client/modules/menu.js +++ b/client/modules/menu.js @@ -11,10 +11,7 @@ const {FS} = require('../../common/cloudfunc'); const {getIdBySrc} = require('../dom/load'); const RESTful = require('../dom/rest'); -const { - config, - Key, -} = CloudCmd; +const {config, Key} = CloudCmd; const { Buffer, @@ -36,15 +33,16 @@ module.exports.ENABLED = false; CloudCmd.Menu = exports; module.exports.init = () => { - const { - isAuth, - menuDataFile, - } = getFileMenuData(); + const {isAuth, menuDataFile} = getFileMenuData(); const fm = DOM.getFM(); const menuData = getMenuData(isAuth); - const options = getOptions({type: 'context'}); - const optionsFile = getOptions({type: 'file'}); + const options = getOptions({ + type: 'context', + }); + const optionsFile = getOptions({ + type: 'file', + }); MenuContext = supermenu(fm, options, menuData); MenuContextFile = supermenu(fm, optionsFile, menuDataFile); @@ -77,7 +75,7 @@ function getPosition(position) { x: position.x, y: position.y, }; - + return getCurrentPosition(); } @@ -105,9 +103,9 @@ function getOptions({type}) { } const options = { - icon : true, - beforeClose : Key.setBind, - beforeShow : exec.with(beforeShow, func), + icon: true, + beforeClose: Key.setBind, + beforeShow: exec.with(beforeShow, func), beforeClick, name, }; @@ -252,7 +250,9 @@ function uploadFromCloud() { if (e) return; - await CloudCmd.refresh({currentName}); + await CloudCmd.refresh({ + currentName, + }); }); } @@ -292,7 +292,7 @@ function download(type) { src = prefixURL + FS + encodedPath + '?download'; const element = createElement('iframe', { - id : id + '-' + date, + id: id + '-' + date, async: false, className: 'hidden', src, @@ -321,10 +321,7 @@ function getCurrentPosition() { } function listener(event) { - const { - F9, - ESC, - } = Key; + const {F9, ESC} = Key; const key = event.keyCode; const isBind = Key.isBind(); diff --git a/client/modules/operation/format.js b/client/modules/operation/format.js index 373d069c..37c5e01e 100644 --- a/client/modules/operation/format.js +++ b/client/modules/operation/format.js @@ -3,7 +3,6 @@ module.exports = (operation, from, to) => { if (!to) return `${operation} ${from}`; - + return `${operation} ${from} -> ${to}`; }; - diff --git a/client/modules/operation/get-next-current-name.js b/client/modules/operation/get-next-current-name.js index d2b96545..d0f120d5 100644 --- a/client/modules/operation/get-next-current-name.js +++ b/client/modules/operation/get-next-current-name.js @@ -16,4 +16,3 @@ module.exports = (currentName, names, removedNames) => { return nextNames[length - 1]; }; - diff --git a/client/modules/operation/index.js b/client/modules/operation/index.js index 99436763..98d461f7 100644 --- a/client/modules/operation/index.js +++ b/client/modules/operation/index.js @@ -20,6 +20,7 @@ const getNextCurrentName = require('./get-next-current-name'); const removeQuery = (a) => a.replace(/\?.*/, ''); const Name = 'Operation'; + CloudCmd[Name] = exports; const {config} = CloudCmd; @@ -61,10 +62,7 @@ module.exports.init = promisify((callback) => { if (config('dropbox')) return callback(); - const { - prefix, - prefixSocket, - } = CloudCmd; + const {prefix, prefixSocket} = CloudCmd; await loadAll(); await initOperations(prefix, prefixSocket, callback); @@ -94,7 +92,10 @@ const onConnect = currify((fn, operator) => { async function initOperations(prefix, socketPrefix, fn) { socketPrefix = `${socketPrefix}/fileop`; - const operator = await fileop({prefix, socketPrefix}); + const operator = await fileop({ + prefix, + socketPrefix, + }); operator.on('connect', authCheck(operator, onConnect(fn))); } @@ -109,7 +110,8 @@ function setOperations(operator) { to, }); - operator.tar(from, to, names) + operator + .tar(from, to, names) .then(listen); }; @@ -123,7 +125,8 @@ function setOperations(operator) { to, }); - operator.zip(from, to, names) + operator + .zip(from, to, names) .then(listen); }; @@ -137,7 +140,8 @@ function setOperations(operator) { from, }); - operator.remove(from, files) + operator + .remove(from, files) .then(listen); }; @@ -151,7 +155,8 @@ function setOperations(operator) { names, }); - operator.copy(from, to, names) + operator + .copy(from, to, names) .then(listen); }; @@ -164,7 +169,8 @@ function setOperations(operator) { to, }); - operator.move(from, to, names) + operator + .move(from, to, names) .then(listen); }; @@ -178,7 +184,8 @@ function setOperations(operator) { to, }); - operator.extract(from, to) + operator + .extract(from, to) .then(listen); }; } @@ -186,7 +193,7 @@ function setOperations(operator) { function getPacker(type) { if (type === 'zip') return packZipFn; - + return packTarFn; } @@ -274,6 +281,7 @@ async function promptDelete() { const type = getType(isDir) + ' '; const name = DOM.getCurrentName(current); + msg = msgAsk + msgSel + type + name + '?'; } @@ -333,20 +341,19 @@ async function _processFiles(options, data) { let names = []; - /* eslint no-multi-spaces: 0 */ if (data) { - from = data.from; - to = data.to; - names = data.names; - panel = Info.panel; + from = data.from; + to = data.to; + names = data.names; + panel = Info.panel; } else { - from = Info.dirPath; - to = DOM.getNotCurrentDirPath(); - selFiles = DOM.getSelectedFiles(); - names = DOM.getFilenames(selFiles); - data = {}; - shouldAsk = true; - panel = Info.panelPassive; + from = Info.dirPath; + to = DOM.getNotCurrentDirPath(); + selFiles = DOM.getSelectedFiles(); + names = DOM.getFilenames(selFiles); + data = {}; + shouldAsk = true; + panel = Info.panelPassive; } if (!names.length) @@ -383,10 +390,14 @@ async function _processFiles(options, data) { if (ok && !shouldAsk || !sameName) return go(); - const str = `"${ name }" already exist. Overwrite?`; + const str = `"${name}" already exist. Overwrite?`; const cancel = false; - Dialog.confirm(str, {cancel}).then(go); + Dialog + .confirm(str, { + cancel, + }) + .then(go); function go() { showLoad(); @@ -400,10 +411,7 @@ async function _processFiles(options, data) { operation(files, async () => { await DOM.Storage.remove(from); - const { - panel, - panelPassive, - } = Info; + const {panel, panelPassive} = Info; if (!Info.isOnePanel) CloudCmd.refresh({ @@ -429,10 +437,7 @@ function twopack(operation, type) { let fileFrom; let currentName = Info.name; - const { - path, - dirPath, - } = Info; + const {path, dirPath} = Info; const activeFiles = DOM.getActiveFiles(); const names = DOM.getFilenames(activeFiles); @@ -446,7 +451,7 @@ function twopack(operation, type) { case 'extract': op = extractFn; - fileFrom = { + fileFrom = { from: path, to: dirPath, }; @@ -459,7 +464,7 @@ function twopack(operation, type) { op = getPacker(type); if (names.length > 1) - currentName = Info.dir; + currentName = Info.dir; currentName += DOM.getPackerExt(type); @@ -487,9 +492,9 @@ async function prompt(msg, to, names) { msg += ' '; if (names.length > 1) - msg += `${n} file(s)`; + msg += `${n} file(s)`; else - msg += `"${name}"`; + msg += `"${name}"`; msg += ' to'; @@ -507,4 +512,3 @@ async function loadAll() { Loaded = true; } - diff --git a/client/modules/operation/remove-extension.js b/client/modules/operation/remove-extension.js index 52772c30..a8389af3 100644 --- a/client/modules/operation/remove-extension.js +++ b/client/modules/operation/remove-extension.js @@ -17,4 +17,3 @@ function getExtension(name) { return getExt(name); } - diff --git a/client/modules/operation/remove-extension.spec.js b/client/modules/operation/remove-extension.spec.js index 0cf0aacc..9896e735 100644 --- a/client/modules/operation/remove-extension.spec.js +++ b/client/modules/operation/remove-extension.spec.js @@ -26,4 +26,3 @@ test('cloudcmd: client: modules: operation: removeExtension: .bz2', (t) => { t.equal(removeExtension(fullName), name, 'should remove .bz2'); t.end(); }); - diff --git a/client/modules/operation/set-listeners.js b/client/modules/operation/set-listeners.js index 8d436ef5..495cd04b 100644 --- a/client/modules/operation/set-listeners.js +++ b/client/modules/operation/set-listeners.js @@ -1,16 +1,12 @@ 'use strict'; /* global DOM */ - const forEachKey = require('for-each-key'); const wraptile = require('wraptile'); const format = require('./format'); -const { - Dialog, - Images, -} = DOM; +const {Dialog, Images} = DOM; module.exports = (options) => (emitter) => { const { @@ -28,6 +24,7 @@ module.exports = (options) => (emitter) => { emitter.abort(); const msg = `${operation} aborted`; + lastError = true; Dialog.alert(msg, { @@ -85,4 +82,3 @@ module.exports = (options) => (emitter) => { forEachKey(on, listeners); }; - diff --git a/client/modules/polyfill.js b/client/modules/polyfill.js index e4fe9fcf..e3cb5fde 100644 --- a/client/modules/polyfill.js +++ b/client/modules/polyfill.js @@ -1,11 +1,10 @@ 'use strict'; /* global DOM */ - require('domtokenlist-shim'); const scrollIntoViewIfNeeded = require('scroll-into-view-if-needed').default; + DOM.scrollIntoViewIfNeeded = (el) => scrollIntoViewIfNeeded(el, { block: 'nearest', }); - diff --git a/client/modules/polyfill.spec.js b/client/modules/polyfill.spec.js index 462a3cb0..ea4524a7 100644 --- a/client/modules/polyfill.spec.js +++ b/client/modules/polyfill.spec.js @@ -1,9 +1,7 @@ 'use strict'; -const { - test, - stub, -} = require('supertape'); +const {test, stub} = require('supertape'); + const mockRequire = require('mock-require'); const {stopAll} = mockRequire; @@ -25,10 +23,9 @@ test('cloudcmd: client: polyfill: scrollIntoViewIfNeaded', (t) => { mockRequire.stop('scroll-into-view-if-neaded'); global.DOM = DOM; - const args = [ - el, { - block: 'nearest', - }]; + const args = [el, { + block: 'nearest', + }]; stopAll(); diff --git a/client/modules/terminal-run.js b/client/modules/terminal-run.js index e0cee4ec..f9001650 100644 --- a/client/modules/terminal-run.js +++ b/client/modules/terminal-run.js @@ -1,7 +1,6 @@ 'use strict'; /* global CloudCmd, gritty */ - const {promisify} = require('es6-promisify'); const tryToCatch = require('try-to-catch'); const fullstore = require('fullstore'); @@ -14,10 +13,7 @@ const DOM = require('../dom'); const Images = require('../dom/images'); const {Dialog} = DOM; -const { - Key, - config, -} = CloudCmd; +const {Key, config} = CloudCmd; CloudCmd.TerminalRun = exports; @@ -152,4 +148,3 @@ function authCheck(spawn) { Dialog.alert('Wrong credentials!'); }); } - diff --git a/client/modules/terminal.js b/client/modules/terminal.js index db203cb9..8f0c97de 100644 --- a/client/modules/terminal.js +++ b/client/modules/terminal.js @@ -2,7 +2,6 @@ /* global CloudCmd */ /* global gritty */ - const tryToCatch = require('try-to-catch'); require('../../css/terminal.css'); @@ -15,10 +14,7 @@ const Images = require('../dom/images'); const loadParallel = load.parallel; const {Dialog} = DOM; -const { - Key, - config, -} = CloudCmd; +const {Key, config} = CloudCmd; CloudCmd.Terminal = exports; @@ -123,4 +119,3 @@ function show() { }, }); } - diff --git a/client/modules/upload.js b/client/modules/upload.js index 868428ad..427e74cb 100644 --- a/client/modules/upload.js +++ b/client/modules/upload.js @@ -66,4 +66,3 @@ function afterShow() { uploadFiles(files); }); } - diff --git a/client/modules/user-menu/get-user-menu.js b/client/modules/user-menu/get-user-menu.js index 2df17696..6281eda1 100644 --- a/client/modules/user-menu/get-user-menu.js +++ b/client/modules/user-menu/get-user-menu.js @@ -8,4 +8,3 @@ module.exports = (menuFn) => { 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 index 911a5e14..20f2e11e 100644 --- a/client/modules/user-menu/get-user-menu.spec.js +++ b/client/modules/user-menu/get-user-menu.spec.js @@ -18,4 +18,3 @@ test('user-menu: getUserMenu', (t) => { t.equal(key, 'F2 - Rename file'); t.end(); }); - diff --git a/client/modules/user-menu/index.js b/client/modules/user-menu/index.js index 19f9e5ab..47fbee39 100644 --- a/client/modules/user-menu/index.js +++ b/client/modules/user-menu/index.js @@ -1,7 +1,6 @@ 'use strict'; /* global CloudCmd, DOM */ - require('../../../css/user-menu.css'); const currify = require('currify'); @@ -25,6 +24,7 @@ const loadCSS = load.css; const sourceStore = fullstore(); const Name = 'UserMenu'; + CloudCmd[Name] = module.exports; const {Key} = CloudCmd; @@ -52,7 +52,10 @@ async function show() { Images.hide(); if (error) - return Dialog.alert(getCodeFrame({error, source})); + return Dialog.alert(getCodeFrame({ + error, + source, + })); sourceStore(source); @@ -118,10 +121,7 @@ const onButtonClick = wraptile(async (items, {value}) => { }); const onKeyDown = currify(async ({keys, userMenu}, e) => { - const { - keyCode, - target, - } = e; + const {keyCode, target} = e; const keyName = e.key.toUpperCase(); @@ -156,6 +156,7 @@ const runUserMenu = async (fn) => { return; const source = sourceStore(); + return Dialog.alert(getCodeFrame({ error, source, @@ -169,6 +170,7 @@ function getCodeFrame({error, source}) { return error.message; const [line, column] = parseError(error); + const start = { line, column, @@ -185,4 +187,3 @@ function getCodeFrame({error, source}) { return `
${frame}
`; } - diff --git a/client/modules/user-menu/navigate.js b/client/modules/user-menu/navigate.js index eaaac9dc..2f0833d4 100644 --- a/client/modules/user-menu/navigate.js +++ b/client/modules/user-menu/navigate.js @@ -16,43 +16,42 @@ module.exports = (el, {key, keyCode}) => { if (isDigit(key)) { store(Number(key)); } - + if (keyCode === DOWN || keyCode === J) { const count = store(); store(1); - + return down(el, count); } - + if (keyCode === UP || keyCode === K) { const count = store(); store(1); - + return up(el, count); } }; function down(el, count) { const {length} = el; - + if (el.selectedIndex === length - 1) el.selectedIndex = 0; else el.selectedIndex += count; - + if (el.selectedIndex < 0) el.selectedIndex = length - 1; } function up(el, count) { const {length} = el; - + if (!el.selectedIndex) el.selectedIndex = length - 1; else el.selectedIndex -= count; - + if (el.selectedIndex < 0) el.selectedIndex = 0; } - diff --git a/client/modules/user-menu/navigate.spec.js b/client/modules/user-menu/navigate.spec.js index 28ebb73d..abf95aab 100644 --- a/client/modules/user-menu/navigate.spec.js +++ b/client/modules/user-menu/navigate.spec.js @@ -15,11 +15,11 @@ test('cloudcmd: user-menu: navigate: DOWN', (t) => { length: 3, selectedIndex: 0, }; - + navigate(el, { keyCode: DOWN, }); - + t.equal(el.selectedIndex, 1); t.end(); }); @@ -29,11 +29,11 @@ test('cloudcmd: user-menu: navigate: J', (t) => { length: 3, selectedIndex: 0, }; - + navigate(el, { keyCode: J, }); - + t.equal(el.selectedIndex, 1); t.end(); }); @@ -43,11 +43,11 @@ test('cloudcmd: user-menu: navigate: DOWN: bottom', (t) => { length: 3, selectedIndex: 2, }; - + navigate(el, { keyCode: DOWN, }); - + t.equal(el.selectedIndex, 0); t.end(); }); @@ -57,11 +57,11 @@ test('cloudcmd: user-menu: navigate: K', (t) => { length: 3, selectedIndex: 2, }; - + navigate(el, { keyCode: K, }); - + t.equal(el.selectedIndex, 1); t.end(); }); @@ -71,11 +71,11 @@ test('cloudcmd: user-menu: navigate: UP', (t) => { length: 3, selectedIndex: 2, }; - + navigate(el, { keyCode: UP, }); - + t.equal(el.selectedIndex, 1); t.end(); }); @@ -85,11 +85,11 @@ test('cloudcmd: user-menu: navigate: UP: top', (t) => { length: 3, selectedIndex: 0, }; - + navigate(el, { keyCode: UP, }); - + t.equal(el.selectedIndex, 2); t.end(); }); @@ -99,11 +99,11 @@ test('cloudcmd: user-menu: navigate', (t) => { length: 3, selectedIndex: 0, }; - + navigate(el, { keyCode: 0, }); - + t.equal(el.selectedIndex, 0, 'should not change'); t.end(); }); @@ -113,16 +113,16 @@ test('cloudcmd: user-menu: navigate: DOWN: count', (t) => { length: 3, selectedIndex: 0, }; - + navigate(el, { keyCode: 53, key: '5', }); - + navigate(el, { keyCode: DOWN, }); - + t.equal(el.selectedIndex, 5); t.end(); }); @@ -132,16 +132,16 @@ test('cloudcmd: user-menu: navigate: J: count: to big', (t) => { length: 3, selectedIndex: -Infinity, }; - + navigate(el, { keyCode: 53, key: '5', }); - + navigate(el, { keyCode: J, }); - + t.equal(el.selectedIndex, 2); t.end(); }); @@ -151,16 +151,16 @@ test('cloudcmd: user-menu: navigate: K: count: to small', (t) => { length: 3, selectedIndex: -Infinity, }; - + navigate(el, { keyCode: 53, key: '5', }); - + navigate(el, { keyCode: K, }); - + t.equal(el.selectedIndex, 0); t.end(); }); diff --git a/client/modules/user-menu/parse-error.js b/client/modules/user-menu/parse-error.js index 190c4ff6..aa7d574a 100644 --- a/client/modules/user-menu/parse-error.js +++ b/client/modules/user-menu/parse-error.js @@ -3,17 +3,11 @@ const isNumber = (a) => typeof a === 'number'; module.exports = (error) => { - const { - lineNumber, - columnNumber, - } = error; + const {lineNumber, columnNumber} = error; // thank you firefox if (isNumber(lineNumber) && isNumber(columnNumber)) - return [ - lineNumber, - columnNumber, - ]; + return [lineNumber, columnNumber]; const before = error.stack.indexOf('>'); const str = error.stack.slice(before + 1); @@ -27,4 +21,3 @@ module.exports = (error) => { Number(column), ]; }; - diff --git a/client/modules/user-menu/parse-error.spec.js b/client/modules/user-menu/parse-error.spec.js index b4ee299b..873525a6 100644 --- a/client/modules/user-menu/parse-error.spec.js +++ b/client/modules/user-menu/parse-error.spec.js @@ -24,7 +24,9 @@ test('user-menu: parse-error: stack', (t) => { at AsyncFunction.show (index.js:67) `; - const result = parseError({stack}); + const result = parseError({ + stack, + }); const expected = [1, 2]; t.deepEqual(result, expected); diff --git a/client/modules/user-menu/parse-user-menu.js b/client/modules/user-menu/parse-user-menu.js index d4013405..2a947f83 100644 --- a/client/modules/user-menu/parse-user-menu.js +++ b/client/modules/user-menu/parse-user-menu.js @@ -32,4 +32,3 @@ module.exports = (userMenu) => { settings, }; }; - diff --git a/client/modules/user-menu/parse-user-menu.spec.js b/client/modules/user-menu/parse-user-menu.spec.js index d2fd9300..0807896f 100644 --- a/client/modules/user-menu/parse-user-menu.spec.js +++ b/client/modules/user-menu/parse-user-menu.spec.js @@ -1,9 +1,7 @@ 'use strict'; -const { - test, - stub, -} = require('supertape'); +const {test, stub} = require('supertape'); + const parse = require('./parse-user-menu'); test('cloudcmd: user menu: parse', (t) => { @@ -15,7 +13,10 @@ test('cloudcmd: user menu: parse', (t) => { '_f': fn, }); - const names = ['F2 - Rename file']; + const names = [ + 'F2 - Rename file', + ]; + const keys = { F2: fn, }; diff --git a/client/modules/user-menu/run.js b/client/modules/user-menu/run.js index 463396d2..61228be9 100644 --- a/client/modules/user-menu/run.js +++ b/client/modules/user-menu/run.js @@ -5,4 +5,3 @@ module.exports.runSelected = async (selectedItems, items, runUserMenu) => { await runUserMenu(items[selected]); } }; - diff --git a/client/modules/user-menu/run.spec.js b/client/modules/user-menu/run.spec.js index a8444e86..488c6c27 100644 --- a/client/modules/user-menu/run.spec.js +++ b/client/modules/user-menu/run.spec.js @@ -1,17 +1,13 @@ 'use strict'; -const { - test, - stub, -} = require('supertape'); +const {test, stub} = require('supertape'); + const {runSelected} = require('./run'); test('cloudcmd: client: user menu: run', async (t) => { const runUserMenu = stub(); const fn = stub(); - const selected = [ - 'hello', - ]; + const selected = ['hello']; const items = { hello: fn, @@ -22,4 +18,3 @@ test('cloudcmd: client: user menu: run', async (t) => { t.calledWith(runUserMenu, [fn]); t.end(); }); - diff --git a/client/modules/view/index.js b/client/modules/view/index.js index a53681fe..377c5e7f 100644 --- a/client/modules/view/index.js +++ b/client/modules/view/index.js @@ -1,7 +1,7 @@ -'use strict'; - /* global CloudCmd, DOM */ +'use strict'; + require('../../../css/view.css'); const rendy = require('rendy'); @@ -15,6 +15,7 @@ const createElement = require('@cloudcmd/create-element'); const {time} = require('../../../common/util'); const {FS} = require('../../../common/cloudfunc'); + const { isImage, isAudio, @@ -49,6 +50,7 @@ module.exports.hide = hide; let Loading = false; const Name = 'View'; + CloudCmd[Name] = module.exports; const Info = DOM.CurrentInfo; @@ -64,84 +66,88 @@ const Config = { Images.hide(); Key.unsetBind(); }, - + beforeClose: () => { Events.rmKey(listener); Key.setBind(); }, - + afterShow: () => { El.focus(); }, - + onOverlayClick, afterClose: noop, autoSize: false, - + helpers: { title: {}, }, }; + module.exports._Config = Config; module.exports.init = async () => { await loadAll(); - + const events = [ 'click', 'contextmenu', ]; - - events.forEach(addEvent(Overlay, onOverlayClick)); + + events.forEach(addEvent( + Overlay, + onOverlayClick, + )); }; async function show(data, options = {}) { const prefixURL = CloudCmd.prefixURL + FS; - + if (Loading) return; - + if (!options || options.bindKeys !== false) Events.addKey(listener); - + El = createElement('div', { className: 'view', notAppend: true, }); - + El.tabIndex = 0; - + if (data) { if (isArray(data)) El.append(...data); else El.append(data); - + modal.open(El, initConfig(options)); return; } - + Images.show.load(); - + const path = prefixURL + Info.path; const type = options.raw ? '' : await getType(path); - + switch(type) { default: return await viewFile(); - + case 'markdown': return await CloudCmd.Markdown.show(Info.path); - + case 'html': return viewHtml(path); - + case 'image': return viewImage(Info.path, prefixURL); - + case 'media': return await viewMedia(path); - + case 'pdf': return viewPDF(path); } @@ -154,11 +160,11 @@ function createIframe(src) { width: '100%', height: '100%', }); - + element.addEventListener('load', () => { element.contentWindow.addEventListener('keydown', listener); }); - + return element; } @@ -169,21 +175,21 @@ function viewHtml(src) { function viewPDF(src) { const element = createIframe(src); - + const options = assign({}, Config); - + if (CloudCmd.config('showFileName')) options.title = Info.name; - + modal.open(element, options); } async function viewMedia(path) { const [e, element] = await getMediaElement(path); - + if (e) return alert(e); - + const allConfig = { ...Config, ...{ @@ -195,22 +201,22 @@ async function viewMedia(path) { }, }, }; - + modal.open(element, allConfig); } async function viewFile() { const [error, data] = await Info.getData(); - + if (error) return Images.hide(); - + const element = document.createTextNode(data); const options = Config; - + if (CloudCmd.config('showFileName')) options.title = Info.name; - + El.append(element); modal.open(El, options); } @@ -220,25 +226,26 @@ const copy = (a) => assign({}, a); module.exports._initConfig = initConfig; function initConfig(options) { const config = copy(Config); - + if (!options) return config; - + const names = Object.keys(options); - + for (const name of names) { const isConfig = Boolean(config[name]); const item = options[name]; - + if (!isFn(item) || !isConfig) { config[name] = options[name]; continue; } - + const fn = config[name]; + config[name] = series(fn, item); } - + return config; } @@ -252,59 +259,60 @@ function viewImage(path, prefixURL) { href: `${prefixURL}${path}`, title: encode(basename(path)), }); - - const names = Info.files + + const names = Info + .files .map(DOM.getCurrentPath) .filter(isSupportedImage); - - const titles = names - .map(makeTitle); - + + const titles = names.map(makeTitle); + const index = names.indexOf(Info.path); + const imageConfig = { index, - autoSize : true, - arrows : true, - keys : true, - helpers : { - title : {}, + autoSize: true, + arrows: true, + keys: true, + helpers: { + title: {}, }, }; - + const config = { ...Config, ...imageConfig, }; - + modal.open(titles, config); } async function getMediaElement(src) { check(src); - + 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]; } @@ -319,9 +327,9 @@ function check(src) { */ async function loadAll() { const {DIR_DIST} = CloudCmd; - + time(`${Name} load`); - + Loading = true; await loadCSS(`${DIR_DIST}/view.css`); Loading = false; @@ -332,32 +340,29 @@ function onOverlayClick(event) { x: event.clientX, y: event.clientY, }; - + setCurrentByPosition(position); } function setCurrentByPosition(position) { const element = DOM.getCurrentByPosition(position); - + if (!element) return; - - const { - files, - filesPassive, - } = Info; - + + const {files, filesPassive} = Info; + const isFiles = files.includes(element); const isFilesPassive = filesPassive.includes(element); - + if (!isFiles && !isFilesPassive) return; - + const isCurrent = DOM.isCurrentFile(element); - + if (isCurrent) return; - + DOM.setCurrentFile(element); } @@ -365,4 +370,3 @@ function listener({keyCode}) { if (keyCode === Key.ESC) hide(); } - diff --git a/client/modules/view/index.spec.js b/client/modules/view/index.spec.js index e88aa9a9..83e6b476 100644 --- a/client/modules/view/index.spec.js +++ b/client/modules/view/index.spec.js @@ -64,12 +64,10 @@ test('cloudcmd: client: view: html', (t) => { open, }); - const { - _viewHtml, - _Config, - } = reRequire('.'); + const {_viewHtml, _Config} = reRequire('.'); const src = '/hello.html'; + _viewHtml(src); global.CloudCmd = CloudCmd; @@ -89,6 +87,7 @@ test('cloudcmd: client: view: createIframe', (t) => { const el = { addEventListener, }; + const createElement = stub().returns(el); mockRequire('@cloudcmd/create-element', createElement); @@ -114,6 +113,7 @@ test('cloudcmd: client: view: createIframe: returns', (t) => { const el = { addEventListener, }; + const createElement = stub().returns(el); mockRequire('@cloudcmd/create-element', createElement); diff --git a/client/modules/view/types.js b/client/modules/view/types.js index c4cf5ce6..c5f6c99c 100644 --- a/client/modules/view/types.js +++ b/client/modules/view/types.js @@ -69,9 +69,10 @@ async function detectType(path) { for (const [name, value] of headers) { if (name === 'content-type') - return `.${value.split('/').pop()}`; + return `.${value + .split('/') + .pop()}`; } return ''; } - diff --git a/client/modules/view/types.spec.js b/client/modules/view/types.spec.js index 9f157841..52ed5bad 100644 --- a/client/modules/view/types.spec.js +++ b/client/modules/view/types.spec.js @@ -23,15 +23,14 @@ test('cloudcmd: client: view: types: detectType', async (t) => { }); const originalFetch = global.fetch; + global.fetch = fetch; await _detectType('/hello'); global.fetch = originalFetch; - const expected = [ - '/hello', { - method: 'HEAD', - }, - ]; + const expected = ['/hello', { + method: 'HEAD', + }]; t.calledWith(fetch, expected); t.end(); @@ -39,6 +38,7 @@ test('cloudcmd: client: view: types: detectType', async (t) => { test('cloudcmd: client: view: types: detectType: found', async (t) => { const originalFetch = global.fetch; + global.fetch = stub().returns({ headers: [ ['content-type', 'image/png'], @@ -51,4 +51,3 @@ test('cloudcmd: client: view: types: detectType: found', async (t) => { t.equal(result, '.png'); t.end(); }); - diff --git a/client/sort.js b/client/sort.js index b3c68ee5..7c5b7330 100644 --- a/client/sort.js +++ b/client/sort.js @@ -5,10 +5,7 @@ const DOM = require('./dom'); const Info = DOM.CurrentInfo; -const { - sort, - order, -} = CloudCmd; +const {sort, order} = CloudCmd; const position = DOM.getPanelPosition(); @@ -17,10 +14,7 @@ let sortPrevious = sort[position]; const {getPanel} = DOM; CloudCmd.sortPanel = (name, panel = getPanel()) => { - const position = panel - .dataset - .name - .replace('js-', ''); + const position = panel.dataset.name.replace('js-', ''); if (name !== sortPrevious) { order[position] = 'asc'; @@ -40,4 +34,3 @@ CloudCmd.sortPanel = (name, panel = getPanel()) => { noCurrent, }); }; - diff --git a/client/sw/register.js b/client/sw/register.js index 1ef95cdb..12431a82 100644 --- a/client/sw/register.js +++ b/client/sw/register.js @@ -25,7 +25,7 @@ async function registerSW(prefix) { if (e) return null; - + return sw; } @@ -33,4 +33,3 @@ async function unregisterSW(prefix) { const reg = await registerSW(prefix); reg?.unregister(prefix); } - diff --git a/client/sw/register.spec.js b/client/sw/register.spec.js index c5032bf9..966ed981 100644 --- a/client/sw/register.spec.js +++ b/client/sw/register.spec.js @@ -114,4 +114,3 @@ test('sw: register: unregisterSW', async (t, {location, navigator}) => { t.calledWith(register, ['/hello/sw.js'], 'should call register'); t.end(); }); - diff --git a/client/sw/sw.js b/client/sw/sw.js index ff9a23fe..c15c4138 100644 --- a/client/sw/sw.js +++ b/client/sw/sw.js @@ -45,7 +45,7 @@ const createRequest = (a) => new Request(a, { const getRequest = (a, request) => { if (a !== '/') return request; - + return createRequest('/'); }; @@ -97,4 +97,3 @@ async function addToCache(request, response) { const cache = await caches.open(NAME); return cache.put(request, response); } - diff --git a/common/base64.js b/common/base64.js index bc73b7f3..6cd8efcd 100644 --- a/common/base64.js +++ b/common/base64.js @@ -3,7 +3,7 @@ module.exports.btoa = (str) => { if (typeof btoa === 'function') return btoa(str); - + return Buffer .from(str) .toString('base64'); @@ -12,9 +12,8 @@ module.exports.btoa = (str) => { module.exports.atob = (str) => { if (typeof atob === 'function') return atob(str); - + return Buffer .from(str, 'base64') .toString('binary'); }; - diff --git a/common/base64.spec.js b/common/base64.spec.js index 2429a13c..bc3ea2f5 100644 --- a/common/base64.spec.js +++ b/common/base64.spec.js @@ -1,9 +1,6 @@ 'use strict'; -const { - test, - stub, -} = require('supertape'); +const {test, stub} = require('supertape'); const {btoa, atob} = require('./base64'); @@ -54,4 +51,3 @@ test('atob: node', (t) => { t.equal(result, expected, 'should encode base64'); t.end(); }); - diff --git a/common/callbackify.js b/common/callbackify.js index a8657480..c2040a3d 100644 --- a/common/callbackify.js +++ b/common/callbackify.js @@ -9,4 +9,3 @@ module.exports = (promise) => (...a) => { .then(success(fn)) .catch(fn); }; - diff --git a/common/callbackify.spec.js b/common/callbackify.spec.js index 3628fc76..b5823293 100644 --- a/common/callbackify.spec.js +++ b/common/callbackify.spec.js @@ -2,10 +2,8 @@ const tryToCatch = require('try-to-catch'); -const { - test, - stub, -} = require('supertape'); +const {test, stub} = require('supertape'); + const callbackify = require('./callbackify'); const {promisify} = require('util'); @@ -30,4 +28,3 @@ test('cloudcmd: common: callbackify', async (t) => { t.equal(data, 'hi'); t.end(); }); - diff --git a/common/cloudfunc.js b/common/cloudfunc.js index 4b686014..8bb1f159 100644 --- a/common/cloudfunc.js +++ b/common/cloudfunc.js @@ -9,7 +9,6 @@ const {btoa} = require('./base64'); const getHeaderField = currify(_getHeaderField); /* КОНСТАНТЫ (общие для клиента и сервера)*/ - /* название программы */ const NAME = 'Cloud Commander'; const FS = '/fs'; @@ -41,10 +40,7 @@ module.exports.formatMsg = (msg, name, status) => { module.exports.getTitle = (options) => { options = options || {}; - const { - path = Path(), - name, - } = options; + const {path = Path(), name} = options; const array = [ name || NAME, @@ -71,7 +67,10 @@ function getPathLink(url, prefix, template) { .split('/') .slice(1, -1); - const allNames = ['/', ...names]; + const allNames = [ + '/', + ...names, + ]; const lines = []; const n = allNames.length; @@ -165,7 +164,7 @@ module.exports.buildFromJSON = (params) => { Path(path); fileTable += `${header}