chore: lint

This commit is contained in:
coderaiser 2023-07-09 12:43:24 +03:00
parent f1279666b5
commit 4717e035ee
173 changed files with 1388 additions and 1627 deletions

6
.github/FUNDING.yml vendored
View file

@ -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

View file

@ -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 }}

View file

@ -1,7 +1,5 @@
{
"plugins": [
"cloudcmd"
],
"plugins": ["cloudcmd"],
"ignore": [
"html",
"fixture*",

View file

@ -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']),
};
}

View file

@ -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,
};
}

View file

@ -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}`;
}

101
HELP.md
View file

@ -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);

View file

@ -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);
}

View file

@ -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);
}

View file

@ -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,
});
};
}

View file

@ -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));
}

View file

@ -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;
}

View file

@ -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;
};

View file

@ -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({
},
};
}

View file

@ -24,4 +24,3 @@ module.exports.alert.noFiles = () => {
cancel: false,
});
};

View file

@ -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`);
}

View file

@ -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;
};

View file

@ -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();
});

View file

@ -15,4 +15,3 @@ module.exports.clear = () => {
};
module.exports.get = () => list;

View file

@ -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);

View file

@ -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!');
}
}

View file

@ -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);
};
}

View file

@ -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;
};

View file

@ -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');
};

View file

@ -29,4 +29,3 @@ test('cloudcmd: client: dom: goToDirectory', async (t) => {
t.calledWith(changeDir, [path]);
t.end();
});

View file

@ -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 = {
});
},
};

View file

@ -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;

View file

@ -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');
}

View file

@ -11,4 +11,3 @@ test('cloudcmd: client: io: replaceHash', (t) => {
t.equal(result, expected);
t.end();
});

View file

@ -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);
});
};

View file

@ -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;
};

View file

@ -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();
};

View file

@ -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,
};
};

View file

@ -42,4 +42,3 @@ module.exports.Markdown = {
read: handleError(IO.Markdown.read),
render: handleError(IO.Markdown.render),
};

View file

@ -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!');
};

View file

@ -26,4 +26,3 @@ module.exports.clear = () => {
module.exports.remove = (item) => {
localStorage.removeItem(item);
};

View file

@ -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();
});

View file

@ -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);
}

View file

@ -1,7 +1,6 @@
'use strict';
/* global DOM */
const Info = DOM.CurrentInfo;
/**
@ -46,4 +45,3 @@ module.exports = () => {
return fileTable;
};

View file

@ -15,4 +15,3 @@ module.exports.createBinder = () => {
},
};
};

View file

@ -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;
}
}

View file

@ -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();
});

View file

@ -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,
};

View file

@ -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]);
}
};

View file

@ -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;
}

View file

@ -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();
});

View file

@ -38,7 +38,7 @@ module.exports.getCloudCmd = () => {
const show = () => {};
return {
Operation: {
Operation: {
show,
},
@ -46,4 +46,3 @@ module.exports.getCloudCmd = () => {
_config: noop,
};
};

View file

@ -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');
}

View file

@ -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();
});

View file

@ -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);
}

View file

@ -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();
});

View file

@ -8,4 +8,3 @@ module.exports = (array, item) => {
return index;
};

View file

@ -9,4 +9,3 @@ module.exports = (indexFrom, indexTo, files) => {
return [files[indexFrom]];
};

View file

@ -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();
});
}

View file

@ -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);
};
};

View file

@ -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),
]);
}

View file

@ -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() {}

View file

@ -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);
}
}

View file

@ -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;
}
};

View file

@ -39,4 +39,3 @@ function onKey({keyCode}) {
if (keyCode === Key.ESC)
hide();
}

View file

@ -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();
}
}

View file

@ -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();
}

View file

@ -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();
}
}

View file

@ -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();
}

View file

@ -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;
};

View file

@ -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();
}

View file

@ -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,
});
};

View file

@ -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);
}

View file

@ -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();

View file

@ -3,7 +3,6 @@
module.exports = (operation, from, to) => {
if (!to)
return `${operation} ${from}`;
return `${operation} ${from} -> ${to}`;
};

View file

@ -16,4 +16,3 @@ module.exports = (currentName, names, removedNames) => {
return nextNames[length - 1];
};

View file

@ -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;
}

View file

@ -17,4 +17,3 @@ function getExtension(name) {
return getExt(name);
}

View file

@ -26,4 +26,3 @@ test('cloudcmd: client: modules: operation: removeExtension: .bz2', (t) => {
t.equal(removeExtension(fullName), name, 'should remove .bz2');
t.end();
});

View file

@ -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);
};

View file

@ -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',
});

View file

@ -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();

View file

@ -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!');
});
}

View file

@ -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() {
},
});
}

View file

@ -66,4 +66,3 @@ function afterShow() {
uploadFiles(files);
});
}

View file

@ -8,4 +8,3 @@ module.exports = (menuFn) => {
return module.exports;
};

View file

@ -18,4 +18,3 @@ test('user-menu: getUserMenu', (t) => {
t.equal(key, 'F2 - Rename file');
t.end();
});

View file

@ -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 `<pre>${frame}</pre>`;
}

View file

@ -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;
}

View file

@ -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();
});

View file

@ -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),
];
};

View file

@ -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);

View file

@ -32,4 +32,3 @@ module.exports = (userMenu) => {
settings,
};
};

View file

@ -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,
};

View file

@ -5,4 +5,3 @@ module.exports.runSelected = async (selectedItems, items, runUserMenu) => {
await runUserMenu(items[selected]);
}
};

View file

@ -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();
});

View file

@ -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();
}

View file

@ -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);

View file

@ -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 '';
}

View file

@ -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();
});

View file

@ -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,
});
};

View file

@ -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);
}

View file

@ -114,4 +114,3 @@ test('sw: register: unregisterSW', async (t, {location, navigator}) => {
t.calledWith(register, ['/hello/sw.js'], 'should call register');
t.end();
});

View file

@ -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);
}

View file

@ -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');
};

Some files were not shown because too many files have changed in this diff Show more