diff --git a/.eslintrc.js b/.eslintrc.js
new file mode 100644
index 00000000..13d9e227
--- /dev/null
+++ b/.eslintrc.js
@@ -0,0 +1,38 @@
+'use strict';
+
+module.exports = {
+ extends: [
+ 'plugin:putout/safe+align',
+ ],
+ plugins: [
+ 'putout',
+ 'n',
+ ],
+ rules: {
+ 'key-spacing': 'off',
+ 'n/prefer-node-protocol': 'error',
+ },
+ overrides: [{
+ files: ['bin/release.js'],
+ rules: {
+ 'no-console': 'off',
+ 'n/shebang': 'off',
+ },
+ }, {
+ files: ['client/dom/index.js'],
+ rules: {
+ 'no-multi-spaces': 'off',
+ },
+ }, {
+ files: ['bin/cloudcmd.js'],
+ rules: {
+ 'no-console': 'off',
+ },
+ }, {
+ files: ['{client,common,static}/**/*.js'],
+ env: {
+ browser: true,
+ },
+ }],
+ ignorePatterns: ['*.md{js}'],
+};
diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml
index 376b0f08..e4877cb7 100644
--- a/.github/workflows/docker.yml
+++ b/.github/workflows/docker.yml
@@ -11,12 +11,12 @@ jobs:
packages: write
steps:
- name: Checkout
- uses: actions/checkout@v5
- - uses: oven-sh/setup-bun@v2
+ uses: actions/checkout@v4
+ - uses: oven-sh/setup-bun@v1
with:
bun-version: latest
- name: Use Node.js 22.x
- uses: actions/setup-node@v6
+ uses: actions/setup-node@v4
with:
node-version: 22.x
- name: Install Redrun
diff --git a/.github/workflows/nodejs.yml b/.github/workflows/nodejs.yml
index 1b392900..88fed4f0 100644
--- a/.github/workflows/nodejs.yml
+++ b/.github/workflows/nodejs.yml
@@ -9,16 +9,15 @@ jobs:
strategy:
matrix:
node-version:
+ - 20.x
- 22.x
- - 24.x
- - 25.x
steps:
- - uses: actions/checkout@v5
- - uses: oven-sh/setup-bun@v2
+ - uses: actions/checkout@v4
+ - uses: oven-sh/setup-bun@v1
with:
bun-version: latest
- name: Use Node.js ${{ matrix.node-version }}
- uses: actions/setup-node@v6
+ uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
- name: Install Redrun
diff --git a/.npmignore b/.npmignore
index b668cf7f..08137773 100644
--- a/.npmignore
+++ b/.npmignore
@@ -18,7 +18,6 @@ now.json
app.json
bower.json
manifest.yml
-deno.json
bin/release.mjs
diff --git a/.putout.json b/.putout.json
index b868f59d..239eb08d 100644
--- a/.putout.json
+++ b/.putout.json
@@ -7,9 +7,6 @@
"fontello.json",
"*.md"
],
- "rules": {
- "package-json/add-type": "off"
- },
"match": {
"base64": {
"types/convert-typeof-to-is-type": "off"
@@ -29,12 +26,9 @@
"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": {
- "nodejs": "off"
- },
"client/sw": {
"remove-console": "off"
},
@@ -49,9 +43,6 @@
},
"vim.js": {
"merge-duplicate-functions": "off"
- },
- "common": {
- "nodejs/declare": "off"
}
}
}
diff --git a/.webpack/css.mjs b/.webpack/css.js
similarity index 71%
rename from .webpack/css.mjs
rename to .webpack/css.js
index 338ae91b..2d3faf55 100644
--- a/.webpack/css.mjs
+++ b/.webpack/css.js
@@ -1,6 +1,9 @@
-import {env} from 'node:process';
-import OptimizeCssAssetsPlugin from 'optimize-css-assets-webpack-plugin';
-import MiniCssExtractPlugin from 'mini-css-extract-plugin';
+'use strict';
+
+const {env} = require('node:process');
+
+const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin');
+const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const isDev = env.NODE_ENV === 'development';
@@ -26,7 +29,7 @@ const rules = [{
type: 'asset/inline',
}];
-export default {
+module.exports = {
plugins,
module: {
rules,
diff --git a/.webpack/html.mjs b/.webpack/html.js
similarity index 85%
rename from .webpack/html.mjs
rename to .webpack/html.js
index e90038ac..3717bcc9 100644
--- a/.webpack/html.mjs
+++ b/.webpack/html.js
@@ -1,9 +1,11 @@
-import {env} from 'node:process';
-import HtmlWebpackPlugin from 'html-webpack-plugin';
+'use strict';
+
+const {env} = require('node:process');
+const HtmlWebpackPlugin = require('html-webpack-plugin');
const isDev = env.NODE_ENV === 'development';
-export const plugins = [
+const plugins = [
new HtmlWebpackPlugin({
inject: false,
template: 'html/index.html',
@@ -11,6 +13,10 @@ export const plugins = [
}),
];
+module.exports = {
+ plugins,
+};
+
function getMinifyHtmlOptions() {
return {
removeComments: true,
diff --git a/.webpack/js.mjs b/.webpack/js.js
similarity index 90%
rename from .webpack/js.mjs
rename to .webpack/js.js
index d52e0388..d666780d 100644
--- a/.webpack/js.mjs
+++ b/.webpack/js.js
@@ -1,12 +1,18 @@
-import {resolve, sep} from 'node:path';
-import {env} from 'node:process';
-import webpack from 'webpack';
-import WebpackBar from 'webpackbar';
+'use strict';
+const {
+ resolve,
+ sep,
+ join,
+} = require('node:path');
+
+const {env} = require('node:process');
const {
EnvironmentPlugin,
NormalModuleReplacementPlugin,
-} = webpack;
+} = require('webpack');
+
+const WebpackBar = require('webpackbar');
const modules = './modules';
const dirModules = './client/modules';
@@ -17,7 +23,7 @@ const dir = './client';
const {NODE_ENV} = env;
const isDev = NODE_ENV === 'development';
-const rootDir = new URL('..', import.meta.url).pathname;
+const rootDir = join(__dirname, '..');
const dist = resolve(rootDir, 'dist');
const distDev = resolve(rootDir, 'dist-dev');
const devtool = isDev ? 'eval' : 'source-map';
@@ -25,7 +31,7 @@ const devtool = isDev ? 'eval' : 'source-map';
const notEmpty = (a) => a;
const clean = (array) => array.filter(notEmpty);
-const noParse = (a) => a.endsWith('.spec.js');
+const noParse = (a) => /\.spec\.js$/.test(a);
const options = {
babelrc: true,
};
@@ -86,7 +92,7 @@ const splitChunks = {
},
};
-export default {
+module.exports = {
resolve: {
symlinks: false,
alias: {
@@ -94,8 +100,8 @@ export default {
'node:path': 'path',
},
fallback: {
- path: import.meta.resolve('path-browserify'),
- process: import.meta.resolve('process/browser'),
+ path: require.resolve('path-browserify'),
+ process: require.resolve('process/browser'),
},
},
devtool,
@@ -114,7 +120,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 +133,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..8b41875d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,226 +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:
-- a523ef65 tests
-
-feature:
-- 64654e8d common: cloudfunc: migrate to ESM
-- add31607 common: cloudfunc: get rid of bas64
-- e36de00c modulas: migrate to ESM
-
-2026.01.16, v19.1.5
-
-feature:
-- 450f1461 client: improve testability
-- d979e949 server: env: migrate to ESM
-
-2026.01.15, v19.1.4
-
-feature:
-- 6e778a35 client: sort: migrate to ESM
-- e27ef51d client: sort: migrate to ESM
-- 917f5851 client: load-module: migrate to ESM
-- 9950caca client: get-json-from-file-table: migrate to ESM
-
-2026.01.15, v19.1.3
-
-feature:
-- f903c5c9 cloudcmd: multi-rename v3.0.0
-
-2026.01.14, v19.1.2
-
-fix:
-- 9e2c5ac6 client: edit-names: group rename not renaming (#453)
-- f0dcbe94 client: key: config
-
-feature:
-- 6856207d server: env -> env.parse
-- dc99417c client: key: get rid of mock-require
-- 4bb7d704 client: modules: view: get rid of mock-require
-
-2026.01.12, v19.1.1
-
-feature:
-- 5cc6f79d cloudcmd: @cloudcmd/stub v5.0.0
-- 024bc413 cloudcmd: fullstore v4.0.0
-- 53f6f9e7 cloudcmd: globals v17.0.0
-- 6d21c539 cloudcmd: madrun v12.1.0
-- 253389ea cloudcmd: supertape v12.0.0
-
-2025.12.31, v19.1.0
-
-feature:
-- 0ff16314 cloudcmd: redlint v5.0.0
-- 43edba8c cloudcmd: try-to-catch v4.0.0
-- 06f3b782 cloudcmd: try-catch v4.0.4
-- dfcd6557 deno config: add
-- ab20a462 server: bun support (oven-sh/bun#25674)
-
-2025.12.24, v19.0.17
-
-feature:
-- 0222d177 cloudcmd: gritty v9.0.0
-
-2025.12.05, v19.0.16
-
-feature:
-- 14ec19e8 cloudcmd: find-up v8.0.0
-- e6a00979 cloudcmd: eslint-plugin-putout v29.0.2
-- 5b5352c7 cloudcmd: putout v41.0.0
-
-2025.11.28, v19.0.15
-
-feature:
-- 00676531 cloudcmd: aleman v1.16.5
-
-2025.11.27, v19.0.14
-
-fix:
-- 2a525e9b aleman: copy paste in text editor (#449)
-
-feature:
-- 3ceb9a8c cloudcmd: open v11.0.0
-
-2025.09.26, v19.0.13
-
-feature:
-- 8477f3e4 cloudcmd: aleman v1.16.3 (#446)
-
-2025.09.25, v19.0.12
-
-feature:
-- 836e908e cloudcmd: aleman v1.16.2
-
-2025.09.24, v19.0.11
-
-feature:
-- f4386a6f cloudcmd: aleman v1.16.1
-
-2025.09.23, v19.0.10
-
-feature:
-- 2e667ba6 cloudcmd: aleman v1.15.0
-
-2025.09.22, v19.0.9
-
-feature:
-- 60c56164 cloudcmd: aleman v1.14.4
-
-2025.09.20, v19.0.8
-
-feature:
-- efe81320 cloudcmd: aleman v1.14.3
-
-2025.09.18, v19.0.7
-
-feature:
-- 5b972e2e cloudcmd: aleman v1.14.0
-
-2025.09.17, v19.0.6
-
-feature:
-- 39a24028 cloudcmd: aleman v1.13.0
-
-2025.09.16, v19.0.5
-
-fix:
-- 64df81bc cloudcmd: client: listeners: f9: stopPropagation
-
-feature:
-- 38dd5101 cloudcmd: aleman v1.12.4
-
-2025.09.15, v19.0.4
-
-feature:
-- 66db798c cloudcmd: aleman v1.12.3
-
-2025.09.15, v19.0.3
-
-feature:
-- c5aed16f cloudcmd: aleman v1.12.2
-
-2025.09.14, v19.0.2
-
-feature:
-- 511347d3 cloudcmd: aleman v1.11.0
-
-2025.09.14, v19.0.1
-
-fix:
-- fc6304a1 tmpl: config: aleman, supermenu
-
-feature:
-- a05ecdb4 cloudcmd: aleman v1.10.0
-
-2025.09.14, v19.0.0
-
-feature:
-- 50b19dcc cloudcmd: menu: default: supermenu -> aleman
-- 5970f10a cloudcmd: drop support of node < 22
-
-2025.09.14, v18.8.11
-
-feature:
-- b0360d8e cloudcmd: aleman v1.9.1
-- 00a20129 cloudcmd: html: importsmap: add
-
-2025.09.14, v18.8.10
-
-feature:
-- ddf9e455 cloudcmd: aleman v1.9.0
-
-2025.09.14, v18.8.9
-
-feature:
-- 2e7bdb8a cloudcmd: aleman v1.8.0
-
-2025.09.13, v18.8.8
-
-feature:
-- 03631d95 cloudcmd: aleman v1.7.0
-
-2025.09.12, v18.8.7
-
-feature:
-- 09408af5 cloudcmd: aleman v1.6.1
-
-2025.09.12, v18.8.6
-
-feature:
-- 4fcaf288 cloudcmd: aleman v1.6.0
-
-2025.09.10, v18.8.5
-
-feature:
-- c69ec16e cloudcmd: aleman v1.5.0
-
2025.09.09, v18.8.4
feature:
diff --git a/HELP.md b/HELP.md
index 68087875..47a6408c 100644
--- a/HELP.md
+++ b/HELP.md
@@ -1,4 +1,4 @@
-# Cloud Commander v19.1.9
+# Cloud Commander v18.8.4
### [Main][MainURL] [Blog][BlogURL] [Support][SupportURL] [Demo][DemoURL]
@@ -190,8 +190,7 @@ Then, start the server again with `cloudcmd` and reload the page.
| `Ctrl + F5` | sort by date
| `Ctrl + F6` | sort by size
| `Ctrl + Command + .` | show/hide dot files
-| `Up` | move cursor up
-| `Down` | move cursor down
+| `Up`, `Down` | file system navigation
| `Enter` | change directory/view file
| `Alt + Left/Right` | show content of directory under cursor in target panel
| `Alt + G` | go to directory
@@ -647,20 +646,10 @@ Right-mouse click to show a context menu with these items:
### Hot keys
-| Key | Operation |
-|:-------------|:------------------------|
-| `F9` | open |
-| `Esc` | close |
-| `Up`, `j` | move cursor up |
-| `Down`, `k` | move cursor down |
-| `Left`, `h` | close submenu |
-| `Right`, `l` | open submenu |
-| `G` or `$` | navigate to bottom |
-| `gg` or `^` | navigate to top |
-
-Commands can be joined, for example:
-
-- `5j` will navigate **5** items below current;
+|Key |Operation
+|:----------------------|:--------------------------------------------
+| `F9` | open
+| `Esc` | close
## One file panel
@@ -1111,41 +1100,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)**
-- *2026.01.15*, **[v19.1.3](//github.com/coderaiser/cloudcmd/releases/tag/v19.1.3)**
-- *2026.01.14*, **[v19.1.2](//github.com/coderaiser/cloudcmd/releases/tag/v19.1.2)**
-- *2026.01.12*, **[v19.1.1](//github.com/coderaiser/cloudcmd/releases/tag/v19.1.1)**
-- *2025.12.31*, **[v19.1.0](//github.com/coderaiser/cloudcmd/releases/tag/v19.1.0)**
-- *2025.12.24*, **[v19.0.17](//github.com/coderaiser/cloudcmd/releases/tag/v19.0.17)**
-- *2025.12.05*, **[v19.0.16](//github.com/coderaiser/cloudcmd/releases/tag/v19.0.16)**
-- *2025.11.28*, **[v19.0.15](//github.com/coderaiser/cloudcmd/releases/tag/v19.0.15)**
-- *2025.11.27*, **[v19.0.14](//github.com/coderaiser/cloudcmd/releases/tag/v19.0.14)**
-- *2025.09.26*, **[v19.0.13](//github.com/coderaiser/cloudcmd/releases/tag/v19.0.13)**
-- *2025.09.25*, **[v19.0.12](//github.com/coderaiser/cloudcmd/releases/tag/v19.0.12)**
-- *2025.09.24*, **[v19.0.11](//github.com/coderaiser/cloudcmd/releases/tag/v19.0.11)**
-- *2025.09.23*, **[v19.0.10](//github.com/coderaiser/cloudcmd/releases/tag/v19.0.10)**
-- *2025.09.22*, **[v19.0.9](//github.com/coderaiser/cloudcmd/releases/tag/v19.0.9)**
-- *2025.09.20*, **[v19.0.8](//github.com/coderaiser/cloudcmd/releases/tag/v19.0.8)**
-- *2025.09.18*, **[v19.0.7](//github.com/coderaiser/cloudcmd/releases/tag/v19.0.7)**
-- *2025.09.17*, **[v19.0.6](//github.com/coderaiser/cloudcmd/releases/tag/v19.0.6)**
-- *2025.09.16*, **[v19.0.5](//github.com/coderaiser/cloudcmd/releases/tag/v19.0.5)**
-- *2025.09.15*, **[v19.0.4](//github.com/coderaiser/cloudcmd/releases/tag/v19.0.4)**
-- *2025.09.15*, **[v19.0.3](//github.com/coderaiser/cloudcmd/releases/tag/v19.0.3)**
-- *2025.09.14*, **[v19.0.2](//github.com/coderaiser/cloudcmd/releases/tag/v19.0.2)**
-- *2025.09.14*, **[v19.0.1](//github.com/coderaiser/cloudcmd/releases/tag/v19.0.1)**
-- *2025.09.14*, **[v19.0.0](//github.com/coderaiser/cloudcmd/releases/tag/v19.0.0)**
-- *2025.09.14*, **[v18.8.11](//github.com/coderaiser/cloudcmd/releases/tag/v18.8.11)**
-- *2025.09.14*, **[v18.8.10](//github.com/coderaiser/cloudcmd/releases/tag/v18.8.10)**
-- *2025.09.14*, **[v18.8.9](//github.com/coderaiser/cloudcmd/releases/tag/v18.8.9)**
-- *2025.09.13*, **[v18.8.8](//github.com/coderaiser/cloudcmd/releases/tag/v18.8.8)**
-- *2025.09.12*, **[v18.8.7](//github.com/coderaiser/cloudcmd/releases/tag/v18.8.7)**
-- *2025.09.12*, **[v18.8.6](//github.com/coderaiser/cloudcmd/releases/tag/v18.8.6)**
-- *2025.09.10*, **[v18.8.5](//github.com/coderaiser/cloudcmd/releases/tag/v18.8.5)**
- *2025.09.09*, **[v18.8.4](//github.com/coderaiser/cloudcmd/releases/tag/v18.8.4)**
- *2025.09.04*, **[v18.8.3](//github.com/coderaiser/cloudcmd/releases/tag/v18.8.3)**
- *2025.09.04*, **[v18.8.2](//github.com/coderaiser/cloudcmd/releases/tag/v18.8.2)**
diff --git a/README.md b/README.md
index 8e510161..2f8726cd 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 v18.8.4 [![Build Status][BuildStatusIMGURL]][BuildStatusURL] [![Codacy][CodacyIMG]][CodacyURL] [![Gitter][GitterIMGURL]][GitterURL]
### [Main][MainURL] [Blog][BlogURL] [Support][SupportURL] [Demo][DemoURL]
diff --git a/bin/cloudcmd.mjs b/bin/cloudcmd.mjs
index e1c358ed..11dabd3d 100755
--- a/bin/cloudcmd.mjs
+++ b/bin/cloudcmd.mjs
@@ -3,12 +3,12 @@
import process from 'node:process';
import {createRequire} from 'node:module';
import {promisify} from 'node:util';
-import {tryToCatch} from 'try-to-catch';
+import tryToCatch from 'try-to-catch';
import {createSimport} from 'simport';
import parse from 'yargs-parser';
import exit from '../server/exit.js';
-import {createConfig, configPath} from '../server/config.mjs';
-import * as env from '../server/env.mjs';
+import {createConfig, configPath} from '../server/config.js';
+import env from '../server/env.js';
import prefixer from '../server/prefixer.js';
import * as validate from '../server/validate.mjs';
@@ -101,27 +101,27 @@ const yargsOptions = {
],
default: {
'server': true,
- 'name': choose(env.parse('name'), config('name')),
+ 'name': choose(env('name'), config('name')),
'auth': choose(env.bool('auth'), config('auth')),
'port': config('port'),
'online': config('online'),
'open': choose(env.bool('open'), config('open')),
- 'editor': env.parse('editor') || config('editor'),
- 'menu': env.parse('menu') || config('menu'),
+ 'editor': env('editor') || config('editor'),
+ 'menu': env('menu') || config('menu'),
'packer': config('packer') || 'tar',
'zip': config('zip'),
- 'username': env.parse('username') || config('username'),
- 'root': choose(env.parse('root'), config('root')),
- 'prefix': choose(env.parse('prefix'), config('prefix')),
+ 'username': env('username') || config('username'),
+ 'root': choose(env('root'), config('root')),
+ 'prefix': choose(env('prefix'), config('prefix')),
'console': choose(env.bool('console'), config('console')),
'contact': choose(env.bool('contact'), config('contact')),
'terminal': choose(env.bool('terminal'), config('terminal')),
- 'columns': env.parse('columns') || config('columns') || '',
- 'theme': env.parse('theme') || config('theme') || '',
+ 'columns': env('columns') || config('columns') || '',
+ 'theme': env('theme') || config('theme') || '',
'vim': choose(env.bool('vim'), config('vim')),
'log': config('log'),
- 'import-url': env.parse('import_url') || config('importUrl'),
+ 'import-url': env('import_url') || config('importUrl'),
'import-listen': choose(env.bool('import_listen'), config('importListen')),
'import': choose(env.bool('import'), config('import')),
'export': choose(env.bool('export'), config('export')),
@@ -132,15 +132,15 @@ const yargsOptions = {
'sync-console-path': choose(env.bool('sync_console_path'), config('syncConsolePath')),
'config-dialog': choose(env.bool('config_dialog'), config('configDialog')),
'config-auth': choose(env.bool('config_auth'), config('configAuth')),
- 'terminal-path': env.parse('terminal_path') || config('terminalPath'),
- 'terminal-command': env.parse('terminal_command') || config('terminalCommand'),
+ 'terminal-path': env('terminal_path') || config('terminalPath'),
+ 'terminal-command': env('terminal_command') || config('terminalCommand'),
'terminal-auto-restart': choose(env.bool('terminal_auto_restart'), config('terminalAutoRestart')),
'one-file-panel': choose(env.bool('one_file_panel'), config('oneFilePanel')),
'confirm-copy': choose(env.bool('confirm_copy'), config('confirmCopy')),
'confirm-move': choose(env.bool('confirm_move'), config('confirmMove')),
'keys-panel': env.bool('keys_panel') || config('keysPanel'),
- 'import-token': env.parse('import_token') || config('importToken'),
- 'export-token': env.parse('export_token') || config('exportToken'),
+ 'import-token': env('import_token') || config('importToken'),
+ 'export-token': env('export_token') || config('exportToken'),
'dropbox': config('dropbox'),
'dropbox-token': config('dropboxToken') || '',
@@ -238,7 +238,7 @@ async function main() {
menu: config('menu'),
};
- const password = env.parse('password') || args.password;
+ const password = env('password') || args.password;
if (password)
config('password', await getPassword(password));
diff --git a/bin/release.mjs b/bin/release.mjs
index 004b908e..694eb7da 100755
--- a/bin/release.mjs
+++ b/bin/release.mjs
@@ -2,7 +2,7 @@
import {promisify} from 'node:util';
import process from 'node:process';
-import {tryToCatch} from 'try-to-catch';
+import tryToCatch from 'try-to-catch';
import {createSimport} from 'simport';
import minor from 'minor';
import _place from 'place';
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..5c547deb 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');
+const Key = require('./key');
+
+const {
apiURL,
formatMsg,
buildFromJSON,
-} from '../common/cloudfunc.mjs';
-import {loadModule} from './load-module.mjs';
+} = require('../common/cloudfunc');
+
+const loadModule = require('./load-module');
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 = '';
@@ -146,7 +151,7 @@ function CloudCmdProto({DOM, Listeners}) {
const [kebabModule] = query;
const module = noJS(pascalCase(kebabModule.slice(1)));
- const [, file] = query;
+ const file = query[1];
const current = DOM.getCurrentByName(file);
if (file && !current) {
@@ -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 50%
rename from client/cloudcmd.mjs
rename to client/cloudcmd.js
index 0dac1a03..d4bac384 100644
--- a/client/cloudcmd.mjs
+++ b/client/cloudcmd.js
@@ -1,44 +1,39 @@
-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 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) => {
+ window.Util = require('../common/util');
+ window.CloudFunc = require('../common/cloudfunc');
+
+ window.DOM = require('./dom');
+ window.CloudCmd = require('./client');
await register(config);
- initSortPanel();
- globalThis.CloudCmd.sortPanel = sortPanel;
+ require('./listeners');
+ require('./key');
+ require('./sort');
+
const prefix = getPrefix(config.prefix);
- globalThis.CloudCmd.init(prefix, config);
+ window.CloudCmd.init(prefix, config);
- if (globalThis.CloudCmd.config('menu') === 'aleman')
+ if (window.CloudCmd.config('menu') === 'aleman')
setTimeout(() => {
import('https://esm.sh/@putout/processor-html');
import('https://esm.sh/@putout/bundle');
}, 100);
-}
+};
+window.CloudCmd = module.exports;
function getPrefix(prefix) {
if (!prefix)
@@ -54,7 +49,7 @@ const onUpdateFound = wraptile(async (config) => {
if (isDev)
return;
- const {DOM} = globalThis;
+ const {DOM} = window;
const prefix = getPrefix(config.prefix);
await load.js(`${prefix}/dist/cloudcmd.common.js`);
@@ -63,7 +58,7 @@ const onUpdateFound = wraptile(async (config) => {
console.log('cloudcmd: sw: updated');
DOM.Events.removeAll();
- globalThis.CloudCmd(config);
+ window.CloudCmd(config);
});
async function register(config) {
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 83%
rename from client/dom/current-file.mjs
rename to client/dom/current-file.js
index e55acbe9..1150de2a 100644
--- a/client/dom/current-file.mjs
+++ b/client/dom/current-file.js
@@ -1,8 +1,13 @@
+'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 {atob, btoa} = require('../../common/base64');
+
+const {encode, decode} = require('../../common/entity');
+
+const {getTitle, FS} = require('../../common/cloudfunc');
let Title;
@@ -10,15 +15,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 +44,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 +71,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 +92,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 +103,7 @@ export const getCurrentPath = (currentFile) => {
/**
* get current direcotory name
*/
-export const getCurrentDirName = () => {
+module.exports.getCurrentDirName = () => {
const href = DOM
.getCurrentDirPath()
.replace(/\/$/, '');
@@ -113,7 +116,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 +130,7 @@ export const getParentDirPath = (panel) => {
/**
* get not current direcotory path
*/
-export const getNotCurrentDirPath = () => {
+module.exports.getNotCurrentDirPath = () => {
const panel = DOM.getPanel({
active: false,
});
@@ -140,14 +143,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 +172,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 +219,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 +230,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 +262,7 @@ export const getCurrentByPosition = ({x, y}) => {
*
* @param currentFile
*/
-export const isCurrentFile = (currentFile) => {
+module.exports.isCurrentFile = (currentFile) => {
if (!currentFile)
return false;
@@ -271,7 +274,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,18 +291,18 @@ 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);
- const isZip = path.endsWith('.zip');
+ const isZip = /\.zip$/.test(path);
const isDir = /^directory(-link)?/.test(fileType);
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 68%
rename from client/dom/current-file.spec.mjs
rename to client/dom/current-file.spec.js
index 2a576dce..de1ba2af 100644
--- a/client/dom/current-file.spec.mjs
+++ b/client/dom/current-file.spec.js
@@ -1,18 +1,20 @@
-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);
const {_CURRENT_FILE} = currentFile;
test('current-file: setCurrentName: setAttribute', (t) => {
- const {DOM, CloudCmd} = globalThis;
+ const {DOM, CloudCmd} = global;
- globalThis.DOM = getDOM();
- globalThis.CloudCmd = getCloudCmd();
+ global.DOM = getDOM();
+ global.CloudCmd = getCloudCmd();
const current = create();
const {setAttribute} = current;
@@ -21,17 +23,17 @@ test('current-file: setCurrentName: setAttribute', (t) => {
t.calledWith(setAttribute, ['data-name', 'js-file-aGVsbG8='], 'should call setAttribute');
- globalThis.DOM = DOM;
- globalThis.CloudCmd = CloudCmd;
+ global.DOM = DOM;
+ global.CloudCmd = CloudCmd;
t.end();
});
test('current-file: setCurrentName: setAttribute: cyrillic', (t) => {
- const {DOM, CloudCmd} = globalThis;
+ const {DOM, CloudCmd} = global;
- globalThis.DOM = getDOM();
- globalThis.CloudCmd = getCloudCmd();
+ global.DOM = getDOM();
+ global.CloudCmd = getCloudCmd();
const current = create();
const {setAttribute} = current;
@@ -40,8 +42,8 @@ test('current-file: setCurrentName: setAttribute: cyrillic', (t) => {
t.calledWith(setAttribute, ['data-name', 'js-file-JUQwJUIwJUQwJUI5'], 'should call setAttribute');
- globalThis.DOM = DOM;
- globalThis.CloudCmd = CloudCmd;
+ global.DOM = DOM;
+ global.CloudCmd = CloudCmd;
t.end();
});
@@ -57,12 +59,12 @@ test('current-file: getCurrentName', (t) => {
});
test('current-file: emit', (t) => {
- const {DOM, CloudCmd} = globalThis;
+ const {DOM, CloudCmd} = global;
const emit = stub();
- globalThis.DOM = getDOM();
- globalThis.CloudCmd = getCloudCmd({
+ global.DOM = getDOM();
+ global.CloudCmd = getCloudCmd({
emit,
});
@@ -72,22 +74,22 @@ test('current-file: emit', (t) => {
t.calledWith(emit, ['current-file', current], 'should call emit');
- globalThis.DOM = DOM;
- globalThis.CloudCmd = CloudCmd;
+ global.DOM = DOM;
+ global.CloudCmd = CloudCmd;
t.end();
});
test('current-file: setCurrentName: return', (t) => {
- const {DOM, CloudCmd} = globalThis;
+ const {DOM, CloudCmd} = global;
const link = {};
- globalThis.DOM = getDOM({
+ global.DOM = getDOM({
link,
});
- globalThis.CloudCmd = getCloudCmd();
+ global.CloudCmd = getCloudCmd();
const current = create();
@@ -95,19 +97,19 @@ test('current-file: setCurrentName: return', (t) => {
t.equal(result, link, 'should return link');
- globalThis.DOM = DOM;
- globalThis.CloudCmd = CloudCmd;
+ global.DOM = DOM;
+ global.CloudCmd = CloudCmd;
t.end();
});
test('current-file: getParentDirPath: result', (t) => {
- const {DOM} = globalThis;
+ const {DOM} = global;
const getCurrentDirPath = returns('/D/Films/+++favorite films/');
const getCurrentDirName = returns('+++favorite films');
- globalThis.DOM = getDOM({
+ global.DOM = getDOM({
getCurrentDirPath,
getCurrentDirName,
});
@@ -115,55 +117,55 @@ test('current-file: getParentDirPath: result', (t) => {
const result = currentFile.getParentDirPath();
const expected = '/D/Films/';
- globalThis.DOM = DOM;
+ global.DOM = DOM;
t.equal(result, expected, 'should return parent dir path');
t.end();
});
test('current-file: isCurrentFile: no', (t) => {
- const {DOM, CloudCmd} = globalThis;
+ const {DOM, CloudCmd} = global;
- globalThis.DOM = getDOM();
- globalThis.CloudCmd = getCloudCmd();
+ global.DOM = getDOM();
+ global.CloudCmd = getCloudCmd();
const result = currentFile.isCurrentFile();
- globalThis.DOM = DOM;
- globalThis.CloudCmd = CloudCmd;
+ global.DOM = DOM;
+ global.CloudCmd = CloudCmd;
t.notOk(result);
t.end();
});
test('current-file: isCurrentFile', (t) => {
- const {DOM, CloudCmd} = globalThis;
+ const {DOM, CloudCmd} = global;
const isContainClass = stub();
- globalThis.DOM = getDOM({
+ global.DOM = getDOM({
isContainClass,
});
- globalThis.CloudCmd = getCloudCmd();
+ global.CloudCmd = getCloudCmd();
const current = {};
currentFile.isCurrentFile(current);
- globalThis.DOM = DOM;
- globalThis.CloudCmd = CloudCmd;
+ global.DOM = DOM;
+ global.CloudCmd = CloudCmd;
t.calledWith(isContainClass, [current, _CURRENT_FILE], 'should call isContainClass');
t.end();
});
test('current-file: getCurrentType', (t) => {
- const {DOM, CloudCmd} = globalThis;
+ const {DOM, CloudCmd} = global;
- globalThis.DOM = getDOM();
- globalThis.CloudCmd = getCloudCmd();
+ global.DOM = getDOM();
+ global.CloudCmd = getCloudCmd();
- const {getByDataName} = globalThis.DOM;
+ const {getByDataName} = global.DOM;
getByDataName.returns({
className: 'mini-icon directory',
@@ -173,87 +175,87 @@ test('current-file: getCurrentType', (t) => {
currentFile.getCurrentType(current);
- globalThis.DOM = DOM;
- globalThis.CloudCmd = CloudCmd;
+ global.DOM = DOM;
+ global.CloudCmd = CloudCmd;
t.calledWith(getByDataName, ['js-type', current]);
t.end();
});
test('current-file: isCurrentIsDir: getCurrentType', (t) => {
- const {DOM, CloudCmd} = globalThis;
+ const {DOM, CloudCmd} = global;
- globalThis.DOM = getDOM();
- globalThis.CloudCmd = getCloudCmd();
+ global.DOM = getDOM();
+ global.CloudCmd = getCloudCmd();
- const {getCurrentType} = globalThis.DOM;
+ const {getCurrentType} = global.DOM;
const current = create();
currentFile.isCurrentIsDir(current);
- globalThis.DOM = DOM;
- globalThis.CloudCmd = CloudCmd;
+ global.DOM = DOM;
+ global.CloudCmd = CloudCmd;
t.calledWith(getCurrentType, [current]);
t.end();
});
test('current-file: isCurrentIsDir: directory', (t) => {
- const {DOM, CloudCmd} = globalThis;
+ const {DOM, CloudCmd} = global;
- globalThis.DOM = getDOM({
+ global.DOM = getDOM({
getCurrentType: stub().returns('directory'),
});
- globalThis.CloudCmd = getCloudCmd();
+ global.CloudCmd = getCloudCmd();
const current = create();
const result = currentFile.isCurrentIsDir(current);
- globalThis.DOM = DOM;
- globalThis.CloudCmd = CloudCmd;
+ global.DOM = DOM;
+ global.CloudCmd = CloudCmd;
t.ok(result);
t.end();
});
test('current-file: isCurrentIsDir: directory-link', (t) => {
- const {DOM, CloudCmd} = globalThis;
+ const {DOM, CloudCmd} = global;
- globalThis.DOM = getDOM({
+ global.DOM = getDOM({
getCurrentType: stub().returns('directory-link'),
});
- globalThis.CloudCmd = getCloudCmd();
+ global.CloudCmd = getCloudCmd();
const current = create();
const result = currentFile.isCurrentIsDir(current);
- globalThis.DOM = DOM;
- globalThis.CloudCmd = CloudCmd;
+ global.DOM = DOM;
+ global.CloudCmd = CloudCmd;
t.ok(result);
t.end();
});
test('current-file: isCurrentIsDir: file', (t) => {
- const {DOM, CloudCmd} = globalThis;
+ const {DOM, CloudCmd} = global;
- globalThis.DOM = getDOM({
+ global.DOM = getDOM({
getCurrentType: stub().returns('file'),
});
- globalThis.CloudCmd = getCloudCmd();
+ global.CloudCmd = getCloudCmd();
const current = create();
const result = currentFile.isCurrentIsDir(current);
- globalThis.DOM = DOM;
- globalThis.CloudCmd = CloudCmd;
+ global.DOM = DOM;
+ global.CloudCmd = CloudCmd;
t.notOk(result);
t.end();
@@ -289,7 +291,7 @@ function getDOM(overrides = {}) {
getByDataName = stub(),
isContainClass = stub(),
getCurrentType = stub(),
- getCurrentPath = stub().returns(''),
+ getCurrentPath = stub(),
} = overrides;
return {
diff --git a/client/dom/dialog.js b/client/dom/dialog.js
index eb342221..f4751456 100644
--- a/client/dom/dialog.js
+++ b/client/dom/dialog.js
@@ -1,6 +1,6 @@
'use strict';
-const {tryToCatch} = require('try-to-catch');
+const tryToCatch = require('try-to-catch');
const {
alert,
diff --git a/client/dom/directory.js b/client/dom/directory.js
index bedb7e95..c7cfa386 100644
--- a/client/dom/directory.js
+++ b/client/dom/directory.js
@@ -3,8 +3,8 @@
/* global CloudCmd */
const philip = require('philip');
-const Images = require('./images.mjs');
-const {FS} = require('../../common/cloudfunc.mjs');
+const Images = require('./images');
+const {FS} = require('../../common/cloudfunc');
const DOM = require('.');
const Dialog = require('./dialog');
diff --git a/client/dom/dom-tree.spec.js b/client/dom/dom-tree.spec.js
index 606df179..044e97b0 100644
--- a/client/dom/dom-tree.spec.js
+++ b/client/dom/dom-tree.spec.js
@@ -2,7 +2,7 @@
const test = require('supertape');
const {create} = require('auto-globals');
-const {tryCatch} = require('try-catch');
+const tryCatch = require('try-catch');
const {isContainClass} = require('./dom-tree');
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..bfb4386c 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');
@@ -416,7 +416,7 @@ module.exports.shrinkSelection = () => {
* setting history wrapper
*/
module.exports.setHistory = (data, title, url) => {
- const ret = globalThis.history;
+ const ret = window.history;
const {prefix} = CloudCmd;
url = prefix + url;
@@ -554,7 +554,7 @@ module.exports.getPanel = (options) => {
* then always work with passive
* panel
*/
- if (globalThis.innerWidth < CloudCmd.MIN_ONE_PANEL_WIDTH)
+ if (window.innerWidth < CloudCmd.MIN_ONE_PANEL_WIDTH)
panel = DOM.getByDataName('js-left');
if (!panel)
@@ -729,19 +729,17 @@ module.exports.getPackerExt = (type) => {
return '.tar.gz';
};
-module.exports.goToDirectory = async (overrides = {}) => {
- const {Dialog} = DOM;
- const {prompt = Dialog.prompt, changeDir = CloudCmd.changeDir} = overrides;
-
+module.exports.goToDirectory = async () => {
const msg = 'Go to directory:';
+ const {Dialog} = DOM;
const {dirPath} = CurrentInfo;
- const [cancel, path = dirPath] = await prompt(msg, dirPath);
+ const [cancel, path = dirPath] = await Dialog.prompt(msg, dirPath);
if (cancel)
return;
- await changeDir(path);
+ await CloudCmd.changeDir(path);
};
module.exports.duplicatePanel = async () => {
diff --git a/client/dom/index.spec.js b/client/dom/index.spec.js
index e3a4b4bc..c5843d11 100644
--- a/client/dom/index.spec.js
+++ b/client/dom/index.spec.js
@@ -3,20 +3,30 @@
require('css-modules-require-hook/preset');
const {test, stub} = require('supertape');
-const {getCSSVar, goToDirectory} = require('./index');
+const mockRequire = require('mock-require');
+const {getCSSVar} = require('./index');
+const {reRequire, stopAll} = mockRequire;
-globalThis.CloudCmd = {};
+global.CloudCmd = {};
test('cloudcmd: client: dom: goToDirectory', async (t) => {
const path = '';
+ const {CloudCmd} = global;
const changeDir = stub();
const prompt = stub().returns([null, path]);
- await goToDirectory({
+ CloudCmd.changeDir = changeDir;
+
+ mockRequire('./dialog', {
prompt,
- changeDir,
});
+ const {goToDirectory} = reRequire('.');
+
+ await goToDirectory();
+
+ stopAll();
+
t.calledWith(changeDir, [path]);
t.end();
});
@@ -25,14 +35,14 @@ test('cloudcmd: client: dom: getCSSVar', (t) => {
const body = {};
const getPropertyValue = stub().returns(0);
- globalThis.getComputedStyle = stub().returns({
+ global.getComputedStyle = stub().returns({
getPropertyValue,
});
const result = getCSSVar('hello', {
body,
});
- delete globalThis.getComputedStyle;
+ delete global.getComputedStyle;
t.notOk(result);
t.end();
@@ -42,14 +52,14 @@ test('cloudcmd: client: dom: getCSSVar: 1', (t) => {
const body = {};
const getPropertyValue = stub().returns(1);
- globalThis.getComputedStyle = stub().returns({
+ global.getComputedStyle = stub().returns({
getPropertyValue,
});
const result = getCSSVar('hello', {
body,
});
- delete globalThis.getComputedStyle;
+ delete global.getComputedStyle;
t.ok(result);
t.end();
diff --git a/client/dom/io/index.js b/client/dom/io/index.js
index a17360ae..577c357a 100644
--- a/client/dom/io/index.js
+++ b/client/dom/io/index.js
@@ -1,14 +1,14 @@
'use strict';
-const {FS} = require('../../../common/cloudfunc.mjs');
-const _sendRequest = require('./send-request');
+const {FS} = require('../../../common/cloudfunc');
+const sendRequest = require('./send-request');
const imgPosition = {
top: true,
};
module.exports.delete = async (url, data) => {
- return await _sendRequest({
+ return await sendRequest({
method: 'DELETE',
url: FS + url,
data,
@@ -19,7 +19,7 @@ module.exports.delete = async (url, data) => {
};
module.exports.patch = async (url, data) => {
- return await _sendRequest({
+ return await sendRequest({
method: 'PATCH',
url: FS + url,
data,
@@ -28,7 +28,7 @@ module.exports.patch = async (url, data) => {
};
module.exports.write = async (url, data) => {
- return await _sendRequest({
+ return await sendRequest({
method: 'PUT',
url: FS + url,
data,
@@ -36,11 +36,7 @@ module.exports.write = async (url, data) => {
});
};
-module.exports.createDirectory = async (url, overrides = {}) => {
- const {
- sendRequest = _sendRequest,
- } = overrides;
-
+module.exports.createDirectory = async (url) => {
return await sendRequest({
method: 'PUT',
url: `${FS}${url}?dir`,
@@ -51,7 +47,7 @@ module.exports.createDirectory = async (url, overrides = {}) => {
module.exports.read = async (url, dataType = 'text') => {
const notLog = !url.includes('?');
- return await _sendRequest({
+ return await sendRequest({
method: 'GET',
url: FS + url,
notLog,
@@ -60,7 +56,7 @@ module.exports.read = async (url, dataType = 'text') => {
};
module.exports.copy = async (from, to, names) => {
- return await _sendRequest({
+ return await sendRequest({
method: 'PUT',
url: '/copy',
data: {
@@ -73,7 +69,7 @@ module.exports.copy = async (from, to, names) => {
};
module.exports.pack = async (data) => {
- return await _sendRequest({
+ return await sendRequest({
method: 'PUT',
url: '/pack',
data,
@@ -81,7 +77,7 @@ module.exports.pack = async (data) => {
};
module.exports.extract = async (data) => {
- return await _sendRequest({
+ return await sendRequest({
method: 'PUT',
url: '/extract',
data,
@@ -89,7 +85,7 @@ module.exports.extract = async (data) => {
};
module.exports.move = async (from, to, names) => {
- return await _sendRequest({
+ return await sendRequest({
method: 'PUT',
url: '/move',
data: {
@@ -102,7 +98,7 @@ module.exports.move = async (from, to, names) => {
};
module.exports.rename = async (from, to) => {
- return await _sendRequest({
+ return await sendRequest({
method: 'PUT',
url: '/rename',
data: {
@@ -115,7 +111,7 @@ module.exports.rename = async (from, to) => {
module.exports.Config = {
read: async () => {
- return await _sendRequest({
+ return await sendRequest({
method: 'GET',
url: '/config',
imgPosition,
@@ -124,7 +120,7 @@ module.exports.Config = {
},
write: async (data) => {
- return await _sendRequest({
+ return await sendRequest({
method: 'PATCH',
url: '/config',
data,
@@ -135,7 +131,7 @@ module.exports.Config = {
module.exports.Markdown = {
read: async (url) => {
- return await _sendRequest({
+ return await sendRequest({
method: 'GET',
url: `/markdown${url}`,
imgPosition,
@@ -144,7 +140,7 @@ module.exports.Markdown = {
},
render: async (data) => {
- return await _sendRequest({
+ return await sendRequest({
method: 'PUT',
url: '/markdown',
data,
diff --git a/client/dom/io/index.spec.js b/client/dom/io/index.spec.js
index 19ebe5bd..2212f91a 100644
--- a/client/dom/io/index.spec.js
+++ b/client/dom/io/index.spec.js
@@ -1,14 +1,18 @@
'use strict';
const {test, stub} = require('supertape');
-const io = require('.');
+
+const mockRequire = require('mock-require');
+
+const {reRequire, stopAll} = mockRequire;
test('client: dom: io', (t) => {
const sendRequest = stub();
+ mockRequire('./send-request', sendRequest);
- io.createDirectory('/hello', {
- sendRequest,
- });
+ const io = reRequire('.');
+
+ io.createDirectory('/hello');
const expected = {
imgPosition: {
@@ -18,6 +22,8 @@ test('client: dom: io', (t) => {
url: '/fs/hello?dir',
};
+ stopAll();
+
t.calledWith(sendRequest, [expected]);
t.end();
});
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-remote.js b/client/dom/load-remote.js
index b1b798a8..84c7e329 100644
--- a/client/dom/load-remote.js
+++ b/client/dom/load-remote.js
@@ -4,7 +4,7 @@
const rendy = require('rendy');
const itype = require('itype');
const load = require('load.js');
-const {tryToCatch} = require('try-to-catch');
+const tryToCatch = require('try-to-catch');
const {findObjByNameInArr} = require('../../common/util');
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..5b2e0ff7 100644
--- a/client/dom/operations/rename-current.js
+++ b/client/dom/operations/rename-current.js
@@ -3,29 +3,21 @@
/* global CloudCmd */
const capitalize = require('just-capitalize');
-const _Dialog = require('../dialog');
+const Dialog = require('../dialog');
const Storage = require('../storage');
const RESTful = require('../rest');
-const _currentFile = require('../current-file.mjs');
+const {
+ isCurrentFile,
+ getCurrentName,
+ getCurrentFile,
+ getCurrentByName,
+ getCurrentType,
+ getCurrentDirPath,
+ setCurrentName,
+} = require('../current-file');
-module.exports = async (current, overrides = {}) => {
- const {
- refresh = CloudCmd.refresh,
- Dialog = _Dialog,
- currentFile = _currentFile,
- } = overrides;
-
- const {
- isCurrentFile,
- getCurrentName,
- getCurrentFile,
- getCurrentByName,
- getCurrentType,
- getCurrentDirPath,
- setCurrentName,
- } = currentFile;
-
+module.exports = async (current) => {
if (!isCurrentFile(current))
current = getCurrentFile();
@@ -66,5 +58,5 @@ module.exports = async (current, overrides = {}) => {
setCurrentName(to, current);
Storage.remove(dirPath);
- refresh();
+ CloudCmd.refresh();
};
diff --git a/client/dom/operations/rename-current.spec.js b/client/dom/operations/rename-current.spec.js
index 4a3c7fec..f39ff6bf 100644
--- a/client/dom/operations/rename-current.spec.js
+++ b/client/dom/operations/rename-current.spec.js
@@ -2,20 +2,23 @@
const {test, stub} = require('supertape');
-const renameCurrent = require('./rename-current');
+const mockRequire = require('mock-require');
+
+const {reRequire, stopAll} = mockRequire;
test('cloudcmd: client: dom: renameCurrent: isCurrentFile', async (t) => {
const current = {};
const isCurrentFile = stub();
- const currentFile = stubCurrentFile({
+ mockRequire('../dialog', stubDialog());
+ mockRequire('../current-file', stubCurrentFile({
isCurrentFile,
- });
+ }));
- await renameCurrent(current, {
- Dialog: stubDialog(),
- currentFile,
- });
+ const renameCurrent = reRequire('./rename-current');
+ await renameCurrent(current);
+
+ stopAll();
t.calledWith(isCurrentFile, [current], 'should call isCurrentFile');
t.end();
@@ -24,6 +27,11 @@ test('cloudcmd: client: dom: renameCurrent: isCurrentFile', async (t) => {
test('cloudcmd: client: dom: renameCurrent: file exist', async (t) => {
const current = {};
const name = 'hello';
+ const {CloudCmd} = global;
+
+ global.CloudCmd = {
+ refresh: stub(),
+ };
const prompt = stub().returns([null, name]);
const confirm = stub().returns([true]);
@@ -31,23 +39,25 @@ test('cloudcmd: client: dom: renameCurrent: file exist', async (t) => {
const getCurrentByName = stub().returns(current);
const getCurrentType = stub().returns('directory');
- const Dialog = stubDialog({
+ mockRequire('../dialog', stubDialog({
confirm,
prompt,
- });
+ }));
- const currentFile = stubCurrentFile({
+ mockRequire('../current-file', stubCurrentFile({
getCurrentByName,
getCurrentType,
- });
+ }));
- await renameCurrent(null, {
- Dialog,
- currentFile,
- });
+ const renameCurrent = reRequire('./rename-current');
+ await renameCurrent();
const expected = 'Directory "hello" already exists. Proceed?';
+ global.CloudCmd = CloudCmd;
+
+ stopAll();
+
t.calledWith(confirm, [expected], 'should call confirm');
t.end();
});
diff --git a/client/dom/rest.js b/client/dom/rest.js
index 7596f620..9c638446 100644
--- a/client/dom/rest.js
+++ b/client/dom/rest.js
@@ -1,10 +1,10 @@
'use strict';
-const {tryToCatch} = require('try-to-catch');
+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/storage.spec.js b/client/dom/storage.spec.js
index 0b281ffc..abd7258a 100644
--- a/client/dom/storage.spec.js
+++ b/client/dom/storage.spec.js
@@ -7,58 +7,58 @@ const storage = require('./storage');
const {stringify} = JSON;
test('cloudcmd: client: storage: set', async (t) => {
- const {localStorage} = globalThis;
+ const {localStorage} = global;
const setItem = stub();
- globalThis.localStorage = {
+ global.localStorage = {
setItem,
};
await storage.set('hello', 'world');
- globalThis.localStorage = localStorage;
+ global.localStorage = localStorage;
t.calledWith(setItem, ['hello', 'world'], 'should call setItem');
t.end();
});
test('cloudcmd: client: storage: get', async (t) => {
- const {localStorage} = globalThis;
+ const {localStorage} = global;
const getItem = stub().returns('world');
- globalThis.localStorage = {
+ global.localStorage = {
getItem,
};
const result = await storage.get('hello');
- globalThis.localStorage = localStorage;
+ global.localStorage = localStorage;
t.equal(result, 'world');
t.end();
});
test('cloudcmd: client: storage: getJson', async (t) => {
- const {localStorage} = globalThis;
+ const {localStorage} = global;
const expected = {
hello: 'world',
};
const getItem = stub().returns(stringify(expected));
- globalThis.localStorage = {
+ global.localStorage = {
getItem,
};
const result = await storage.getJson('hello');
- globalThis.localStorage = localStorage;
+ global.localStorage = localStorage;
t.deepEqual(result, expected);
t.end();
});
test('cloudcmd: client: storage: setJson', async (t) => {
- const {localStorage} = globalThis;
+ const {localStorage} = global;
const data = {
hello: 'world',
};
@@ -66,42 +66,42 @@ test('cloudcmd: client: storage: setJson', async (t) => {
const expected = stringify(data);
const setItem = stub();
- globalThis.localStorage = {
+ global.localStorage = {
setItem,
};
await storage.setJson('hello', data);
- globalThis.localStorage = localStorage;
+ global.localStorage = localStorage;
t.calledWith(setItem, ['hello', expected]);
t.end();
});
test('cloudcmd: client: storage: remove', async (t) => {
- const {localStorage} = globalThis;
+ const {localStorage} = global;
const removeItem = stub();
- globalThis.localStorage = {
+ global.localStorage = {
removeItem,
};
await storage.remove('hello');
- globalThis.localStorage = localStorage;
+ global.localStorage = localStorage;
t.calledWith(removeItem, ['hello'], 'should call removeItem');
t.end();
});
test('cloudcmd: client: storage: clear', async (t) => {
- const {localStorage} = globalThis;
+ const {localStorage} = global;
const clear = stub();
- globalThis.localStorage = {
+ global.localStorage = {
clear,
};
await storage.clear();
- globalThis.localStorage = localStorage;
+ global.localStorage = localStorage;
t.calledWithNoArgs(clear, 'should call clear');
t.end();
diff --git a/client/dom/upload-files.js b/client/dom/upload-files.js
index a1206282..7ac460ea 100644
--- a/client/dom/upload-files.js
+++ b/client/dom/upload-files.js
@@ -5,10 +5,10 @@ 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');
+const {FS} = require('../../common/cloudfunc');
const {getCurrentDirPath: getPathWhenRootEmpty} = require('.');
const loadFile = wraptile(_loadFile);
diff --git a/client/get-json-from-file-table.js b/client/get-json-from-file-table.js
new file mode 100644
index 00000000..e6fbc872
--- /dev/null
+++ b/client/get-json-from-file-table.js
@@ -0,0 +1,47 @@
+'use strict';
+
+/* global DOM */
+const Info = DOM.CurrentInfo;
+
+/**
+ * Функция генерирует JSON из html-таблицы файлов и
+ * используеться при первом заходе в корень
+ */
+module.exports = () => {
+ 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);
+
+ const fileTable = {
+ path,
+ files,
+ };
+
+ return fileTable;
+};
diff --git a/client/get-json-from-file-table.mjs b/client/get-json-from-file-table.mjs
deleted file mode 100644
index ea90f366..00000000
--- a/client/get-json-from-file-table.mjs
+++ /dev/null
@@ -1,44 +0,0 @@
-/* global DOM */
-/**
- * Функция генерирует JSON из html-таблицы файлов и
- * используеться при первом заходе в корень
- */
-export const getJsonFromFileTable = () => {
- const Info = DOM.CurrentInfo;
- const path = DOM.getCurrentDirPath();
- const infoFiles = Info.files || [];
-
- const files = infoFiles
- .filter(notParent)
- .map(parse);
-
- const fileTable = {
- path,
- files,
- };
-
- 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 92%
rename from client/key/index.mjs
rename to client/key/index.js
index 64fd1bc3..403e81ff 100644
--- a/client/key/index.mjs
+++ b/client/key/index.js
@@ -1,17 +1,22 @@
-/* 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 = {}) => {
- const {_config, config} = overrides;
+const toggleVim = (keyCode) => {
+ const {_config, config} = CloudCmd;
if (keyCode === KEY.ESC)
_config('vim', !config('vim'));
@@ -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) {
/*
@@ -53,14 +55,7 @@ function getChar(event) {
return [symbol, char];
}
-async function listener(event, overrides = {}) {
- const {
- config = CloudCmd.config,
- _config = CloudCmd._config,
- switchKey = _switchKey,
- vim = _vim,
- } = overrides;
-
+async function listener(event) {
const {keyCode} = event;
// strange chrome bug calles listener twice
@@ -79,12 +74,8 @@ async function listener(event, overrides = {}) {
if (!binder.isBind())
return;
- toggleVim(keyCode, {
- config,
- _config,
- });
-
- const isVim = config('vim');
+ toggleVim(keyCode);
+ const isVim = CloudCmd.config('vim');
if (!isVim && !isNumpad && !alt && !ctrl && !meta && (isBetween || symbol))
return setCurrentByChar(char, Chars);
@@ -121,8 +112,7 @@ function fromCharCode(keyIdentifier) {
return String.fromCharCode(hex);
}
-async function _switchKey(event) {
- const Info = DOM.CurrentInfo;
+async function switchKey(event) {
let i;
let isSelected;
let prev;
diff --git a/client/key/index.spec.js b/client/key/index.spec.js
index d8167079..8ab7a960 100644
--- a/client/key/index.spec.js
+++ b/client/key/index.spec.js
@@ -3,23 +3,27 @@
require('css-modules-require-hook/preset');
const autoGlobals = require('auto-globals');
+const mockRequire = require('mock-require');
const supertape = require('supertape');
const {ESC} = require('./key');
-
-const {Key, _listener} = require('./index.mjs');
-
const {getDOM, getCloudCmd} = require('./vim/globals.fixture');
const test = autoGlobals(supertape);
+const {reRequire, stopAll} = mockRequire;
const {stub} = supertape;
-globalThis.DOM = getDOM();
-globalThis.CloudCmd = getCloudCmd();
+global.DOM = getDOM();
+global.CloudCmd = getCloudCmd();
test('cloudcmd: client: key: enable vim', async (t) => {
const vim = stub();
- const config = stub().returns(true);
- const _config = stub();
+ const {CloudCmd} = global;
+ const {config} = CloudCmd;
+
+ CloudCmd.config = stub().returns(true);
+ CloudCmd._config = stub();
+ mockRequire('./vim', vim);
+ const {_listener, setBind} = reRequire('.');
const event = {
keyCode: ESC,
@@ -27,14 +31,11 @@ test('cloudcmd: client: key: enable vim', async (t) => {
altKey: false,
};
- Key.setBind();
+ setBind();
+ await _listener(event);
- await _listener(event, {
- vim,
- config,
- _config,
- switchKey: stub(),
- });
+ CloudCmd.config = config;
+ stopAll();
t.calledWith(vim, ['Escape', event]);
t.end();
@@ -42,20 +43,25 @@ test('cloudcmd: client: key: enable vim', async (t) => {
test('cloudcmd: client: key: disable vim', async (t) => {
const _config = stub();
- const config = stub();
const event = {
keyCode: ESC,
key: 'Escape',
altKey: false,
};
- Key.setBind();
- await _listener(event, {
- config,
- _config,
- switchKey: stub(),
- });
+ const {CloudCmd} = global;
+ const {config} = CloudCmd;
- t.calledWith(_config, ['vim', true]);
+ global.CloudCmd.config = _config;
+ global.CloudCmd._config = _config;
+
+ const {_listener, setBind} = reRequire('.');
+
+ setBind();
+ await _listener(event);
+
+ CloudCmd.config = config;
+
+ t.calledWith(_config, ['vim']);
t.end();
});
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/find.js b/client/key/vim/find.js
index d8b517c1..43b3d36a 100644
--- a/client/key/vim/find.js
+++ b/client/key/vim/find.js
@@ -1,6 +1,6 @@
'use strict';
-const {fullstore} = require('fullstore');
+const fullstore = require('fullstore');
const limier = require('limier');
const searchStore = fullstore([]);
diff --git a/client/key/vim/find.spec.js b/client/key/vim/find.spec.js
index 74cc7fb1..1b36216b 100644
--- a/client/key/vim/find.spec.js
+++ b/client/key/vim/find.spec.js
@@ -5,7 +5,7 @@ const dir = './';
const {getDOM} = require('./globals.fixture');
-globalThis.DOM = getDOM();
+global.DOM = getDOM();
const {_next, _previous} = require(`${dir}find`);
diff --git a/client/key/vim/index.js b/client/key/vim/index.js
index ddfe49c3..7c94f773 100644
--- a/client/key/vim/index.js
+++ b/client/key/vim/index.js
@@ -9,43 +9,32 @@ const {
selectFileNotParent,
} = require('./set-current');
-module.exports = (key, event, overrides = {}) => {
- const defaults = {
- ...globalThis.DOM,
- ...globalThis.CloudCmd,
- };
-
- const deps = {
- ...defaults,
- ...overrides,
- };
-
+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);
};
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,
- preventDefault = event?.preventDefault?.bind(event),
toggleSelectedFile,
Buffer = {},
- createFindNext = _createFindNext,
} = deps;
return {
- findNext: createFindNext({
- setCurrentByName,
- }),
escape: unselectFiles,
remove: () => {
@@ -111,8 +100,8 @@ const getOperations = (event, deps) => {
},
find: async () => {
- preventDefault();
- const [, value] = await prompt('Find', '');
+ event.preventDefault();
+ const [, value] = await Dialog.prompt('Find', '');
if (!value)
return;
@@ -123,6 +112,11 @@ const getOperations = (event, deps) => {
setCurrentByName(result);
},
+ findNext: () => {
+ const name = finder.findNext();
+ setCurrentByName(name);
+ },
+
findPrevious: () => {
const name = finder.findPrevious();
setCurrentByName(name);
@@ -131,10 +125,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..245e21cc 100644
--- a/client/key/vim/index.spec.js
+++ b/client/key/vim/index.spec.js
@@ -10,13 +10,13 @@ const pathVim = join(dir, 'vim');
const {getDOM, getCloudCmd} = require('./globals.fixture');
-globalThis.DOM = getDOM();
-globalThis.CloudCmd = getCloudCmd();
+global.DOM = getDOM();
+global.CloudCmd = getCloudCmd();
-const vim = require('./index.js');
+const vim = require(pathVim);
const {assign} = Object;
-const {DOM} = globalThis;
+const {DOM} = global;
const {Buffer} = DOM;
const pathFind = join(dir, 'vim', 'find');
const {reRequire, stopAll} = mockRequire;
@@ -520,26 +520,15 @@ test('cloudcmd: client: key: Enter', async (t) => {
test('cloudcmd: client: key: /', (t) => {
const preventDefault = stub();
const element = {};
- const Info = {
- element,
- files: [],
- };
- const getCurrentName = stub().returns('');
+ DOM.CurrentInfo.element = element;
+ DOM.getCurrentName = () => '';
- const event = {
+ vim('/', {
preventDefault,
- };
-
- const prompt = stub().returns([]);
-
- vim('/', event, {
- getCurrentName,
- Info,
- prompt,
});
- t.calledWithNoArgs(preventDefault);
+ t.calledWithNoArgs(preventDefault, 'should call preventDefault');
t.end();
});
@@ -570,13 +559,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();
@@ -602,7 +595,7 @@ test('cloudcmd: client: key: N', (t) => {
test('cloudcmd: client: key: make directory', async (t) => {
const vim = reRequire(pathVim);
- const {DOM} = globalThis;
+ const {DOM} = global;
assign(DOM, {
promptNewDir: stub(),
@@ -622,7 +615,7 @@ test('cloudcmd: client: key: make directory', async (t) => {
test('cloudcmd: client: key: make file', (t) => {
const vim = reRequire(pathVim);
- const {DOM} = globalThis;
+ const {DOM} = global;
assign(DOM, {
promptNewFile: stub(),
@@ -641,30 +634,28 @@ test('cloudcmd: client: key: make file', (t) => {
});
test('cloudcmd: client: vim: terminal', (t) => {
- const CloudCmd = {
+ const {CloudCmd} = global;
+
+ 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) => {
- globalThis.DOM = getDOM();
- globalThis.CloudCmd = getCloudCmd();
+ global.DOM = getDOM();
+ global.CloudCmd = getCloudCmd();
- const {CloudCmd} = globalThis;
+ const {CloudCmd} = global;
assign(CloudCmd, {
EditFileVim: {
diff --git a/client/key/vim/vim.js b/client/key/vim/vim.js
index 175f36ac..99fe2acf 100644
--- a/client/key/vim/vim.js
+++ b/client/key/vim/vim.js
@@ -1,6 +1,6 @@
'use strict';
-const {fullstore} = require('fullstore');
+const fullstore = require('fullstore');
const store = fullstore('');
const visual = fullstore(false);
diff --git a/client/listeners/index.js b/client/listeners/index.js
index c12c62ed..3e824a7b 100644
--- a/client/listeners/index.js
+++ b/client/listeners/index.js
@@ -5,13 +5,12 @@
const exec = require('execon');
const itype = require('itype');
const currify = require('currify');
-const {tryToCatch} = require('try-to-catch');
+const tryToCatch = require('try-to-catch');
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 {FS} = require('../../common/cloudfunc');
const getIndex = currify(require('./get-index'));
@@ -30,8 +29,10 @@ module.exports.init = async () => {
]);
};
+CloudCmd.Listeners = module.exports;
+
const unselect = (event) => {
- const isMac = /Mac/.test(globalThis.navigator.platform);
+ const isMac = /Mac/.test(window.navigator.platform);
const {
shiftKey,
metaKey,
@@ -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)]),
@@ -108,6 +112,8 @@ module.exports.initKeysPanel = () => {
return;
Events.addClick(keysElement, (event) => {
+ event.stopPropagation();
+
const {target} = event;
const {id} = target;
@@ -126,10 +132,7 @@ module.exports.initKeysPanel = () => {
'f6': operation('move'),
'f7': DOM.promptNewDir,
'f8': operation('delete'),
- 'f9': () => {
- event.stopPropagation();
- CloudCmd.Menu.show();
- },
+ 'f9': CloudCmd.Menu.show,
'f10': CloudCmd.Config.show,
'~': CloudCmd.Konsole.show,
'shift~': CloudCmd.Terminal.show,
@@ -163,7 +166,6 @@ function getPathListener(panel) {
}
function isNoCurrent(panel) {
- const Info = DOM.CurrentInfo;
const infoPanel = Info.panel;
if (!infoPanel)
@@ -188,7 +190,6 @@ function decodePath(path) {
}
async function onPathElementClick(panel, event) {
- const Info = DOM.CurrentInfo;
event.preventDefault();
const element = event.target;
@@ -244,7 +245,7 @@ function onClick(event) {
}
function toggleSelect(key, files) {
- const isMac = /Mac/.test(globalThis.navigator.platform);
+ const isMac = /Mac/.test(window.navigator.platform);
if (!key)
throw Error('key should not be undefined!');
@@ -259,7 +260,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 +301,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 +337,6 @@ function getULElement(element) {
}
function setCurrentFileByEvent(event) {
- const Info = DOM.CurrentInfo;
const BUTTON_LEFT = 0;
const key = {
@@ -452,7 +450,7 @@ function dragndrop() {
}
function unload() {
- Events.add(['unload', 'beforeunload'], (event) => {
+ DOM.Events.add(['unload', 'beforeunload'], (event) => {
const {Key} = CloudCmd;
const isBind = Key?.isBind();
@@ -481,8 +479,7 @@ function pop() {
function resize() {
Events.add('resize', () => {
- const Info = DOM.CurrentInfo;
- const is = globalThis.innerWidth < CloudCmd.MIN_ONE_PANEL_WIDTH;
+ const is = window.innerWidth < CloudCmd.MIN_ONE_PANEL_WIDTH;
if (!is)
return;
diff --git a/client/load-module.mjs b/client/load-module.js
similarity index 81%
rename from client/load-module.mjs
rename to client/load-module.js
index 7fc2c328..0ce0cc64 100644
--- a/client/load-module.mjs
+++ b/client/load-module.js
@@ -1,16 +1,18 @@
-/* global CloudCmd */
-import exec from 'execon';
-import {tryToCatch} from 'try-to-catch';
-import {js as loadJS} from 'load.js';
-import pascalCase from 'just-pascal-case';
+'use strict';
+/* global CloudCmd */
+const exec = require('execon');
+const tryToCatch = require('try-to-catch');
+const loadJS = require('load.js').js;
+
+const pascalCase = require('just-pascal-case');
const noJS = (a) => a.replace(/.js$/, '');
/**
* function load modules
* @params = {name, path, func, dobefore, arg}
*/
-export const loadModule = (params) => {
+module.exports = function loadModule(params) {
if (!params)
return;
@@ -49,7 +51,7 @@ export const loadModule = (params) => {
const [e, a] = await tryToCatch(m);
if (e)
- return;
+ return console.error(e);
return await a.show(...args);
};
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..759ea85d 100644
--- a/client/modules/config/index.js
+++ b/client/modules/config/index.js
@@ -8,16 +8,16 @@ const currify = require('currify');
const wraptile = require('wraptile');
const squad = require('squad');
const {promisify} = require('es6-promisify');
-const {tryToCatch} = require('try-to-catch');
+const tryToCatch = require('try-to-catch');
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');
+const {getTitle} = require('../../../common/cloudfunc');
const {Dialog, setTitle} = DOM;
const Name = 'Config';
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-file.js b/client/modules/edit-file.js
index 59050a3c..f631351a 100644
--- a/client/modules/edit-file.js
+++ b/client/modules/edit-file.js
@@ -4,7 +4,7 @@
CloudCmd.EditFile = exports;
const Format = require('format-io');
-const {fullstore} = require('fullstore');
+const fullstore = require('fullstore');
const exec = require('execon');
const supermenu = require('supermenu');
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/edit-names.js b/client/modules/edit-names.js
index 710ed7ea..c2eaac12 100644
--- a/client/modules/edit-names.js
+++ b/client/modules/edit-names.js
@@ -1,17 +1,21 @@
'use strict';
-const {tryToCatch} = require('try-to-catch');
-
/* global CloudCmd, DOM */
CloudCmd.EditNames = exports;
+const currify = require('currify');
const exec = require('execon');
const supermenu = require('supermenu');
-const {multiRename} = require('multi-rename');
+const multiRename = require('multi-rename');
+
+const reject = Promise.reject.bind(Promise);
const Info = DOM.CurrentInfo;
const {Dialog} = DOM;
+const refresh = currify(_refresh);
+const rename = currify(_rename);
+
let Menu;
const ConfigView = {
@@ -89,7 +93,7 @@ function setListeners() {
DOM.Events.addOnce('contextmenu', element, setMenu);
}
-async function applyNames() {
+function applyNames() {
const dir = Info.dirPath;
const from = getActiveNames();
const nameIndex = from.indexOf(Info.name);
@@ -101,18 +105,18 @@ async function applyNames() {
const root = CloudCmd.config('root');
- const response = rename(dir, from, to, root);
- const [error] = await tryToCatch(refresh, to, nameIndex, response);
-
- if (error)
- alert(error);
+ Promise
+ .resolve(root)
+ .then(rename(dir, from, to))
+ .then(refresh(to, nameIndex))
+ .catch(alert);
}
-function refresh(to, nameIndex, res) {
- if (res.status === 404) {
- const error = res.text();
- throw error;
- }
+function _refresh(to, nameIndex, res) {
+ if (res.status === 404)
+ return res
+ .text()
+ .then(reject);
const currentName = to[nameIndex];
@@ -128,7 +132,7 @@ function getDir(root, dir) {
return root + dir;
}
-function rename(path, from, to, root) {
+function _rename(path, from, to, root) {
const dir = getDir(root, path);
const {prefix} = CloudCmd;
@@ -168,8 +172,8 @@ function setMenu(event) {
};
const menuData = {
- 'Save Ctrl+S': async () => {
- await applyNames();
+ 'Save Ctrl+S': () => {
+ applyNames();
hide();
},
'Go To Line Ctrl+G': () => {
@@ -210,7 +214,6 @@ async function isChanged() {
if (!editor.isChanged())
return;
- const [cancel] = await Dialog.confirm(msg);
-
- !cancel && await applyNames();
+ const [, names] = await Dialog.confirm(msg);
+ names && applyNames();
}
diff --git a/client/modules/edit.js b/client/modules/edit.js
index ecefaad8..441aaf62 100644
--- a/client/modules/edit.js
+++ b/client/modules/edit.js
@@ -5,10 +5,10 @@
const montag = require('montag');
const {promisify} = require('es6-promisify');
-const {tryToCatch} = require('try-to-catch');
+const tryToCatch = require('try-to-catch');
const createElement = require('@cloudcmd/create-element');
const load = require('load.js');
-const {MAX_FILE_SIZE: maxSize} = require('../../common/cloudfunc.mjs');
+const {MAX_FILE_SIZE: maxSize} = require('../../common/cloudfunc');
const {time, timeEnd} = require('../../common/util');
const getEditor = () => editor;
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..6993380d 100644
--- a/client/modules/konsole.js
+++ b/client/modules/konsole.js
@@ -8,11 +8,11 @@ CloudCmd.Konsole = exports;
const exec = require('execon');
const currify = require('currify');
-const {tryToCatch} = require('try-to-catch');
+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/menu/cloudmenu.mjs b/client/modules/menu/cloudmenu.mjs
index 1fbe5165..b36ca828 100644
--- a/client/modules/menu/cloudmenu.mjs
+++ b/client/modules/menu/cloudmenu.mjs
@@ -14,7 +14,7 @@ export const createCloudMenu = async (fm, options, menuData) => {
async function loadMenu() {
if (CloudCmd.config('menu') === 'aleman') {
- const {host, protocol} = globalThis.location;
+ const {host, protocol} = window.location;
const url = `${protocol}//${host}/node_modules/aleman/menu/menu.js`;
const {createMenu} = await import(/* webpackIgnore: true */url);
diff --git a/client/modules/menu/index.js b/client/modules/menu/index.js
index facb385a..bc2682f4 100644
--- a/client/modules/menu/index.js
+++ b/client/modules/menu/index.js
@@ -6,7 +6,7 @@ const exec = require('execon');
const wrap = require('wraptile');
const createElement = require('@cloudcmd/create-element');
-const {FS} = require('../../../common/cloudfunc.mjs');
+const {FS} = require('../../../common/cloudfunc');
const {getIdBySrc} = require('../../dom/load');
const RESTful = require('../../dom/rest');
@@ -109,7 +109,6 @@ function getOptions({type}) {
const options = {
icon: true,
- infiniteScroll: false,
beforeClose: Key.setBind,
beforeHide: Key.setBind,
beforeShow: exec.with(beforeShow, func),
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..bf19bda8 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/remove-extension.js b/client/modules/operation/remove-extension.js
index 5e98727d..a8389af3 100644
--- a/client/modules/operation/remove-extension.js
+++ b/client/modules/operation/remove-extension.js
@@ -9,10 +9,10 @@ module.exports = (name) => {
};
function getExtension(name) {
- if (name.endsWith('.tar.gz'))
+ if (/\.tar\.gz$/.test(name))
return '.tar.gz';
- if (name.endsWith('.tar.bz2'))
+ if (/\.tar\.bz2$/.test(name))
return '.tar.bz2';
return getExt(name);
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/polyfill.js b/client/modules/polyfill.js
index ff0e59c5..f5e7dc7a 100644
--- a/client/modules/polyfill.js
+++ b/client/modules/polyfill.js
@@ -1,20 +1,10 @@
'use strict';
+/* global DOM */
require('domtokenlist-shim');
-const _scrollIntoViewIfNeeded = require('scroll-into-view-if-needed');
+const scrollIntoViewIfNeeded = require('scroll-into-view-if-needed');
-globalThis.DOM = globalThis.DOM || {};
-
-const scrollIntoViewIfNeeded = (el, overrides = {}) => {
- const {
- scroll = _scrollIntoViewIfNeeded,
- } = overrides;
-
- return scroll(el, {
- block: 'nearest',
- });
-};
-
-globalThis.DOM.scrollIntoViewIfNeeded = scrollIntoViewIfNeeded;
-module.exports.scrollIntoViewIfNeeded = scrollIntoViewIfNeeded;
+DOM.scrollIntoViewIfNeeded = (el) => scrollIntoViewIfNeeded(el, {
+ block: 'nearest',
+});
diff --git a/client/modules/polyfill.spec.js b/client/modules/polyfill.spec.js
index 79d9dfda..67149e46 100644
--- a/client/modules/polyfill.spec.js
+++ b/client/modules/polyfill.spec.js
@@ -1,15 +1,24 @@
'use strict';
const {test, stub} = require('supertape');
-const {scrollIntoViewIfNeeded} = require('./polyfill');
+
+const mockRequire = require('mock-require');
+
+const {stopAll} = mockRequire;
test('cloudcmd: client: polyfill: scrollIntoViewIfNeaded', (t) => {
+ const {DOM} = global;
const scroll = stub();
const el = {};
- scrollIntoViewIfNeeded(el, {
- scroll,
- });
+ global.DOM = {};
+
+ mockRequire('scroll-into-view-if-needed', scroll);
+ mockRequire.reRequire('./polyfill');
+
+ global.DOM.scrollIntoViewIfNeeded(el);
+ mockRequire.stop('scroll-into-view-if-neaded');
+ global.DOM = DOM;
const args = [
el, {
@@ -17,6 +26,8 @@ test('cloudcmd: client: polyfill: scrollIntoViewIfNeaded', (t) => {
},
];
+ stopAll();
+
t.calledWith(scroll, args, 'should call scrollIntoViewIfNeaded');
t.end();
});
diff --git a/client/modules/terminal-run.js b/client/modules/terminal-run.js
index 4dcf24ac..3e4b857d 100644
--- a/client/modules/terminal-run.js
+++ b/client/modules/terminal-run.js
@@ -2,15 +2,15 @@
/* global CloudCmd, gritty */
const {promisify} = require('es6-promisify');
-const {tryToCatch} = require('try-to-catch');
-const {fullstore} = require('fullstore');
+const tryToCatch = require('try-to-catch');
+const fullstore = require('fullstore');
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;
@@ -33,7 +33,7 @@ const loadAll = async () => {
const [e] = await tryToCatch(load.parallel, [js, css]);
if (e) {
- const src = e.target.src.replace(globalThis.location.href, '');
+ const src = e.target.src.replace(window.location.href, '');
return Dialog.alert(`file ${src} could not be loaded`);
}
diff --git a/client/modules/terminal.js b/client/modules/terminal.js
index 6a355560..d36b700a 100644
--- a/client/modules/terminal.js
+++ b/client/modules/terminal.js
@@ -2,14 +2,14 @@
/* global CloudCmd */
/* global gritty */
-const {tryToCatch} = require('try-to-catch');
+const tryToCatch = require('try-to-catch');
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;
@@ -32,7 +32,7 @@ const loadAll = async () => {
const [e] = await tryToCatch(loadParallel, [js, css]);
if (e) {
- const src = e.target.src.replace(globalThis.location.href, '');
+ const src = e.target.src.replace(window.location.href, '');
return Dialog.alert(`file ${src} could not be loaded`);
}
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..47fbee39 100644
--- a/client/modules/user-menu/index.js
+++ b/client/modules/user-menu/index.js
@@ -5,14 +5,14 @@ require('../../../css/user-menu.css');
const currify = require('currify');
const wraptile = require('wraptile');
-const {fullstore} = require('fullstore');
+const fullstore = require('fullstore');
const load = require('load.js');
const createElement = require('@cloudcmd/create-element');
-const {tryCatch} = require('try-catch');
-const {tryToCatch} = require('try-to-catch');
+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/user-menu/navigate.js b/client/modules/user-menu/navigate.js
index a87801ed..445d47d1 100644
--- a/client/modules/user-menu/navigate.js
+++ b/client/modules/user-menu/navigate.js
@@ -1,6 +1,6 @@
'use strict';
-const {fullstore} = require('fullstore');
+const fullstore = require('fullstore');
const {
J,
diff --git a/client/modules/view/get-type.js b/client/modules/view/get-type.js
index 9fc1df1d..3ac092e0 100644
--- a/client/modules/view/get-type.js
+++ b/client/modules/view/get-type.js
@@ -5,7 +5,7 @@ const testRegExp = currify((name, reg) => reg.test(name));
const getRegExp = (ext) => RegExp(`\\.${ext}$`, 'i');
const isPDF = (a) => /\.pdf$/i.test(a);
-const isHTML = (a) => a.endsWith('.html');
+const isHTML = (a) => /\.html$/.test(a);
const isMarkdown = (a) => /.\.md$/.test(a);
module.exports = (name) => {
diff --git a/client/modules/view/index.js b/client/modules/view/index.js
index 89d68ee4..c6d34d18 100644
--- a/client/modules/view/index.js
+++ b/client/modules/view/index.js
@@ -2,22 +2,19 @@
'use strict';
-const CloudCmd = globalThis.CloudCmd || {};
-const DOM = globalThis.DOM || {};
-
require('../../../css/view.css');
const rendy = require('rendy');
const currify = require('currify');
const wraptile = require('wraptile');
-const {tryToCatch} = require('try-to-catch');
+const tryToCatch = require('try-to-catch');
const load = require('load.js');
-const _modal = require('@cloudcmd/modal');
-const _createElement = require('@cloudcmd/create-element');
+const modal = require('@cloudcmd/modal');
+const createElement = require('@cloudcmd/create-element');
const {time} = require('../../../common/util');
-const {FS} = require('../../../common/cloudfunc.mjs');
+const {FS} = require('../../../common/cloudfunc');
const {
isImage,
@@ -26,8 +23,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';
@@ -116,7 +113,7 @@ async function show(data, options = {}) {
if (!options || options.bindKeys !== false)
Events.addKey(listener);
- El = _createElement('div', {
+ El = createElement('div', {
className: 'view',
notAppend: true,
});
@@ -129,7 +126,7 @@ async function show(data, options = {}) {
else
El.append(data);
- _modal.open(El, initConfig(options));
+ modal.open(El, initConfig(options));
return;
}
@@ -160,11 +157,7 @@ async function show(data, options = {}) {
}
module.exports._createIframe = createIframe;
-function createIframe(src, overrides = {}) {
- const {
- createElement = _createElement,
- } = overrides;
-
+function createIframe(src) {
const element = createElement('iframe', {
src,
width: '100%',
@@ -179,8 +172,7 @@ function createIframe(src, overrides = {}) {
}
module.exports._viewHtml = viewHtml;
-function viewHtml(src, overrides = {}) {
- const {modal = _modal} = overrides;
+function viewHtml(src) {
modal.open(createIframe(src), Config);
}
@@ -192,7 +184,7 @@ function viewPDF(src) {
if (CloudCmd.config('showFileName'))
options.title = Info.name;
- _modal.open(element, options);
+ modal.open(element, options);
}
async function viewMedia(path) {
@@ -213,7 +205,7 @@ async function viewMedia(path) {
},
};
- _modal.open(element, allConfig);
+ modal.open(element, allConfig);
}
async function viewFile() {
@@ -229,7 +221,7 @@ async function viewFile() {
options.title = Info.name;
El.append(element);
- _modal.open(El, options);
+ modal.open(El, options);
}
const copy = (a) => assign({}, a);
@@ -261,7 +253,7 @@ function initConfig(options) {
}
function hide() {
- _modal.close();
+ modal.close();
}
function viewImage(path, prefixURL) {
@@ -294,7 +286,7 @@ function viewImage(path, prefixURL) {
...imageConfig,
};
- _modal.open(titles, config);
+ modal.open(titles, config);
}
async function getMediaElement(src) {
@@ -319,7 +311,7 @@ async function getMediaElement(src) {
name,
});
- const element = _createElement('div', {
+ const element = createElement('div', {
innerHTML,
});
diff --git a/client/modules/view/index.spec.js b/client/modules/view/index.spec.js
index cc46d07d..83e6b476 100644
--- a/client/modules/view/index.spec.js
+++ b/client/modules/view/index.spec.js
@@ -3,20 +3,22 @@
require('css-modules-require-hook/preset');
const autoGlobals = require('auto-globals');
-const {stub} = require('@cloudcmd/stub');
-
+const stub = require('@cloudcmd/stub');
+const mockRequire = require('mock-require');
const test = autoGlobals(require('supertape'));
-const {
- _initConfig,
- _viewHtml,
- _Config,
- _createIframe,
-} = require('.');
+const {reRequire, stopAll} = mockRequire;
test('cloudcmd: client: view: initConfig', (t) => {
let config;
let i = 0;
+ const {CloudCmd, DOM} = global;
+
+ global.CloudCmd = {};
+ global.DOM = {};
+
+ const {_initConfig} = reRequire('.');
+
const afterClose = () => ++i;
const options = {
afterClose,
@@ -28,32 +30,54 @@ test('cloudcmd: client: view: initConfig', (t) => {
config = _initConfig(options);
config.afterClose();
+ global.CloudCmd = CloudCmd;
+ global.DOM = DOM;
+
t.equal(i, 2, 'should not change default config');
t.end();
});
test('cloudcmd: client: view: initConfig: no options', (t) => {
+ const {CloudCmd, DOM} = global;
+
+ global.CloudCmd = {};
+ global.DOM = {};
+
+ const {_initConfig} = reRequire('.');
const config = _initConfig();
+ global.CloudCmd = CloudCmd;
+ global.DOM = DOM;
+
t.equal(typeof config, 'object');
t.end();
});
test('cloudcmd: client: view: html', (t) => {
+ const {CloudCmd, DOM} = global;
+
+ global.CloudCmd = {};
+ global.DOM = {};
const open = stub();
- const modal = {
+
+ mockRequire('@cloudcmd/modal', {
open,
- };
+ });
+
+ const {_viewHtml, _Config} = reRequire('.');
const src = '/hello.html';
- _viewHtml(src, {
- modal,
- });
+ _viewHtml(src);
+
+ global.CloudCmd = CloudCmd;
+ global.DOM = DOM;
const [first] = open.args;
const [arg] = first;
+ stopAll();
+
t.deepEqual(first, [arg, _Config]);
t.end();
});
@@ -65,11 +89,12 @@ test('cloudcmd: client: view: createIframe', (t) => {
};
const createElement = stub().returns(el);
- const src = '/hello.html';
- _createIframe(src, {
- createElement,
- });
+ mockRequire('@cloudcmd/create-element', createElement);
+ const {_createIframe} = reRequire('.');
+
+ const src = '/hello.html';
+ _createIframe(src);
const expected = {
src,
@@ -77,6 +102,8 @@ test('cloudcmd: client: view: createIframe', (t) => {
width: '100%',
};
+ stopAll();
+
t.calledWith(createElement, ['iframe', expected]);
t.end();
});
@@ -89,10 +116,13 @@ test('cloudcmd: client: view: createIframe: returns', (t) => {
const createElement = stub().returns(el);
+ mockRequire('@cloudcmd/create-element', createElement);
+ const {_createIframe} = reRequire('.');
+
const src = '/hello.html';
- const result = _createIframe(src, {
- createElement,
- });
+ const result = _createIframe(src);
+
+ stopAll();
t.equal(result, el);
t.end();
diff --git a/client/modules/view/types.js b/client/modules/view/types.js
index d94dd971..e36fec4d 100644
--- a/client/modules/view/types.js
+++ b/client/modules/view/types.js
@@ -7,7 +7,7 @@ const testRegExp = currify((name, reg) => reg.test(name));
const getRegExp = (ext) => RegExp(`\\.${ext}$`, 'i');
const isPDF = (a) => /\.pdf$/i.test(a);
-const isHTML = (a) => a.endsWith('.html');
+const isHTML = (a) => /\.html$/.test(a);
const isMarkdown = (a) => /.\.md$/.test(a);
module.exports.getType = async (path) => {
diff --git a/client/modules/view/types.spec.js b/client/modules/view/types.spec.js
index d8004f9e..52ed5bad 100644
--- a/client/modules/view/types.spec.js
+++ b/client/modules/view/types.spec.js
@@ -22,9 +22,12 @@ test('cloudcmd: client: view: types: detectType', async (t) => {
headers: [],
});
- globalThis.fetch = fetch;
+ const originalFetch = global.fetch;
+
+ global.fetch = fetch;
await _detectType('/hello');
+ global.fetch = originalFetch;
const expected = ['/hello', {
method: 'HEAD',
}];
@@ -34,13 +37,17 @@ test('cloudcmd: client: view: types: detectType', async (t) => {
});
test('cloudcmd: client: view: types: detectType: found', async (t) => {
- globalThis.fetch = stub().returns({
+ const originalFetch = global.fetch;
+
+ global.fetch = stub().returns({
headers: [
['content-type', 'image/png'],
],
});
const result = await _detectType('/hello');
+ global.fetch = originalFetch;
+
t.equal(result, '.png');
t.end();
});
diff --git a/client/sort.js b/client/sort.js
new file mode 100644
index 00000000..cf9fb4a4
--- /dev/null
+++ b/client/sort.js
@@ -0,0 +1,31 @@
+'use strict';
+
+/* global CloudCmd */
+const DOM = require('./dom');
+
+const Info = DOM.CurrentInfo;
+const {sort, order} = CloudCmd;
+const position = DOM.getPanelPosition();
+let sortPrevious = sort[position];
+
+const {getPanel} = DOM;
+
+CloudCmd.sortPanel = (name, panel = getPanel()) => {
+ const position = panel.dataset.name.replace('js-', '');
+
+ if (name !== sortPrevious)
+ order[position] = 'asc';
+ else if (order[position] === 'asc')
+ order[position] = 'desc';
+ else
+ order[position] = 'asc';
+
+ sortPrevious = name;
+ sort[position] = name;
+ const noCurrent = position !== Info.panelPosition;
+
+ CloudCmd.refresh({
+ panel,
+ noCurrent,
+ });
+};
diff --git a/client/sort.mjs b/client/sort.mjs
deleted file mode 100644
index 73539c81..00000000
--- a/client/sort.mjs
+++ /dev/null
@@ -1,36 +0,0 @@
-/* global CloudCmd */
-import {fullstore} from 'fullstore';
-import DOM from './dom/index.js';
-
-const sortPrevious = fullstore();
-
-const {getPanel} = DOM;
-
-export const initSortPanel = () => {
- const {sort} = CloudCmd;
- const position = DOM.getPanelPosition();
-
- sortPrevious(sort[position]);
-};
-
-export const sortPanel = (name, panel = getPanel()) => {
- const {sort, order} = CloudCmd;
- const Info = DOM.CurrentInfo;
- const position = panel.dataset.name.replace('js-', '');
-
- if (name !== sortPrevious())
- order[position] = 'asc';
- else if (order[position] === 'asc')
- order[position] = 'desc';
- else
- order[position] = 'asc';
-
- sortPrevious(name);
- sort[position] = name;
- const noCurrent = position !== Info.panelPosition;
-
- CloudCmd.refresh({
- panel,
- noCurrent,
- });
-};
diff --git a/client/sw/register.js b/client/sw/register.js
index 0e6db472..12431a82 100644
--- a/client/sw/register.js
+++ b/client/sw/register.js
@@ -1,6 +1,6 @@
'use strict';
-const {tryToCatch} = require('try-to-catch');
+const tryToCatch = require('try-to-catch');
module.exports.registerSW = registerSW;
module.exports.unregisterSW = unregisterSW;
diff --git a/client/sw/register.spec.js b/client/sw/register.spec.js
index 9b42a0e6..c4368c94 100644
--- a/client/sw/register.spec.js
+++ b/client/sw/register.spec.js
@@ -3,18 +3,14 @@
const autoGlobals = require('auto-globals');
const tape = require('supertape');
-const {stub} = require('@cloudcmd/stub');
-
-const {tryCatch} = require('try-catch');
-const {
- listenSW,
- registerSW,
- unregisterSW,
-} = require('./register');
+const stub = require('@cloudcmd/stub');
+const tryCatch = require('try-catch');
+const {reRequire} = require('mock-require');
const test = autoGlobals(tape);
test('sw: listen', (t) => {
+ const {listenSW} = reRequire('./register');
const addEventListener = stub();
const sw = {
addEventListener,
@@ -27,6 +23,7 @@ test('sw: listen', (t) => {
});
test('sw: lesten: no sw', (t) => {
+ const {listenSW} = reRequire('./register');
const [e] = tryCatch(listenSW, null, 'hello', 'world');
t.notOk(e, 'should not throw');
@@ -34,6 +31,8 @@ test('sw: lesten: no sw', (t) => {
});
test('sw: register: registerSW: no serviceWorker', async (t, {navigator}) => {
+ const {registerSW} = reRequire('./register');
+
delete navigator.serviceWorker;
await registerSW();
@@ -47,6 +46,8 @@ test('sw: register: registerSW: no https', async (t, {location, navigator}) => {
location.protocol = 'http:';
+ const {registerSW} = reRequire('./register');
+
await registerSW();
t.notCalled(register, 'should not call register');
@@ -61,6 +62,8 @@ test('sw: register: registerSW: http', async (t, {location, navigator}) => {
const {register} = navigator.serviceWorker;
+ const {registerSW} = reRequire('./register');
+
await registerSW();
t.notCalled(register, 'should not call register');
@@ -76,6 +79,8 @@ test('sw: register: registerSW: https self-signed', async (t, {location, navigat
const {register} = navigator.serviceWorker;
register.throws(Error('Cannot register service worker!'));
+ const {registerSW} = reRequire('./register');
+
const result = await registerSW();
t.notOk(result, 'should not throw');
@@ -86,6 +91,8 @@ test('sw: register: registerSW', async (t, {location, navigator}) => {
location.hostname = 'localhost';
const {register} = navigator.serviceWorker;
+ const {registerSW} = reRequire('./register');
+
await registerSW('/hello');
t.calledWith(register, ['/hello/sw.js'], 'should call register');
@@ -100,6 +107,8 @@ test('sw: register: unregisterSW', async (t, {location, navigator}) => {
register.returns(serviceWorker);
+ const {unregisterSW} = reRequire('./register');
+
await unregisterSW('/hello');
t.calledWith(register, ['/hello/sw.js'], 'should call register');
diff --git a/client/sw/sw.js b/client/sw/sw.js
index e4cad253..15f3e0ad 100644
--- a/client/sw/sw.js
+++ b/client/sw/sw.js
@@ -2,7 +2,7 @@
const process = require('node:process');
const codegen = require('codegen.macro');
-const {tryToCatch} = require('try-to-catch');
+const tryToCatch = require('try-to-catch');
const currify = require('currify');
const isDev = process.env.NODE_ENV === 'development';
@@ -50,14 +50,14 @@ const getRequest = (a, request) => {
return createRequest('/');
};
-globalThis.addEventListener('install', wait(onInstall));
-globalThis.addEventListener('fetch', respondWith(onFetch));
-globalThis.addEventListener('activate', wait(onActivate));
+self.addEventListener('install', wait(onInstall));
+self.addEventListener('fetch', respondWith(onFetch));
+self.addEventListener('activate', wait(onActivate));
async function onActivate() {
console.info(`cloudcmd: sw: activate: ${NAME}`);
- await globalThis.clients.claim();
+ await self.clients.claim();
const keys = await caches.keys();
const deleteCache = caches.delete.bind(caches);
@@ -67,7 +67,7 @@ async function onActivate() {
async function onInstall() {
console.info(`cloudcmd: sw: install: ${NAME}`);
- await globalThis.skipWaiting();
+ await self.skipWaiting();
}
async function onFetch(event) {
diff --git a/common/base64.js b/common/base64.js
new file mode 100644
index 00000000..c1a82c17
--- /dev/null
+++ b/common/base64.js
@@ -0,0 +1,19 @@
+'use strict';
+
+module.exports.btoa = (str) => {
+ if (typeof btoa === 'function')
+ return btoa(str);
+
+ return Buffer
+ .from(str)
+ .toString('base64');
+};
+
+module.exports.atob = (str) => {
+ if (typeof atob === 'function')
+ return atob(str);
+
+ return Buffer
+ .from(str, 'base64')
+ .toString('binary');
+};
diff --git a/common/base64.spec.js b/common/base64.spec.js
new file mode 100644
index 00000000..cc096ee2
--- /dev/null
+++ b/common/base64.spec.js
@@ -0,0 +1,55 @@
+'use strict';
+
+const {test, stub} = require('supertape');
+
+const {btoa, atob} = require('./base64');
+
+test('btoa: browser', (t) => {
+ const btoaOriginal = global.btoa;
+ const btoaStub = stub();
+ const str = 'hello';
+
+ global.btoa = btoaStub;
+
+ btoa(str);
+ global.btoa = btoaOriginal;
+
+ t.calledWith(btoaStub, [str], 'should call global.btoa');
+ t.end();
+});
+
+test('btoa: node', (t) => {
+ const str = 'hello';
+ const expected = 'aGVsbG8=';
+
+ const result = btoa(str);
+
+ t.equal(result, expected, 'should encode base64');
+ t.end();
+});
+
+test('atob: browser', (t) => {
+ const atobOriginal = global.atob;
+ const atobStub = stub();
+
+ const str = 'hello';
+
+ global.atob = atobStub;
+
+ atob(str);
+
+ global.atob = atobOriginal;
+
+ t.calledWith(atobStub, [str], 'should call global.btoa');
+ t.end();
+});
+
+test('atob: node', (t) => {
+ const str = 'aGVsbG8=';
+ const expected = 'hello';
+
+ const result = atob(str);
+
+ t.equal(result, expected, 'should encode base64');
+ t.end();
+});
diff --git a/common/callbackify.spec.js b/common/callbackify.spec.js
index 0a46d9e9..1b742169 100644
--- a/common/callbackify.spec.js
+++ b/common/callbackify.spec.js
@@ -1,7 +1,7 @@
'use strict';
const {promisify} = require('node:util');
-const {tryToCatch} = require('try-to-catch');
+const tryToCatch = require('try-to-catch');
const {test, stub} = require('supertape');
diff --git a/common/cloudfunc.mjs b/common/cloudfunc.js
similarity index 87%
rename from common/cloudfunc.mjs
rename to common/cloudfunc.js
index 00a48360..c906b548 100644
--- a/common/cloudfunc.mjs
+++ b/common/cloudfunc.js
@@ -1,16 +1,17 @@
-import rendy from 'rendy';
-import currify from 'currify';
-import store from 'fullstore';
-import {encode} from './entity.js';
+'use strict';
-export const getHeaderField = currify(_getHeaderField);
+const rendy = require('rendy');
+const currify = require('currify');
+const store = require('fullstore');
+const {encode} = require('./entity');
+const {btoa} = require('./base64');
+
+const getHeaderField = currify(_getHeaderField);
/* КОНСТАНТЫ (общие для клиента и сервера)*/
/* название программы */
const NAME = 'Cloud Commander';
-
-export const FS = '/fs';
-
+const FS = '/fs';
const Path = store();
Path('/');
@@ -22,10 +23,14 @@ const filterOutDotFiles = ({showDotFiles}) => ({name}) => {
return !name.startsWith('.');
};
-export const apiURL = '/api/v1';
-export const MAX_FILE_SIZE = 500 * 1024;
+module.exports.FS = FS;
+module.exports.apiURL = '/api/v1';
+module.exports.MAX_FILE_SIZE = 500 * 1024;
+module.exports.getHeaderField = getHeaderField;
+module.exports.getPathLink = getPathLink;
+module.exports.getDotDot = getDotDot;
-export const formatMsg = (msg, name, status) => {
+module.exports.formatMsg = (msg, name, status) => {
status = status || 'ok';
name = name || '';
@@ -39,7 +44,7 @@ export const formatMsg = (msg, name, status) => {
* Функция возвращает заголовок веб страницы
* @path
*/
-export const getTitle = (options) => {
+module.exports.getTitle = (options) => {
options = options || {};
const {path = Path(), name} = options;
@@ -58,7 +63,7 @@ export const getTitle = (options) => {
* возвращаеться массив каталогов
* @param url - адрес каталога
*/
-export function getPathLink(url, prefix, template) {
+function getPathLink(url, prefix, template) {
if (!url)
throw Error('url could not be empty!');
@@ -104,17 +109,17 @@ export function getPathLink(url, prefix, template) {
return lines.join('');
}
-export function _getDataName(name) {
+const getDataName = (name) => {
const encoded = btoa(encodeURI(name));
return `data-name="js-file-${encoded}" `;
-}
+};
/**
* Функция строит таблицу файлв из JSON-информации о файлах
* @param params - информация о файлах
*
*/
-export const buildFromJSON = (params) => {
+module.exports.buildFromJSON = (params) => {
const {
prefix,
template,
@@ -180,7 +185,7 @@ export const buildFromJSON = (params) => {
name: '..',
});
- const dataName = _getDataName('..');
+ const dataName = getDataName('..');
const attribute = `draggable="true" ${dataName}`;
/* Сохраняем путь к каталогу верхнего уровня*/
@@ -221,7 +226,7 @@ export const buildFromJSON = (params) => {
attribute: getAttribute(file.type),
});
- const dataName = _getDataName(file.name);
+ const dataName = getDataName(file.name);
const attribute = `draggable="true" ${dataName}`;
return rendy(templateFile, {
@@ -257,8 +262,7 @@ function getAttribute(type) {
return 'target="_blank" ';
}
-export const _getSize = getSize;
-
+module.exports._getSize = getSize;
function getSize({size, type}) {
if (type === 'directory')
return '<dir>';
@@ -281,7 +285,7 @@ function _getHeaderField(sort, order, name) {
return `${name}${arrow}`;
}
-export function getDotDot(path) {
+function getDotDot(path) {
// убираем последний слеш и каталог в котором мы сейчас находимся
const lastSlash = path.substr(path, path.lastIndexOf('/'));
const dotDot = lastSlash.substr(lastSlash, lastSlash.lastIndexOf('/'));
diff --git a/common/cloudfunc.spec.mjs b/common/cloudfunc.spec.js
similarity index 89%
rename from common/cloudfunc.spec.mjs
rename to common/cloudfunc.spec.js
index 79ddfedf..e4e06dd7 100644
--- a/common/cloudfunc.spec.mjs
+++ b/common/cloudfunc.spec.js
@@ -1,15 +1,19 @@
-import {readFileSync} from 'node:fs';
-import test from 'supertape';
-import montag from 'montag';
-import * as cheerio from 'cheerio';
-import {
+'use strict';
+
+const {join} = require('node:path');
+const {readFileSync} = require('node:fs');
+
+const test = require('supertape');
+const montag = require('montag');
+const cheerio = require('cheerio');
+
+const {
_getSize,
getPathLink,
buildFromJSON,
- _getDataName,
-} from './cloudfunc.mjs';
+} = require('./cloudfunc');
-const templatePath = new URL('../tmpl/fs', import.meta.url).pathname;
+const templatePath = join(__dirname, '../tmpl/fs');
const template = {
pathLink: readFileSync(`${templatePath}/pathLink.hbs`, 'utf8'),
@@ -171,11 +175,3 @@ test('cloudfunc: buildFromJSON: showDotFiles: false', (t) => {
t.equal(result, expected);
t.end();
});
-
-test('cloudfunc: _getDataName', (t) => {
- const result = _getDataName('s');
- const expected = 'data-name="js-file-cw==" ';
-
- t.equal(result, expected);
- t.end();
-});
diff --git a/common/datetime.spec.js b/common/datetime.spec.js
index cc321d8a..db7a2483 100644
--- a/common/datetime.spec.js
+++ b/common/datetime.spec.js
@@ -1,7 +1,7 @@
'use strict';
const test = require('supertape');
-const {tryCatch} = require('try-catch');
+const tryCatch = require('try-catch');
const datetime = require('./datetime');
@@ -16,11 +16,11 @@ test('common: datetime', (t) => {
});
test('common: datetime: no arg', (t) => {
- const {Date} = globalThis;
+ const {Date} = global;
let called = false;
- globalThis.Date = class extends Date {
+ global.Date = class extends Date {
constructor() {
super();
called = true;
@@ -29,7 +29,7 @@ test('common: datetime: no arg', (t) => {
datetime();
- globalThis.Date = Date;
+ global.Date = Date;
t.ok(called, 'should call new Date');
t.end();
diff --git a/common/try-to-promise-all.js b/common/try-to-promise-all.js
index e839d27e..5c91b026 100644
--- a/common/try-to-promise-all.js
+++ b/common/try-to-promise-all.js
@@ -1,6 +1,6 @@
'use strict';
-const {tryToCatch} = require('try-to-catch');
+const tryToCatch = require('try-to-catch');
const all = Promise.all.bind(Promise);
module.exports = async (a) => {
diff --git a/common/util.spec.js b/common/util.spec.js
index f62cb4ca..ed15bd09 100644
--- a/common/util.spec.js
+++ b/common/util.spec.js
@@ -1,7 +1,8 @@
'use strict';
const test = require('supertape');
-const {tryCatch} = require('try-catch');
+const {reRequire} = require('mock-require');
+const tryCatch = require('try-catch');
const Util = require('./util');
const {
@@ -116,3 +117,15 @@ test('util: escapeRegExp', (t) => {
t.equal(escapeRegExp('#hello'), '\\#hello');
t.end();
});
+
+test('util: scope', (t) => {
+ global.window = {};
+
+ reRequire('./util');
+
+ t.pass('should set window in scope');
+
+ delete global.window;
+
+ t.end();
+});
diff --git a/cssnano.config.mjs b/cssnano.config.js
similarity index 63%
rename from cssnano.config.mjs
rename to cssnano.config.js
index 44abaeaf..91ae5f81 100644
--- a/cssnano.config.mjs
+++ b/cssnano.config.js
@@ -1,7 +1,9 @@
-// used by OptimizeCssAssetsPlugin
-import defaultPreset from 'cssnano-preset-default';
+'use strict';
-export default defaultPreset({
+// used by OptimizeCssAssetsPlugin
+const defaultPreset = require('cssnano-preset-default');
+
+module.exports = defaultPreset({
svgo: {
plugins: [{
convertPathData: false,
diff --git a/deno.json b/deno.json
deleted file mode 100644
index 64c1bde2..00000000
--- a/deno.json
+++ /dev/null
@@ -1,14 +0,0 @@
-{
- "tasks": {
- "start": "deno run -P=cloudcmd bin/cloudcmd.mjs"
- },
- "permissions": {
- "cloudcmd": {
- "env": true,
- "read": true,
- "sys": true,
- "net": true,
- "run": true
- }
- }
-}
diff --git a/eslint.config.mjs b/eslint.config.mjs
index cf7a6a2d..ad22cf4a 100644
--- a/eslint.config.mjs
+++ b/eslint.config.mjs
@@ -19,6 +19,9 @@ export const match = {
'bin/cloudcmd.js': {
'no-console': 'off',
},
+ 'cssnano.config.js': {
+ 'n/no-extraneous-require': 'off',
+ },
};
export default defineConfig([
safeAlign, {
@@ -33,7 +36,9 @@ export default defineConfig([
}, {
files: ['{client,common,static}/**/*.js'],
languageOptions: {
- globals: globals.browser,
+ globals: {
+ ...globals.browser,
+ },
},
},
...matchToFlat(match),
diff --git a/html/index.html b/html/index.html
index 0cfc73c5..53429a06 100644
--- a/html/index.html
+++ b/html/index.html
@@ -42,15 +42,5 @@
-