diff --git a/.putout.json b/.putout.json index b868f59d..bc60b230 100644 --- a/.putout.json +++ b/.putout.json @@ -8,6 +8,7 @@ "*.md" ], "rules": { + "tape/remove-skip": "off", "package-json/add-type": "off" }, "match": { @@ -29,7 +30,7 @@ "server/{server,exit,terminal,distribute/log}.{js,mjs}": { "remove-console": "off" }, - "client/{client,cloudcmd,load-module}.{js,mjs}": { + "client/{client,cloudcmd,load-module}.js": { "remove-console": "off" }, "client": { diff --git a/.webpack/js.mjs b/.webpack/js.mjs index d52e0388..5788300b 100644 --- a/.webpack/js.mjs +++ b/.webpack/js.mjs @@ -114,7 +114,7 @@ export default { 'terminal': `${dirCss}/terminal.css`, 'user-menu': `${dirCss}/user-menu.css`, 'sw': `${dir}/sw/sw.js`, - 'cloudcmd': `${dir}/cloudcmd.mjs`, + 'cloudcmd': `${dir}/cloudcmd.js`, [`${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.mjs`, + [`${modules}/operation`]: `${dirModules}/operation/index.js`, [`${modules}/konsole`]: `${dirModules}/konsole.js`, [`${modules}/terminal`]: `${dirModules}/terminal.js`, [`${modules}/terminal-run`]: `${dirModules}/terminal-run.js`, diff --git a/ChangeLog b/ChangeLog index edf5330e..040474d5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,30 +1,3 @@ -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: diff --git a/HELP.md b/HELP.md index 68087875..b62cc360 100644 --- a/HELP.md +++ b/HELP.md @@ -1,4 +1,4 @@ -# Cloud Commander v19.1.9 +# Cloud Commander v19.1.6 ### [Main][MainURL] [Blog][BlogURL] [Support][SupportURL] [Demo][DemoURL] @@ -1111,9 +1111,6 @@ 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)** diff --git a/README.md b/README.md index 8e510161..ea3baa8b 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Cloud Commander v19.1.9 [![Build Status][BuildStatusIMGURL]][BuildStatusURL] [![Codacy][CodacyIMG]][CodacyURL] [![Gitter][GitterIMGURL]][GitterURL] +# Cloud Commander v19.1.6 [![Build Status][BuildStatusIMGURL]][BuildStatusURL] [![Codacy][CodacyIMG]][CodacyURL] [![Gitter][GitterIMGURL]][GitterURL] ### [Main][MainURL] [Blog][BlogURL] [Support][SupportURL] [Demo][DemoURL] diff --git a/client/client.mjs b/client/client.js similarity index 92% rename from client/client.mjs rename to client/client.js index b6c3a436..529b904b 100644 --- a/client/client.mjs +++ b/client/client.js @@ -1,24 +1,30 @@ -import process from 'node:process'; +'use strict'; + +const process = require('node:process'); /* global DOM */ -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 { +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 { apiURL, formatMsg, buildFromJSON, -} from '../common/cloudfunc.mjs'; -import {loadModule} from './load-module.mjs'; +} = require('../common/cloudfunc.mjs'); + +const {loadModule} = require('./load-module.mjs'); const noJS = (a) => a.replace(/.js$/, ''); @@ -26,19 +32,16 @@ const isDev = process.env.NODE_ENV === 'development'; inherits(CloudCmdProto, Emitify); -export const createCloudCmd = ({DOM, Listeners}) => { - return new CloudCmdProto({ - DOM, - Listeners, - }); -}; +module.exports = new CloudCmdProto(DOM); load.addErrorListener((e, src) => { const msg = `file ${src} could not be loaded`; Images.show.error(msg); }); -function CloudCmdProto({DOM, Listeners}) { +function CloudCmdProto(DOM) { + let Listeners; + Emitify.call(this); const CloudCmd = this; @@ -46,9 +49,11 @@ function CloudCmdProto({DOM, Listeners}) { const {Storage, Files} = DOM; - this.log = () => { + this.log = (...a) => { if (!isDev) return; + + console.log(...a); }; this.prefix = ''; this.prefixSocket = ''; @@ -225,6 +230,7 @@ function CloudCmdProto({DOM, Listeners}) { const dirPath = DOM.getCurrentDirPath(); + ({Listeners} = CloudCmd); Listeners.init(); const panels = getPanels(); diff --git a/client/cloudcmd.mjs b/client/cloudcmd.js similarity index 62% rename from client/cloudcmd.mjs rename to client/cloudcmd.js index 0dac1a03..8c3de848 100644 --- a/client/cloudcmd.mjs +++ b/client/cloudcmd.js @@ -1,32 +1,28 @@ -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'; +'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'); const isDev = process.env.NODE_ENV === 'development'; -export default init; - -globalThis.CloudCmd = init; - -async function init(config) { - globalThis.CloudCmd = createCloudCmd({ - DOM, - Listeners, - }); - globalThis.DOM = DOM; - globalThis.Util = Util; - globalThis.CloudFunc = CloudFunc; +module.exports = async (config) => { + globalThis.Util = require('../common/util'); + globalThis.CloudFunc = require('../common/cloudfunc.mjs'); + + globalThis.DOM = require('./dom'); + globalThis.CloudCmd = require('./client'); await register(config); + require('./listeners'); + require('./key'); + initSortPanel(); globalThis.CloudCmd.sortPanel = sortPanel; const prefix = getPrefix(config.prefix); @@ -38,7 +34,8 @@ async function init(config) { import('https://esm.sh/@putout/processor-html'); import('https://esm.sh/@putout/bundle'); }, 100); -} +}; +globalThis.CloudCmd = module.exports; function getPrefix(prefix) { if (!prefix) diff --git a/client/dom/buffer.js b/client/dom/buffer.js new file mode 100644 index 00000000..afa78dd7 --- /dev/null +++ b/client/dom/buffer.js @@ -0,0 +1,135 @@ +'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; +} diff --git a/client/dom/buffer.mjs b/client/dom/buffer.mjs deleted file mode 100644 index 01e8142a..00000000 --- a/client/dom/buffer.mjs +++ /dev/null @@ -1,124 +0,0 @@ -/* 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(); -}); diff --git a/client/dom/current-file.mjs b/client/dom/current-file.js similarity index 84% rename from client/dom/current-file.mjs rename to client/dom/current-file.js index e55acbe9..963b2a29 100644 --- a/client/dom/current-file.mjs +++ b/client/dom/current-file.js @@ -1,8 +1,10 @@ +'use strict'; + /* global DOM */ /* global CloudCmd */ -import createElement from '@cloudcmd/create-element'; -import {encode, decode} from '../../common/entity.js'; -import {getTitle, FS} from '../../common/cloudfunc.mjs'; +const createElement = require('@cloudcmd/create-element'); +const {encode, decode} = require('../../common/entity'); +const {getTitle, FS} = require('../../common/cloudfunc.mjs'); let Title; @@ -10,15 +12,14 @@ const CURRENT_FILE = 'current-file'; const encodeNBSP = (a) => a?.replace('\xa0', ' '); const decodeNBSP = (a) => a?.replace(' ', '\xa0'); -export const _CURRENT_FILE = CURRENT_FILE; - +module.exports._CURRENT_FILE = CURRENT_FILE; /** * set name from current (or param) file * * @param name * @param current */ -export const setCurrentName = (name, current) => { +module.exports.setCurrentName = (name, current) => { const Info = DOM.CurrentInfo; const {link} = Info; const {prefix} = CloudCmd; @@ -40,7 +41,7 @@ export const setCurrentName = (name, current) => { * * @param currentFile */ -export const getCurrentName = (currentFile) => { +module.exports.getCurrentName = (currentFile) => { const current = currentFile || DOM.getCurrentFile(); if (!current) @@ -67,19 +68,18 @@ const parseNameAttribute = (attribute) => { return decodeNBSP(decodeURI(atob(attribute))); }; -export const _parseNameAttribute = parseNameAttribute; +module.exports._parseNameAttribute = parseNameAttribute; const parseHrefAttribute = (prefix, attribute) => { attribute = attribute.replace(RegExp('^' + prefix + FS), ''); return decode(decodeNBSP(attribute)); }; -export const _parseHrefAttribute = parseHrefAttribute; - +module.exports._parseHrefAttribute = parseHrefAttribute; /** * get current direcotory path */ -export const getCurrentDirPath = (panel = DOM.getPanel()) => { +module.exports.getCurrentDirPath = (panel = DOM.getPanel()) => { const path = DOM.getByDataName('js-path', panel); return path.textContent; }; @@ -89,7 +89,7 @@ export const getCurrentDirPath = (panel = DOM.getPanel()) => { * * @param currentFile - current file by default */ -export const getCurrentPath = (currentFile) => { +module.exports.getCurrentPath = (currentFile) => { const current = currentFile || DOM.getCurrentFile(); const [element] = DOM.getByTag('a', current); const {prefix} = CloudCmd; @@ -100,7 +100,7 @@ export const getCurrentPath = (currentFile) => { /** * get current direcotory name */ -export const getCurrentDirName = () => { +module.exports.getCurrentDirName = () => { const href = DOM .getCurrentDirPath() .replace(/\/$/, ''); @@ -113,7 +113,7 @@ export const getCurrentDirName = () => { /** * get current direcotory path */ -export const getParentDirPath = (panel) => { +module.exports.getParentDirPath = (panel) => { const path = DOM.getCurrentDirPath(panel); const dirName = DOM.getCurrentDirName() + '/'; const index = path.lastIndexOf(dirName); @@ -127,7 +127,7 @@ export const getParentDirPath = (panel) => { /** * get not current direcotory path */ -export const getNotCurrentDirPath = () => { +module.exports.getNotCurrentDirPath = () => { const panel = DOM.getPanel({ active: false, }); @@ -140,14 +140,14 @@ export const getNotCurrentDirPath = () => { * * @currentFile */ -export const getCurrentFile = () => { +module.exports.getCurrentFile = () => { return DOM.getByClass(CURRENT_FILE); }; /** * get current file by name */ -export const getCurrentByName = (name, panel = DOM.CurrentInfo.panel) => { +module.exports.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 */ -export const setCurrentFile = (currentFile, options) => { +module.exports.setCurrentFile = (currentFile, options) => { const o = options; const currentFileWas = DOM.getCurrentFile(); @@ -216,7 +216,7 @@ export const setCurrentFile = (currentFile, options) => { return DOM; }; -export const setCurrentByName = (name) => { +this.setCurrentByName = (name) => { const current = DOM.getCurrentByName(name); return DOM.setCurrentFile(current); }; @@ -227,7 +227,7 @@ export const setCurrentByName = (name) => { * @param layer - element * @param - position {x, y} */ -export const getCurrentByPosition = ({x, y}) => { +module.exports.getCurrentByPosition = ({x, y}) => { const element = document.elementFromPoint(x, y); const getEl = (el) => { @@ -259,7 +259,7 @@ export const getCurrentByPosition = ({x, y}) => { * * @param currentFile */ -export const isCurrentFile = (currentFile) => { +module.exports.isCurrentFile = (currentFile) => { if (!currentFile) return false; @@ -271,7 +271,7 @@ export const isCurrentFile = (currentFile) => { * * @param name */ -export const setTitle = (name) => { +module.exports.setTitle = (name) => { if (!Title) Title = DOM.getByTag('title')[0] || createElement('title', { innerHTML: name, @@ -288,7 +288,7 @@ export const setTitle = (name) => { * * @param currentFile */ -export const isCurrentIsDir = (currentFile) => { +module.exports.isCurrentIsDir = (currentFile) => { const current = currentFile || DOM.getCurrentFile(); const path = DOM.getCurrentPath(current); const fileType = DOM.getCurrentType(current); @@ -299,7 +299,7 @@ export const isCurrentIsDir = (currentFile) => { return isDir || isZip; }; -export const getCurrentType = (currentFile) => { +module.exports.getCurrentType = (currentFile) => { const current = currentFile || DOM.getCurrentFile(); const el = DOM.getByDataName('js-type', current); const type = el.className diff --git a/client/dom/current-file.spec.mjs b/client/dom/current-file.spec.js similarity index 97% rename from client/dom/current-file.spec.mjs rename to client/dom/current-file.spec.js index 2a576dce..88d966e7 100644 --- a/client/dom/current-file.spec.mjs +++ b/client/dom/current-file.spec.js @@ -1,8 +1,10 @@ -import {test, stub} from 'supertape'; -import {create} from 'auto-globals'; -import wraptile from 'wraptile'; -import * as currentFile from './current-file.mjs'; +'use strict'; +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); diff --git a/client/dom/directory.js b/client/dom/directory.js index bedb7e95..6efd989c 100644 --- a/client/dom/directory.js +++ b/client/dom/directory.js @@ -3,7 +3,7 @@ /* global CloudCmd */ const philip = require('philip'); -const Images = require('./images.mjs'); +const Images = require('./images'); const {FS} = require('../../common/cloudfunc.mjs'); const DOM = require('.'); const Dialog = require('./dialog'); diff --git a/client/dom/events/index.js b/client/dom/events/index.js new file mode 100644 index 00000000..22e9261e --- /dev/null +++ b/client/dom/events/index.js @@ -0,0 +1,198 @@ +'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!'); + } +} diff --git a/client/dom/events/index.mjs b/client/dom/events/index.mjs deleted file mode 100644 index 0762d560..00000000 --- a/client/dom/events/index.mjs +++ /dev/null @@ -1,203 +0,0 @@ -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, -}; diff --git a/client/dom/images.mjs b/client/dom/images.js similarity index 84% rename from client/dom/images.mjs rename to client/dom/images.js index 9682e666..bb5579c1 100644 --- a/client/dom/images.mjs +++ b/client/dom/images.js @@ -1,5 +1,10 @@ /* global DOM */ -import createElement from '@cloudcmd/create-element'; + +'use strict'; + +const createElement = require('@cloudcmd/create-element'); + +const Images = module.exports; const LOADING = 'loading'; const HIDDEN = 'hidden'; @@ -7,8 +12,7 @@ const ERROR = 'error'; const getLoadingType = () => isSVG() ? '-svg' : '-gif'; -export const get = getElement; - +module.exports.get = getElement; /** * check SVG SMIL animation support */ @@ -36,7 +40,7 @@ function getElement() { } /* Функция создаёт картинку загрузки */ -export const loading = () => { +module.exports.loading = () => { const element = getElement(); const {classList} = element; const loadingImage = LOADING + getLoadingType(); @@ -48,7 +52,7 @@ export const loading = () => { }; /* Функция создаёт картинку ошибки загрузки */ -export const error = () => { +module.exports.error = () => { const element = getElement(); const {classList} = element; const loadingImage = LOADING + getLoadingType(); @@ -59,21 +63,14 @@ export const error = () => { return element; }; -show.load = show; -show.error = (text) => { - const image = Images.error(); - - DOM.show(image); - image.title = text; - - return image; -}; - +module.exports.show = show; +module.exports.show.load = show; +module.exports.show.error = error; /** * Function shows loading spinner * position = {top: true}; */ -export function show(position, panel) { +function show(position, panel) { const image = Images.loading(); const parent = image.parentElement; const refreshButton = DOM.getRefreshButton(panel); @@ -99,10 +96,19 @@ export function show(position, panel) { return image; } +function error(text) { + const image = Images.error(); + + DOM.show(image); + image.title = text; + + return image; +} + /** * hide load image */ -export const hide = () => { +module.exports.hide = () => { const element = Images.get(); DOM.hide(element); @@ -110,7 +116,7 @@ export const hide = () => { return Images; }; -export const setProgress = (value, title) => { +module.exports.setProgress = (value, title) => { const DATA = 'data-progress'; const element = Images.get(); @@ -125,7 +131,7 @@ export const setProgress = (value, title) => { return Images; }; -export const clearProgress = () => { +module.exports.clearProgress = () => { const DATA = 'data-progress'; const element = Images.get(); @@ -137,13 +143,3 @@ export const clearProgress = () => { return Images; }; - -const Images = { - clearProgress, - setProgress, - show, - hide, - get, - error, - loading, -}; diff --git a/client/dom/index.js b/client/dom/index.js index 27a1a5c6..965f1972 100644 --- a/client/dom/index.js +++ b/client/dom/index.js @@ -3,12 +3,12 @@ /* global CloudCmd */ const Util = require('../../common/util'); -const Images = require('./images.mjs'); +const Images = require('./images'); const RESTful = require('./rest'); const Storage = require('./storage'); const renameCurrent = require('./operations/rename-current'); -const CurrentFile = require('./current-file.mjs'); +const CurrentFile = require('./current-file'); 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.mjs'); -DOM.Events = require('#dom/events'); +DOM.Buffer = require('./buffer'); +DOM.Events = require('./events'); const loadRemote = require('./load-remote'); const selectByPattern = require('./select-by-pattern'); diff --git a/client/dom/io/send-request.js b/client/dom/io/send-request.js index c61544f1..bc52d667 100644 --- a/client/dom/io/send-request.js +++ b/client/dom/io/send-request.js @@ -3,7 +3,7 @@ /* global CloudCmd */ const {promisify} = require('es6-promisify'); -const Images = require('../images.mjs'); +const Images = require('../images'); const load = require('../load'); module.exports = promisify((params, callback) => { diff --git a/client/dom/load.js b/client/dom/load.js index d060a92c..03c25d73 100644 --- a/client/dom/load.js +++ b/client/dom/load.js @@ -4,7 +4,7 @@ const itype = require('itype'); const jonny = require('jonny'); const Emitify = require('emitify'); const exec = require('execon'); -const Images = require('./images.mjs'); +const Images = require('./images'); module.exports.getIdBySrc = getIdBySrc; /** diff --git a/client/dom/operations/rename-current.js b/client/dom/operations/rename-current.js index ab658edf..1293dc33 100644 --- a/client/dom/operations/rename-current.js +++ b/client/dom/operations/rename-current.js @@ -7,7 +7,7 @@ const _Dialog = require('../dialog'); const Storage = require('../storage'); const RESTful = require('../rest'); -const _currentFile = require('../current-file.mjs'); +const _currentFile = require('../current-file'); module.exports = async (current, overrides = {}) => { const { diff --git a/client/dom/rest.js b/client/dom/rest.js index 7596f620..444fce15 100644 --- a/client/dom/rest.js +++ b/client/dom/rest.js @@ -4,7 +4,7 @@ const {tryToCatch} = require('try-to-catch'); const {encode} = require('../../common/entity'); -const Images = require('./images.mjs'); +const Images = require('./images'); const IO = require('./io'); const Dialog = require('./dialog'); diff --git a/client/dom/upload-files.js b/client/dom/upload-files.js index a1206282..1a64fb6c 100644 --- a/client/dom/upload-files.js +++ b/client/dom/upload-files.js @@ -5,7 +5,7 @@ const {eachSeries} = require('execon'); const wraptile = require('wraptile'); const load = require('./load'); -const Images = require('./images.mjs'); +const Images = require('./images'); const {alert} = require('./dialog'); const {FS} = require('../../common/cloudfunc.mjs'); diff --git a/client/get-json-from-file-table.mjs b/client/get-json-from-file-table.mjs index ea90f366..86edebf9 100644 --- a/client/get-json-from-file-table.mjs +++ b/client/get-json-from-file-table.mjs @@ -8,6 +8,29 @@ 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); @@ -19,26 +42,3 @@ 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, - }; -}; diff --git a/client/key/index.mjs b/client/key/index.js similarity index 95% rename from client/key/index.mjs rename to client/key/index.js index 64fd1bc3..3e8aeeab 100644 --- a/client/key/index.mjs +++ b/client/key/index.js @@ -1,13 +1,18 @@ -/* global CloudCmd, DOM */ -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'; +'use strict'; +/* global CloudCmd, DOM */ +const clipboard = require('@cloudcmd/clipboard'); +const {fullstore} = require('fullstore'); + +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 = {}) => { @@ -24,16 +29,13 @@ Chars([]); const {assign} = Object; const binder = createBinder(); -const bind = () => { +module.exports = assign(binder, KEY); +module.exports.bind = () => { Events.addKey(listener, true); binder.setBind(); }; -export const Key = assign(binder, KEY, { - bind, -}); - -export const _listener = listener; +module.exports._listener = listener; function getChar(event) { /* @@ -96,7 +98,7 @@ async function listener(event, overrides = {}) { return; if (isVim) - vim(char, event); + await vim(char, event); } function getSymbol(shift, keyCode) { @@ -122,7 +124,6 @@ function fromCharCode(keyIdentifier) { } async function _switchKey(event) { - const Info = DOM.CurrentInfo; let i; let isSelected; let prev; diff --git a/client/key/index.spec.js b/client/key/index.spec.js index d8167079..3e52e5ac 100644 --- a/client/key/index.spec.js +++ b/client/key/index.spec.js @@ -7,8 +7,7 @@ const supertape = require('supertape'); const {ESC} = require('./key'); -const {Key, _listener} = require('./index.mjs'); - +const {_listener, setBind} = require('.'); const {getDOM, getCloudCmd} = require('./vim/globals.fixture'); const test = autoGlobals(supertape); const {stub} = supertape; @@ -27,7 +26,7 @@ test('cloudcmd: client: key: enable vim', async (t) => { altKey: false, }; - Key.setBind(); + setBind(); await _listener(event, { vim, @@ -49,7 +48,7 @@ test('cloudcmd: client: key: disable vim', async (t) => { altKey: false, }; - Key.setBind(); + setBind(); await _listener(event, { config, _config, diff --git a/client/key/set-current-by-char.js b/client/key/set-current-by-char.js index ab9329f3..f54881a3 100644 --- a/client/key/set-current-by-char.js +++ b/client/key/set-current-by-char.js @@ -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; diff --git a/client/key/vim/index.js b/client/key/vim/index.js index ddfe49c3..4509ae13 100644 --- a/client/key/vim/index.js +++ b/client/key/vim/index.js @@ -9,43 +9,37 @@ const { selectFileNotParent, } = require('./set-current'); -module.exports = (key, event, overrides = {}) => { - const defaults = { - ...globalThis.DOM, - ...globalThis.CloudCmd, - }; - - const deps = { - ...defaults, - ...overrides, - }; - +const {DOM = {}, CloudCmd = {}, +} = globalThis; + +const {Dialog = {}} = DOM; + +const DEPS = { + ...DOM, + ...CloudCmd, +}; + +module.exports = async (key, event, deps = DEPS) => { const operations = getOperations(event, deps); - - vim(key, operations, deps); + await vim(key, operations, deps); }; const getOperations = (event, deps) => { const { - Info = globalThis.DOM.CurrentInfo, - CloudCmd = globalThis.CloudCmd, + Info = DOM.CurrentInfo, Operation, unselectFiles, setCurrentFile, setCurrentByName, getCurrentName, - prompt = globalThis.DOM.Dialog.prompt, + prompt = Dialog.prompt, preventDefault = event?.preventDefault?.bind(event), toggleSelectedFile, Buffer = {}, - createFindNext = _createFindNext, } = deps; return { - findNext: createFindNext({ - setCurrentByName, - }), escape: unselectFiles, remove: () => { @@ -123,6 +117,11 @@ const getOperations = (event, deps) => { setCurrentByName(result); }, + findNext: () => { + const name = finder.findNext(); + setCurrentByName(name); + }, + findPrevious: () => { const name = finder.findPrevious(); setCurrentByName(name); @@ -131,10 +130,3 @@ const getOperations = (event, deps) => { }; module.exports.selectFile = selectFileNotParent; - -const _createFindNext = (overrides = {}) => () => { - const {setCurrentByName} = overrides; - const name = finder.findNext(); - - setCurrentByName(name); -}; diff --git a/client/key/vim/index.spec.js b/client/key/vim/index.spec.js index 6fcad11e..384f3aea 100644 --- a/client/key/vim/index.spec.js +++ b/client/key/vim/index.spec.js @@ -570,13 +570,17 @@ 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, { - createFindNext, - }); + vim('n', event); + + stopAll(); t.calledWithNoArgs(findNext, 'should call findNext'); t.end(); @@ -640,27 +644,25 @@ test('cloudcmd: client: key: make file', (t) => { t.end(); }); -test('cloudcmd: client: vim: terminal', (t) => { - const CloudCmd = { +test.skip('cloudcmd: client: vim: terminal', (t) => { + const {CloudCmd} = globalThis; + + assign(CloudCmd, { Terminal: { show: stub(), }, - }; + }); const event = {}; - vim('t', event, { - CloudCmd, - }); - vim('t', event, { - CloudCmd, - }); + vim('t', event); + vim('t', event); t.calledWithNoArgs(CloudCmd.Terminal.show); t.end(); }); -test('cloudcmd: client: vim: edit', async (t) => { +test.skip('cloudcmd: client: vim: edit', async (t) => { globalThis.DOM = getDOM(); globalThis.CloudCmd = getCloudCmd(); diff --git a/client/listeners/index.js b/client/listeners/index.js index c12c62ed..f3b99f70 100644 --- a/client/listeners/index.js +++ b/client/listeners/index.js @@ -11,7 +11,6 @@ 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')); @@ -30,6 +29,8 @@ module.exports.init = async () => { ]); }; +CloudCmd.Listeners = module.exports; + const unselect = (event) => { const isMac = /Mac/.test(globalThis.navigator.platform); const { @@ -49,6 +50,9 @@ 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)]), @@ -163,7 +167,6 @@ function getPathListener(panel) { } function isNoCurrent(panel) { - const Info = DOM.CurrentInfo; const infoPanel = Info.panel; if (!infoPanel) @@ -188,7 +191,6 @@ function decodePath(path) { } async function onPathElementClick(panel, event) { - const Info = DOM.CurrentInfo; event.preventDefault(); const element = event.target; @@ -259,7 +261,6 @@ 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); @@ -301,7 +302,6 @@ 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,7 +338,6 @@ function getULElement(element) { } function setCurrentFileByEvent(event) { - const Info = DOM.CurrentInfo; const BUTTON_LEFT = 0; const key = { @@ -452,7 +451,7 @@ function dragndrop() { } function unload() { - Events.add(['unload', 'beforeunload'], (event) => { + DOM.Events.add(['unload', 'beforeunload'], (event) => { const {Key} = CloudCmd; const isBind = Key?.isBind(); @@ -481,7 +480,6 @@ function pop() { function resize() { Events.add('resize', () => { - const Info = DOM.CurrentInfo; const is = globalThis.innerWidth < CloudCmd.MIN_ONE_PANEL_WIDTH; if (!is) diff --git a/client/modules/cloud.js b/client/modules/cloud.js index 53a6d9e9..81498c4b 100644 --- a/client/modules/cloud.js +++ b/client/modules/cloud.js @@ -9,7 +9,7 @@ const load = require('load.js'); const {ajax} = require('../dom/load'); const Files = require('../dom/files'); -const Images = require('../dom/images.mjs'); +const Images = require('../dom/images'); const {log} = CloudCmd; const upload = currify(_upload); diff --git a/client/modules/config/index.js b/client/modules/config/index.js index db778cbc..a92594ef 100644 --- a/client/modules/config/index.js +++ b/client/modules/config/index.js @@ -13,8 +13,8 @@ const load = require('load.js'); const createElement = require('@cloudcmd/create-element'); const input = require('./input'); -const Images = require('../../dom/images.mjs'); -const Events = require('#dom/events'); +const Images = require('../../dom/images'); +const Events = require('../../dom/events'); const Files = require('../../dom/files'); const {getTitle} = require('../../../common/cloudfunc.mjs'); diff --git a/client/modules/contact.js b/client/modules/contact.js index c6266de0..76a07d30 100644 --- a/client/modules/contact.js +++ b/client/modules/contact.js @@ -6,7 +6,7 @@ CloudCmd.Contact = exports; const olark = require('@cloudcmd/olark'); -const Images = require('../dom/images.mjs'); +const Images = require('../dom/images'); const {Events} = DOM; const {Key} = CloudCmd; diff --git a/client/modules/edit-file-vim.js b/client/modules/edit-file-vim.js index 0edd203b..48cfd93e 100644 --- a/client/modules/edit-file-vim.js +++ b/client/modules/edit-file-vim.js @@ -3,7 +3,7 @@ /* global CloudCmd */ CloudCmd.EditFileVim = exports; -const Events = require('#dom/events'); +const Events = require('../dom/events'); const {Key} = CloudCmd; diff --git a/client/modules/edit-names-vim.js b/client/modules/edit-names-vim.js index 0dbd92b2..266dc9dc 100644 --- a/client/modules/edit-names-vim.js +++ b/client/modules/edit-names-vim.js @@ -3,7 +3,7 @@ /* global CloudCmd */ CloudCmd.EditNamesVim = exports; -const Events = require('#dom/events'); +const Events = require('../dom/events'); const {Key} = CloudCmd; const ConfigView = { diff --git a/client/modules/help.js b/client/modules/help.js index 242b7c16..785bb32c 100644 --- a/client/modules/help.js +++ b/client/modules/help.js @@ -3,7 +3,7 @@ /* global CloudCmd */ CloudCmd.Help = exports; -const Images = require('../dom/images.mjs'); +const Images = require('../dom/images'); module.exports.init = () => { Images.show.load('top'); diff --git a/client/modules/konsole.js b/client/modules/konsole.js index ae5bc42c..3de160fd 100644 --- a/client/modules/konsole.js +++ b/client/modules/konsole.js @@ -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.mjs'); +const Images = require('../dom/images'); const {Dialog, CurrentInfo: Info} = DOM; const rmLastSlash = (a) => a.replace(/\/$/, '') || '/'; diff --git a/client/modules/markdown.js b/client/modules/markdown.js index 9dc224af..6c5c3282 100644 --- a/client/modules/markdown.js +++ b/client/modules/markdown.js @@ -5,7 +5,7 @@ CloudCmd.Markdown = exports; const createElement = require('@cloudcmd/create-element'); -const Images = require('../dom/images.mjs'); +const Images = require('../dom/images'); const {Markdown} = require('../dom/rest'); const {alert} = require('../dom/dialog'); diff --git a/client/modules/operation/index.mjs b/client/modules/operation/index.js similarity index 93% rename from client/modules/operation/index.mjs rename to client/modules/operation/index.js index 8e8149e5..3cce60d8 100644 --- a/client/modules/operation/index.mjs +++ b/client/modules/operation/index.js @@ -1,20 +1,28 @@ -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'; +/* global CloudCmd */ +/* global Util */ +/* global DOM */ +/* global fileop */ -const {DOM, CloudCmd} = globalThis; +'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 removeQuery = (a) => a.replace(/\?.*/, ''); const Name = 'Operation'; +CloudCmd[Name] = exports; + const {config} = CloudCmd; const {Dialog, Images} = DOM; @@ -45,7 +53,7 @@ const noFilesCheck = () => { return is; }; -export const init = promisify((callback) => { +module.exports.init = promisify((callback) => { showLoad(); exec.series([ @@ -84,7 +92,7 @@ const onConnect = currify((fn, operator) => { async function initOperations(prefix, socketPrefix, fn) { socketPrefix = `${socketPrefix}/fileop`; - const operator = await globalThis.fileop({ + const operator = await fileop({ prefix, socketPrefix, }); @@ -190,11 +198,11 @@ function getPacker(type) { return packTarFn; } -export const hide = () => { +module.exports.hide = () => { CloudCmd.View.hide(); }; -export const show = (operation, data) => { +module.exports.show = (operation, data) => { if (!Loaded) return; @@ -497,14 +505,8 @@ async function prompt(msg, to, names) { return await Dialog.prompt(msg, to); } -globalThis.CloudCmd[Name] = { - init, - hide, - show, -}; - async function loadAll() { - const {prefix} = globalThis.CloudCmd; + const {prefix} = CloudCmd; const file = `${prefix}/fileop/fileop.js`; const [error] = await tryToCatch(load.js, file); diff --git a/client/modules/operation/set-listeners.mjs b/client/modules/operation/set-listeners.js similarity index 85% rename from client/modules/operation/set-listeners.mjs rename to client/modules/operation/set-listeners.js index d5052cff..495cd04b 100644 --- a/client/modules/operation/set-listeners.mjs +++ b/client/modules/operation/set-listeners.js @@ -1,11 +1,14 @@ +'use strict'; + /* global DOM */ -import forEachKey from 'for-each-key'; -import wraptile from 'wraptile'; -import format from './format.js'; +const forEachKey = require('for-each-key'); + +const wraptile = require('wraptile'); +const format = require('./format'); const {Dialog, Images} = DOM; -export const setListeners = (options) => (emitter) => { +module.exports = (options) => (emitter) => { const { operation, callback, @@ -40,13 +43,10 @@ export const setListeners = (options) => (emitter) => { operation, })); - let noProgress = true; - const listeners = { progress: (value) => { done = value === 100; progress.setProgress(value); - noProgress = false; }, end: () => { @@ -54,7 +54,7 @@ export const setListeners = (options) => (emitter) => { forEachKey(removeListener, listeners); progress.remove(); - if (lastError || done || noProgress) + if (lastError || done) callback(); }, diff --git a/client/modules/terminal-run.js b/client/modules/terminal-run.js index 4dcf24ac..33b5dbae 100644 --- a/client/modules/terminal-run.js +++ b/client/modules/terminal-run.js @@ -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.mjs'); +const Images = require('../dom/images'); const {Dialog} = DOM; const {Key, config} = CloudCmd; diff --git a/client/modules/terminal.js b/client/modules/terminal.js index 6a355560..7b9197ca 100644 --- a/client/modules/terminal.js +++ b/client/modules/terminal.js @@ -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.mjs'); +const Images = require('../dom/images'); const loadParallel = load.parallel; diff --git a/client/modules/upload.js b/client/modules/upload.js index 23fbdaf5..63a2cd0f 100644 --- a/client/modules/upload.js +++ b/client/modules/upload.js @@ -6,7 +6,7 @@ CloudCmd.Upload = exports; const createElement = require('@cloudcmd/create-element'); const Files = require('../dom/files'); -const Images = require('../dom/images.mjs'); +const Images = require('../dom/images'); const uploadFiles = require('../dom/upload-files'); module.exports.init = async () => { diff --git a/client/modules/user-menu/index.js b/client/modules/user-menu/index.js index 1dba5d23..713bdb8a 100644 --- a/client/modules/user-menu/index.js +++ b/client/modules/user-menu/index.js @@ -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.mjs'); +const Images = require('../../dom/images'); const Dialog = require('../../dom/dialog'); const getUserMenu = require('./get-user-menu'); const navigate = require('./navigate'); diff --git a/client/modules/view/index.js b/client/modules/view/index.js index 89d68ee4..5262f85a 100644 --- a/client/modules/view/index.js +++ b/client/modules/view/index.js @@ -26,8 +26,8 @@ const { } = require('./types'); const Files = require('../../dom/files'); -const Events = require('#dom/events'); -const Images = require('../../dom/images.mjs'); +const Events = require('../../dom/events'); +const Images = require('../../dom/images'); const {encode} = require('../../../common/entity'); const isString = (a) => typeof a === 'string'; diff --git a/eslint.config.mjs b/eslint.config.mjs index cf7a6a2d..d445c4a9 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -33,7 +33,9 @@ export default defineConfig([ }, { files: ['{client,common,static}/**/*.js'], languageOptions: { - globals: globals.browser, + globals: { + ...globals.browser, + }, }, }, ...matchToFlat(match), diff --git a/package.json b/package.json index c9760653..3cc979f3 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,6 @@ { "name": "cloudcmd", - "version": "19.1.9", - "type": "commonjs", + "version": "19.1.6", "author": "coderaiser (https://github.com/coderaiser)", "description": "File manager for the web with console and editor", "homepage": "http://cloudcmd.io", @@ -158,7 +157,7 @@ "@cloudcmd/olark": "^3.0.2", "@cloudcmd/stub": "^5.0.0", "@iocmd/wait": "^2.1.0", - "@putout/eslint-flat": "^4.0.0", + "@putout/eslint-flat": "^3.0.1", "@putout/plugin-cloudcmd": "^4.0.0", "@types/node-fetch": "^2.6.11", "auto-globals": "^4.0.0", @@ -175,13 +174,12 @@ "emitify": "^4.0.1", "eslint": "^9.23.0", "eslint-plugin-n": "^17.0.0-4", - "eslint-plugin-putout": "^30.0.0", + "eslint-plugin-putout": "^29.0.2", "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", @@ -218,9 +216,6 @@ "webpack-merge": "^6.0.1", "webpackbar": "^7.0.0" }, - "imports": { - "#dom/events": "./client/dom/events/index.mjs" - }, "engines": { "node": ">=22" },