Compare commits

...

23 commits

Author SHA1 Message Date
coderiaser
78e87796df chore: cloudcmd: v19.1.9 2026-01-21 20:08:24 +02:00
coderiaser
75ad4415c4 feature: cloudcmd: @putout/eslint-flat v4.0.0 2026-01-21 20:06:53 +02:00
coderiaser
c5d9bd7c1f feature: client: key: vim: get rid of mock-require 2026-01-21 20:06:35 +02:00
coderiaser
f437a52ff0 feature: client: images: migrate to EMS 2026-01-21 19:59:27 +02:00
coderiaser
7192a56e94 feature: client: dom: current-file: migrate to ESM 2026-01-21 19:50:30 +02:00
coderiaser
b9dd4f2676 chore: cloudcmd: v19.1.8 2026-01-20 23:43:51 +02:00
coderiaser
e8cf3c92f9 chore: lint 2026-01-20 23:43:06 +02:00
coderiaser
d574a93d6d feature: client: key: migrate to ESM 2026-01-20 23:41:26 +02:00
coderiaser
8a769fd512 fix: client: modules: operation: no update after copy 2026-01-20 23:41:26 +02:00
coderiaser
3b409074c1 feature: client: modules: operation: migrate to ESM 2026-01-20 23:41:26 +02:00
coderiaser
3b6b0b5a5b feature: client: buffer: migrate to ESM 2026-01-20 23:41:26 +02:00
coderiaser
8876f050e0 feature: cloudcmd: eslint-plugin-putout v30.0.0 2026-01-20 23:41:26 +02:00
coderiaser
8507282d55 test: cloudcmd: client: key: rm skip 2026-01-20 23:41:26 +02:00
coderaiser
f61b21eecc chore: cloudcmd: actions: lint ☘️ 2026-01-17 12:36:49 +00:00
coderiaser
242820b7cf chore: cloudcmd: v19.1.7 2026-01-17 14:36:00 +02:00
coderiaser
dd240ba9b2 test: client: key: vim: rm skip 2026-01-17 14:36:00 +02:00
coderaiser
4b945c0047 chore: cloudcmd: actions: lint ☘️ 2026-01-17 12:23:41 +00:00
coderiaser
23a6a6981a feature: client: dom/events -> #dom/events 2026-01-17 14:22:49 +02:00
coderiaser
9cebb2416f feature: client: dom: events: migrate to ESM 2026-01-17 14:22:49 +02:00
coderiaser
a94fa0d465 feature: client: cloudcmd: migrate to ESM 2026-01-17 14:22:49 +02:00
coderiaser
3bdf47a5bb feature: client: migrate to ESM 2026-01-17 14:22:49 +02:00
coderaiser
0ccd109a50 chore: cloudcmd: actions: lint ☘️ 2026-01-16 22:25:24 +00:00
coderaiser
6b0bd2e1de
refactor: client: move out inner functions 2026-01-16 23:24:31 +01:00
45 changed files with 624 additions and 593 deletions

View file

@ -8,7 +8,6 @@
"*.md"
],
"rules": {
"tape/remove-skip": "off",
"package-json/add-type": "off"
},
"match": {
@ -30,7 +29,7 @@
"server/{server,exit,terminal,distribute/log}.{js,mjs}": {
"remove-console": "off"
},
"client/{client,cloudcmd,load-module}.js": {
"client/{client,cloudcmd,load-module}.{js,mjs}": {
"remove-console": "off"
},
"client": {

View file

@ -114,7 +114,7 @@ export default {
'terminal': `${dirCss}/terminal.css`,
'user-menu': `${dirCss}/user-menu.css`,
'sw': `${dir}/sw/sw.js`,
'cloudcmd': `${dir}/cloudcmd.js`,
'cloudcmd': `${dir}/cloudcmd.mjs`,
[`${modules}/edit`]: `${dirModules}/edit.js`,
[`${modules}/edit-file`]: `${dirModules}/edit-file.js`,
[`${modules}/edit-file-vim`]: `${dirModules}/edit-file-vim.js`,
@ -127,7 +127,7 @@ export default {
[`${modules}/config`]: `${dirModules}/config/index.js`,
[`${modules}/contact`]: `${dirModules}/contact.js`,
[`${modules}/upload`]: `${dirModules}/upload.js`,
[`${modules}/operation`]: `${dirModules}/operation/index.js`,
[`${modules}/operation`]: `${dirModules}/operation/index.mjs`,
[`${modules}/konsole`]: `${dirModules}/konsole.js`,
[`${modules}/terminal`]: `${dirModules}/terminal.js`,
[`${modules}/terminal-run`]: `${dirModules}/terminal-run.js`,

View file

@ -1,3 +1,30 @@
2026.01.21, v19.1.9
feature:
- 75ad4415 cloudcmd: @putout/eslint-flat v4.0.0
- c5d9bd7c client: key: vim: get rid of mock-require
- f437a52f client: images: migrate to EMS
- 7192a56e client: dom: current-file: migrate to ESM
2026.01.20, v19.1.8
fix:
- 8a769fd5 client: modules: operation: no update after copy
feature:
- d574a93d client: key: migrate to ESM
- 3b409074 client: modules: operation: migrate to ESM
- 3b6b0b5a client: buffer: migrate to ESM
- 8876f050 cloudcmd: eslint-plugin-putout v30.0.0
2026.01.17, v19.1.7
feature:
- 23a6a698 client: dom/events -> #dom/events
- 9cebb241 client: dom: events: migrate to ESM
- a94fa0d4 client: cloudcmd: migrate to ESM
- 3bdf47a5 client: migrate to ESM
2026.01.16, v19.1.6
fix:

View file

@ -1,4 +1,4 @@
# Cloud Commander v19.1.6
# Cloud Commander v19.1.9
### [Main][MainURL] [Blog][BlogURL] [Support][SupportURL] [Demo][DemoURL]
@ -1111,6 +1111,9 @@ There are a lot of ways to be involved in `Cloud Commander` development:
## Version history
- *2026.01.21*, **[v19.1.9](//github.com/coderaiser/cloudcmd/releases/tag/v19.1.9)**
- *2026.01.20*, **[v19.1.8](//github.com/coderaiser/cloudcmd/releases/tag/v19.1.8)**
- *2026.01.17*, **[v19.1.7](//github.com/coderaiser/cloudcmd/releases/tag/v19.1.7)**
- *2026.01.16*, **[v19.1.6](//github.com/coderaiser/cloudcmd/releases/tag/v19.1.6)**
- *2026.01.16*, **[v19.1.5](//github.com/coderaiser/cloudcmd/releases/tag/v19.1.5)**
- *2026.01.15*, **[v19.1.4](//github.com/coderaiser/cloudcmd/releases/tag/v19.1.4)**

View file

@ -1,4 +1,4 @@
# Cloud Commander v19.1.6 [![Build Status][BuildStatusIMGURL]][BuildStatusURL] [![Codacy][CodacyIMG]][CodacyURL] [![Gitter][GitterIMGURL]][GitterURL]
# Cloud Commander v19.1.9 [![Build Status][BuildStatusIMGURL]][BuildStatusURL] [![Codacy][CodacyIMG]][CodacyURL] [![Gitter][GitterIMGURL]][GitterURL]
### [Main][MainURL] [Blog][BlogURL] [Support][SupportURL] [Demo][DemoURL]

View file

@ -1,30 +1,24 @@
'use strict';
const process = require('node:process');
import process from 'node:process';
/* global DOM */
const Emitify = require('emitify');
const inherits = require('inherits');
const rendy = require('rendy');
const load = require('load.js');
const {tryToCatch} = require('try-to-catch');
const {addSlashToEnd} = require('format-io');
const pascalCase = require('just-pascal-case');
const currify = require('currify');
const Images = require('./dom/images');
const {unregisterSW} = require('./sw/register');
const {getJsonFromFileTable} = require('./get-json-from-file-table.mjs');
const Key = require('./key');
const {
import Emitify from 'emitify';
import inherits from 'inherits';
import rendy from 'rendy';
import load from 'load.js';
import {tryToCatch} from 'try-to-catch';
import {addSlashToEnd} from 'format-io';
import pascalCase from 'just-pascal-case';
import currify from 'currify';
import * as Images from './dom/images.mjs';
import {unregisterSW} from './sw/register.js';
import {getJsonFromFileTable} from './get-json-from-file-table.mjs';
import {Key} from './key/index.mjs';
import {
apiURL,
formatMsg,
buildFromJSON,
} = require('../common/cloudfunc.mjs');
const {loadModule} = require('./load-module.mjs');
} from '../common/cloudfunc.mjs';
import {loadModule} from './load-module.mjs';
const noJS = (a) => a.replace(/.js$/, '');
@ -32,16 +26,19 @@ const isDev = process.env.NODE_ENV === 'development';
inherits(CloudCmdProto, Emitify);
module.exports = new CloudCmdProto(DOM);
export const createCloudCmd = ({DOM, Listeners}) => {
return new CloudCmdProto({
DOM,
Listeners,
});
};
load.addErrorListener((e, src) => {
const msg = `file ${src} could not be loaded`;
Images.show.error(msg);
});
function CloudCmdProto(DOM) {
let Listeners;
function CloudCmdProto({DOM, Listeners}) {
Emitify.call(this);
const CloudCmd = this;
@ -49,11 +46,9 @@ function CloudCmdProto(DOM) {
const {Storage, Files} = DOM;
this.log = (...a) => {
this.log = () => {
if (!isDev)
return;
console.log(...a);
};
this.prefix = '';
this.prefixSocket = '';
@ -230,7 +225,6 @@ function CloudCmdProto(DOM) {
const dirPath = DOM.getCurrentDirPath();
({Listeners} = CloudCmd);
Listeners.init();
const panels = getPanels();

View file

@ -1,28 +1,32 @@
'use strict';
const process = require('node:process');
require('../css/main.css');
const wraptile = require('wraptile');
const load = require('load.js');
const {registerSW, listenSW} = require('./sw/register');
const {initSortPanel, sortPanel} = require('./sort.mjs');
import process from 'node:process';
import wraptile from 'wraptile';
import load from 'load.js';
import '../css/main.css';
import {registerSW, listenSW} from './sw/register.js';
import {initSortPanel, sortPanel} from './sort.mjs';
import Util from '../common/util.js';
import * as CloudFunc from '../common/cloudfunc.mjs';
import DOM from './dom/index.js';
import {createCloudCmd} from './client.mjs';
import * as Listeners from './listeners/index.js';
const isDev = process.env.NODE_ENV === 'development';
module.exports = async (config) => {
globalThis.Util = require('../common/util');
globalThis.CloudFunc = require('../common/cloudfunc.mjs');
export default init;
globalThis.DOM = require('./dom');
globalThis.CloudCmd = require('./client');
globalThis.CloudCmd = init;
async function init(config) {
globalThis.CloudCmd = createCloudCmd({
DOM,
Listeners,
});
globalThis.DOM = DOM;
globalThis.Util = Util;
globalThis.CloudFunc = CloudFunc;
await register(config);
require('./listeners');
require('./key');
initSortPanel();
globalThis.CloudCmd.sortPanel = sortPanel;
const prefix = getPrefix(config.prefix);
@ -34,8 +38,7 @@ module.exports = async (config) => {
import('https://esm.sh/@putout/processor-html');
import('https://esm.sh/@putout/bundle');
}, 100);
};
globalThis.CloudCmd = module.exports;
}
function getPrefix(prefix) {
if (!prefix)

View file

@ -1,135 +0,0 @@
'use strict';
/* global CloudCmd */
const tryToPromiseAll = require('../../common/try-to-promise-all');
const Storage = require('./storage');
const DOM = require('./');
module.exports = new BufferProto();
function BufferProto() {
const Info = DOM.CurrentInfo;
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),
};
function showMessage(msg) {
DOM.Dialog.alert(msg);
}
function getNames() {
const files = DOM.getActiveFiles();
return DOM.getFilenames(files);
}
function addCutClass() {
const files = DOM.getActiveFiles();
for (const element of files) {
element.classList.add(CLASS);
}
}
function rmCutClass() {
const files = DOM.getByClassAll(CLASS);
for (const element of files) {
element.classList.remove(CLASS);
}
}
function callIfEnabled(callback) {
const is = CloudCmd.config('buffer');
if (is)
return callback();
showMessage('Buffer disabled in config!');
}
async function readBuffer() {
const [e, cp, ct] = await tryToPromiseAll([
Storage.getJson(COPY),
Storage.getJson(CUT),
]);
return [
e,
cp,
ct,
];
}
async function copy() {
const names = getNames();
const from = Info.dirPath;
await clear();
if (!names.length)
return;
await Storage.remove(CUT);
await Storage.setJson(COPY, {
from,
names,
});
}
async function cut() {
const names = getNames();
const from = Info.dirPath;
await clear();
if (!names.length)
return;
addCutClass();
await Storage.setJson(CUT, {
from,
names,
});
}
async function clear() {
await Storage.remove(COPY);
await Storage.remove(CUT);
rmCutClass();
}
async function paste() {
const [error, cp, ct] = await readBuffer();
if (error || !cp && !ct)
return showMessage(error || 'Buffer is empty!');
const opStr = cp ? 'copy' : 'move';
const data = cp || ct;
const {Operation} = CloudCmd;
const msg = 'Path is same!';
const to = Info.dirPath;
if (data.from === to)
return showMessage(msg);
Operation.show(opStr, {
...data,
to,
});
await clear();
}
return Buffer;
}

124
client/dom/buffer.mjs Normal file
View file

@ -0,0 +1,124 @@
/* global CloudCmd*/
import tryToPromiseAll from '../../common/try-to-promise-all.js';
import Storage from './storage.js';
const CLASS = 'cut-file';
const COPY = 'copy';
const CUT = 'cut';
function showMessage(msg) {
globalThis.DOM.Dialog.alert(msg);
}
function getNames() {
const {DOM} = globalThis;
const files = DOM.getActiveFiles();
return DOM.getFilenames(files);
}
function addCutClass() {
const {DOM} = globalThis;
const files = DOM.getActiveFiles();
for (const element of files) {
element.classList.add(CLASS);
}
}
function rmCutClass() {
const {DOM} = globalThis;
const files = DOM.getByClassAll(CLASS);
for (const element of files) {
element.classList.remove(CLASS);
}
}
const checkEnabled = (fn) => () => {
const is = CloudCmd.config('buffer');
if (is)
return fn();
showMessage('Buffer disabled in config!');
};
async function readBuffer() {
const [e, cp, ct] = await tryToPromiseAll([
Storage.getJson(COPY),
Storage.getJson(CUT),
]);
return [
e,
cp,
ct,
];
}
export const copy = checkEnabled(async () => {
const Info = globalThis.DOM.CurrentInfo;
const names = getNames();
const from = Info.dirPath;
await clear();
if (!names.length)
return;
await Storage.remove(CUT);
await Storage.setJson(COPY, {
from,
names,
});
});
export const cut = checkEnabled(async () => {
const Info = globalThis.DOM.CurrentInfo;
const names = getNames();
const from = Info.dirPath;
await clear();
if (!names.length)
return;
addCutClass();
await Storage.setJson(CUT, {
from,
names,
});
});
export const clear = checkEnabled(async () => {
await Storage.remove(COPY);
await Storage.remove(CUT);
rmCutClass();
});
export const paste = checkEnabled(async () => {
const Info = globalThis.DOM.CurrentInfo;
const [error, cp, ct] = await readBuffer();
if (error || !cp && !ct)
return showMessage(error || 'Buffer is empty!');
const opStr = cp ? 'copy' : 'move';
const data = cp || ct;
const {Operation} = CloudCmd;
const msg = 'Path is same!';
const to = Info.dirPath;
if (data.from === to)
return showMessage(msg);
Operation.show(opStr, {
...data,
to,
});
await clear();
});

View file

@ -1,10 +1,8 @@
'use strict';
/* global DOM */
/* global CloudCmd */
const createElement = require('@cloudcmd/create-element');
const {encode, decode} = require('../../common/entity');
const {getTitle, FS} = require('../../common/cloudfunc.mjs');
import createElement from '@cloudcmd/create-element';
import {encode, decode} from '../../common/entity.js';
import {getTitle, FS} from '../../common/cloudfunc.mjs';
let Title;
@ -12,14 +10,15 @@ const CURRENT_FILE = 'current-file';
const encodeNBSP = (a) => a?.replace('\xa0', ' ');
const decodeNBSP = (a) => a?.replace(' ', '\xa0');
module.exports._CURRENT_FILE = CURRENT_FILE;
export const _CURRENT_FILE = CURRENT_FILE;
/**
* set name from current (or param) file
*
* @param name
* @param current
*/
module.exports.setCurrentName = (name, current) => {
export const setCurrentName = (name, current) => {
const Info = DOM.CurrentInfo;
const {link} = Info;
const {prefix} = CloudCmd;
@ -41,7 +40,7 @@ module.exports.setCurrentName = (name, current) => {
*
* @param currentFile
*/
module.exports.getCurrentName = (currentFile) => {
export const getCurrentName = (currentFile) => {
const current = currentFile || DOM.getCurrentFile();
if (!current)
@ -68,18 +67,19 @@ const parseNameAttribute = (attribute) => {
return decodeNBSP(decodeURI(atob(attribute)));
};
module.exports._parseNameAttribute = parseNameAttribute;
export const _parseNameAttribute = parseNameAttribute;
const parseHrefAttribute = (prefix, attribute) => {
attribute = attribute.replace(RegExp('^' + prefix + FS), '');
return decode(decodeNBSP(attribute));
};
module.exports._parseHrefAttribute = parseHrefAttribute;
export const _parseHrefAttribute = parseHrefAttribute;
/**
* get current direcotory path
*/
module.exports.getCurrentDirPath = (panel = DOM.getPanel()) => {
export const getCurrentDirPath = (panel = DOM.getPanel()) => {
const path = DOM.getByDataName('js-path', panel);
return path.textContent;
};
@ -89,7 +89,7 @@ module.exports.getCurrentDirPath = (panel = DOM.getPanel()) => {
*
* @param currentFile - current file by default
*/
module.exports.getCurrentPath = (currentFile) => {
export const getCurrentPath = (currentFile) => {
const current = currentFile || DOM.getCurrentFile();
const [element] = DOM.getByTag('a', current);
const {prefix} = CloudCmd;
@ -100,7 +100,7 @@ module.exports.getCurrentPath = (currentFile) => {
/**
* get current direcotory name
*/
module.exports.getCurrentDirName = () => {
export const getCurrentDirName = () => {
const href = DOM
.getCurrentDirPath()
.replace(/\/$/, '');
@ -113,7 +113,7 @@ module.exports.getCurrentDirName = () => {
/**
* get current direcotory path
*/
module.exports.getParentDirPath = (panel) => {
export const getParentDirPath = (panel) => {
const path = DOM.getCurrentDirPath(panel);
const dirName = DOM.getCurrentDirName() + '/';
const index = path.lastIndexOf(dirName);
@ -127,7 +127,7 @@ module.exports.getParentDirPath = (panel) => {
/**
* get not current direcotory path
*/
module.exports.getNotCurrentDirPath = () => {
export const getNotCurrentDirPath = () => {
const panel = DOM.getPanel({
active: false,
});
@ -140,14 +140,14 @@ module.exports.getNotCurrentDirPath = () => {
*
* @currentFile
*/
module.exports.getCurrentFile = () => {
export const getCurrentFile = () => {
return DOM.getByClass(CURRENT_FILE);
};
/**
* get current file by name
*/
module.exports.getCurrentByName = (name, panel = DOM.CurrentInfo.panel) => {
export const getCurrentByName = (name, panel = DOM.CurrentInfo.panel) => {
const dataName = 'js-file-' + btoa(encodeURI(encodeNBSP(name)));
return DOM.getByDataName(dataName, panel);
};
@ -169,7 +169,7 @@ function unsetCurrentFile(currentFile) {
/**
* unified way to set current file
*/
module.exports.setCurrentFile = (currentFile, options) => {
export const setCurrentFile = (currentFile, options) => {
const o = options;
const currentFileWas = DOM.getCurrentFile();
@ -216,7 +216,7 @@ module.exports.setCurrentFile = (currentFile, options) => {
return DOM;
};
this.setCurrentByName = (name) => {
export const setCurrentByName = (name) => {
const current = DOM.getCurrentByName(name);
return DOM.setCurrentFile(current);
};
@ -227,7 +227,7 @@ this.setCurrentByName = (name) => {
* @param layer - element
* @param - position {x, y}
*/
module.exports.getCurrentByPosition = ({x, y}) => {
export const getCurrentByPosition = ({x, y}) => {
const element = document.elementFromPoint(x, y);
const getEl = (el) => {
@ -259,7 +259,7 @@ module.exports.getCurrentByPosition = ({x, y}) => {
*
* @param currentFile
*/
module.exports.isCurrentFile = (currentFile) => {
export const isCurrentFile = (currentFile) => {
if (!currentFile)
return false;
@ -271,7 +271,7 @@ module.exports.isCurrentFile = (currentFile) => {
*
* @param name
*/
module.exports.setTitle = (name) => {
export const setTitle = (name) => {
if (!Title)
Title = DOM.getByTag('title')[0] || createElement('title', {
innerHTML: name,
@ -288,7 +288,7 @@ module.exports.setTitle = (name) => {
*
* @param currentFile
*/
module.exports.isCurrentIsDir = (currentFile) => {
export const isCurrentIsDir = (currentFile) => {
const current = currentFile || DOM.getCurrentFile();
const path = DOM.getCurrentPath(current);
const fileType = DOM.getCurrentType(current);
@ -299,7 +299,7 @@ module.exports.isCurrentIsDir = (currentFile) => {
return isDir || isZip;
};
module.exports.getCurrentType = (currentFile) => {
export const getCurrentType = (currentFile) => {
const current = currentFile || DOM.getCurrentFile();
const el = DOM.getByDataName('js-type', current);
const type = el.className

View file

@ -1,10 +1,8 @@
'use strict';
import {test, stub} from 'supertape';
import {create} from 'auto-globals';
import wraptile from 'wraptile';
import * as currentFile from './current-file.mjs';
const {test, stub} = require('supertape');
const {create} = require('auto-globals');
const wraptile = require('wraptile');
const currentFile = require('./current-file');
const id = (a) => a;
const returns = wraptile(id);

View file

@ -3,7 +3,7 @@
/* global CloudCmd */
const philip = require('philip');
const Images = require('./images');
const Images = require('./images.mjs');
const {FS} = require('../../common/cloudfunc.mjs');
const DOM = require('.');
const Dialog = require('./dialog');

View file

@ -1,198 +0,0 @@
'use strict';
const itype = require('itype');
const EventStore = require('./event-store');
module.exports = new EventsProto();
function EventsProto() {
const Events = this;
const getEventOptions = (eventName) => {
if (eventName !== 'touchstart')
return false;
return {
passive: true,
};
};
function parseArgs(eventName, element, listener, callback) {
let isFunc;
const args = [
eventName,
element,
listener,
callback,
];
const EVENT_NAME = 1;
const ELEMENT = 0;
const type = itype(eventName);
switch(type) {
default:
if (!type.endsWith('element'))
throw Error(`unknown eventName: ${type}`);
parseArgs(args[EVENT_NAME], args[ELEMENT], listener, callback);
break;
case 'string':
isFunc = itype.function(element);
if (isFunc) {
listener = element;
element = null;
}
if (!element)
element = window;
callback(element, [
eventName,
listener,
getEventOptions(eventName),
]);
break;
case 'array':
for (const name of eventName) {
parseArgs(name, element, listener, callback);
}
break;
case 'object':
for (const name of Object.keys(eventName)) {
const eventListener = eventName[name];
parseArgs(name, element, eventListener, callback);
}
break;
}
}
/**
* safe add event listener
*
* @param type
* @param element - document by default
* @param listener
*/
this.add = (type, element, listener) => {
checkType(type);
parseArgs(type, element, listener, (element, args) => {
const [name, fn, options] = args;
element.addEventListener(name, fn, options);
EventStore.add(element, name, fn);
});
return Events;
};
/**
* safe add event listener
*
* @param type
* @param listener
* @param element - document by default
*/
this.addOnce = (type, element, listener) => {
const once = (event) => {
Events.remove(type, element, once);
listener(event);
};
if (!listener) {
listener = element;
element = null;
}
this.add(type, element, once);
return Events;
};
/**
* safe remove event listener
*
* @param type
* @param listener
* @param element - document by default
*/
this.remove = (type, element, listener) => {
checkType(type);
parseArgs(type, element, listener, (element, args) => {
element.removeEventListener(...args);
});
return Events;
};
/**
* remove all added event listeners
*/
this.removeAll = () => {
const events = EventStore.get();
for (const [el, name, fn] of events)
el.removeEventListener(name, fn);
EventStore.clear();
};
/**
* safe add event keydown listener
*
* @param args
*/
this.addKey = function(...args) {
return Events.add('keydown', ...args);
};
/**
* safe remove event click listener
*
* @param args
*/
this.rmKey = function(...args) {
return Events.remove('keydown', ...args);
};
/**
* safe add event click listener
*/
this.addClick = function(...args) {
return Events.add('click', ...args);
};
/**
* safe remove event click listener
*/
this.rmClick = function(...args) {
return Events.remove('click', ...args);
};
this.addContextMenu = function(...args) {
return Events.add('contextmenu', ...args);
};
/**
* safe add load listener
*/
this.addLoad = function(...args) {
return Events.add('load', ...args);
};
function checkType(type) {
if (!type)
throw Error('type could not be empty!');
}
}

203
client/dom/events/index.mjs Normal file
View file

@ -0,0 +1,203 @@
import itype from 'itype';
import EventStore from './event-store.js';
/**
* safe add event listener
*
* @param type
* @param element - document by default
* @param listener
*/
export const add = (type, element, listener) => {
checkType(type);
parseArgs(type, element, listener, (element, args) => {
const [name, fn, options] = args;
element.addEventListener(name, fn, options);
EventStore.add(element, name, fn);
});
return Events;
};
/**
* safe add event listener
*
* @param type
* @param listener
* @param element - document by default
*/
export const addOnce = (type, element, listener) => {
const once = (event) => {
Events.remove(type, element, once);
listener(event);
};
if (!listener) {
listener = element;
element = null;
}
add(type, element, once);
return Events;
};
/**
* safe remove event listener
*
* @param type
* @param listener
* @param element - document by default
*/
export const remove = (type, element, listener) => {
checkType(type);
parseArgs(type, element, listener, (element, args) => {
element.removeEventListener(...args);
});
return Events;
};
/**
* remove all added event listeners
*/
export const removeAll = () => {
const events = EventStore.get();
for (const [el, name, fn] of events)
el.removeEventListener(name, fn);
EventStore.clear();
};
/**
* safe add event keydown listener
*
* @param args
*/
export const addKey = function(...args) {
return add('keydown', ...args);
};
/**
* safe remove event click listener
*
* @param args
*/
export const rmKey = function(...args) {
return Events.remove('keydown', ...args);
};
/**
* safe add event click listener
*/
export const addClick = function(...args) {
return Events.add('click', ...args);
};
/**
* safe remove event click listener
*/
export const rmClick = function(...args) {
return remove('click', ...args);
};
export const addContextMenu = function(...args) {
return add('contextmenu', ...args);
};
/**
* safe add load listener
*/
export const addLoad = function(...args) {
return add('load', ...args);
};
function checkType(type) {
if (!type)
throw Error('type could not be empty!');
}
const getEventOptions = (eventName) => {
if (eventName !== 'touchstart')
return false;
return {
passive: true,
};
};
function parseArgs(eventName, element, listener, callback) {
let isFunc;
const args = [
eventName,
element,
listener,
callback,
];
const EVENT_NAME = 1;
const ELEMENT = 0;
const type = itype(eventName);
switch(type) {
default:
if (!type.endsWith('element'))
throw Error(`unknown eventName: ${type}`);
parseArgs(args[EVENT_NAME], args[ELEMENT], listener, callback);
break;
case 'string':
isFunc = itype.function(element);
if (isFunc) {
listener = element;
element = null;
}
if (!element)
element = window;
callback(element, [
eventName,
listener,
getEventOptions(eventName),
]);
break;
case 'array':
for (const name of eventName) {
parseArgs(name, element, listener, callback);
}
break;
case 'object':
for (const name of Object.keys(eventName)) {
const eventListener = eventName[name];
parseArgs(name, element, eventListener, callback);
}
break;
}
}
const Events = {
add,
addClick,
addContextMenu,
addKey,
addLoad,
addOnce,
remove,
removeAll,
rmClick,
rmKey,
};

View file

@ -1,10 +1,5 @@
/* global DOM */
'use strict';
const createElement = require('@cloudcmd/create-element');
const Images = module.exports;
import createElement from '@cloudcmd/create-element';
const LOADING = 'loading';
const HIDDEN = 'hidden';
@ -12,7 +7,8 @@ const ERROR = 'error';
const getLoadingType = () => isSVG() ? '-svg' : '-gif';
module.exports.get = getElement;
export const get = getElement;
/**
* check SVG SMIL animation support
*/
@ -40,7 +36,7 @@ function getElement() {
}
/* Функция создаёт картинку загрузки */
module.exports.loading = () => {
export const loading = () => {
const element = getElement();
const {classList} = element;
const loadingImage = LOADING + getLoadingType();
@ -52,7 +48,7 @@ module.exports.loading = () => {
};
/* Функция создаёт картинку ошибки загрузки */
module.exports.error = () => {
export const error = () => {
const element = getElement();
const {classList} = element;
const loadingImage = LOADING + getLoadingType();
@ -63,14 +59,21 @@ module.exports.error = () => {
return element;
};
module.exports.show = show;
module.exports.show.load = show;
module.exports.show.error = error;
show.load = show;
show.error = (text) => {
const image = Images.error();
DOM.show(image);
image.title = text;
return image;
};
/**
* Function shows loading spinner
* position = {top: true};
*/
function show(position, panel) {
export function show(position, panel) {
const image = Images.loading();
const parent = image.parentElement;
const refreshButton = DOM.getRefreshButton(panel);
@ -96,19 +99,10 @@ function show(position, panel) {
return image;
}
function error(text) {
const image = Images.error();
DOM.show(image);
image.title = text;
return image;
}
/**
* hide load image
*/
module.exports.hide = () => {
export const hide = () => {
const element = Images.get();
DOM.hide(element);
@ -116,7 +110,7 @@ module.exports.hide = () => {
return Images;
};
module.exports.setProgress = (value, title) => {
export const setProgress = (value, title) => {
const DATA = 'data-progress';
const element = Images.get();
@ -131,7 +125,7 @@ module.exports.setProgress = (value, title) => {
return Images;
};
module.exports.clearProgress = () => {
export const clearProgress = () => {
const DATA = 'data-progress';
const element = Images.get();
@ -143,3 +137,13 @@ module.exports.clearProgress = () => {
return Images;
};
const Images = {
clearProgress,
setProgress,
show,
hide,
get,
error,
loading,
};

View file

@ -3,12 +3,12 @@
/* global CloudCmd */
const Util = require('../../common/util');
const Images = require('./images');
const Images = require('./images.mjs');
const RESTful = require('./rest');
const Storage = require('./storage');
const renameCurrent = require('./operations/rename-current');
const CurrentFile = require('./current-file');
const CurrentFile = require('./current-file.mjs');
const DOMTree = require('./dom-tree');
const Cmd = module.exports;
@ -32,8 +32,8 @@ DOM.CurrentInfo = CurrentInfo;
module.exports = DOM;
DOM.uploadDirectory = require('./directory');
DOM.Buffer = require('./buffer');
DOM.Events = require('./events');
DOM.Buffer = require('./buffer.mjs');
DOM.Events = require('#dom/events');
const loadRemote = require('./load-remote');
const selectByPattern = require('./select-by-pattern');

View file

@ -3,7 +3,7 @@
/* global CloudCmd */
const {promisify} = require('es6-promisify');
const Images = require('../images');
const Images = require('../images.mjs');
const load = require('../load');
module.exports = promisify((params, callback) => {

View file

@ -4,7 +4,7 @@ const itype = require('itype');
const jonny = require('jonny');
const Emitify = require('emitify');
const exec = require('execon');
const Images = require('./images');
const Images = require('./images.mjs');
module.exports.getIdBySrc = getIdBySrc;
/**

View file

@ -7,7 +7,7 @@ const _Dialog = require('../dialog');
const Storage = require('../storage');
const RESTful = require('../rest');
const _currentFile = require('../current-file');
const _currentFile = require('../current-file.mjs');
module.exports = async (current, overrides = {}) => {
const {

View file

@ -4,7 +4,7 @@ const {tryToCatch} = require('try-to-catch');
const {encode} = require('../../common/entity');
const Images = require('./images');
const Images = require('./images.mjs');
const IO = require('./io');
const Dialog = require('./dialog');

View file

@ -5,7 +5,7 @@ const {eachSeries} = require('execon');
const wraptile = require('wraptile');
const load = require('./load');
const Images = require('./images');
const Images = require('./images.mjs');
const {alert} = require('./dialog');
const {FS} = require('../../common/cloudfunc.mjs');

View file

@ -8,29 +8,6 @@ export const getJsonFromFileTable = () => {
const path = DOM.getCurrentDirPath();
const infoFiles = Info.files || [];
const notParent = (current) => {
const name = DOM.getCurrentName(current);
return name !== '..';
};
const parse = (current) => {
const name = DOM.getCurrentName(current);
const size = DOM.getCurrentSize(current);
const owner = DOM.getCurrentOwner(current);
const mode = DOM.getCurrentMode(current);
const date = DOM.getCurrentDate(current);
const type = DOM.getCurrentType(current);
return {
name,
size,
mode,
owner,
date,
type,
};
};
const files = infoFiles
.filter(notParent)
.map(parse);
@ -42,3 +19,26 @@ export const getJsonFromFileTable = () => {
return fileTable;
};
const notParent = (current) => {
const name = DOM.getCurrentName(current);
return name !== '..';
};
const parse = (current) => {
const name = DOM.getCurrentName(current);
const size = DOM.getCurrentSize(current);
const owner = DOM.getCurrentOwner(current);
const mode = DOM.getCurrentMode(current);
const date = DOM.getCurrentDate(current);
const type = DOM.getCurrentType(current);
return {
name,
size,
mode,
owner,
date,
type,
};
};

View file

@ -1,18 +1,13 @@
'use strict';
/* global CloudCmd, DOM */
const clipboard = require('@cloudcmd/clipboard');
const {fullstore} = require('fullstore');
import clipboard from '@cloudcmd/clipboard';
import {fullstore} from 'fullstore';
import * as Events from '#dom/events';
import * as Buffer from '../dom/buffer.mjs';
import KEY from './key.js';
import _vim from './vim/index.js';
import setCurrentByChar from './set-current-by-char.js';
import {createBinder} from './binder.js';
const Buffer = require('../dom/buffer');
const Events = require('../dom/events');
const KEY = require('./key');
const _vim = require('./vim');
const setCurrentByChar = require('./set-current-by-char');
const {createBinder} = require('./binder');
const Info = DOM.CurrentInfo;
const Chars = fullstore();
const toggleVim = (keyCode, overrides = {}) => {
@ -29,13 +24,16 @@ Chars([]);
const {assign} = Object;
const binder = createBinder();
module.exports = assign(binder, KEY);
module.exports.bind = () => {
const bind = () => {
Events.addKey(listener, true);
binder.setBind();
};
module.exports._listener = listener;
export const Key = assign(binder, KEY, {
bind,
});
export const _listener = listener;
function getChar(event) {
/*
@ -98,7 +96,7 @@ async function listener(event, overrides = {}) {
return;
if (isVim)
await vim(char, event);
vim(char, event);
}
function getSymbol(shift, keyCode) {
@ -124,6 +122,7 @@ function fromCharCode(keyIdentifier) {
}
async function _switchKey(event) {
const Info = DOM.CurrentInfo;
let i;
let isSelected;
let prev;

View file

@ -7,7 +7,8 @@ const supertape = require('supertape');
const {ESC} = require('./key');
const {_listener, setBind} = require('.');
const {Key, _listener} = require('./index.mjs');
const {getDOM, getCloudCmd} = require('./vim/globals.fixture');
const test = autoGlobals(supertape);
const {stub} = supertape;
@ -26,7 +27,7 @@ test('cloudcmd: client: key: enable vim', async (t) => {
altKey: false,
};
setBind();
Key.setBind();
await _listener(event, {
vim,
@ -48,7 +49,7 @@ test('cloudcmd: client: key: disable vim', async (t) => {
altKey: false,
};
setBind();
Key.setBind();
await _listener(event, {
config,
_config,

View file

@ -3,9 +3,9 @@
'use strict';
const {escapeRegExp} = require('../../common/util');
const Info = DOM.CurrentInfo;
module.exports = function setCurrentByChar(char, charStore) {
const Info = DOM.CurrentInfo;
let firstByName;
let skipCount = 0;
let setted = false;

View file

@ -9,37 +9,43 @@ const {
selectFileNotParent,
} = require('./set-current');
const {DOM = {}, CloudCmd = {},
} = globalThis;
module.exports = (key, event, overrides = {}) => {
const defaults = {
...globalThis.DOM,
...globalThis.CloudCmd,
};
const {Dialog = {}} = DOM;
const deps = {
...defaults,
...overrides,
};
const DEPS = {
...DOM,
...CloudCmd,
};
module.exports = async (key, event, deps = DEPS) => {
const operations = getOperations(event, deps);
await vim(key, operations, deps);
vim(key, operations, deps);
};
const getOperations = (event, deps) => {
const {
Info = DOM.CurrentInfo,
Info = globalThis.DOM.CurrentInfo,
CloudCmd = globalThis.CloudCmd,
Operation,
unselectFiles,
setCurrentFile,
setCurrentByName,
getCurrentName,
prompt = Dialog.prompt,
prompt = globalThis.DOM.Dialog.prompt,
preventDefault = event?.preventDefault?.bind(event),
toggleSelectedFile,
Buffer = {},
createFindNext = _createFindNext,
} = deps;
return {
findNext: createFindNext({
setCurrentByName,
}),
escape: unselectFiles,
remove: () => {
@ -117,11 +123,6 @@ const getOperations = (event, deps) => {
setCurrentByName(result);
},
findNext: () => {
const name = finder.findNext();
setCurrentByName(name);
},
findPrevious: () => {
const name = finder.findPrevious();
setCurrentByName(name);
@ -130,3 +131,10 @@ const getOperations = (event, deps) => {
};
module.exports.selectFile = selectFileNotParent;
const _createFindNext = (overrides = {}) => () => {
const {setCurrentByName} = overrides;
const name = finder.findNext();
setCurrentByName(name);
};

View file

@ -570,17 +570,13 @@ test('cloudcmd: client: find', (t) => {
test('cloudcmd: client: key: n', (t) => {
const findNext = stub();
const createFindNext = stub().returns(findNext);
mockRequire(pathFind, {
findNext,
});
const vim = reRequire(pathVim);
const event = {};
vim('n', event);
stopAll();
vim('n', event, {
createFindNext,
});
t.calledWithNoArgs(findNext, 'should call findNext');
t.end();
@ -644,25 +640,27 @@ test('cloudcmd: client: key: make file', (t) => {
t.end();
});
test.skip('cloudcmd: client: vim: terminal', (t) => {
const {CloudCmd} = globalThis;
assign(CloudCmd, {
test('cloudcmd: client: vim: terminal', (t) => {
const CloudCmd = {
Terminal: {
show: stub(),
},
});
};
const event = {};
vim('t', event);
vim('t', event);
vim('t', event, {
CloudCmd,
});
vim('t', event, {
CloudCmd,
});
t.calledWithNoArgs(CloudCmd.Terminal.show);
t.end();
});
test.skip('cloudcmd: client: vim: edit', async (t) => {
test('cloudcmd: client: vim: edit', async (t) => {
globalThis.DOM = getDOM();
globalThis.CloudCmd = getCloudCmd();

View file

@ -11,6 +11,7 @@ const clipboard = require('@cloudcmd/clipboard');
const getRange = require('./get-range');
const uploadFiles = require('../dom/upload-files');
const {FS} = require('../../common/cloudfunc.mjs');
const Events = require('#dom/events');
const getIndex = currify(require('./get-index'));
@ -29,8 +30,6 @@ module.exports.init = async () => {
]);
};
CloudCmd.Listeners = module.exports;
const unselect = (event) => {
const isMac = /Mac/.test(globalThis.navigator.platform);
const {
@ -50,9 +49,6 @@ const execAll = currify((funcs, event) => {
fn(event);
});
const Info = DOM.CurrentInfo;
const {Events} = DOM;
const EventsFiles = {
mousedown: exec.with(execIfNotUL, setCurrentFileByEvent),
click: execAll([onClick, exec.with(execIfNotMobile, unselect)]),
@ -167,6 +163,7 @@ function getPathListener(panel) {
}
function isNoCurrent(panel) {
const Info = DOM.CurrentInfo;
const infoPanel = Info.panel;
if (!infoPanel)
@ -191,6 +188,7 @@ function decodePath(path) {
}
async function onPathElementClick(panel, event) {
const Info = DOM.CurrentInfo;
event.preventDefault();
const element = event.target;
@ -261,6 +259,7 @@ function toggleSelect(key, files) {
}
function changePanel(element) {
const Info = DOM.CurrentInfo;
const {panel} = Info;
const files = DOM.getByDataName('js-files', panel);
const ul = getULElement(element);
@ -302,6 +301,7 @@ async function onTouch(event) {
* in Chrome (HTML5)
*/
function onDragStart(event) {
const Info = DOM.CurrentInfo;
const {prefixURL} = CloudCmd;
const element = getLIElement(event.target);
const {isDir} = Info;
@ -338,6 +338,7 @@ function getULElement(element) {
}
function setCurrentFileByEvent(event) {
const Info = DOM.CurrentInfo;
const BUTTON_LEFT = 0;
const key = {
@ -451,7 +452,7 @@ function dragndrop() {
}
function unload() {
DOM.Events.add(['unload', 'beforeunload'], (event) => {
Events.add(['unload', 'beforeunload'], (event) => {
const {Key} = CloudCmd;
const isBind = Key?.isBind();
@ -480,6 +481,7 @@ function pop() {
function resize() {
Events.add('resize', () => {
const Info = DOM.CurrentInfo;
const is = globalThis.innerWidth < CloudCmd.MIN_ONE_PANEL_WIDTH;
if (!is)

View file

@ -9,7 +9,7 @@ const load = require('load.js');
const {ajax} = require('../dom/load');
const Files = require('../dom/files');
const Images = require('../dom/images');
const Images = require('../dom/images.mjs');
const {log} = CloudCmd;
const upload = currify(_upload);

View file

@ -13,8 +13,8 @@ const load = require('load.js');
const createElement = require('@cloudcmd/create-element');
const input = require('./input');
const Images = require('../../dom/images');
const Events = require('../../dom/events');
const Images = require('../../dom/images.mjs');
const Events = require('#dom/events');
const Files = require('../../dom/files');
const {getTitle} = require('../../../common/cloudfunc.mjs');

View file

@ -6,7 +6,7 @@
CloudCmd.Contact = exports;
const olark = require('@cloudcmd/olark');
const Images = require('../dom/images');
const Images = require('../dom/images.mjs');
const {Events} = DOM;
const {Key} = CloudCmd;

View file

@ -3,7 +3,7 @@
/* global CloudCmd */
CloudCmd.EditFileVim = exports;
const Events = require('../dom/events');
const Events = require('#dom/events');
const {Key} = CloudCmd;

View file

@ -3,7 +3,7 @@
/* global CloudCmd */
CloudCmd.EditNamesVim = exports;
const Events = require('../dom/events');
const Events = require('#dom/events');
const {Key} = CloudCmd;
const ConfigView = {

View file

@ -3,7 +3,7 @@
/* global CloudCmd */
CloudCmd.Help = exports;
const Images = require('../dom/images');
const Images = require('../dom/images.mjs');
module.exports.init = () => {
Images.show.load('top');

View file

@ -12,7 +12,7 @@ const {tryToCatch} = require('try-to-catch');
const loadJS = require('load.js').js;
const createElement = require('@cloudcmd/create-element');
const Images = require('../dom/images');
const Images = require('../dom/images.mjs');
const {Dialog, CurrentInfo: Info} = DOM;
const rmLastSlash = (a) => a.replace(/\/$/, '') || '/';

View file

@ -5,7 +5,7 @@ CloudCmd.Markdown = exports;
const createElement = require('@cloudcmd/create-element');
const Images = require('../dom/images');
const Images = require('../dom/images.mjs');
const {Markdown} = require('../dom/rest');
const {alert} = require('../dom/dialog');

View file

@ -1,28 +1,20 @@
/* global CloudCmd */
/* global Util */
/* global DOM */
/* global fileop */
import currify from 'currify';
import wraptile from 'wraptile';
import {promisify} from 'es6-promisify';
import exec from 'execon';
import load from 'load.js';
import {tryToCatch} from 'try-to-catch';
import {encode} from '../../../common/entity.js';
import removeExtension from './remove-extension.js';
import {setListeners} from './set-listeners.mjs';
import getNextCurrentName from './get-next-current-name.js';
'use strict';
const currify = require('currify');
const wraptile = require('wraptile');
const {promisify} = require('es6-promisify');
const exec = require('execon');
const load = require('load.js');
const {tryToCatch} = require('try-to-catch');
const {encode} = require('../../../common/entity');
const removeExtension = require('./remove-extension');
const setListeners = require('./set-listeners');
const getNextCurrentName = require('./get-next-current-name');
const {DOM, CloudCmd} = globalThis;
const removeQuery = (a) => a.replace(/\?.*/, '');
const Name = 'Operation';
CloudCmd[Name] = exports;
const {config} = CloudCmd;
const {Dialog, Images} = DOM;
@ -53,7 +45,7 @@ const noFilesCheck = () => {
return is;
};
module.exports.init = promisify((callback) => {
export const init = promisify((callback) => {
showLoad();
exec.series([
@ -92,7 +84,7 @@ const onConnect = currify((fn, operator) => {
async function initOperations(prefix, socketPrefix, fn) {
socketPrefix = `${socketPrefix}/fileop`;
const operator = await fileop({
const operator = await globalThis.fileop({
prefix,
socketPrefix,
});
@ -198,11 +190,11 @@ function getPacker(type) {
return packTarFn;
}
module.exports.hide = () => {
export const hide = () => {
CloudCmd.View.hide();
};
module.exports.show = (operation, data) => {
export const show = (operation, data) => {
if (!Loaded)
return;
@ -505,8 +497,14 @@ async function prompt(msg, to, names) {
return await Dialog.prompt(msg, to);
}
globalThis.CloudCmd[Name] = {
init,
hide,
show,
};
async function loadAll() {
const {prefix} = CloudCmd;
const {prefix} = globalThis.CloudCmd;
const file = `${prefix}/fileop/fileop.js`;
const [error] = await tryToCatch(load.js, file);

View file

@ -1,14 +1,11 @@
'use strict';
/* global DOM */
const forEachKey = require('for-each-key');
const wraptile = require('wraptile');
const format = require('./format');
import forEachKey from 'for-each-key';
import wraptile from 'wraptile';
import format from './format.js';
const {Dialog, Images} = DOM;
module.exports = (options) => (emitter) => {
export const setListeners = (options) => (emitter) => {
const {
operation,
callback,
@ -43,10 +40,13 @@ module.exports = (options) => (emitter) => {
operation,
}));
let noProgress = true;
const listeners = {
progress: (value) => {
done = value === 100;
progress.setProgress(value);
noProgress = false;
},
end: () => {
@ -54,7 +54,7 @@ module.exports = (options) => (emitter) => {
forEachKey(removeListener, listeners);
progress.remove();
if (lastError || done)
if (lastError || done || noProgress)
callback();
},

View file

@ -10,7 +10,7 @@ require('../../css/terminal.css');
const exec = require('execon');
const load = require('load.js');
const DOM = require('../dom');
const Images = require('../dom/images');
const Images = require('../dom/images.mjs');
const {Dialog} = DOM;
const {Key, config} = CloudCmd;

View file

@ -9,7 +9,7 @@ require('../../css/terminal.css');
const exec = require('execon');
const load = require('load.js');
const DOM = require('../dom');
const Images = require('../dom/images');
const Images = require('../dom/images.mjs');
const loadParallel = load.parallel;

View file

@ -6,7 +6,7 @@ CloudCmd.Upload = exports;
const createElement = require('@cloudcmd/create-element');
const Files = require('../dom/files');
const Images = require('../dom/images');
const Images = require('../dom/images.mjs');
const uploadFiles = require('../dom/upload-files');
module.exports.init = async () => {

View file

@ -12,7 +12,7 @@ const {tryCatch} = require('try-catch');
const {tryToCatch} = require('try-to-catch');
const {codeFrameColumns} = require('@babel/code-frame');
const Images = require('../../dom/images');
const Images = require('../../dom/images.mjs');
const Dialog = require('../../dom/dialog');
const getUserMenu = require('./get-user-menu');
const navigate = require('./navigate');

View file

@ -26,8 +26,8 @@ const {
} = require('./types');
const Files = require('../../dom/files');
const Events = require('../../dom/events');
const Images = require('../../dom/images');
const Events = require('#dom/events');
const Images = require('../../dom/images.mjs');
const {encode} = require('../../../common/entity');
const isString = (a) => typeof a === 'string';

View file

@ -33,9 +33,7 @@ export default defineConfig([
}, {
files: ['{client,common,static}/**/*.js'],
languageOptions: {
globals: {
...globals.browser,
},
globals: globals.browser,
},
},
...matchToFlat(match),

View file

@ -1,6 +1,7 @@
{
"name": "cloudcmd",
"version": "19.1.6",
"version": "19.1.9",
"type": "commonjs",
"author": "coderaiser <mnemonic.enemy@gmail.com> (https://github.com/coderaiser)",
"description": "File manager for the web with console and editor",
"homepage": "http://cloudcmd.io",
@ -157,7 +158,7 @@
"@cloudcmd/olark": "^3.0.2",
"@cloudcmd/stub": "^5.0.0",
"@iocmd/wait": "^2.1.0",
"@putout/eslint-flat": "^3.0.1",
"@putout/eslint-flat": "^4.0.0",
"@putout/plugin-cloudcmd": "^4.0.0",
"@types/node-fetch": "^2.6.11",
"auto-globals": "^4.0.0",
@ -174,12 +175,13 @@
"emitify": "^4.0.1",
"eslint": "^9.23.0",
"eslint-plugin-n": "^17.0.0-4",
"eslint-plugin-putout": "^29.0.2",
"eslint-plugin-putout": "^30.0.0",
"globals": "^17.0.0",
"gritty": "^9.0.0",
"gunzip-maybe": "^1.3.1",
"html-webpack-plugin": "^5.6.3",
"inherits": "^2.0.3",
"itype": "^3.0.1",
"just-capitalize": "^3.2.0",
"just-pascal-case": "^3.2.0",
"limier": "^3.0.0",
@ -216,6 +218,9 @@
"webpack-merge": "^6.0.1",
"webpackbar": "^7.0.0"
},
"imports": {
"#dom/events": "./client/dom/events/index.mjs"
},
"engines": {
"node": ">=22"
},