mirror of
https://github.com/coderaiser/cloudcmd.git
synced 2026-01-23 18:55:26 +00:00
Compare commits
401 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
78e87796df | ||
|
|
75ad4415c4 | ||
|
|
c5d9bd7c1f | ||
|
|
f437a52ff0 | ||
|
|
7192a56e94 | ||
|
|
b9dd4f2676 | ||
|
|
e8cf3c92f9 | ||
|
|
d574a93d6d | ||
|
|
8a769fd512 | ||
|
|
3b409074c1 | ||
|
|
3b6b0b5a5b | ||
|
|
8876f050e0 | ||
|
|
8507282d55 | ||
|
|
f61b21eecc | ||
|
|
242820b7cf | ||
|
|
dd240ba9b2 | ||
|
|
4b945c0047 | ||
|
|
23a6a6981a | ||
|
|
9cebb2416f | ||
|
|
a94fa0d465 | ||
|
|
3bdf47a5bb | ||
|
|
0ccd109a50 | ||
|
|
6b0bd2e1de | ||
|
|
c23a6a12c8 | ||
|
|
a523ef65f5 | ||
|
|
0971ac4e94 | ||
|
|
64654e8d5c | ||
|
|
a063353a27 | ||
|
|
add31607f9 | ||
|
|
e36de00ce8 | ||
|
|
2c1210bbb1 | ||
|
|
85ebf21122 | ||
|
|
450f14614d | ||
|
|
f75bf4a401 | ||
|
|
d979e94927 | ||
|
|
8de9bd0847 | ||
|
|
e178321be9 | ||
|
|
4b84d20bb0 | ||
|
|
6e778a35ba | ||
|
|
e27ef51d43 | ||
|
|
917f585137 | ||
|
|
9950cacad9 | ||
|
|
457e23f31d | ||
|
|
cfa0b5e382 | ||
|
|
f903c5c9c5 | ||
|
|
08dd5ac183 | ||
|
|
9e2c5ac635 | ||
|
|
6856207d0d | ||
|
|
f0dcbe946f | ||
|
|
008279df57 | ||
|
|
dc99417c27 | ||
|
|
12751646fe | ||
|
|
8234201a39 | ||
|
|
4bb7d704b4 | ||
|
|
feb5aad36b | ||
|
|
c231fca334 | ||
|
|
14452d05b6 | ||
|
|
5c1ad5f8ff | ||
|
|
5b4bb90d61 | ||
|
|
5cc6f79d6a | ||
|
|
024bc41345 | ||
|
|
fb115c675e | ||
|
|
53f6f9e76f | ||
|
|
6d21c539d4 | ||
|
|
253389ea7b | ||
|
|
cdf11f7483 | ||
|
|
0ff16314d7 | ||
|
|
cc889bda4f | ||
|
|
43edba8cb8 | ||
|
|
06f3b78256 | ||
|
|
dfcd655780 | ||
|
|
ab20a462db | ||
|
|
2ec57132ed | ||
|
|
0222d177fc | ||
|
|
db0e0aef73 | ||
|
|
14ec19e80a | ||
|
|
e6a00979ff | ||
|
|
5b5352c7d9 | ||
|
|
78ddbd8a39 | ||
|
|
0067653109 | ||
|
|
5a2ac765d4 | ||
|
|
3ceb9a8c59 | ||
|
|
2a525e9bbb | ||
|
|
a49e963dc9 | ||
|
|
1037a1a264 | ||
|
|
8477f3e466 | ||
|
|
e5d004c0af | ||
|
|
836e908e11 | ||
|
|
9fd4a451ab | ||
|
|
f4386a6f0f | ||
|
|
91f9c0a1aa | ||
|
|
babeb9fb85 | ||
|
|
2e667ba693 | ||
|
|
07d18cfe96 | ||
|
|
60c56164b0 | ||
|
|
d8453236c2 | ||
|
|
efe81320e1 | ||
|
|
14e6754be3 | ||
|
|
3033aed2e3 | ||
|
|
5b972e2e4a | ||
|
|
543e08a837 | ||
|
|
2a8109f090 | ||
|
|
39a24028ac | ||
|
|
3f3c644500 | ||
|
|
38dd510158 | ||
|
|
64df81bc45 | ||
|
|
8366b3bbe2 | ||
|
|
66db798c35 | ||
|
|
56ed1cd535 | ||
|
|
c5aed16f63 | ||
|
|
1537fa73fc | ||
|
|
511347d3ef | ||
|
|
c963ffefee | ||
|
|
fc6304a1c6 | ||
|
|
a05ecdb406 | ||
|
|
9e4d66df4d | ||
|
|
3f7e17721e | ||
|
|
50b19dcc44 | ||
|
|
7fb130cdbd | ||
|
|
5970f10a84 | ||
|
|
84a51a932c | ||
|
|
b0360d8ef4 | ||
|
|
00a20129de | ||
|
|
5e657e9bd1 | ||
|
|
2559343eef | ||
|
|
ddf9e45567 | ||
|
|
84bfef562d | ||
|
|
2e7bdb8aa0 | ||
|
|
a2f66951a8 | ||
|
|
03631d95f7 | ||
|
|
1fc57fdb91 | ||
|
|
09408af5dd | ||
|
|
4eb47f9d42 | ||
|
|
4fcaf2885d | ||
|
|
eaea183536 | ||
|
|
c69ec16ef0 | ||
|
|
3cf13a92c0 | ||
|
|
08d13c6d6b | ||
|
|
df79dda4d0 | ||
|
|
b4792fc3f2 | ||
|
|
c164766895 | ||
|
|
0584f4f431 | ||
|
|
67e4b8f0e4 | ||
|
|
876bbfded5 | ||
|
|
15b71c1485 | ||
|
|
d252fe5fcb | ||
|
|
25119ac6ea | ||
|
|
fc20b9a4e1 | ||
|
|
faa2f9c765 | ||
|
|
08b5c6b2b5 | ||
|
|
83a1e527e5 | ||
|
|
a6d18ddb88 | ||
|
|
7db31363ff | ||
|
|
2077468a85 | ||
|
|
e3fcb7f24e | ||
|
|
64e4aba414 | ||
|
|
899266a62a | ||
|
|
d568a4d896 | ||
|
|
884c83eb60 | ||
|
|
b34ee44bb1 | ||
|
|
c3251bf5e1 | ||
|
|
54bbd4e34d | ||
|
|
3d13b9c5f8 | ||
|
|
61107329fc | ||
|
|
f0bc286aea | ||
|
|
8eb724b58c | ||
|
|
784bb2ebdd | ||
|
|
8f52376d3f | ||
|
|
ed31dd2409 | ||
|
|
8200874912 | ||
|
|
4b8568b264 | ||
|
|
de41aec77d | ||
|
|
74f5eb0cae | ||
|
|
1d983e9950 | ||
|
|
f9b3844153 | ||
|
|
546d061068 | ||
|
|
b1e231a5bb | ||
|
|
121b114e89 | ||
|
|
8592cedce0 | ||
|
|
a53ab67b7d | ||
|
|
de2cedd99d | ||
|
|
da545ea418 | ||
|
|
db6e8334b8 | ||
|
|
2f0c1a616c | ||
|
|
e100dcf627 | ||
|
|
76c4000890 | ||
|
|
fb5e5a320f | ||
|
|
8551cd54a6 | ||
|
|
c93803190b | ||
|
|
ddc94adbf1 | ||
|
|
ef42330848 | ||
|
|
a54caa1d7c | ||
|
|
9eafa189a8 | ||
|
|
baaf47e62f | ||
|
|
0d61a972fb | ||
|
|
af77eeed8d | ||
|
|
e99d084728 | ||
|
|
b77e9c91d4 | ||
|
|
4b476a6dff | ||
|
|
2057065dbf | ||
|
|
a87e5ceaf6 | ||
|
|
2eb3dc6692 | ||
|
|
5f0391fc44 | ||
|
|
1679b788c2 | ||
|
|
9a4cf388d3 | ||
|
|
f4b0f92f05 | ||
|
|
4ab4be124b | ||
|
|
99ad0c217d | ||
|
|
8ccec23d6c | ||
|
|
2a97ac66fb | ||
|
|
b26c8bba37 | ||
|
|
4b78d70b5c | ||
|
|
8450bfa611 | ||
|
|
84c6935ae4 | ||
|
|
9f52ed795d | ||
|
|
f7379c0562 | ||
|
|
51f51b54de | ||
|
|
e87418adde | ||
|
|
08ab63d704 | ||
|
|
e7cc9b92ae | ||
|
|
368c9bb814 | ||
|
|
43fd5ed660 | ||
|
|
f774d5b290 | ||
|
|
b0a7fc1648 | ||
|
|
f1193955fb | ||
|
|
2d21001e55 | ||
|
|
99118e65a6 | ||
|
|
8ff0ee6a1a | ||
|
|
ac9a27b333 | ||
|
|
84719365b1 | ||
|
|
34fb175d63 | ||
|
|
dbd8c6ab7c | ||
|
|
716765104c | ||
|
|
51a4cee688 | ||
|
|
b2f113bf0a | ||
|
|
2e02ba46e8 | ||
|
|
38666cbb8b | ||
|
|
53acae1a63 | ||
|
|
e2591061af | ||
|
|
3d52ce80f2 | ||
|
|
a598ef3ed0 | ||
|
|
e71550d557 | ||
|
|
56d621b1ff | ||
|
|
a38b3a79ce | ||
|
|
7ae60605bb | ||
|
|
7492b4bfc7 | ||
|
|
3adfec81c2 | ||
|
|
c68a3a7f07 | ||
|
|
4eaeccba1c | ||
|
|
2dea0a3b2d | ||
|
|
467f0a79c3 | ||
|
|
353a1fb6c1 | ||
|
|
8e98b778bd | ||
|
|
3ad6720f5f | ||
|
|
b0be119474 | ||
|
|
161d4f952b | ||
|
|
301252906f | ||
|
|
ddd1722f39 | ||
|
|
907afc6e4a | ||
|
|
d8da7922d9 | ||
|
|
2fc503f71f | ||
|
|
ad8e55d824 | ||
|
|
5d22722010 | ||
|
|
13cb970a55 | ||
|
|
94ebbf84cb | ||
|
|
100e940e4b | ||
|
|
a6ce6d3953 | ||
|
|
da0e99ad8c | ||
|
|
dff0267239 | ||
|
|
03e3ba6ad8 | ||
|
|
4c73315b5c | ||
|
|
71dc8dd6be | ||
|
|
f2ef160ca8 | ||
|
|
be4f6271f4 | ||
|
|
a733d81441 | ||
|
|
06cf0eebce | ||
|
|
59024eea98 | ||
|
|
62af673117 | ||
|
|
f22120dc38 | ||
|
|
1a0af863a2 | ||
|
|
0446a74d28 | ||
|
|
5562b47d84 | ||
|
|
7309ceff37 | ||
|
|
ac9abbd385 | ||
|
|
4bc5a7834e | ||
|
|
0f5fe2d4fe | ||
|
|
f5015e75e8 | ||
|
|
ddf4542b75 | ||
|
|
9dbd812b3d | ||
|
|
3d03efbe63 | ||
|
|
a522c49c1f | ||
|
|
9ec94dee15 | ||
|
|
62ed8411ae | ||
|
|
75a75365cf | ||
|
|
ac3f20c5d1 | ||
|
|
9109511e95 | ||
|
|
b63d6fccde | ||
|
|
88df2f0518 | ||
|
|
5e93bcca1e | ||
|
|
74d1eb7e28 | ||
|
|
544e30dbf8 | ||
|
|
282b3d5cca | ||
|
|
a6aa9bbc44 | ||
|
|
3140b7f998 | ||
|
|
d70362fbf1 | ||
|
|
6e8348b843 | ||
|
|
61ca7f36a4 | ||
|
|
b5e9ae5ad9 | ||
|
|
ba2d0b36af | ||
|
|
4cc47e30de | ||
|
|
d8451e56aa | ||
|
|
6abf327d0d | ||
|
|
79fb49479e | ||
|
|
2ae6ad34fc | ||
|
|
14d9618a64 | ||
|
|
05ef0ae452 | ||
|
|
883eee96a2 | ||
|
|
9c8c0533a4 | ||
|
|
14d46c007b | ||
|
|
25872c3b11 | ||
|
|
610ba8827f | ||
|
|
154b4bd627 | ||
|
|
c409a2db82 | ||
|
|
52df5bfcf4 | ||
|
|
2428853613 | ||
|
|
6fb2102099 | ||
|
|
37ab7068d9 | ||
|
|
d061aa82ea | ||
|
|
b088b84eb1 | ||
|
|
fceddc20f8 | ||
|
|
f7a6a36696 | ||
|
|
91de9b3d27 | ||
|
|
2d37f6c6e9 | ||
|
|
d75818297b | ||
|
|
faa2cb3f90 | ||
|
|
29914c09f1 | ||
|
|
7f5e5c6825 | ||
|
|
6bc4f3ec26 | ||
|
|
35622082a9 | ||
|
|
65cf97a7be | ||
|
|
cf9ed97c3e | ||
|
|
cc134464a4 | ||
|
|
e3f89e8845 | ||
|
|
c45b23fe55 | ||
|
|
b1f74c0057 | ||
|
|
bf2e8f9a7d | ||
|
|
f5f34a85ea | ||
|
|
04e5d5b7e0 | ||
|
|
3e565109b3 | ||
|
|
770a0812aa | ||
|
|
25d8faea63 | ||
|
|
98e0011e8e | ||
|
|
401a669aca | ||
|
|
4e32241d83 | ||
|
|
cfa3d69538 | ||
|
|
e01ee4575b | ||
|
|
a03185e14e | ||
|
|
564de89333 | ||
|
|
0655988ed7 | ||
|
|
c7f9090126 | ||
|
|
1bef0d4381 | ||
|
|
fcce26d4e1 | ||
|
|
6e99c7e3c5 | ||
|
|
3f83f6f09a | ||
|
|
bf90bf2295 | ||
|
|
043ba29b32 | ||
|
|
95c36b0a37 | ||
|
|
98d3a4cc56 | ||
|
|
46c8accd84 | ||
|
|
57d2f8e93d | ||
|
|
e080a54022 | ||
|
|
eff34215ee | ||
|
|
4503237ac4 | ||
|
|
bf614e1dc9 | ||
|
|
857c97006d | ||
|
|
b2478a8145 | ||
|
|
3c5ca3dca4 | ||
|
|
a92a5a0d34 | ||
|
|
c51ba1d8f6 | ||
|
|
a57833aaf8 | ||
|
|
0bcff30faa | ||
|
|
10d6d2e247 | ||
|
|
2047cb7ad8 | ||
|
|
6b793cca04 | ||
|
|
5fa9fcc57c | ||
|
|
bc617c17ef | ||
|
|
0ecd1853d0 | ||
|
|
dc2d3146a1 | ||
|
|
266aff4ffb | ||
|
|
a407e0c3fa | ||
|
|
97627dc2ff | ||
|
|
683c865eda | ||
|
|
b795a1f5dd | ||
|
|
d928c0b83d | ||
|
|
1d3567f3a3 | ||
|
|
33201dade2 | ||
|
|
5ced36b0d6 | ||
|
|
7ce954503c | ||
|
|
1c73e525ff | ||
|
|
da967f080c | ||
|
|
f0a6109a7d |
198 changed files with 3877 additions and 3006 deletions
|
|
@ -9,7 +9,7 @@ root = true
|
||||||
charset = utf-8
|
charset = utf-8
|
||||||
end_of_line = lf
|
end_of_line = lf
|
||||||
insert_final_newline = true
|
insert_final_newline = true
|
||||||
trim_trailing_whitespace = true
|
trim_trailing_whitespace = false
|
||||||
indent_style = space
|
indent_style = space
|
||||||
indent_size = 4
|
indent_size = 4
|
||||||
|
|
||||||
|
|
|
||||||
42
.eslintrc.js
42
.eslintrc.js
|
|
@ -1,42 +0,0 @@
|
||||||
'use strict';
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
extends: [
|
|
||||||
'plugin:putout/safe',
|
|
||||||
],
|
|
||||||
plugins: [
|
|
||||||
'putout',
|
|
||||||
'n',
|
|
||||||
],
|
|
||||||
rules: {
|
|
||||||
'key-spacing': 'off',
|
|
||||||
},
|
|
||||||
overrides: [{
|
|
||||||
files: ['bin/release.js'],
|
|
||||||
rules: {
|
|
||||||
'no-console': 'off',
|
|
||||||
'n/shebang': 'off',
|
|
||||||
},
|
|
||||||
extends: [
|
|
||||||
'plugin:n/recommended',
|
|
||||||
],
|
|
||||||
}, {
|
|
||||||
files: ['client/dom/index.js'],
|
|
||||||
rules: {
|
|
||||||
'no-multi-spaces': 'off',
|
|
||||||
},
|
|
||||||
}, {
|
|
||||||
files: ['bin/cloudcmd.js'],
|
|
||||||
rules: {
|
|
||||||
'no-console': 'off',
|
|
||||||
},
|
|
||||||
extends: [
|
|
||||||
'plugin:n/recommended',
|
|
||||||
],
|
|
||||||
}, {
|
|
||||||
files: ['{client,common,static}/**/*.js'],
|
|
||||||
env: {
|
|
||||||
browser: true,
|
|
||||||
},
|
|
||||||
}],
|
|
||||||
};
|
|
||||||
1
.github/FUNDING.yml
vendored
1
.github/FUNDING.yml
vendored
|
|
@ -1,4 +1,3 @@
|
||||||
github: coderaiser
|
github: coderaiser
|
||||||
patreon: coderaiser
|
|
||||||
open_collective: cloudcmd
|
open_collective: cloudcmd
|
||||||
ko_fi: coderaiser
|
ko_fi: coderaiser
|
||||||
|
|
|
||||||
11
.github/ISSUE_TEMPLATE.md
vendored
11
.github/ISSUE_TEMPLATE.md
vendored
|
|
@ -1,11 +0,0 @@
|
||||||
<!--
|
|
||||||
Thank you for reporting an issue. Please fill in the template below. If unsure
|
|
||||||
about something, just do as best as you're able.
|
|
||||||
-->
|
|
||||||
|
|
||||||
- **Version** (`cloudcmd -v`):
|
|
||||||
- **Node Version** `node -v`:
|
|
||||||
- **OS** (`uname -a` on Linux):
|
|
||||||
- **Browser name/version**:
|
|
||||||
- **Used Command Line Parameters**:
|
|
||||||
- **Changed Config**:
|
|
||||||
45
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
45
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
|
|
@ -0,0 +1,45 @@
|
||||||
|
---
|
||||||
|
|
||||||
|
name: Bug report
|
||||||
|
about: Create a report to help us improve
|
||||||
|
title: ''
|
||||||
|
labels: needs clarification
|
||||||
|
assignees: coderaiser
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Describe the bug**
|
||||||
|
A clear and concise description of what the bug is.
|
||||||
|
|
||||||
|
**To Reproduce**
|
||||||
|
Steps to reproduce the behavior:
|
||||||
|
|
||||||
|
1. Go to '...'
|
||||||
|
2. Click on '....'
|
||||||
|
3. Scroll down to '....'
|
||||||
|
4. See error
|
||||||
|
|
||||||
|
**Expected behavior**
|
||||||
|
A clear and concise description of what you expected to happen.
|
||||||
|
|
||||||
|
**Screenshots**
|
||||||
|
If applicable, add screenshots to help explain your problem.
|
||||||
|
|
||||||
|
**Desktop (please complete the following information):**
|
||||||
|
|
||||||
|
- **Version** (`cloudcmd -v`):
|
||||||
|
- **Node Version** `node -v`:
|
||||||
|
- **OS** (`uname -a` on Linux):
|
||||||
|
- **Browser name/version**:
|
||||||
|
- **Used Command Line Parameters**:
|
||||||
|
- **Changed Config**:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{}
|
||||||
|
```
|
||||||
|
- [ ] 🎁 **I'm ready to donate on https://opencollective.com/cloudcmd**
|
||||||
|
- [ ] 🎁 **I'm ready to donate on https://ko-fi.com/coderaiser**
|
||||||
|
- [ ] 💪 **I'm willing to work on this issue**
|
||||||
|
|
||||||
|
**Additional context**
|
||||||
|
Add any other context about the problem here.
|
||||||
5
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
5
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
blank_issues_enabled: false
|
||||||
|
contact_links:
|
||||||
|
- name: Stack Overflow
|
||||||
|
url: https://stackoverflow.com/search?q=cloudcmd
|
||||||
|
about: Please ask and answer questions here.
|
||||||
21
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
21
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
---
|
||||||
|
|
||||||
|
name: Feature request
|
||||||
|
about: Suggest an idea for this project
|
||||||
|
title: ''
|
||||||
|
labels: ''
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Is your feature request related to a problem? Please describe.**
|
||||||
|
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||||
|
|
||||||
|
**Describe the solution you'd like**
|
||||||
|
A clear and concise description of what you want to happen.
|
||||||
|
|
||||||
|
**Describe alternatives you've considered**
|
||||||
|
A clear and concise description of any alternative solutions or features you've considered.
|
||||||
|
|
||||||
|
**Additional context**
|
||||||
|
Add any other context or screenshots about the feature request here.
|
||||||
24
.github/ISSUE_TEMPLATE/issue_template.md
vendored
Normal file
24
.github/ISSUE_TEMPLATE/issue_template.md
vendored
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
***
|
||||||
|
|
||||||
|
name: Tracking issue
|
||||||
|
about: Create an issue with bug report or feature request.
|
||||||
|
title: ""
|
||||||
|
labels: needs triage
|
||||||
|
assignees: coderaiser
|
||||||
|
|
||||||
|
***
|
||||||
|
|
||||||
|
- **Version** (`cloudcmd -v`):
|
||||||
|
- **Node Version** `node -v`:
|
||||||
|
- **OS** (`uname -a` on Linux):
|
||||||
|
- **Browser name/version**:
|
||||||
|
- **Used Command Line Parameters**:
|
||||||
|
- **Changed Config**:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{}
|
||||||
|
```
|
||||||
|
|
||||||
|
- [ ] 🎁 **I'm ready to donate on https://opencollective.com/cloudcmd**
|
||||||
|
- [ ] 🎁 **I'm ready to donate on https://ko-fi.com/coderaiser**
|
||||||
|
- [ ] 💪 **I'm willing to work on this issue**
|
||||||
42
.github/workflows/docker.yml
vendored
42
.github/workflows/docker.yml
vendored
|
|
@ -6,39 +6,47 @@ on:
|
||||||
jobs:
|
jobs:
|
||||||
buildx:
|
buildx:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
packages: write
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v5
|
||||||
- uses: oven-sh/setup-bun@v1
|
- uses: oven-sh/setup-bun@v2
|
||||||
with:
|
with:
|
||||||
bun-version: latest
|
bun-version: latest
|
||||||
- name: Use Node.js 18.x
|
- name: Use Node.js 22.x
|
||||||
uses: actions/setup-node@v4
|
uses: actions/setup-node@v6
|
||||||
with:
|
with:
|
||||||
node-version: 18.x
|
node-version: 22.x
|
||||||
- name: Install Redrun
|
- name: Install Redrun
|
||||||
run: bun i yarn redrun -g --no-save
|
run: bun i redrun -g --no-save
|
||||||
- name: NPM Install
|
- name: NPM Install
|
||||||
run: yarn --no-lockfile
|
run: bun i --no-save
|
||||||
- name: Lint
|
- name: Lint
|
||||||
run: redrun lint
|
run: redrun lint
|
||||||
- name: Build
|
- name: Build
|
||||||
id: build
|
id: build
|
||||||
run: >
|
run: |
|
||||||
redrun build
|
redrun build
|
||||||
|
|
||||||
echo "::set-output name=version::$(grep '"version":' package.json -m1 | cut -d\" -f4)"
|
echo "::set-output name=version::$(grep '"version":' package.json -m1 | cut -d\" -f4)"
|
||||||
- name: Set up QEMU
|
- name: Set up QEMU
|
||||||
uses: docker/setup-qemu-action@v2
|
uses: docker/setup-qemu-action@v3
|
||||||
- name: Set up Docker Buildx
|
- name: Set up Docker Buildx
|
||||||
uses: docker/setup-buildx-action@v2
|
uses: docker/setup-buildx-action@v3
|
||||||
- name: Login to DockerHub
|
- name: Login to DockerHub
|
||||||
uses: docker/login-action@v2
|
uses: docker/login-action@v3
|
||||||
with:
|
with:
|
||||||
username: ${{ secrets.DOCKER_USERNAME }}
|
username: ${{ secrets.DOCKER_USERNAME }}
|
||||||
password: ${{ secrets.DOCKER_TOKEN }}
|
password: ${{ secrets.DOCKER_TOKEN }}
|
||||||
|
- name: Login to GitHub Container Registry
|
||||||
|
uses: docker/login-action@v3
|
||||||
|
with:
|
||||||
|
registry: ghcr.io
|
||||||
|
username: ${{ github.actor }}
|
||||||
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
- name: Build and push base-image
|
- name: Build and push base-image
|
||||||
uses: docker/build-push-action@v4
|
uses: docker/build-push-action@v5
|
||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
file: docker/Dockerfile
|
file: docker/Dockerfile
|
||||||
|
|
@ -47,13 +55,17 @@ jobs:
|
||||||
tags: |
|
tags: |
|
||||||
coderaiser/cloudcmd:latest
|
coderaiser/cloudcmd:latest
|
||||||
coderaiser/cloudcmd:${{ steps.build.outputs.version }}
|
coderaiser/cloudcmd:${{ steps.build.outputs.version }}
|
||||||
|
ghcr.io/${{ github.repository }}:latest
|
||||||
|
ghcr.io/${{ github.repository }}:${{ steps.build.outputs.version }}
|
||||||
- name: Build and push alpine-image
|
- name: Build and push alpine-image
|
||||||
uses: docker/build-push-action@v4
|
uses: docker/build-push-action@v5
|
||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
file: docker/Dockerfile.alpine
|
file: docker/Dockerfile.alpine
|
||||||
platforms: linux/amd64,linux/arm/v7,linux/arm64
|
platforms: linux/amd64,linux/arm64
|
||||||
push: true
|
push: true
|
||||||
tags: |
|
tags: |
|
||||||
coderaiser/cloudcmd:latest-alpine
|
coderaiser/cloudcmd:latest-alpine
|
||||||
coderaiser/cloudcmd:${{ steps.build.outputs.version }}-alpine
|
coderaiser/cloudcmd:${{ steps.build.outputs.version }}-alpine
|
||||||
|
ghcr.io/${{ github.repository }}:latest-alpine
|
||||||
|
ghcr.io/${{ github.repository }}:${{ steps.build.outputs.version }}-alpine
|
||||||
|
|
|
||||||
17
.github/workflows/nodejs.yml
vendored
17
.github/workflows/nodejs.yml
vendored
|
|
@ -9,24 +9,25 @@ jobs:
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
node-version:
|
node-version:
|
||||||
- 18.x
|
- 22.x
|
||||||
- 20.x
|
- 24.x
|
||||||
|
- 25.x
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v5
|
||||||
- uses: oven-sh/setup-bun@v1
|
- uses: oven-sh/setup-bun@v2
|
||||||
with:
|
with:
|
||||||
bun-version: latest
|
bun-version: latest
|
||||||
- name: Use Node.js ${{ matrix.node-version }}
|
- name: Use Node.js ${{ matrix.node-version }}
|
||||||
uses: actions/setup-node@v4
|
uses: actions/setup-node@v6
|
||||||
with:
|
with:
|
||||||
node-version: ${{ matrix.node-version }}
|
node-version: ${{ matrix.node-version }}
|
||||||
- name: Install Redrun
|
- name: Install Redrun
|
||||||
run: bun i yarn redrun -g --no-save
|
run: bun i redrun -g --no-save
|
||||||
- name: Install
|
- name: Install
|
||||||
run: yarn --no-lockfile
|
run: bun i --no-save
|
||||||
- name: Lint
|
- name: Lint
|
||||||
run: redrun fix:lint
|
run: redrun fix:lint
|
||||||
- uses: actions/cache@v3
|
- uses: actions/cache@v4
|
||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
~/.cargo/bin/
|
~/.cargo/bin/
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,7 @@
|
||||||
import {
|
|
||||||
run,
|
|
||||||
cutEnv,
|
|
||||||
} from 'madrun';
|
|
||||||
import process from 'node:process';
|
import process from 'node:process';
|
||||||
|
import {run, cutEnv} from 'madrun';
|
||||||
|
|
||||||
const testEnv = {
|
const testEnv = {
|
||||||
THREAD_IT_COUNT: 0,
|
|
||||||
SUPERTAPE_TIMEOUT: 7000,
|
SUPERTAPE_TIMEOUT: 7000,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -19,6 +15,7 @@ const is20 = process.version.startsWith('v2');
|
||||||
// https://stackoverflow.com/a/69746937/4536327
|
// https://stackoverflow.com/a/69746937/4536327
|
||||||
const buildEnv = (is17 || is20) && {
|
const buildEnv = (is17 || is20) && {
|
||||||
NODE_OPTIONS: '--openssl-legacy-provider',
|
NODE_OPTIONS: '--openssl-legacy-provider',
|
||||||
|
NODE_ENV: 'production',
|
||||||
};
|
};
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
|
@ -36,7 +33,7 @@ export default {
|
||||||
'lint:fresh': () => run('lint', '--fresh'),
|
'lint:fresh': () => run('lint', '--fresh'),
|
||||||
'fix:lint': () => run('lint', '--fix'),
|
'fix:lint': () => run('lint', '--fix'),
|
||||||
'lint:stream': () => run('lint', '-f stream'),
|
'lint:stream': () => run('lint', '-f stream'),
|
||||||
'test': () => [testEnv, `tape 'test/**/*.js' '{client,static,common,server}/**/*.spec.js' -f fail`],
|
'test': () => [testEnv, `tape 'test/**/*.{js,mjs}' '{client,static,common,server}/**/*.spec.{js,mjs}' -f fail`],
|
||||||
'test:client': () => `tape 'test/client/**/*.js'`,
|
'test:client': () => `tape 'test/client/**/*.js'`,
|
||||||
'test:server': () => `tape 'test/**/*.js' 'server/**/*.spec.js' 'common/**/*.spec.js'`,
|
'test:server': () => `tape 'test/**/*.js' 'server/**/*.spec.js' 'common/**/*.spec.js'`,
|
||||||
'wisdom': () => run(['lint:all', 'build', 'test']),
|
'wisdom': () => run(['lint:all', 'build', 'test']),
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
.*
|
.*
|
||||||
*.spec.js
|
*.spec.*
|
||||||
|
*.config.*
|
||||||
*.fixture.js*
|
*.fixture.js*
|
||||||
manifest.yml
|
manifest.yml
|
||||||
docker
|
docker
|
||||||
|
|
@ -13,13 +14,13 @@ html
|
||||||
yarn-error.log
|
yarn-error.log
|
||||||
yarn.lock
|
yarn.lock
|
||||||
now.json
|
now.json
|
||||||
cssnano.config.js
|
|
||||||
|
|
||||||
app.json
|
app.json
|
||||||
bower.json
|
bower.json
|
||||||
manifest.yml
|
manifest.yml
|
||||||
|
deno.json
|
||||||
|
|
||||||
bin/release.js
|
bin/release.mjs
|
||||||
|
|
||||||
client
|
client
|
||||||
img/logo/cloudcmd-hq.png
|
img/logo/cloudcmd-hq.png
|
||||||
|
|
@ -30,3 +31,4 @@ webpack.config.js
|
||||||
*.cdr
|
*.cdr
|
||||||
*.eps
|
*.eps
|
||||||
|
|
||||||
|
*.config.*
|
||||||
|
|
|
||||||
1
.nvmrc
Normal file
1
.nvmrc
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
v20.15.1
|
||||||
|
|
@ -4,7 +4,9 @@
|
||||||
"exclude": [
|
"exclude": [
|
||||||
"**/*.spec.js",
|
"**/*.spec.js",
|
||||||
"**/fixture",
|
"**/fixture",
|
||||||
"**/*.*.js"
|
"**/*.*.js",
|
||||||
|
"**/*.config.*",
|
||||||
|
"**/test/**"
|
||||||
],
|
],
|
||||||
"branches": 100,
|
"branches": 100,
|
||||||
"lines": 100,
|
"lines": 100,
|
||||||
|
|
|
||||||
21
.putout.json
21
.putout.json
|
|
@ -4,20 +4,15 @@
|
||||||
"html",
|
"html",
|
||||||
"fixture*",
|
"fixture*",
|
||||||
"app.json",
|
"app.json",
|
||||||
"fontello.json"
|
"fontello.json",
|
||||||
|
"*.md"
|
||||||
],
|
],
|
||||||
"rules": {
|
"rules": {
|
||||||
"github/convert-npm-to-bun": "off",
|
"package-json/add-type": "off"
|
||||||
"github/set-node-versions": ["on", {
|
|
||||||
"versions": [
|
|
||||||
"18.x",
|
|
||||||
"20.x"
|
|
||||||
]
|
|
||||||
}]
|
|
||||||
},
|
},
|
||||||
"match": {
|
"match": {
|
||||||
"base64": {
|
"base64": {
|
||||||
"convert-typeof-to-is-type": "off"
|
"types/convert-typeof-to-is-type": "off"
|
||||||
},
|
},
|
||||||
"*.md": {
|
"*.md": {
|
||||||
"nodejs/convert-commonjs-to-esm": "on"
|
"nodejs/convert-commonjs-to-esm": "on"
|
||||||
|
|
@ -34,9 +29,12 @@
|
||||||
"server/{server,exit,terminal,distribute/log}.{js,mjs}": {
|
"server/{server,exit,terminal,distribute/log}.{js,mjs}": {
|
||||||
"remove-console": "off"
|
"remove-console": "off"
|
||||||
},
|
},
|
||||||
"client/{client,cloudcmd,load-module}.js": {
|
"client/{client,cloudcmd,load-module}.{js,mjs}": {
|
||||||
"remove-console": "off"
|
"remove-console": "off"
|
||||||
},
|
},
|
||||||
|
"client": {
|
||||||
|
"nodejs": "off"
|
||||||
|
},
|
||||||
"client/sw": {
|
"client/sw": {
|
||||||
"remove-console": "off"
|
"remove-console": "off"
|
||||||
},
|
},
|
||||||
|
|
@ -51,6 +49,9 @@
|
||||||
},
|
},
|
||||||
"vim.js": {
|
"vim.js": {
|
||||||
"merge-duplicate-functions": "off"
|
"merge-duplicate-functions": "off"
|
||||||
|
},
|
||||||
|
"common": {
|
||||||
|
"nodejs/declare": "off"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,76 +0,0 @@
|
||||||
'use strict';
|
|
||||||
|
|
||||||
const fs = require('fs');
|
|
||||||
const {
|
|
||||||
basename,
|
|
||||||
extname,
|
|
||||||
join,
|
|
||||||
} = require('path');
|
|
||||||
|
|
||||||
const ExtractTextPlugin = require('extract-text-webpack-plugin');
|
|
||||||
const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin');
|
|
||||||
|
|
||||||
const {env} = require('process');
|
|
||||||
const isDev = env.NODE_ENV === 'development';
|
|
||||||
|
|
||||||
const extractCSS = (a) => new ExtractTextPlugin(`${a}.css`);
|
|
||||||
const extractMain = extractCSS('[name]');
|
|
||||||
|
|
||||||
const cssNames = [
|
|
||||||
'nojs',
|
|
||||||
'view',
|
|
||||||
'config',
|
|
||||||
'terminal',
|
|
||||||
'user-menu',
|
|
||||||
...getCSSList('columns'),
|
|
||||||
];
|
|
||||||
|
|
||||||
const cssPlugins = cssNames.map(extractCSS);
|
|
||||||
const clean = (a) => a.filter(Boolean);
|
|
||||||
|
|
||||||
const plugins = clean([
|
|
||||||
...cssPlugins,
|
|
||||||
extractMain,
|
|
||||||
!isDev && new OptimizeCssAssetsPlugin(),
|
|
||||||
]);
|
|
||||||
|
|
||||||
const rules = [{
|
|
||||||
test: /\.css$/,
|
|
||||||
exclude: /css\/(nojs|view|config|terminal|user-menu|columns.*)\.css/,
|
|
||||||
use: extractMain.extract(['css-loader']),
|
|
||||||
}, ...cssPlugins.map(extract), {
|
|
||||||
test: /\.(png|gif|svg|woff|woff2|eot|ttf)$/,
|
|
||||||
use: {
|
|
||||||
loader: 'url-loader',
|
|
||||||
options: {
|
|
||||||
limit: 100_000,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}];
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
plugins,
|
|
||||||
module: {
|
|
||||||
rules,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
function getCSSList(dir) {
|
|
||||||
const base = (a) => basename(a, extname(a));
|
|
||||||
const addDir = (name) => `${dir}/${name}`;
|
|
||||||
const rootDir = join(__dirname, '..');
|
|
||||||
|
|
||||||
return fs
|
|
||||||
.readdirSync(`${rootDir}/css/${dir}`)
|
|
||||||
.map(base)
|
|
||||||
.map(addDir);
|
|
||||||
}
|
|
||||||
|
|
||||||
function extract(extractPlugin) {
|
|
||||||
const {filename} = extractPlugin;
|
|
||||||
|
|
||||||
return {
|
|
||||||
test: RegExp(`css/${filename}`),
|
|
||||||
use: extractPlugin.extract(['css-loader']),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
34
.webpack/css.mjs
Normal file
34
.webpack/css.mjs
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
import {env} from 'node:process';
|
||||||
|
import OptimizeCssAssetsPlugin from 'optimize-css-assets-webpack-plugin';
|
||||||
|
import MiniCssExtractPlugin from 'mini-css-extract-plugin';
|
||||||
|
|
||||||
|
const isDev = env.NODE_ENV === 'development';
|
||||||
|
|
||||||
|
const clean = (a) => a.filter(Boolean);
|
||||||
|
|
||||||
|
const plugins = clean([
|
||||||
|
new MiniCssExtractPlugin({
|
||||||
|
filename: '[name].css',
|
||||||
|
}),
|
||||||
|
!isDev && new OptimizeCssAssetsPlugin(),
|
||||||
|
]);
|
||||||
|
|
||||||
|
const rules = [{
|
||||||
|
test: /\.css$/i,
|
||||||
|
use: [MiniCssExtractPlugin.loader, {
|
||||||
|
loader: 'css-loader',
|
||||||
|
options: {
|
||||||
|
url: true,
|
||||||
|
},
|
||||||
|
}],
|
||||||
|
}, {
|
||||||
|
test: /\.(png|gif|svg|woff|woff2|eot|ttf)$/,
|
||||||
|
type: 'asset/inline',
|
||||||
|
}];
|
||||||
|
|
||||||
|
export default {
|
||||||
|
plugins,
|
||||||
|
module: {
|
||||||
|
rules,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
@ -1,11 +1,9 @@
|
||||||
'use strict';
|
import {env} from 'node:process';
|
||||||
|
import HtmlWebpackPlugin from 'html-webpack-plugin';
|
||||||
const HtmlWebpackPlugin = require('html-webpack-plugin');
|
|
||||||
const {env} = require('process');
|
|
||||||
|
|
||||||
const isDev = env.NODE_ENV === 'development';
|
const isDev = env.NODE_ENV === 'development';
|
||||||
|
|
||||||
const plugins = [
|
export const plugins = [
|
||||||
new HtmlWebpackPlugin({
|
new HtmlWebpackPlugin({
|
||||||
inject: false,
|
inject: false,
|
||||||
template: 'html/index.html',
|
template: 'html/index.html',
|
||||||
|
|
@ -13,10 +11,6 @@ const plugins = [
|
||||||
}),
|
}),
|
||||||
];
|
];
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
plugins,
|
|
||||||
};
|
|
||||||
|
|
||||||
function getMinifyHtmlOptions() {
|
function getMinifyHtmlOptions() {
|
||||||
return {
|
return {
|
||||||
removeComments: true,
|
removeComments: true,
|
||||||
|
|
@ -1,24 +1,23 @@
|
||||||
'use strict';
|
import {resolve, sep} from 'node:path';
|
||||||
|
import {env} from 'node:process';
|
||||||
|
import webpack from 'webpack';
|
||||||
|
import WebpackBar from 'webpackbar';
|
||||||
|
|
||||||
const {
|
const {
|
||||||
resolve,
|
EnvironmentPlugin,
|
||||||
sep,
|
NormalModuleReplacementPlugin,
|
||||||
join,
|
} = webpack;
|
||||||
} = require('path');
|
|
||||||
|
|
||||||
const {EnvironmentPlugin} = require('webpack');
|
|
||||||
const WebpackBar = require('webpackbar');
|
|
||||||
|
|
||||||
const ServiceWorkerWebpackPlugin = require('serviceworker-webpack-plugin');
|
|
||||||
|
|
||||||
const {env} = require('process');
|
|
||||||
const modules = './modules';
|
const modules = './modules';
|
||||||
const dirModules = './client/modules';
|
const dirModules = './client/modules';
|
||||||
|
const dirCss = './css';
|
||||||
|
const dirThemes = `${dirCss}/themes`;
|
||||||
|
const dirColumns = `${dirCss}/columns`;
|
||||||
const dir = './client';
|
const dir = './client';
|
||||||
const {NODE_ENV} = env;
|
const {NODE_ENV} = env;
|
||||||
const isDev = NODE_ENV === 'development';
|
const isDev = NODE_ENV === 'development';
|
||||||
|
|
||||||
const rootDir = join(__dirname, '..');
|
const rootDir = new URL('..', import.meta.url).pathname;
|
||||||
const dist = resolve(rootDir, 'dist');
|
const dist = resolve(rootDir, 'dist');
|
||||||
const distDev = resolve(rootDir, 'dist-dev');
|
const distDev = resolve(rootDir, 'dist-dev');
|
||||||
const devtool = isDev ? 'eval' : 'source-map';
|
const devtool = isDev ? 'eval' : 'source-map';
|
||||||
|
|
@ -26,9 +25,7 @@ const devtool = isDev ? 'eval' : 'source-map';
|
||||||
const notEmpty = (a) => a;
|
const notEmpty = (a) => a;
|
||||||
const clean = (array) => array.filter(notEmpty);
|
const clean = (array) => array.filter(notEmpty);
|
||||||
|
|
||||||
const noParse = (a) => /\.spec\.js$/.test(a);
|
const noParse = (a) => a.endsWith('.spec.js');
|
||||||
const convertToWebpack5Externals = (fn) => (context, request, cb) => fn({context, request}, cb);
|
|
||||||
|
|
||||||
const options = {
|
const options = {
|
||||||
babelrc: true,
|
babelrc: true,
|
||||||
};
|
};
|
||||||
|
|
@ -48,44 +45,89 @@ const rules = clean([
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const plugins = [
|
const plugins = [
|
||||||
|
new NormalModuleReplacementPlugin(/^node:/, (resource) => {
|
||||||
|
resource.request = resource.request.replace(/^node:/, '');
|
||||||
|
}),
|
||||||
|
new NormalModuleReplacementPlugin(/^putout$/, '@putout/bundle'),
|
||||||
new EnvironmentPlugin({
|
new EnvironmentPlugin({
|
||||||
NODE_ENV,
|
NODE_ENV,
|
||||||
}),
|
}),
|
||||||
new ServiceWorkerWebpackPlugin({
|
|
||||||
entry: join(__dirname, '..', 'client', 'sw', 'sw.js'),
|
|
||||||
excludes: ['*'],
|
|
||||||
}),
|
|
||||||
new WebpackBar(),
|
new WebpackBar(),
|
||||||
];
|
];
|
||||||
|
|
||||||
const splitChunks = {
|
const splitChunks = {
|
||||||
name: 'cloudcmd.common',
|
|
||||||
chunks: 'all',
|
chunks: 'all',
|
||||||
|
cacheGroups: {
|
||||||
|
abcCommon: {
|
||||||
|
name: 'cloudcmd.common',
|
||||||
|
chunks: (chunk) => {
|
||||||
|
const lazyChunks = [
|
||||||
|
'sw',
|
||||||
|
'nojs',
|
||||||
|
'view',
|
||||||
|
'edit',
|
||||||
|
'terminal',
|
||||||
|
'config',
|
||||||
|
'user-menu',
|
||||||
|
'help',
|
||||||
|
'themes/dark',
|
||||||
|
'themes/light',
|
||||||
|
'columns/name-size',
|
||||||
|
'columns/name-size-date',
|
||||||
|
];
|
||||||
|
|
||||||
|
return !lazyChunks.includes(chunk.name);
|
||||||
|
},
|
||||||
|
minChunks: 1,
|
||||||
|
enforce: true,
|
||||||
|
priority: -1,
|
||||||
|
reuseExistingChunk: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = {
|
export default {
|
||||||
resolve: {
|
resolve: {
|
||||||
symlinks: false,
|
symlinks: false,
|
||||||
|
alias: {
|
||||||
|
'node:process': 'process',
|
||||||
|
'node:path': 'path',
|
||||||
|
},
|
||||||
|
fallback: {
|
||||||
|
path: import.meta.resolve('path-browserify'),
|
||||||
|
process: import.meta.resolve('process/browser'),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
devtool,
|
devtool,
|
||||||
optimization: {
|
optimization: {
|
||||||
splitChunks,
|
splitChunks,
|
||||||
},
|
},
|
||||||
entry: {
|
entry: {
|
||||||
cloudcmd: `${dir}/cloudcmd.js`,
|
'themes/dark': `${dirThemes}/dark.css`,
|
||||||
|
'themes/light': `${dirThemes}/light.css`,
|
||||||
|
'columns/name-size': `${dirColumns}/name-size.css`,
|
||||||
|
'columns/name-size-date': `${dirColumns}/name-size-date.css`,
|
||||||
|
'nojs': `${dirCss}/nojs.css`,
|
||||||
|
'help': `${dirCss}/help.css`,
|
||||||
|
'view': `${dirCss}/view.css`,
|
||||||
|
'config': `${dirCss}/config.css`,
|
||||||
|
'terminal': `${dirCss}/terminal.css`,
|
||||||
|
'user-menu': `${dirCss}/user-menu.css`,
|
||||||
|
'sw': `${dir}/sw/sw.js`,
|
||||||
|
'cloudcmd': `${dir}/cloudcmd.mjs`,
|
||||||
[`${modules}/edit`]: `${dirModules}/edit.js`,
|
[`${modules}/edit`]: `${dirModules}/edit.js`,
|
||||||
[`${modules}/edit-file`]: `${dirModules}/edit-file.js`,
|
[`${modules}/edit-file`]: `${dirModules}/edit-file.js`,
|
||||||
[`${modules}/edit-file-vim`]: `${dirModules}/edit-file-vim.js`,
|
[`${modules}/edit-file-vim`]: `${dirModules}/edit-file-vim.js`,
|
||||||
[`${modules}/edit-names`]: `${dirModules}/edit-names.js`,
|
[`${modules}/edit-names`]: `${dirModules}/edit-names.js`,
|
||||||
[`${modules}/edit-names-vim`]: `${dirModules}/edit-names-vim.js`,
|
[`${modules}/edit-names-vim`]: `${dirModules}/edit-names-vim.js`,
|
||||||
[`${modules}/menu`]: `${dirModules}/menu.js`,
|
[`${modules}/menu`]: `${dirModules}/menu/index.js`,
|
||||||
[`${modules}/view`]: `${dirModules}/view/index.js`,
|
[`${modules}/view`]: `${dirModules}/view/index.js`,
|
||||||
[`${modules}/help`]: `${dirModules}/help.js`,
|
[`${modules}/help`]: `${dirModules}/help.js`,
|
||||||
[`${modules}/markdown`]: `${dirModules}/markdown.js`,
|
[`${modules}/markdown`]: `${dirModules}/markdown.js`,
|
||||||
[`${modules}/config`]: `${dirModules}/config/index.js`,
|
[`${modules}/config`]: `${dirModules}/config/index.js`,
|
||||||
[`${modules}/contact`]: `${dirModules}/contact.js`,
|
[`${modules}/contact`]: `${dirModules}/contact.js`,
|
||||||
[`${modules}/upload`]: `${dirModules}/upload.js`,
|
[`${modules}/upload`]: `${dirModules}/upload.js`,
|
||||||
[`${modules}/operation`]: `${dirModules}/operation/index.js`,
|
[`${modules}/operation`]: `${dirModules}/operation/index.mjs`,
|
||||||
[`${modules}/konsole`]: `${dirModules}/konsole.js`,
|
[`${modules}/konsole`]: `${dirModules}/konsole.js`,
|
||||||
[`${modules}/terminal`]: `${dirModules}/terminal.js`,
|
[`${modules}/terminal`]: `${dirModules}/terminal.js`,
|
||||||
[`${modules}/terminal-run`]: `${dirModules}/terminal-run.js`,
|
[`${modules}/terminal-run`]: `${dirModules}/terminal-run.js`,
|
||||||
|
|
@ -101,7 +143,6 @@ module.exports = {
|
||||||
devtoolModuleFilenameTemplate,
|
devtoolModuleFilenameTemplate,
|
||||||
publicPath: '/dist/',
|
publicPath: '/dist/',
|
||||||
},
|
},
|
||||||
externals: [convertToWebpack5Externals(externals)],
|
|
||||||
module: {
|
module: {
|
||||||
rules,
|
rules,
|
||||||
noParse,
|
noParse,
|
||||||
|
|
@ -113,18 +154,6 @@ module.exports = {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
function externals({request}, fn) {
|
|
||||||
if (!isDev)
|
|
||||||
return fn();
|
|
||||||
|
|
||||||
const list = [];
|
|
||||||
|
|
||||||
if (list.includes(request))
|
|
||||||
return fn(null, request);
|
|
||||||
|
|
||||||
fn();
|
|
||||||
}
|
|
||||||
|
|
||||||
function devtoolModuleFilenameTemplate(info) {
|
function devtoolModuleFilenameTemplate(info) {
|
||||||
const resource = info.absoluteResourcePath.replace(rootDir + sep, '');
|
const resource = info.absoluteResourcePath.replace(rootDir + sep, '');
|
||||||
return `file://cloudcmd/${resource}`;
|
return `file://cloudcmd/${resource}`;
|
||||||
|
|
@ -26,5 +26,5 @@ For example util, console, view, edit, style etc...
|
||||||
|
|
||||||
**Examples**:
|
**Examples**:
|
||||||
|
|
||||||
- [fix(style) .name{width}: 37% -> 35%](https://github.com/coderaiser/cloudcmd/commit/94b0642e3990c17b3a0ee3efeb75f343e1e7c050)
|
- [fix: style: .name{width}: 37% -> 35%](https://github.com/coderaiser/cloudcmd/commit/94b0642e3990c17b3a0ee3efeb75f343e1e7c050)
|
||||||
- [fix(console) dispatch: focus -> mouseup](https://github.com/coderaiser/cloudcmd/commit/f41ec5058d1411e86a881f8e8077e0572e0409ec)
|
- [fix: console: dispatch: focus -> mouseup](https://github.com/coderaiser/cloudcmd/commit/f41ec5058d1411e86a881f8e8077e0572e0409ec)
|
||||||
|
|
|
||||||
548
ChangeLog
548
ChangeLog
|
|
@ -1,3 +1,549 @@
|
||||||
|
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:
|
||||||
|
- 08d13c6d cloudcmd: aleman v1.4.9
|
||||||
|
|
||||||
|
2025.09.04, v18.8.3
|
||||||
|
|
||||||
|
feature:
|
||||||
|
- b4792fc3 cloudcmd: aleman v1.4.0
|
||||||
|
|
||||||
|
2025.09.04, v18.8.2
|
||||||
|
|
||||||
|
feature:
|
||||||
|
- a0b3285b cloudcmd: aleman v1.3.0
|
||||||
|
|
||||||
|
2025.09.04, v18.8.1
|
||||||
|
|
||||||
|
feature:
|
||||||
|
- 15b71c14 cloudcmd: aleman v1.2.5
|
||||||
|
- d252fe5f robots.txt: add
|
||||||
|
|
||||||
|
2025.09.02, v18.8.0
|
||||||
|
|
||||||
|
feature:
|
||||||
|
- 08b5c6b2 client: menu: aleman: add
|
||||||
|
|
||||||
|
2025.08.30, v18.7.4
|
||||||
|
|
||||||
|
fix:
|
||||||
|
- a6d18ddb select file: name -> line
|
||||||
|
- 2077468a client: listeners: click: avoid select on conext menu
|
||||||
|
- 64e4aba4 client: menu: before show: unsetBind
|
||||||
|
|
||||||
|
2025.07.26, v18.7.3
|
||||||
|
|
||||||
|
fix:
|
||||||
|
- 884c83eb client: polyfill (#442)
|
||||||
|
|
||||||
|
2025.07.24, v18.7.2
|
||||||
|
|
||||||
|
feature:
|
||||||
|
- 2e775908 cloudcmd: html-looks-like: remove
|
||||||
|
- bb6a7a28 docker: npm -> bun
|
||||||
|
|
||||||
|
2025.07.06, v18.7.1
|
||||||
|
|
||||||
|
fix:
|
||||||
|
- 784bb2eb build: sw
|
||||||
|
|
||||||
|
feature:
|
||||||
|
- 8f52376d cloudcmd: revert: optimize-css-assets-webpack-plugin -> css-minimizer-webpack-plugin: broken spinner
|
||||||
|
- 82008749 cloudcmd: optimize-css-assets-webpack-plugin -> css-minimizer-webpack-plugin
|
||||||
|
|
||||||
|
2025.07.05, v18.7.0
|
||||||
|
|
||||||
|
fix:
|
||||||
|
- b1e231a5 client: menu: close: ESC
|
||||||
|
|
||||||
|
feature:
|
||||||
|
- 546d0610 cloudcmd: process v0.11.10
|
||||||
|
- 121b114e cloudcmd: path-browserify v1.0.1
|
||||||
|
- 8592cedc cloudcmd: mini-css-extract-plugin v2.9.2
|
||||||
|
- a53ab67b cloudcmd: webpack-cli v6.0.1
|
||||||
|
- de2cedd9 cloudcmd: webpack v5.99.9
|
||||||
|
- da545ea4 cloudcmd: style-loader v4.0.0
|
||||||
|
- db6e8334 cloudcmd: optimize-css-assets-webpack-plugin v6.0.1
|
||||||
|
- 2f0c1a61 cloudcmd: html-webpack-plugin v5.6.3
|
||||||
|
- e100dcf6 cloudcmd: extract-text-webpack-plugin v3.0.2
|
||||||
|
- 76c40008 cloudcmd: css-loader v7.1.2
|
||||||
|
- fb5e5a32 cloudcmd: clean-css-loader v4.2.1
|
||||||
|
- 8551cd54 cloudcmd: babel-loader v10.0.0
|
||||||
|
- c9380319 webpack 5
|
||||||
|
- ddc94adb cloudcmd: eslint-plugin-putout v28.0.0
|
||||||
|
|
||||||
|
2025.07.04, v18.6.1
|
||||||
|
|
||||||
|
feature:
|
||||||
|
- 9eafa189 cloudcmd: http-auth v4.2.1
|
||||||
|
- e99d0847 cloudcmd: montag v1.2.1
|
||||||
|
- b77e9c91 cloudcmd: pipe-io v4.0.1
|
||||||
|
- 4b476a6d cloudcmd: globals v16.3.0
|
||||||
|
- 2057065d cloudcmd: @putout/eslint-flat v3.0.1
|
||||||
|
|
||||||
|
2025.07.02, v18.6.0
|
||||||
|
|
||||||
|
feature:
|
||||||
|
- 2eb3dc66 cloudcmd: @iocmd/wait v2.1.0
|
||||||
|
- 1679b788 cloudcmd: webpackbar v7.0.0
|
||||||
|
- 9a4cf388 cloudcmd: eslint-plugin-putout v27.2.1
|
||||||
|
- f4b0f92f cloudcmd: express v5.1.0
|
||||||
|
- 4ab4be12 thread-it: get rid (#438)
|
||||||
|
- 99ad0c21 cloudcmd: rm @putout/babel
|
||||||
|
- 8ccec23d cloudcmd: help: require -> import
|
||||||
|
- 2a97ac66 cloudcmd: yargs-parser v22.0.0
|
||||||
|
- b26c8bba cloudcmd: thread-it v3.0.0
|
||||||
|
|
||||||
|
2025.04.10, v18.5.2
|
||||||
|
|
||||||
|
feature:
|
||||||
|
- 8450bfa6 cloudcmd: putout v40.0.3
|
||||||
|
- 51f51b54 cloudcmd: @putout/plugin-cloudcmd v4.0.0
|
||||||
|
- 08ab63d7 cloudcmd: supertape v11.0.4
|
||||||
|
- e7cc9b92 cloudcmd: redlint v4.1.1
|
||||||
|
- 368c9bb8 cloudcmd: eslint v9.23.0
|
||||||
|
- 43fd5ed6 cloudcmd: madrun v11.0.0
|
||||||
|
- f774d5b2 cloudcmd: eslint-plugin-putout v26.1.0
|
||||||
|
- b0a7fc16 cloudcmd: putout v39.3.0
|
||||||
|
|
||||||
|
2025.02.03, v18.5.1
|
||||||
|
|
||||||
|
feature:
|
||||||
|
- 467f0a79 cloudcmd: webpack-merge v6.0.1
|
||||||
|
- 353a1fb6 cloudcmd: putout v38.0.5
|
||||||
|
- 8e98b778 cloudcmd: eslint-plugin-putout v24.0.0
|
||||||
|
|
||||||
|
2025.01.20, v18.5.0
|
||||||
|
|
||||||
|
fix:
|
||||||
|
- ad8e55d8 client: themes -> columns (#434)
|
||||||
|
|
||||||
|
feature:
|
||||||
|
- 2fc503f7 cloudcmd: @putout/babel v3.0.0
|
||||||
|
|
||||||
|
2024.12.13, v18.4.1
|
||||||
|
|
||||||
|
feature:
|
||||||
|
- 100e940e cloudcmd: putout v37.0.1
|
||||||
|
|
||||||
|
2024.11.22, v18.4.0
|
||||||
|
|
||||||
|
fix:
|
||||||
|
- dff02672 cloudcmd: make manifest.json accessible when authentication is enabled (#428)
|
||||||
|
|
||||||
|
2024.11.14, v18.3.0
|
||||||
|
|
||||||
|
feature:
|
||||||
|
- 71dc8dd6 cloudcmd: Add support for Progressive Web App (#426)
|
||||||
|
|
||||||
|
2024.11.06, v18.2.1
|
||||||
|
|
||||||
|
feature:
|
||||||
|
- a733d814 css: --is-mobile: add
|
||||||
|
- f22120dc cloudcmd: prevent unselect being fired on panel click when in mobile view (#422)
|
||||||
|
- 1a0af863 docker: add image source label to dockerfiles (#421)
|
||||||
|
- 0446a74d docker: add image source label to dockerfiles (#419)
|
||||||
|
|
||||||
|
2024.10.27, v18.2.0
|
||||||
|
|
||||||
|
feature:
|
||||||
|
- ac9abbd3 cloudcmd: eslint-plugin-putout v23.1.0
|
||||||
|
- 4bc5a783 cloudcmd: add context menu option to toggle file selection (#420)
|
||||||
|
|
||||||
|
2024.08.17, v18.1.0
|
||||||
|
|
||||||
|
feature:
|
||||||
|
- ddf4542b cloudcmd: add ability to hide dot files (#307)
|
||||||
|
|
||||||
|
2024.08.16, v18.0.2
|
||||||
|
|
||||||
|
feature:
|
||||||
|
- 3d03efbe css: show links in one small screens
|
||||||
|
|
||||||
|
2024.08.16, v18.0.1
|
||||||
|
|
||||||
|
fix:
|
||||||
|
- 62ed8411 bin: validateArgs is not a function (#147)
|
||||||
|
|
||||||
|
feature:
|
||||||
|
- 9ec94dee cloudcmd: chalk v5.3.0
|
||||||
|
|
||||||
|
2024.08.16, v18.0.0
|
||||||
|
|
||||||
|
feature:
|
||||||
|
- 5e93bcca cloudcmd: rimraf v6.0.1
|
||||||
|
- 74d1eb7e drop support of node < 20
|
||||||
|
|
||||||
|
2024.08.16, v17.4.4
|
||||||
|
|
||||||
|
fix:
|
||||||
|
- a6aa9bbc revert rimraf v6.0.1
|
||||||
|
|
||||||
|
feature:
|
||||||
|
- 282b3d5c cloudcmd: @putout/cli-validate-args v2.0.0
|
||||||
|
|
||||||
|
2024.07.27, v17.4.3
|
||||||
|
|
||||||
|
feature:
|
||||||
|
- 6e8348b8 cloudcmd: rimraf v6.0.1
|
||||||
|
- 61ca7f36 cloudcmd: putout v36.0.2
|
||||||
|
|
||||||
|
2024.07.03, v17.4.2
|
||||||
|
|
||||||
|
feature:
|
||||||
|
- ba2d0b36 cloudcmd: just-snake-case v3.2.0
|
||||||
|
- 4cc47e30 cloudcmd: just-capitalize v3.2.0
|
||||||
|
- d8451e56 cloudcmd: just-pascal-case v3.2.0
|
||||||
|
- 6abf327d cloudcmd: package-json v10.0.0
|
||||||
|
- 2ae6ad34 docker: Dockerimage update Debian12 (#414)
|
||||||
|
- 05ef0ae4 cloudcmd: c8 v10.1.2
|
||||||
|
|
||||||
|
2024.05.06, v17.4.1
|
||||||
|
|
||||||
|
feature:
|
||||||
|
- 154b4bd6 cloudcmd: @cloudcmd/move-files v8.0.0
|
||||||
|
- c409a2db cloudcmd: copymitter v9.0.0
|
||||||
|
|
||||||
|
2024.04.17, v17.4.0
|
||||||
|
|
||||||
|
fix:
|
||||||
|
- 6fb21020 server: route: path traversal
|
||||||
|
|
||||||
|
feature:
|
||||||
|
- 37ab7068 publish container image to GHCR (#409)
|
||||||
|
|
||||||
|
2024.04.03, v17.3.3
|
||||||
|
|
||||||
|
feature:
|
||||||
|
- b088b84e cloudcmd: deepword v10.0.0
|
||||||
|
|
||||||
|
2024.03.29, v17.3.2
|
||||||
|
|
||||||
|
fix:
|
||||||
|
- f7a6a366 typo: Wraped -> Wrapped
|
||||||
|
|
||||||
|
2024.03.29, v17.3.1
|
||||||
|
|
||||||
|
feature:
|
||||||
|
- d7581829 distribute: convert to ESM
|
||||||
|
|
||||||
|
2024.03.29, v17.3.0
|
||||||
|
|
||||||
|
feature:
|
||||||
|
- 6bc4f3ec dark theme: add (#332)
|
||||||
|
- 35622082 route: convert to ESM
|
||||||
|
|
||||||
|
2024.03.29, v17.2.1
|
||||||
|
|
||||||
|
fix:
|
||||||
|
- cc134464 client: vim: space
|
||||||
|
|
||||||
|
feature:
|
||||||
|
- e3f89e88 dark mode: add
|
||||||
|
- c45b23fe css: vars: add
|
||||||
|
- b1f74c00 css: add vars
|
||||||
|
|
||||||
|
2024.03.22, v17.2.0
|
||||||
|
|
||||||
|
feature:
|
||||||
|
- 3e565109 convert to ESM
|
||||||
|
- 770a0812 pack: get rid of mock-require
|
||||||
|
- 25d8faea rest: get rid of mock-require
|
||||||
|
- 401a669a user-menu: get rid of mock-require
|
||||||
|
- 4e32241d terminal: get rid of mock-require
|
||||||
|
|
||||||
|
2024.03.21, v17.1.6
|
||||||
|
|
||||||
|
feature:
|
||||||
|
- e01ee457 server: route: get rid of mock-require
|
||||||
|
- c7f90901 root: get rid of mock-require
|
||||||
|
- fcce26d4 cloudfunc: get rid of mock-require
|
||||||
|
|
||||||
|
2024.03.20, v17.1.5
|
||||||
|
|
||||||
|
feature:
|
||||||
|
- bf90bf22 server: validate: get rid of mock-require
|
||||||
|
|
||||||
|
2024.03.20, v17.1.4
|
||||||
|
|
||||||
|
feature:
|
||||||
|
- 98d3a4cc server: columns: get rid of mock-require
|
||||||
|
|
||||||
|
2024.03.18, v17.1.3
|
||||||
|
|
||||||
|
feature:
|
||||||
|
- e080a540 server: cloudcmd: get rid of mock-require
|
||||||
|
|
||||||
|
2024.03.18, v17.1.2
|
||||||
|
|
||||||
|
fix:
|
||||||
|
- 857c9700 docker: alpine
|
||||||
|
|
||||||
|
feature:
|
||||||
|
- bf614e1d cloudcmd: redlint v3.13.1
|
||||||
|
|
||||||
|
2024.03.16, v17.1.1
|
||||||
|
|
||||||
|
feature:
|
||||||
|
- a92a5a0d cloudcmd: restbox v4.0.0
|
||||||
|
- c51ba1d8 docker: drop arm v7
|
||||||
|
|
||||||
|
2024.03.16, v17.1.0
|
||||||
|
|
||||||
|
feature:
|
||||||
|
- 10d6d2e2 cloudcmd: @types/node-fetch v2.6.11
|
||||||
|
- 2047cb7a cloudcmd: @cloudcmd/dropbox v5.0.1
|
||||||
|
- 6b793cca cloudcmd: docker: alpine
|
||||||
|
- 5fa9fcc5 cloudcmd: pullout v5.0.0
|
||||||
|
- bc617c17 cloudcmd: serve-once v3.0.1
|
||||||
|
|
||||||
|
2024.03.12, v17.0.7
|
||||||
|
|
||||||
|
feature:
|
||||||
|
- 97627dc2 cloudcmd: auto-globals v4.0.0
|
||||||
|
- 683c865e cloudcmd: gritty v8.0.0
|
||||||
|
|
||||||
|
2024.03.11, v17.0.6
|
||||||
|
|
||||||
|
fix:
|
||||||
|
- d928c0b8 cloudcmd: ocker: revert alpine (#406)
|
||||||
|
|
||||||
|
2024.03.11, v17.0.5
|
||||||
|
|
||||||
|
fix:
|
||||||
|
- 33201dad cloudcmd: docker: alpine (#406)
|
||||||
|
|
||||||
|
2024.02.02, v17.0.4
|
||||||
|
|
||||||
|
feature:
|
||||||
|
- 7ce95450 cloudcmd: deepword v9.0.0
|
||||||
|
- 1c73e525 cloudcmd: edward v15.0.0
|
||||||
|
- da967f08 cloudcmd: dword v15.0.0
|
||||||
|
- f0a6109a cloudcmd: restafary v12.0.0
|
||||||
|
|
||||||
2024.02.01, v17.0.3
|
2024.02.01, v17.0.3
|
||||||
|
|
||||||
feature:
|
feature:
|
||||||
|
|
@ -5518,7 +6064,7 @@ fix:
|
||||||
- (rest) onDelete: func(null, body) -> func
|
- (rest) onDelete: func(null, body) -> func
|
||||||
- (rest) onStat: add var
|
- (rest) onStat: add var
|
||||||
- (cloudcmd) change index path
|
- (cloudcmd) change index path
|
||||||
- (server) start: url -> URL
|
- (server) start: url -> PREFIX
|
||||||
- (server) start: SSLPort -> sslPort
|
- (server) start: SSLPort -> sslPort
|
||||||
- (server) start: Port -> port
|
- (server) start: Port -> port
|
||||||
- (dom) getCurrentDirPath: "," -> ";"
|
- (dom) getCurrentDirPath: "," -> ";"
|
||||||
|
|
|
||||||
361
HELP.md
361
HELP.md
|
|
@ -1,11 +1,11 @@
|
||||||
# Cloud Commander v17.0.3
|
# Cloud Commander v19.1.9
|
||||||
|
|
||||||
### [Main][MainURL] [Blog][BlogURL] [Support][SupportURL] [Demo][DemoURL]
|
### [Main][MainURL] [Blog][BlogURL] [Support][SupportURL] [Demo][DemoURL]
|
||||||
|
|
||||||
[MainURL]: https://cloudcmd.io "Main"
|
[MainURL]: https://cloudcmd.io "Main"
|
||||||
[BlogURL]: https://blog.cloudcmd.io "Blog"
|
[BlogURL]: https://blog.cloudcmd.io "Blog"
|
||||||
[SupportURL]: https://patreon.com/coderaiser "Patreon"
|
[SupportURL]: https://patreon.com/coderaiser "Patreon"
|
||||||
[DemoURL]: https://cloudcmd.onrender.com/
|
[DemoURL]: https://cloudcmd-zdp6.onrender.com/
|
||||||
[DWORD]: https://github.com/cloudcmd/dword "Editor based on CodeMirror"
|
[DWORD]: https://github.com/cloudcmd/dword "Editor based on CodeMirror"
|
||||||
[EDWARD]: https://github.com/cloudcmd/edward "Editor based on Ace"
|
[EDWARD]: https://github.com/cloudcmd/edward "Editor based on Ace"
|
||||||
[DEEPWORD]: https://github.com/cloudcmd/deepword "Editor based on Monaco"
|
[DEEPWORD]: https://github.com/cloudcmd/deepword "Editor based on Monaco"
|
||||||
|
|
@ -59,81 +59,84 @@ cloudcmd
|
||||||
|
|
||||||
Cloud Commander supports the following command-line parameters:
|
Cloud Commander supports the following command-line parameters:
|
||||||
|
|
||||||
|Parameter |Operation
|
| Parameter |Operation
|
||||||
|:------------------------------|:------------------------------
|
|:-----------------------------|:------------------------------
|
||||||
| `-h, --help` | display help and exit
|
| `-h, --help` | display help and exit
|
||||||
| `-v, --version` | display version and exit
|
| `-v, --version` | display version and exit
|
||||||
| `-s, --save` | save configuration
|
| `-s, --save` | save configuration
|
||||||
| `-o, --online` | load scripts from remote servers
|
| `-o, --online` | load scripts from remote servers
|
||||||
| `-a, --auth` | enable authorization
|
| `-a, --auth` | enable authorization
|
||||||
| `-u, --username` | set username
|
| `-u, --username` | set username
|
||||||
| `-p, --password` | set password
|
| `-p, --password` | set password
|
||||||
| `-c, --config` | configuration file path
|
| `-c, --config` | configuration file path
|
||||||
| `--show-config` | show config values
|
| `--show-config` | show config values
|
||||||
| `--show-file-name` | show file name in view and edit
|
| `--show-dot-files` | show dot files
|
||||||
| `--editor` | set editor: "dword", "edward" or "deepword"
|
| `--show-file-name` | show file name in view and edit
|
||||||
| `--packer` | set packer: "tar" or "zip"
|
| `--editor` | set editor: "dword", "edward" or "deepword"
|
||||||
| `--root` | set root directory
|
| `--packer` | set packer: "tar" or "zip"
|
||||||
| `--prefix` | set url prefix
|
| `--root` | set root directory
|
||||||
| `--prefix-socket` | set prefix for url connection
|
| `--prefix` | set url prefix
|
||||||
| `--port` | set port number
|
| `--prefix-socket` | set prefix for url connection
|
||||||
| `--confirm-copy` | confirm copy
|
| `--port` | set port number
|
||||||
| `--confirm-move` | confirm move
|
| `--confirm-copy` | confirm copy
|
||||||
| `--open` | open web browser when server starts
|
| `--confirm-move` | confirm move
|
||||||
| `--name` | set tab name in web browser
|
| `--open` | open web browser when server starts
|
||||||
| `--one-file-panel` | show one file panel
|
| `--name` | set tab name in web browser
|
||||||
| `--keys-panel` | show keys panel
|
| `--menu` | set menu: "supermenu" or "aleman"
|
||||||
| `--contact` | enable contact
|
| `--one-file-panel` | show one file panel
|
||||||
| `--config-dialog` | enable config dialog
|
| `--keys-panel` | show keys panel
|
||||||
| `--config-auth` | enable auth change in config dialog
|
| `--contact` | enable contact
|
||||||
| `--console` | enable console
|
| `--config-dialog` | enable config dialog
|
||||||
| `--sync-console-path` | sync console path
|
| `--config-auth` | enable auth change in config dialog
|
||||||
| `--terminal` | enable terminal
|
| `--console` | enable console
|
||||||
| `--terminal-path` | set terminal path
|
| `--sync-console-path` | sync console path
|
||||||
| `--terminal-command` | set command to run in terminal (shell by default)
|
| `--terminal` | enable terminal
|
||||||
| `--terminal-auto-restart` | restart command on exit
|
| `--terminal-path` | set terminal path
|
||||||
| `--vim` | enable vim hot keys
|
| `--terminal-command` | set command to run in terminal (shell by default)
|
||||||
| `--columns` | set visible columns
|
| `--terminal-auto-restart` | restart command on exit
|
||||||
| `--export` | enable export of config through a server
|
| `--vim` | enable vim hot keys
|
||||||
| `--export-token` | authorization token used by export server
|
| `--columns` | set visible columns
|
||||||
| `--import` | enable import of config
|
| `--theme` | set theme 'light' or 'dark'"
|
||||||
| `--import-token` | authorization token used to connect to export server
|
| `--export` | enable export of config through a server
|
||||||
| `--import-url` | url of an import server
|
| `--export-token` | authorization token used by export server
|
||||||
| `--import-listen` | enable listen on config updates from import server
|
| `--import` | enable import of config
|
||||||
| `--dropbox` | enable dropbox integration
|
| `--import-token` | authorization token used to connect to export server
|
||||||
| `--dropbox-token` | set dropbox token
|
| `--import-url` | url of an import server
|
||||||
| `--log` | enable logging
|
| `--import-listen` | enable listen on config updates from import server
|
||||||
| `--no-show-config` | do not show config values
|
| `--dropbox` | enable dropbox integration
|
||||||
| `--no-server` | do not start server
|
| `--dropbox-token` | set dropbox token
|
||||||
| `--no-auth` | disable authorization
|
| `--log` | enable logging
|
||||||
| `--no-online` | load scripts from local server
|
| `--no-show-config` | do not show config values
|
||||||
| `--no-open` | do not open web browser when server started
|
| `--no-server` | do not start server
|
||||||
| `--no-name` | set default tab name in web browser
|
| `--no-auth` | disable authorization
|
||||||
| `--no-keys-panel` | hide keys panel
|
| `--no-online` | load scripts from local server
|
||||||
| `--no-one-file-panel` | show two file panels
|
| `--no-open` | do not open web browser when server started
|
||||||
| `--no-confirm-copy` | do not confirm copy
|
| `--no-name` | set default tab name in web browser
|
||||||
| `--no-confirm-move` | do not confirm move
|
| `--no-keys-panel` | hide keys panel
|
||||||
| `--no-config-dialog` | disable config dialog
|
| `--no-one-file-panel` | show two file panels
|
||||||
| `--no-config-auth` | disable auth change in config dialog
|
| `--no-confirm-copy` | do not confirm copy
|
||||||
| `--no-console` | disable console
|
| `--no-confirm-move` | do not confirm move
|
||||||
| `--no-sync-console-path` | do not sync console path
|
| `--no-config-dialog` | disable config dialog
|
||||||
| `--no-contact` | disable contact
|
| `--no-config-auth` | disable auth change in config dialog
|
||||||
| `--no-terminal` | disable terminal
|
| `--no-console` | disable console
|
||||||
| `--no-terminal-command` | set default shell to run in terminal
|
| `--no-sync-console-path` | do not sync console path
|
||||||
| `--no-terminal-auto-restart` | do not restart command on exit
|
| `--no-contact` | disable contact
|
||||||
| `--no-vim` | disable vim hot keys
|
| `--no-terminal` | disable terminal
|
||||||
| `--no-columns` | set default visible columns
|
| `--no-terminal-command` | set default shell to run in terminal
|
||||||
| `--no-export` | disable export config through a server
|
| `--no-terminal-auto-restart` | do not restart command on exit
|
||||||
| `--no-import` | disable import of config
|
| `--no-vim` | disable vim hot keys
|
||||||
| `--no-import-listen` | disable listen on config updates from import server
|
| `--no-themes` | set default visible themes
|
||||||
| `--no-show-file-name` | do not show file name in view and edit
|
| `--no-export` | disable export config through a server
|
||||||
| `--no-dropbox` | disable dropbox integration
|
| `--no-import` | disable import of config
|
||||||
| `--no-dropbox-token` | unset dropbox token
|
| `--no-import-listen` | disable listen on config updates from import server
|
||||||
| `--no-log` | disable logging
|
| `--no-show-file-name` | do not show file name in view and edit
|
||||||
|
| `--no-dropbox` | disable dropbox integration
|
||||||
|
| `--no-dropbox-token` | unset dropbox token
|
||||||
|
| `--no-log` | disable logging
|
||||||
|
|
||||||
For options not specified by command-line parameters, Cloud Commander then reads configuration data from `~/.cloudcmd.json`. It uses port `8000` by default.
|
For options not specified by command-line parameters, Cloud Commander then reads configuration data from `~/.cloudcmd.json`. It uses port `8000` by default.
|
||||||
|
|
||||||
To begin using the web client, go to this URL in your browser:
|
To begin using the web client, go to this PREFIX in your browser:
|
||||||
|
|
||||||
```
|
```
|
||||||
http://localhost:8000
|
http://localhost:8000
|
||||||
|
|
@ -151,56 +154,58 @@ Then, start the server again with `cloudcmd` and reload the page.
|
||||||
|
|
||||||
## Hot keys
|
## Hot keys
|
||||||
|
|
||||||
|Key |Operation
|
| Key |Operation
|
||||||
|:----------------------|:--------------------------------------------
|
|:---------------------|:--------------------------------------------
|
||||||
| `F1` | help
|
| `F1` | help
|
||||||
| `F2` | show `user menu`
|
| `F2` | show `user menu`
|
||||||
| `F3` | view, change directory
|
| `F3` | view, change directory
|
||||||
| `Shift + F3` | view raw file, change directory
|
| `Shift + F3` | view raw file, change directory
|
||||||
| `F4` | edit
|
| `F4` | edit
|
||||||
| `F5` | copy
|
| `F5` | copy
|
||||||
| `Alt` + `F5` | pack
|
| `Alt` + `F5` | pack
|
||||||
| `F6` | rename/move
|
| `F6` | rename/move
|
||||||
| `Shift` + `F6` | rename current file
|
| `Shift` + `F6` | rename current file
|
||||||
| `F7` | new directory
|
| `F7` | new directory
|
||||||
| `Shift + F7` | new file
|
| `Shift + F7` | new file
|
||||||
| `F8`, `Delete` | remove
|
| `F8`, `Delete` | remove
|
||||||
| `Shift + Delete` | remove without prompt
|
| `Shift + Delete` | remove without prompt
|
||||||
| `F9` | menu
|
| `F9` | menu
|
||||||
| `Alt` + `F9` | extract
|
| `Alt` + `F9` | extract
|
||||||
| `F10` | config
|
| `F10` | config
|
||||||
| `*` | select/unselect all
|
| `*` | select/unselect all
|
||||||
| `+` | expand selection
|
| `+` | expand selection
|
||||||
| `-` | shrink selection
|
| `-` | shrink selection
|
||||||
| `:` | open Command Line
|
| `:` | open Command Line
|
||||||
| `Ctrl + X` | cut to buffer
|
| `Ctrl + X` | cut to buffer
|
||||||
| `Ctrl + C` | copy to buffer
|
| `Ctrl + C` | copy to buffer
|
||||||
| `Ctrl + V` | paste from buffer
|
| `Ctrl + V` | paste from buffer
|
||||||
| `Ctrl + Z` | clear buffer
|
| `Ctrl + Z` | clear buffer
|
||||||
| `Ctrl + P` | copy path
|
| `Ctrl + P` | copy path
|
||||||
| `Ctrl + R` | refresh
|
| `Ctrl + R` | refresh
|
||||||
| `Ctrl + D` | clear local storage
|
| `Ctrl + D` | clear local storage
|
||||||
| `Ctrl + A` | select all files in a panel
|
| `Ctrl + A` | select all files in a panel
|
||||||
| `Ctrl + M` | [rename selected files](https://github.com/coderaiser/cloudcmd/releases/tag/v12.1.0) in editor
|
| `Ctrl + M` | [rename selected files](https://github.com/coderaiser/cloudcmd/releases/tag/v12.1.0) in editor
|
||||||
| `Ctrl + U` | swap panels
|
| `Ctrl + U` | swap panels
|
||||||
| `Ctrl + F3` | sort by name
|
| `Ctrl + F3` | sort by name
|
||||||
| `Ctrl + F5` | sort by date
|
| `Ctrl + F5` | sort by date
|
||||||
| `Ctrl + F6` | sort by size
|
| `Ctrl + F6` | sort by size
|
||||||
| `Up`, `Down` | file system navigation
|
| `Ctrl + Command + .` | show/hide dot files
|
||||||
| `Enter` | change directory/view file
|
| `Up` | move cursor up
|
||||||
| `Alt + Left/Right` | show content of directory under cursor in target panel
|
| `Down` | move cursor down
|
||||||
| `Alt + G` | go to directory
|
| `Enter` | change directory/view file
|
||||||
| `Ctrl + \` | go to the root directory
|
| `Alt + Left/Right` | show content of directory under cursor in target panel
|
||||||
| `Tab` | move via panels
|
| `Alt + G` | go to directory
|
||||||
| `Page Up` | up on one page
|
| `Ctrl + \` | go to the root directory
|
||||||
| `Page Down` | down on one page
|
| `Tab` | move via panels
|
||||||
| `Home` | to begin of list
|
| `Page Up` | up on one page
|
||||||
| `End` | to end of list
|
| `Page Down` | down on one page
|
||||||
| `Space` | select current file (and get size of directory)
|
| `Home` | to begin of list
|
||||||
| `Insert` | select current file (and move to next)
|
| `End` | to end of list
|
||||||
| `F9` | context menu
|
| `Space` | select current file (and get size of directory)
|
||||||
| `~` | console
|
| `Insert` | select current file (and move to next)
|
||||||
| `Esc` | toggle vim hotkeys (`file manager`, `editor`)
|
| `F9` | context menu
|
||||||
|
| `~` | console
|
||||||
|
| `Esc` | toggle vim hotkeys (`file manager`, `editor`)
|
||||||
|
|
||||||
### Vim
|
### Vim
|
||||||
|
|
||||||
|
|
@ -397,6 +402,7 @@ Here's a description of all options:
|
||||||
"confirmCopy": true, // confirm copy
|
"confirmCopy": true, // confirm copy
|
||||||
"confirmMove": true, // confirm move
|
"confirmMove": true, // confirm move
|
||||||
"showConfig": false, // show config at startup
|
"showConfig": false, // show config at startup
|
||||||
|
"showDotFiles": true, // show dot files
|
||||||
"showFileName": false, // do not show file name in view and edit
|
"showFileName": false, // do not show file name in view and edit
|
||||||
"contact": true, // enable contact
|
"contact": true, // enable contact
|
||||||
"configDialog": true, // enable config dialog
|
"configDialog": true, // enable config dialog
|
||||||
|
|
@ -408,7 +414,7 @@ Here's a description of all options:
|
||||||
"terminalCommand": "", // set command to run in terminal
|
"terminalCommand": "", // set command to run in terminal
|
||||||
"terminalAutoRestart": true, // restart command on exit
|
"terminalAutoRestart": true, // restart command on exit
|
||||||
"vim": false, // disable vim hot keys
|
"vim": false, // disable vim hot keys
|
||||||
"columns": "name-size-date-owner-mode", // set visible columns
|
"themes": "name-size-date-owner-mode", // set visible themes
|
||||||
"export": false, // enable export of config through a server
|
"export": false, // enable export of config through a server
|
||||||
"exportToken": "root", // token used by export server
|
"exportToken": "root", // token used by export server
|
||||||
"import": false, // enable import of config
|
"import": false, // enable import of config
|
||||||
|
|
@ -428,7 +434,9 @@ Some config options can be overridden with environment variables, such as:
|
||||||
- `CLOUDCMD_NAME` - set tab name in web browser
|
- `CLOUDCMD_NAME` - set tab name in web browser
|
||||||
- `CLOUDCMD_OPEN` - open web browser when server started
|
- `CLOUDCMD_OPEN` - open web browser when server started
|
||||||
- `CLOUDCMD_EDITOR` - set editor
|
- `CLOUDCMD_EDITOR` - set editor
|
||||||
- `CLOUDCMD_COLUMNS` - set visible columns
|
- `CLOUDCMD_COLUMNS` - set visible themes
|
||||||
|
- `CLOUDCMD_THEME` - set themes "light" or "dark"
|
||||||
|
- `CLOUDCMD_MENU` - set menu "supermenu" or "aleman"
|
||||||
- `CLOUDCMD_CONTACT` - enable contact
|
- `CLOUDCMD_CONTACT` - enable contact
|
||||||
- `CLOUDCMD_CONFIG_DIALOG` - enable config dialog
|
- `CLOUDCMD_CONFIG_DIALOG` - enable config dialog
|
||||||
- `CLOUDCMD_CONFIG_AUTH` - enable auth change in config dialog
|
- `CLOUDCMD_CONFIG_AUTH` - enable auth change in config dialog
|
||||||
|
|
@ -639,10 +647,20 @@ Right-mouse click to show a context menu with these items:
|
||||||
|
|
||||||
### Hot keys
|
### Hot keys
|
||||||
|
|
||||||
|Key |Operation
|
| Key | Operation |
|
||||||
|:----------------------|:--------------------------------------------
|
|:-------------|:------------------------|
|
||||||
| `F9` | open
|
| `F9` | open |
|
||||||
| `Esc` | close
|
| `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;
|
||||||
|
|
||||||
## One file panel
|
## One file panel
|
||||||
|
|
||||||
|
|
@ -1093,6 +1111,87 @@ There are a lot of ways to be involved in `Cloud Commander` development:
|
||||||
|
|
||||||
## Version history
|
## 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)**
|
||||||
|
- *2025.09.04*, **[v18.8.1](//github.com/coderaiser/cloudcmd/releases/tag/v18.8.1)**
|
||||||
|
- *2025.09.02*, **[v18.8.0](//github.com/coderaiser/cloudcmd/releases/tag/v18.8.0)**
|
||||||
|
- *2025.08.30*, **[v18.7.4](//github.com/coderaiser/cloudcmd/releases/tag/v18.7.4)**
|
||||||
|
- *2025.07.26*, **[v18.7.3](//github.com/coderaiser/cloudcmd/releases/tag/v18.7.3)**
|
||||||
|
- *2025.07.24*, **[v18.7.2](//github.com/coderaiser/cloudcmd/releases/tag/v18.7.2)**
|
||||||
|
- *2025.07.06*, **[v18.7.1](//github.com/coderaiser/cloudcmd/releases/tag/v18.7.1)**
|
||||||
|
- *2025.07.05*, **[v18.7.0](//github.com/coderaiser/cloudcmd/releases/tag/v18.7.0)**
|
||||||
|
- *2025.07.04*, **[v18.6.1](//github.com/coderaiser/cloudcmd/releases/tag/v18.6.1)**
|
||||||
|
- *2025.07.02*, **[v18.6.0](//github.com/coderaiser/cloudcmd/releases/tag/v18.6.0)**
|
||||||
|
- *2025.04.10*, **[v18.5.2](//github.com/coderaiser/cloudcmd/releases/tag/v18.5.2)**
|
||||||
|
- *2025.02.03*, **[v18.5.1](//github.com/coderaiser/cloudcmd/releases/tag/v18.5.1)**
|
||||||
|
- *2025.01.20*, **[v18.5.0](//github.com/coderaiser/cloudcmd/releases/tag/v18.5.0)**
|
||||||
|
- *2024.12.13*, **[v18.4.1](//github.com/coderaiser/cloudcmd/releases/tag/v18.4.1)**
|
||||||
|
- *2024.11.22*, **[v18.4.0](//github.com/coderaiser/cloudcmd/releases/tag/v18.4.0)**
|
||||||
|
- *2024.11.14*, **[v18.3.0](//github.com/coderaiser/cloudcmd/releases/tag/v18.3.0)**
|
||||||
|
- *2024.11.06*, **[v18.2.1](//github.com/coderaiser/cloudcmd/releases/tag/v18.2.1)**
|
||||||
|
- *2024.10.27*, **[v18.2.0](//github.com/coderaiser/cloudcmd/releases/tag/v18.2.0)**
|
||||||
|
- *2024.08.17*, **[v18.1.0](//github.com/coderaiser/cloudcmd/releases/tag/v18.1.0)**
|
||||||
|
- *2024.08.16*, **[v18.0.2](//github.com/coderaiser/cloudcmd/releases/tag/v18.0.2)**
|
||||||
|
- *2024.08.16*, **[v18.0.1](//github.com/coderaiser/cloudcmd/releases/tag/v18.0.1)**
|
||||||
|
- *2024.08.16*, **[v18.0.0](//github.com/coderaiser/cloudcmd/releases/tag/v18.0.0)**
|
||||||
|
- *2024.08.16*, **[v17.4.4](//github.com/coderaiser/cloudcmd/releases/tag/v17.4.4)**
|
||||||
|
- *2024.07.27*, **[v17.4.3](//github.com/coderaiser/cloudcmd/releases/tag/v17.4.3)**
|
||||||
|
- *2024.07.03*, **[v17.4.2](//github.com/coderaiser/cloudcmd/releases/tag/v17.4.2)**
|
||||||
|
- *2024.05.06*, **[v17.4.1](//github.com/coderaiser/cloudcmd/releases/tag/v17.4.1)**
|
||||||
|
- *2024.04.17*, **[v17.4.0](//github.com/coderaiser/cloudcmd/releases/tag/v17.4.0)**
|
||||||
|
- *2024.04.03*, **[v17.3.3](//github.com/coderaiser/cloudcmd/releases/tag/v17.3.3)**
|
||||||
|
- *2024.03.29*, **[v17.3.2](//github.com/coderaiser/cloudcmd/releases/tag/v17.3.2)**
|
||||||
|
- *2024.03.29*, **[v17.3.1](//github.com/coderaiser/cloudcmd/releases/tag/v17.3.1)**
|
||||||
|
- *2024.03.29*, **[v17.3.0](//github.com/coderaiser/cloudcmd/releases/tag/v17.3.0)**
|
||||||
|
- *2024.03.29*, **[v17.2.1](//github.com/coderaiser/cloudcmd/releases/tag/v17.2.1)**
|
||||||
|
- *2024.03.22*, **[v17.2.0](//github.com/coderaiser/cloudcmd/releases/tag/v17.2.0)**
|
||||||
|
- *2024.03.21*, **[v17.1.6](//github.com/coderaiser/cloudcmd/releases/tag/v17.1.6)**
|
||||||
|
- *2024.03.20*, **[v17.1.5](//github.com/coderaiser/cloudcmd/releases/tag/v17.1.5)**
|
||||||
|
- *2024.03.20*, **[v17.1.4](//github.com/coderaiser/cloudcmd/releases/tag/v17.1.4)**
|
||||||
|
- *2024.03.18*, **[v17.1.3](//github.com/coderaiser/cloudcmd/releases/tag/v17.1.3)**
|
||||||
|
- *2024.03.18*, **[v17.1.2](//github.com/coderaiser/cloudcmd/releases/tag/v17.1.2)**
|
||||||
|
- *2024.03.16*, **[v17.1.1](//github.com/coderaiser/cloudcmd/releases/tag/v17.1.1)**
|
||||||
|
- *2024.03.16*, **[v17.1.0](//github.com/coderaiser/cloudcmd/releases/tag/v17.1.0)**
|
||||||
|
- *2024.03.12*, **[v17.0.7](//github.com/coderaiser/cloudcmd/releases/tag/v17.0.7)**
|
||||||
|
- *2024.03.11*, **[v17.0.6](//github.com/coderaiser/cloudcmd/releases/tag/v17.0.6)**
|
||||||
|
- *2024.03.11*, **[v17.0.5](//github.com/coderaiser/cloudcmd/releases/tag/v17.0.5)**
|
||||||
|
- *2024.02.02*, **[v17.0.4](//github.com/coderaiser/cloudcmd/releases/tag/v17.0.4)**
|
||||||
- *2024.02.01*, **[v17.0.3](//github.com/coderaiser/cloudcmd/releases/tag/v17.0.3)**
|
- *2024.02.01*, **[v17.0.3](//github.com/coderaiser/cloudcmd/releases/tag/v17.0.3)**
|
||||||
- *2024.02.01*, **[v17.0.2](//github.com/coderaiser/cloudcmd/releases/tag/v17.0.2)**
|
- *2024.02.01*, **[v17.0.2](//github.com/coderaiser/cloudcmd/releases/tag/v17.0.2)**
|
||||||
- *2024.01.25*, **[v17.0.1](//github.com/coderaiser/cloudcmd/releases/tag/v17.0.1)**
|
- *2024.01.25*, **[v17.0.1](//github.com/coderaiser/cloudcmd/releases/tag/v17.0.1)**
|
||||||
|
|
@ -1532,7 +1631,7 @@ There are a lot of ways to be involved in `Cloud Commander` development:
|
||||||
|
|
||||||
## Special Thanks
|
## Special Thanks
|
||||||
|
|
||||||
- [Olena Zalitok](http://www.linkedin.com/in/olena-zalitok-ux-designer "Olena Zalitok") for **logo** and **favicon**.
|
- [Olena Zalitok](https://www.linkedin.com/in/ozalitok-ux-ui/ "Olena Zalitok") for **logo** and **favicon**.
|
||||||
- [TarZak](https://github.com/tarzak "TarZak")
|
- [TarZak](https://github.com/tarzak "TarZak")
|
||||||
- Russian and Ukrainian translations;
|
- Russian and Ukrainian translations;
|
||||||
- config template and style;
|
- config template and style;
|
||||||
|
|
|
||||||
2
LICENSE
2
LICENSE
|
|
@ -1,6 +1,6 @@
|
||||||
(The MIT License)
|
(The MIT License)
|
||||||
|
|
||||||
Copyright (c) 2012-2024 Coderaiser <mnemonic.enemy@gmail.com>
|
Copyright (c) 2012-2025 Coderaiser <mnemonic.enemy@gmail.com>
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
a copy of this software and associated documentation files (the
|
a copy of this software and associated documentation files (the
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
# Cloud Commander v17.0.3 [![Build Status][BuildStatusIMGURL]][BuildStatusURL] [![Codacy][CodacyIMG]][CodacyURL] [![Gitter][GitterIMGURL]][GitterURL]
|
# Cloud Commander v19.1.9 [![Build Status][BuildStatusIMGURL]][BuildStatusURL] [![Codacy][CodacyIMG]][CodacyURL] [![Gitter][GitterIMGURL]][GitterURL]
|
||||||
|
|
||||||
### [Main][MainURL] [Blog][BlogURL] [Support][SupportURL] [Demo][DemoURL]
|
### [Main][MainURL] [Blog][BlogURL] [Support][SupportURL] [Demo][DemoURL]
|
||||||
|
|
||||||
[MainURL]: https://cloudcmd.io "Main"
|
[MainURL]: https://cloudcmd.io "Main"
|
||||||
[BlogURL]: https://blog.cloudcmd.io "Blog"
|
[BlogURL]: https://blog.cloudcmd.io "Blog"
|
||||||
[SupportURL]: https://patreon.com/coderaiser "Patreon"
|
[SupportURL]: https://patreon.com/coderaiser "Patreon"
|
||||||
[DemoURL]: https://cloudcmd.onrender.com/
|
[DemoURL]: https://cloudcmd-zdp6.onrender.com
|
||||||
[NPM_INFO_IMG]: https://nodei.co/npm/cloudcmd.png
|
[NPM_INFO_IMG]: https://nodei.co/npm/cloudcmd.png
|
||||||
[BuildStatusURL]: https://github.com/coderaiser/cloudcmd/actions/workflows/nodejs.yml "Build Status"
|
[BuildStatusURL]: https://github.com/coderaiser/cloudcmd/actions/workflows/nodejs.yml "Build Status"
|
||||||
[BuildStatusIMGURL]: https://github.com/coderaiser/cloudcmd/actions/workflows/nodejs.yml/badge.svg
|
[BuildStatusIMGURL]: https://github.com/coderaiser/cloudcmd/actions/workflows/nodejs.yml/badge.svg
|
||||||
|
|
@ -126,10 +126,8 @@ The docker images are provided for multiple architectures and types. The followi
|
||||||
| Architecture | Type |
|
| Architecture | Type |
|
||||||
|----------------|--------------|
|
|----------------|--------------|
|
||||||
| amd64 | linux |
|
| amd64 | linux |
|
||||||
| arm/v7 | linux |
|
|
||||||
| arm64 (arm/v8) | linux |
|
| arm64 (arm/v8) | linux |
|
||||||
| amd64 | linux-alpine |
|
| amd64 | linux-alpine |
|
||||||
| arm/v7 | linux-alpine |
|
|
||||||
| arm64 (arm/v8) | linux-alpine |
|
| arm64 (arm/v8) | linux-alpine |
|
||||||
|
|
||||||
`Cloud Commander` could be used as a [docker container](https://hub.docker.com/r/coderaiser/cloudcmd/ "Docker container") this way:
|
`Cloud Commander` could be used as a [docker container](https://hub.docker.com/r/coderaiser/cloudcmd/ "Docker container") this way:
|
||||||
|
|
|
||||||
|
|
@ -1,29 +1,27 @@
|
||||||
#!/usr/bin/env node
|
#!/usr/bin/env node
|
||||||
|
|
||||||
|
import process from 'node:process';
|
||||||
import {createRequire} from 'node:module';
|
import {createRequire} from 'node:module';
|
||||||
import {promisify} from 'node:util';
|
import {promisify} from 'node:util';
|
||||||
import tryToCatch from 'try-to-catch';
|
import {tryToCatch} from 'try-to-catch';
|
||||||
import {createSimport} from 'simport';
|
import {createSimport} from 'simport';
|
||||||
import parse from 'yargs-parser';
|
import parse from 'yargs-parser';
|
||||||
import process from 'node:process';
|
|
||||||
import exit from '../server/exit.js';
|
import exit from '../server/exit.js';
|
||||||
import {
|
import {createConfig, configPath} from '../server/config.mjs';
|
||||||
createConfig,
|
import * as env from '../server/env.mjs';
|
||||||
configPath,
|
|
||||||
} from '../server/config.js';
|
|
||||||
import env from '../server/env.js';
|
|
||||||
import prefixer from '../server/prefixer.js';
|
import prefixer from '../server/prefixer.js';
|
||||||
|
import * as validate from '../server/validate.mjs';
|
||||||
|
|
||||||
process.on('unhandledRejection', exit);
|
process.on('unhandledRejection', exit);
|
||||||
|
|
||||||
const require = createRequire(import.meta.url);
|
const require = createRequire(import.meta.url);
|
||||||
|
|
||||||
const Info = require('../package.json');
|
const Info = require('../package.json');
|
||||||
|
const isUndefined = (a) => typeof a === 'undefined';
|
||||||
const simport = createSimport(import.meta.url);
|
const simport = createSimport(import.meta.url);
|
||||||
|
|
||||||
const choose = (a, b) => {
|
const choose = (a, b) => {
|
||||||
if (a === undefined)
|
if (isUndefined(a))
|
||||||
return b;
|
return b;
|
||||||
|
|
||||||
return a;
|
return a;
|
||||||
|
|
@ -64,6 +62,8 @@ const yargsOptions = {
|
||||||
'terminal-path',
|
'terminal-path',
|
||||||
'terminal-command',
|
'terminal-command',
|
||||||
'columns',
|
'columns',
|
||||||
|
'menu',
|
||||||
|
'theme',
|
||||||
'import-url',
|
'import-url',
|
||||||
'import-token',
|
'import-token',
|
||||||
'export-token',
|
'export-token',
|
||||||
|
|
@ -87,6 +87,7 @@ const yargsOptions = {
|
||||||
'confirm-copy',
|
'confirm-copy',
|
||||||
'confirm-move',
|
'confirm-move',
|
||||||
'show-config',
|
'show-config',
|
||||||
|
'show-dot-files',
|
||||||
'show-file-name',
|
'show-file-name',
|
||||||
'vim',
|
'vim',
|
||||||
'keys-panel',
|
'keys-panel',
|
||||||
|
|
@ -100,43 +101,46 @@ const yargsOptions = {
|
||||||
],
|
],
|
||||||
default: {
|
default: {
|
||||||
'server': true,
|
'server': true,
|
||||||
'name': choose(env('name'), config('name')),
|
'name': choose(env.parse('name'), config('name')),
|
||||||
'auth': choose(env.bool('auth'), config('auth')),
|
'auth': choose(env.bool('auth'), config('auth')),
|
||||||
'port': config('port'),
|
'port': config('port'),
|
||||||
'online': config('online'),
|
'online': config('online'),
|
||||||
'open': choose(env.bool('open'), config('open')),
|
'open': choose(env.bool('open'), config('open')),
|
||||||
'editor': env('editor') || config('editor'),
|
'editor': env.parse('editor') || config('editor'),
|
||||||
|
'menu': env.parse('menu') || config('menu'),
|
||||||
'packer': config('packer') || 'tar',
|
'packer': config('packer') || 'tar',
|
||||||
'zip': config('zip'),
|
'zip': config('zip'),
|
||||||
'username': env('username') || config('username'),
|
'username': env.parse('username') || config('username'),
|
||||||
'root': choose(env('root'), config('root')),
|
'root': choose(env.parse('root'), config('root')),
|
||||||
'prefix': choose(env('prefix'), config('prefix')),
|
'prefix': choose(env.parse('prefix'), config('prefix')),
|
||||||
'console': choose(env.bool('console'), config('console')),
|
'console': choose(env.bool('console'), config('console')),
|
||||||
'contact': choose(env.bool('contact'), config('contact')),
|
'contact': choose(env.bool('contact'), config('contact')),
|
||||||
'terminal': choose(env.bool('terminal'), config('terminal')),
|
'terminal': choose(env.bool('terminal'), config('terminal')),
|
||||||
'columns': env('columns') || config('columns') || '',
|
'columns': env.parse('columns') || config('columns') || '',
|
||||||
|
'theme': env.parse('theme') || config('theme') || '',
|
||||||
'vim': choose(env.bool('vim'), config('vim')),
|
'vim': choose(env.bool('vim'), config('vim')),
|
||||||
'log': config('log'),
|
'log': config('log'),
|
||||||
|
|
||||||
'import-url': env('import_url') || config('importUrl'),
|
'import-url': env.parse('import_url') || config('importUrl'),
|
||||||
'import-listen': choose(env.bool('import_listen'), config('importListen')),
|
'import-listen': choose(env.bool('import_listen'), config('importListen')),
|
||||||
'import': choose(env.bool('import'), config('import')),
|
'import': choose(env.bool('import'), config('import')),
|
||||||
'export': choose(env.bool('export'), config('export')),
|
'export': choose(env.bool('export'), config('export')),
|
||||||
|
|
||||||
'prefix-socket': config('prefixSocket'),
|
'prefix-socket': config('prefixSocket'),
|
||||||
|
'show-dot-files': choose(env.bool('show_dot_files'), config('showDotFiles')),
|
||||||
'show-file-name': choose(env.bool('show_file_name'), config('showFileName')),
|
'show-file-name': choose(env.bool('show_file_name'), config('showFileName')),
|
||||||
'sync-console-path': choose(env.bool('sync_console_path'), config('syncConsolePath')),
|
'sync-console-path': choose(env.bool('sync_console_path'), config('syncConsolePath')),
|
||||||
'config-dialog': choose(env.bool('config_dialog'), config('configDialog')),
|
'config-dialog': choose(env.bool('config_dialog'), config('configDialog')),
|
||||||
'config-auth': choose(env.bool('config_auth'), config('configAuth')),
|
'config-auth': choose(env.bool('config_auth'), config('configAuth')),
|
||||||
'terminal-path': env('terminal_path') || config('terminalPath'),
|
'terminal-path': env.parse('terminal_path') || config('terminalPath'),
|
||||||
'terminal-command': env('terminal_command') || config('terminalCommand'),
|
'terminal-command': env.parse('terminal_command') || config('terminalCommand'),
|
||||||
'terminal-auto-restart': choose(env.bool('terminal_auto_restart'), config('terminalAutoRestart')),
|
'terminal-auto-restart': choose(env.bool('terminal_auto_restart'), config('terminalAutoRestart')),
|
||||||
'one-file-panel': choose(env.bool('one_file_panel'), config('oneFilePanel')),
|
'one-file-panel': choose(env.bool('one_file_panel'), config('oneFilePanel')),
|
||||||
'confirm-copy': choose(env.bool('confirm_copy'), config('confirmCopy')),
|
'confirm-copy': choose(env.bool('confirm_copy'), config('confirmCopy')),
|
||||||
'confirm-move': choose(env.bool('confirm_move'), config('confirmMove')),
|
'confirm-move': choose(env.bool('confirm_move'), config('confirmMove')),
|
||||||
'keys-panel': env.bool('keys_panel') || config('keysPanel'),
|
'keys-panel': env.bool('keys_panel') || config('keysPanel'),
|
||||||
'import-token': env('import_token') || config('importToken'),
|
'import-token': env.parse('import_token') || config('importToken'),
|
||||||
'export-token': env('export_token') || config('exportToken'),
|
'export-token': env.parse('export_token') || config('exportToken'),
|
||||||
|
|
||||||
'dropbox': config('dropbox'),
|
'dropbox': config('dropbox'),
|
||||||
'dropbox-token': config('dropboxToken') || '',
|
'dropbox-token': config('dropboxToken') || '',
|
||||||
|
|
@ -164,7 +168,7 @@ else
|
||||||
main();
|
main();
|
||||||
|
|
||||||
async function main() {
|
async function main() {
|
||||||
const validateArgs = await simport('@putout/cli-validate-args');
|
const {validateArgs} = await simport('@putout/cli-validate-args');
|
||||||
|
|
||||||
const error = await validateArgs(args, [
|
const error = await validateArgs(args, [
|
||||||
...yargsOptions.boolean,
|
...yargsOptions.boolean,
|
||||||
|
|
@ -177,6 +181,9 @@ async function main() {
|
||||||
if (args.repl)
|
if (args.repl)
|
||||||
repl();
|
repl();
|
||||||
|
|
||||||
|
validate.columns(args.columns);
|
||||||
|
validate.theme(args.theme);
|
||||||
|
|
||||||
port(args.port);
|
port(args.port);
|
||||||
|
|
||||||
config('name', args.name);
|
config('name', args.name);
|
||||||
|
|
@ -186,6 +193,7 @@ async function main() {
|
||||||
config('username', args.username);
|
config('username', args.username);
|
||||||
config('console', args.console);
|
config('console', args.console);
|
||||||
config('syncConsolePath', args.syncConsolePath);
|
config('syncConsolePath', args.syncConsolePath);
|
||||||
|
config('showDotFiles', args.showDotFiles);
|
||||||
config('showFileName', args.showFileName);
|
config('showFileName', args.showFileName);
|
||||||
config('contact', args.contact);
|
config('contact', args.contact);
|
||||||
config('terminal', args.terminal);
|
config('terminal', args.terminal);
|
||||||
|
|
@ -193,10 +201,12 @@ async function main() {
|
||||||
config('terminalCommand', args.terminalCommand);
|
config('terminalCommand', args.terminalCommand);
|
||||||
config('terminalAutoRestart', args.terminalAutoRestart);
|
config('terminalAutoRestart', args.terminalAutoRestart);
|
||||||
config('editor', args.editor);
|
config('editor', args.editor);
|
||||||
|
config('menu', args.menu);
|
||||||
config('prefix', prefixer(args.prefix));
|
config('prefix', prefixer(args.prefix));
|
||||||
config('prefixSocket', prefixer(args.prefixSocket));
|
config('prefixSocket', prefixer(args.prefixSocket));
|
||||||
config('root', args.root || '/');
|
config('root', args.root || '/');
|
||||||
config('vim', args.vim);
|
config('vim', args.vim);
|
||||||
|
config('theme', args.theme);
|
||||||
config('columns', args.columns);
|
config('columns', args.columns);
|
||||||
config('log', args.log);
|
config('log', args.log);
|
||||||
config('confirmCopy', args.confirmCopy);
|
config('confirmCopy', args.confirmCopy);
|
||||||
|
|
@ -224,20 +234,22 @@ async function main() {
|
||||||
prefix: config('prefix'),
|
prefix: config('prefix'),
|
||||||
prefixSocket: config('prefixSocket'),
|
prefixSocket: config('prefixSocket'),
|
||||||
columns: config('columns'),
|
columns: config('columns'),
|
||||||
|
theme: config('theme'),
|
||||||
|
menu: config('menu'),
|
||||||
};
|
};
|
||||||
|
|
||||||
const password = env('password') || args.password;
|
const password = env.parse('password') || args.password;
|
||||||
|
|
||||||
if (password)
|
if (password)
|
||||||
config('password', await getPassword(password));
|
config('password', await getPassword(password));
|
||||||
|
|
||||||
await validateRoot(options.root, config);
|
validateRoot(options.root, config);
|
||||||
|
|
||||||
if (args.showConfig)
|
if (args.showConfig)
|
||||||
await showConfig();
|
await showConfig();
|
||||||
|
|
||||||
const distribute = await simport('../server/distribute/index.js');
|
const {distributeImport} = await simport('../server/distribute/import.mjs');
|
||||||
const importConfig = promisify(distribute.import);
|
const importConfig = promisify(distributeImport);
|
||||||
|
|
||||||
await start(options, config);
|
await start(options, config);
|
||||||
|
|
||||||
|
|
@ -248,8 +260,7 @@ async function main() {
|
||||||
await importConfig(config);
|
await importConfig(config);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function validateRoot(root, config) {
|
function validateRoot(root, config) {
|
||||||
const validate = await simport(`${DIR_SERVER}validate.js`);
|
|
||||||
validate.root(root, config);
|
validate.root(root, config);
|
||||||
|
|
||||||
if (root === '/')
|
if (root === '/')
|
||||||
|
|
@ -309,7 +320,12 @@ async function readConfig(name) {
|
||||||
}
|
}
|
||||||
|
|
||||||
async function help() {
|
async function help() {
|
||||||
const bin = require('../json/help.json');
|
const {default: bin} = await import('../json/help.json', {
|
||||||
|
with: {
|
||||||
|
type: 'json',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
const forEachKey = await simport('for-each-key');
|
const forEachKey = await simport('for-each-key');
|
||||||
const currify = await simport('currify');
|
const currify = await simport('currify');
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,13 @@
|
||||||
#!/usr/bin/env node
|
#!/usr/bin/env node
|
||||||
|
|
||||||
import {promisify} from 'node:util';
|
import {promisify} from 'node:util';
|
||||||
import tryToCatch from 'try-to-catch';
|
import process from 'node:process';
|
||||||
|
import {tryToCatch} from 'try-to-catch';
|
||||||
import {createSimport} from 'simport';
|
import {createSimport} from 'simport';
|
||||||
import minor from 'minor';
|
import minor from 'minor';
|
||||||
import _place from 'place';
|
import _place from 'place';
|
||||||
import rendy from 'rendy';
|
import rendy from 'rendy';
|
||||||
import shortdate from 'shortdate';
|
import shortdate from 'shortdate';
|
||||||
import process from 'node:process';
|
|
||||||
|
|
||||||
const simport = createSimport(import.meta.url);
|
const simport = createSimport(import.meta.url);
|
||||||
const place = promisify(_place);
|
const place = promisify(_place);
|
||||||
|
|
@ -19,7 +19,8 @@ await main();
|
||||||
async function main() {
|
async function main() {
|
||||||
const history = '## Version history\n\n';
|
const history = '## Version history\n\n';
|
||||||
const link = '//github.com/coderaiser/cloudcmd/releases/tag/';
|
const link = '//github.com/coderaiser/cloudcmd/releases/tag/';
|
||||||
const template = '- *{{ date }}*, ' +
|
const template = '- ' +
|
||||||
|
'*{{ date }}*, ' +
|
||||||
'**[v{{ version }}]' +
|
'**[v{{ version }}]' +
|
||||||
'(' + link +
|
'(' + link +
|
||||||
'v{{ version }})**\n';
|
'v{{ version }})**\n';
|
||||||
|
|
|
||||||
|
|
@ -1,30 +1,24 @@
|
||||||
'use strict';
|
import process from 'node:process';
|
||||||
|
|
||||||
const process = require('process');
|
|
||||||
|
|
||||||
/* global DOM */
|
/* global DOM */
|
||||||
const Emitify = require('emitify');
|
import Emitify from 'emitify';
|
||||||
const inherits = require('inherits');
|
import inherits from 'inherits';
|
||||||
const rendy = require('rendy');
|
import rendy from 'rendy';
|
||||||
const load = require('load.js');
|
import load from 'load.js';
|
||||||
const tryToCatch = require('try-to-catch');
|
import {tryToCatch} from 'try-to-catch';
|
||||||
const {addSlashToEnd} = require('format-io');
|
import {addSlashToEnd} from 'format-io';
|
||||||
const pascalCase = require('just-pascal-case');
|
import pascalCase from 'just-pascal-case';
|
||||||
const currify = require('currify');
|
import currify from 'currify';
|
||||||
|
import * as Images from './dom/images.mjs';
|
||||||
const Images = require('./dom/images');
|
import {unregisterSW} from './sw/register.js';
|
||||||
|
import {getJsonFromFileTable} from './get-json-from-file-table.mjs';
|
||||||
const {unregisterSW} = require('./sw/register');
|
import {Key} from './key/index.mjs';
|
||||||
const getJsonFromFileTable = require('./get-json-from-file-table');
|
import {
|
||||||
const Key = require('./key');
|
|
||||||
|
|
||||||
const {
|
|
||||||
apiURL,
|
apiURL,
|
||||||
formatMsg,
|
formatMsg,
|
||||||
buildFromJSON,
|
buildFromJSON,
|
||||||
} = require('../common/cloudfunc');
|
} from '../common/cloudfunc.mjs';
|
||||||
|
import {loadModule} from './load-module.mjs';
|
||||||
const loadModule = require('./load-module');
|
|
||||||
|
|
||||||
const noJS = (a) => a.replace(/.js$/, '');
|
const noJS = (a) => a.replace(/.js$/, '');
|
||||||
|
|
||||||
|
|
@ -32,16 +26,19 @@ const isDev = process.env.NODE_ENV === 'development';
|
||||||
|
|
||||||
inherits(CloudCmdProto, Emitify);
|
inherits(CloudCmdProto, Emitify);
|
||||||
|
|
||||||
module.exports = new CloudCmdProto(DOM);
|
export const createCloudCmd = ({DOM, Listeners}) => {
|
||||||
|
return new CloudCmdProto({
|
||||||
|
DOM,
|
||||||
|
Listeners,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
load.addErrorListener((e, src) => {
|
load.addErrorListener((e, src) => {
|
||||||
const msg = `file ${src} could not be loaded`;
|
const msg = `file ${src} could not be loaded`;
|
||||||
Images.show.error(msg);
|
Images.show.error(msg);
|
||||||
});
|
});
|
||||||
|
|
||||||
function CloudCmdProto(DOM) {
|
function CloudCmdProto({DOM, Listeners}) {
|
||||||
let Listeners;
|
|
||||||
|
|
||||||
Emitify.call(this);
|
Emitify.call(this);
|
||||||
|
|
||||||
const CloudCmd = this;
|
const CloudCmd = this;
|
||||||
|
|
@ -49,21 +46,16 @@ function CloudCmdProto(DOM) {
|
||||||
|
|
||||||
const {Storage, Files} = DOM;
|
const {Storage, Files} = DOM;
|
||||||
|
|
||||||
this.log = (...a) => {
|
this.log = () => {
|
||||||
if (!isDev)
|
if (!isDev)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
console.log(...a);
|
|
||||||
};
|
};
|
||||||
this.prefix = '';
|
this.prefix = '';
|
||||||
this.prefixSocket = '';
|
this.prefixSocket = '';
|
||||||
this.prefixURL = '';
|
this.prefixURL = '';
|
||||||
|
|
||||||
this.MIN_ONE_PANEL_WIDTH = 1155;
|
this.MIN_ONE_PANEL_WIDTH = DOM.getCSSVar('min-one-panel-width');
|
||||||
this.HOST = location.origin || location.protocol + '//' + location.host;
|
this.HOST = location.origin || location.protocol + '//' + location.host;
|
||||||
|
|
||||||
this.TITLE = 'Cloud Commander';
|
|
||||||
|
|
||||||
this.sort = {
|
this.sort = {
|
||||||
left: 'name',
|
left: 'name',
|
||||||
right: 'name',
|
right: 'name',
|
||||||
|
|
@ -74,13 +66,15 @@ function CloudCmdProto(DOM) {
|
||||||
right: 'asc',
|
right: 'asc',
|
||||||
};
|
};
|
||||||
|
|
||||||
this.changeDir = async (path, {
|
this.changeDir = async (path, overrides = {}) => {
|
||||||
isRefresh,
|
const {
|
||||||
panel,
|
isRefresh,
|
||||||
history = true,
|
panel,
|
||||||
noCurrent,
|
history = true,
|
||||||
currentName,
|
noCurrent,
|
||||||
} = {}) => {
|
currentName,
|
||||||
|
} = overrides;
|
||||||
|
|
||||||
const refresh = isRefresh;
|
const refresh = isRefresh;
|
||||||
let panelChanged;
|
let panelChanged;
|
||||||
|
|
||||||
|
|
@ -95,15 +89,17 @@ function CloudCmdProto(DOM) {
|
||||||
imgPosition = 'top';
|
imgPosition = 'top';
|
||||||
|
|
||||||
Images.show.load(imgPosition, panel);
|
Images.show.load(imgPosition, panel);
|
||||||
|
|
||||||
/* загружаем содержимое каталога */
|
/* загружаем содержимое каталога */
|
||||||
await ajaxLoad(addSlashToEnd(path), {
|
await ajaxLoad(addSlashToEnd(path), {
|
||||||
refresh,
|
refresh,
|
||||||
history,
|
history,
|
||||||
noCurrent,
|
noCurrent,
|
||||||
currentName,
|
currentName,
|
||||||
|
showDotFiles: CloudCmd.config('showDotFiles'),
|
||||||
}, panel);
|
}, panel);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Конструктор CloudClient, который
|
* Конструктор CloudClient, который
|
||||||
* выполняет весь функционал по
|
* выполняет весь функционал по
|
||||||
|
|
@ -137,18 +133,10 @@ function CloudCmdProto(DOM) {
|
||||||
|
|
||||||
await initModules();
|
await initModules();
|
||||||
await baseInit();
|
await baseInit();
|
||||||
await loadStyle();
|
|
||||||
|
|
||||||
CloudCmd.route(location.hash);
|
CloudCmd.route(location.hash);
|
||||||
};
|
};
|
||||||
|
|
||||||
async function loadStyle() {
|
|
||||||
const {prefix} = CloudCmd;
|
|
||||||
const name = `${prefix}/dist/cloudcmd.common.css`;
|
|
||||||
|
|
||||||
await load.css(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.route = (path) => {
|
this.route = (path) => {
|
||||||
const query = path.split('/');
|
const query = path.split('/');
|
||||||
|
|
||||||
|
|
@ -158,7 +146,7 @@ function CloudCmdProto(DOM) {
|
||||||
const [kebabModule] = query;
|
const [kebabModule] = query;
|
||||||
const module = noJS(pascalCase(kebabModule.slice(1)));
|
const module = noJS(pascalCase(kebabModule.slice(1)));
|
||||||
|
|
||||||
const file = query[1];
|
const [, file] = query;
|
||||||
const current = DOM.getCurrentByName(file);
|
const current = DOM.getCurrentByName(file);
|
||||||
|
|
||||||
if (file && !current) {
|
if (file && !current) {
|
||||||
|
|
@ -216,7 +204,7 @@ function CloudCmdProto(DOM) {
|
||||||
async function saveCurrentName(currentName) {
|
async function saveCurrentName(currentName) {
|
||||||
await Storage.set('current-name', currentName);
|
await Storage.set('current-name', currentName);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function baseInit() {
|
async function baseInit() {
|
||||||
const files = DOM.getFiles();
|
const files = DOM.getFiles();
|
||||||
|
|
||||||
|
|
@ -237,7 +225,6 @@ function CloudCmdProto(DOM) {
|
||||||
|
|
||||||
const dirPath = DOM.getCurrentDirPath();
|
const dirPath = DOM.getCurrentDirPath();
|
||||||
|
|
||||||
Listeners = CloudCmd.Listeners;
|
|
||||||
Listeners.init();
|
Listeners.init();
|
||||||
|
|
||||||
const panels = getPanels();
|
const panels = getPanels();
|
||||||
|
|
@ -253,7 +240,7 @@ function CloudCmdProto(DOM) {
|
||||||
if (!data)
|
if (!data)
|
||||||
await Storage.setJson(dirPath, getJsonFromFileTable());
|
await Storage.setJson(dirPath, getJsonFromFileTable());
|
||||||
}
|
}
|
||||||
|
|
||||||
function getPanels() {
|
function getPanels() {
|
||||||
const panels = ['left'];
|
const panels = ['left'];
|
||||||
|
|
||||||
|
|
@ -265,7 +252,7 @@ function CloudCmdProto(DOM) {
|
||||||
'right',
|
'right',
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
this.execFromModule = async (moduleName, funcName, ...args) => {
|
this.execFromModule = async (moduleName, funcName, ...args) => {
|
||||||
await CloudCmd[moduleName]();
|
await CloudCmd[moduleName]();
|
||||||
|
|
||||||
|
|
@ -290,7 +277,7 @@ function CloudCmdProto(DOM) {
|
||||||
currentName,
|
currentName,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Функция загружает json-данные о Файловой Системе
|
* Функция загружает json-данные о Файловой Системе
|
||||||
* через ajax-запрос.
|
* через ajax-запрос.
|
||||||
|
|
@ -298,7 +285,6 @@ function CloudCmdProto(DOM) {
|
||||||
* @param options
|
* @param options
|
||||||
* { refresh, history } - необходимость обновить данные о каталоге
|
* { refresh, history } - необходимость обновить данные о каталоге
|
||||||
* @param panel
|
* @param panel
|
||||||
* @param callback
|
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
async function ajaxLoad(path, options = {}, panel) {
|
async function ajaxLoad(path, options = {}, panel) {
|
||||||
|
|
@ -343,16 +329,19 @@ function CloudCmdProto(DOM) {
|
||||||
|
|
||||||
Storage.setJson(path, newObj);
|
Storage.setJson(path, newObj);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Функция строит файловую таблицу
|
* Функция строит файловую таблицу
|
||||||
* @param json - данные о файлах
|
* @param data - данные о файлах
|
||||||
* @param panelParam
|
* @param panelParam
|
||||||
* @param history
|
* @param options - history, noCurrent, showDotFiles
|
||||||
* @param callback
|
|
||||||
*/
|
*/
|
||||||
async function createFileTable(data, panelParam, options) {
|
async function createFileTable(data, panelParam, options) {
|
||||||
const {history, noCurrent} = options;
|
const {
|
||||||
|
history,
|
||||||
|
noCurrent,
|
||||||
|
showDotFiles,
|
||||||
|
} = options;
|
||||||
|
|
||||||
const names = [
|
const names = [
|
||||||
'file',
|
'file',
|
||||||
|
|
@ -383,6 +372,7 @@ function CloudCmdProto(DOM) {
|
||||||
data,
|
data,
|
||||||
id: panel.id,
|
id: panel.id,
|
||||||
prefix,
|
prefix,
|
||||||
|
showDotFiles,
|
||||||
template: {
|
template: {
|
||||||
file,
|
file,
|
||||||
path,
|
path,
|
||||||
|
|
@ -409,7 +399,7 @@ function CloudCmdProto(DOM) {
|
||||||
CloudCmd.emit('active-dir', Info.dirPath);
|
CloudCmd.emit('active-dir', Info.dirPath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.goToParentDir = async () => {
|
this.goToParentDir = async () => {
|
||||||
const {
|
const {
|
||||||
dir,
|
dir,
|
||||||
|
|
@ -1,65 +0,0 @@
|
||||||
'use strict';
|
|
||||||
|
|
||||||
const process = require('process');
|
|
||||||
require('../css/main.css');
|
|
||||||
require('../css/nojs.css');
|
|
||||||
require('../css/columns/name-size-date.css');
|
|
||||||
require('../css/columns/name-size.css');
|
|
||||||
|
|
||||||
const wraptile = require('wraptile');
|
|
||||||
const load = require('load.js');
|
|
||||||
|
|
||||||
const {registerSW, listenSW} = require('./sw/register');
|
|
||||||
|
|
||||||
const isDev = process.env.NODE_ENV === 'development';
|
|
||||||
|
|
||||||
module.exports = window.CloudCmd = async (config) => {
|
|
||||||
window.Util = require('../common/util');
|
|
||||||
window.CloudFunc = require('../common/cloudfunc');
|
|
||||||
|
|
||||||
window.DOM = require('./dom');
|
|
||||||
window.CloudCmd = require('./client');
|
|
||||||
|
|
||||||
await register(config);
|
|
||||||
|
|
||||||
require('./listeners');
|
|
||||||
require('./key');
|
|
||||||
require('./sort');
|
|
||||||
|
|
||||||
const prefix = getPrefix(config.prefix);
|
|
||||||
|
|
||||||
window.CloudCmd.init(prefix, config);
|
|
||||||
};
|
|
||||||
|
|
||||||
function getPrefix(prefix) {
|
|
||||||
if (!prefix)
|
|
||||||
return '';
|
|
||||||
|
|
||||||
if (!prefix.indexOf('/'))
|
|
||||||
return prefix;
|
|
||||||
|
|
||||||
return `/${prefix}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
const onUpdateFound = wraptile(async (config) => {
|
|
||||||
if (isDev)
|
|
||||||
return;
|
|
||||||
|
|
||||||
const {DOM} = window;
|
|
||||||
const prefix = getPrefix(config.prefix);
|
|
||||||
|
|
||||||
await load.js(`${prefix}/dist/cloudcmd.common.js`);
|
|
||||||
await load.js(`${prefix}/dist/cloudcmd.js`);
|
|
||||||
|
|
||||||
console.log('cloudcmd: sw: updated');
|
|
||||||
|
|
||||||
DOM.Events.removeAll();
|
|
||||||
window.CloudCmd(config);
|
|
||||||
});
|
|
||||||
|
|
||||||
async function register(config) {
|
|
||||||
const {prefix} = config;
|
|
||||||
const sw = await registerSW(prefix);
|
|
||||||
|
|
||||||
listenSW(sw, 'updatefound', onUpdateFound(config));
|
|
||||||
}
|
|
||||||
74
client/cloudcmd.mjs
Normal file
74
client/cloudcmd.mjs
Normal file
|
|
@ -0,0 +1,74 @@
|
||||||
|
import process from 'node:process';
|
||||||
|
import wraptile from 'wraptile';
|
||||||
|
import load from 'load.js';
|
||||||
|
import '../css/main.css';
|
||||||
|
import {registerSW, listenSW} from './sw/register.js';
|
||||||
|
import {initSortPanel, sortPanel} from './sort.mjs';
|
||||||
|
import Util from '../common/util.js';
|
||||||
|
import * as CloudFunc from '../common/cloudfunc.mjs';
|
||||||
|
import DOM from './dom/index.js';
|
||||||
|
import {createCloudCmd} from './client.mjs';
|
||||||
|
import * as Listeners from './listeners/index.js';
|
||||||
|
|
||||||
|
const isDev = process.env.NODE_ENV === 'development';
|
||||||
|
|
||||||
|
export default init;
|
||||||
|
|
||||||
|
globalThis.CloudCmd = init;
|
||||||
|
|
||||||
|
async function init(config) {
|
||||||
|
globalThis.CloudCmd = createCloudCmd({
|
||||||
|
DOM,
|
||||||
|
Listeners,
|
||||||
|
});
|
||||||
|
globalThis.DOM = DOM;
|
||||||
|
globalThis.Util = Util;
|
||||||
|
globalThis.CloudFunc = CloudFunc;
|
||||||
|
|
||||||
|
await register(config);
|
||||||
|
|
||||||
|
initSortPanel();
|
||||||
|
globalThis.CloudCmd.sortPanel = sortPanel;
|
||||||
|
const prefix = getPrefix(config.prefix);
|
||||||
|
|
||||||
|
globalThis.CloudCmd.init(prefix, config);
|
||||||
|
|
||||||
|
if (globalThis.CloudCmd.config('menu') === 'aleman')
|
||||||
|
setTimeout(() => {
|
||||||
|
import('https://esm.sh/@putout/processor-html');
|
||||||
|
import('https://esm.sh/@putout/bundle');
|
||||||
|
}, 100);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getPrefix(prefix) {
|
||||||
|
if (!prefix)
|
||||||
|
return '';
|
||||||
|
|
||||||
|
if (!prefix.indexOf('/'))
|
||||||
|
return prefix;
|
||||||
|
|
||||||
|
return `/${prefix}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
const onUpdateFound = wraptile(async (config) => {
|
||||||
|
if (isDev)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const {DOM} = globalThis;
|
||||||
|
const prefix = getPrefix(config.prefix);
|
||||||
|
|
||||||
|
await load.js(`${prefix}/dist/cloudcmd.common.js`);
|
||||||
|
await load.js(`${prefix}/dist/cloudcmd.js`);
|
||||||
|
|
||||||
|
console.log('cloudcmd: sw: updated');
|
||||||
|
|
||||||
|
DOM.Events.removeAll();
|
||||||
|
globalThis.CloudCmd(config);
|
||||||
|
});
|
||||||
|
|
||||||
|
async function register(config) {
|
||||||
|
const {prefix} = config;
|
||||||
|
const sw = await registerSW(prefix);
|
||||||
|
|
||||||
|
listenSW(sw, 'updatefound', onUpdateFound(config));
|
||||||
|
}
|
||||||
|
|
@ -1,135 +0,0 @@
|
||||||
'use strict';
|
|
||||||
|
|
||||||
/* global CloudCmd */
|
|
||||||
const tryToPromiseAll = require('../../common/try-to-promise-all');
|
|
||||||
const Storage = require('./storage');
|
|
||||||
const DOM = require('./');
|
|
||||||
|
|
||||||
module.exports = new BufferProto();
|
|
||||||
|
|
||||||
function BufferProto() {
|
|
||||||
const Info = DOM.CurrentInfo;
|
|
||||||
const CLASS = 'cut-file';
|
|
||||||
const COPY = 'copy';
|
|
||||||
const CUT = 'cut';
|
|
||||||
|
|
||||||
const Buffer = {
|
|
||||||
cut: callIfEnabled.bind(null, cut),
|
|
||||||
copy: callIfEnabled.bind(null, copy),
|
|
||||||
clear: callIfEnabled.bind(null, clear),
|
|
||||||
paste: callIfEnabled.bind(null, paste),
|
|
||||||
};
|
|
||||||
|
|
||||||
function showMessage(msg) {
|
|
||||||
DOM.Dialog.alert(msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
function getNames() {
|
|
||||||
const files = DOM.getActiveFiles();
|
|
||||||
|
|
||||||
return DOM.getFilenames(files);
|
|
||||||
}
|
|
||||||
|
|
||||||
function addCutClass() {
|
|
||||||
const files = DOM.getActiveFiles();
|
|
||||||
|
|
||||||
for (const element of files) {
|
|
||||||
element.classList.add(CLASS);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function rmCutClass() {
|
|
||||||
const files = DOM.getByClassAll(CLASS);
|
|
||||||
|
|
||||||
for (const element of files) {
|
|
||||||
element.classList.remove(CLASS);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function callIfEnabled(callback) {
|
|
||||||
const is = CloudCmd.config('buffer');
|
|
||||||
|
|
||||||
if (is)
|
|
||||||
return callback();
|
|
||||||
|
|
||||||
showMessage('Buffer disabled in config!');
|
|
||||||
}
|
|
||||||
|
|
||||||
async function readBuffer() {
|
|
||||||
const [e, cp, ct] = await tryToPromiseAll([
|
|
||||||
Storage.getJson(COPY),
|
|
||||||
Storage.getJson(CUT),
|
|
||||||
]);
|
|
||||||
|
|
||||||
return [
|
|
||||||
e,
|
|
||||||
cp,
|
|
||||||
ct,
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
async function copy() {
|
|
||||||
const names = getNames();
|
|
||||||
const from = Info.dirPath;
|
|
||||||
|
|
||||||
await clear();
|
|
||||||
|
|
||||||
if (!names.length)
|
|
||||||
return;
|
|
||||||
|
|
||||||
await Storage.remove(CUT);
|
|
||||||
await Storage.setJson(COPY, {
|
|
||||||
from,
|
|
||||||
names,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async function cut() {
|
|
||||||
const names = getNames();
|
|
||||||
const from = Info.dirPath;
|
|
||||||
|
|
||||||
await clear();
|
|
||||||
|
|
||||||
if (!names.length)
|
|
||||||
return;
|
|
||||||
|
|
||||||
addCutClass();
|
|
||||||
|
|
||||||
await Storage.setJson(CUT, {
|
|
||||||
from,
|
|
||||||
names,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async function clear() {
|
|
||||||
await Storage.remove(COPY);
|
|
||||||
await Storage.remove(CUT);
|
|
||||||
|
|
||||||
rmCutClass();
|
|
||||||
}
|
|
||||||
|
|
||||||
async function paste() {
|
|
||||||
const [error, cp, ct] = await readBuffer();
|
|
||||||
|
|
||||||
if (error || !cp && !ct)
|
|
||||||
return showMessage(error || 'Buffer is empty!');
|
|
||||||
|
|
||||||
const opStr = cp ? 'copy' : 'move';
|
|
||||||
const data = cp || ct;
|
|
||||||
const {Operation} = CloudCmd;
|
|
||||||
const msg = 'Path is same!';
|
|
||||||
const to = Info.dirPath;
|
|
||||||
|
|
||||||
if (data.from === to)
|
|
||||||
return showMessage(msg);
|
|
||||||
|
|
||||||
Operation.show(opStr, {
|
|
||||||
...data,
|
|
||||||
to,
|
|
||||||
});
|
|
||||||
|
|
||||||
await clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
return Buffer;
|
|
||||||
}
|
|
||||||
124
client/dom/buffer.mjs
Normal file
124
client/dom/buffer.mjs
Normal file
|
|
@ -0,0 +1,124 @@
|
||||||
|
/* global CloudCmd*/
|
||||||
|
import tryToPromiseAll from '../../common/try-to-promise-all.js';
|
||||||
|
import Storage from './storage.js';
|
||||||
|
|
||||||
|
const CLASS = 'cut-file';
|
||||||
|
const COPY = 'copy';
|
||||||
|
const CUT = 'cut';
|
||||||
|
|
||||||
|
function showMessage(msg) {
|
||||||
|
globalThis.DOM.Dialog.alert(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getNames() {
|
||||||
|
const {DOM} = globalThis;
|
||||||
|
const files = DOM.getActiveFiles();
|
||||||
|
|
||||||
|
return DOM.getFilenames(files);
|
||||||
|
}
|
||||||
|
|
||||||
|
function addCutClass() {
|
||||||
|
const {DOM} = globalThis;
|
||||||
|
const files = DOM.getActiveFiles();
|
||||||
|
|
||||||
|
for (const element of files) {
|
||||||
|
element.classList.add(CLASS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function rmCutClass() {
|
||||||
|
const {DOM} = globalThis;
|
||||||
|
const files = DOM.getByClassAll(CLASS);
|
||||||
|
|
||||||
|
for (const element of files) {
|
||||||
|
element.classList.remove(CLASS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const checkEnabled = (fn) => () => {
|
||||||
|
const is = CloudCmd.config('buffer');
|
||||||
|
|
||||||
|
if (is)
|
||||||
|
return fn();
|
||||||
|
|
||||||
|
showMessage('Buffer disabled in config!');
|
||||||
|
};
|
||||||
|
|
||||||
|
async function readBuffer() {
|
||||||
|
const [e, cp, ct] = await tryToPromiseAll([
|
||||||
|
Storage.getJson(COPY),
|
||||||
|
Storage.getJson(CUT),
|
||||||
|
]);
|
||||||
|
|
||||||
|
return [
|
||||||
|
e,
|
||||||
|
cp,
|
||||||
|
ct,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
export const copy = checkEnabled(async () => {
|
||||||
|
const Info = globalThis.DOM.CurrentInfo;
|
||||||
|
const names = getNames();
|
||||||
|
const from = Info.dirPath;
|
||||||
|
|
||||||
|
await clear();
|
||||||
|
|
||||||
|
if (!names.length)
|
||||||
|
return;
|
||||||
|
|
||||||
|
await Storage.remove(CUT);
|
||||||
|
await Storage.setJson(COPY, {
|
||||||
|
from,
|
||||||
|
names,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
export const cut = checkEnabled(async () => {
|
||||||
|
const Info = globalThis.DOM.CurrentInfo;
|
||||||
|
const names = getNames();
|
||||||
|
const from = Info.dirPath;
|
||||||
|
|
||||||
|
await clear();
|
||||||
|
|
||||||
|
if (!names.length)
|
||||||
|
return;
|
||||||
|
|
||||||
|
addCutClass();
|
||||||
|
|
||||||
|
await Storage.setJson(CUT, {
|
||||||
|
from,
|
||||||
|
names,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
export const clear = checkEnabled(async () => {
|
||||||
|
await Storage.remove(COPY);
|
||||||
|
await Storage.remove(CUT);
|
||||||
|
|
||||||
|
rmCutClass();
|
||||||
|
});
|
||||||
|
|
||||||
|
export const paste = checkEnabled(async () => {
|
||||||
|
const Info = globalThis.DOM.CurrentInfo;
|
||||||
|
const [error, cp, ct] = await readBuffer();
|
||||||
|
|
||||||
|
if (error || !cp && !ct)
|
||||||
|
return showMessage(error || 'Buffer is empty!');
|
||||||
|
|
||||||
|
const opStr = cp ? 'copy' : 'move';
|
||||||
|
const data = cp || ct;
|
||||||
|
const {Operation} = CloudCmd;
|
||||||
|
const msg = 'Path is same!';
|
||||||
|
const to = Info.dirPath;
|
||||||
|
|
||||||
|
if (data.from === to)
|
||||||
|
return showMessage(msg);
|
||||||
|
|
||||||
|
Operation.show(opStr, {
|
||||||
|
...data,
|
||||||
|
to,
|
||||||
|
});
|
||||||
|
|
||||||
|
await clear();
|
||||||
|
});
|
||||||
|
|
@ -1,13 +1,8 @@
|
||||||
'use strict';
|
|
||||||
|
|
||||||
/* global DOM */
|
/* global DOM */
|
||||||
/* global CloudCmd */
|
/* global CloudCmd */
|
||||||
const {atob, btoa} = require('../../common/base64');
|
import createElement from '@cloudcmd/create-element';
|
||||||
const createElement = require('@cloudcmd/create-element');
|
import {encode, decode} from '../../common/entity.js';
|
||||||
|
import {getTitle, FS} from '../../common/cloudfunc.mjs';
|
||||||
const {encode, decode} = require('../../common/entity');
|
|
||||||
|
|
||||||
const {getTitle, FS} = require('../../common/cloudfunc');
|
|
||||||
|
|
||||||
let Title;
|
let Title;
|
||||||
|
|
||||||
|
|
@ -15,14 +10,15 @@ const CURRENT_FILE = 'current-file';
|
||||||
const encodeNBSP = (a) => a?.replace('\xa0', ' ');
|
const encodeNBSP = (a) => a?.replace('\xa0', ' ');
|
||||||
const decodeNBSP = (a) => a?.replace(' ', '\xa0');
|
const decodeNBSP = (a) => a?.replace(' ', '\xa0');
|
||||||
|
|
||||||
module.exports._CURRENT_FILE = CURRENT_FILE;
|
export const _CURRENT_FILE = CURRENT_FILE;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* set name from current (or param) file
|
* set name from current (or param) file
|
||||||
*
|
*
|
||||||
* @param name
|
* @param name
|
||||||
* @param current
|
* @param current
|
||||||
*/
|
*/
|
||||||
module.exports.setCurrentName = (name, current) => {
|
export const setCurrentName = (name, current) => {
|
||||||
const Info = DOM.CurrentInfo;
|
const Info = DOM.CurrentInfo;
|
||||||
const {link} = Info;
|
const {link} = Info;
|
||||||
const {prefix} = CloudCmd;
|
const {prefix} = CloudCmd;
|
||||||
|
|
@ -44,7 +40,7 @@ module.exports.setCurrentName = (name, current) => {
|
||||||
*
|
*
|
||||||
* @param currentFile
|
* @param currentFile
|
||||||
*/
|
*/
|
||||||
module.exports.getCurrentName = (currentFile) => {
|
export const getCurrentName = (currentFile) => {
|
||||||
const current = currentFile || DOM.getCurrentFile();
|
const current = currentFile || DOM.getCurrentFile();
|
||||||
|
|
||||||
if (!current)
|
if (!current)
|
||||||
|
|
@ -71,18 +67,19 @@ const parseNameAttribute = (attribute) => {
|
||||||
return decodeNBSP(decodeURI(atob(attribute)));
|
return decodeNBSP(decodeURI(atob(attribute)));
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports._parseNameAttribute = parseNameAttribute;
|
export const _parseNameAttribute = parseNameAttribute;
|
||||||
|
|
||||||
const parseHrefAttribute = (prefix, attribute) => {
|
const parseHrefAttribute = (prefix, attribute) => {
|
||||||
attribute = attribute.replace(RegExp('^' + prefix + FS), '');
|
attribute = attribute.replace(RegExp('^' + prefix + FS), '');
|
||||||
return decode(decodeNBSP(attribute));
|
return decode(decodeNBSP(attribute));
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports._parseHrefAttribute = parseHrefAttribute;
|
export const _parseHrefAttribute = parseHrefAttribute;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* get current direcotory path
|
* get current direcotory path
|
||||||
*/
|
*/
|
||||||
module.exports.getCurrentDirPath = (panel = DOM.getPanel()) => {
|
export const getCurrentDirPath = (panel = DOM.getPanel()) => {
|
||||||
const path = DOM.getByDataName('js-path', panel);
|
const path = DOM.getByDataName('js-path', panel);
|
||||||
return path.textContent;
|
return path.textContent;
|
||||||
};
|
};
|
||||||
|
|
@ -92,7 +89,7 @@ module.exports.getCurrentDirPath = (panel = DOM.getPanel()) => {
|
||||||
*
|
*
|
||||||
* @param currentFile - current file by default
|
* @param currentFile - current file by default
|
||||||
*/
|
*/
|
||||||
module.exports.getCurrentPath = (currentFile) => {
|
export const getCurrentPath = (currentFile) => {
|
||||||
const current = currentFile || DOM.getCurrentFile();
|
const current = currentFile || DOM.getCurrentFile();
|
||||||
const [element] = DOM.getByTag('a', current);
|
const [element] = DOM.getByTag('a', current);
|
||||||
const {prefix} = CloudCmd;
|
const {prefix} = CloudCmd;
|
||||||
|
|
@ -103,7 +100,7 @@ module.exports.getCurrentPath = (currentFile) => {
|
||||||
/**
|
/**
|
||||||
* get current direcotory name
|
* get current direcotory name
|
||||||
*/
|
*/
|
||||||
module.exports.getCurrentDirName = () => {
|
export const getCurrentDirName = () => {
|
||||||
const href = DOM
|
const href = DOM
|
||||||
.getCurrentDirPath()
|
.getCurrentDirPath()
|
||||||
.replace(/\/$/, '');
|
.replace(/\/$/, '');
|
||||||
|
|
@ -116,7 +113,7 @@ module.exports.getCurrentDirName = () => {
|
||||||
/**
|
/**
|
||||||
* get current direcotory path
|
* get current direcotory path
|
||||||
*/
|
*/
|
||||||
module.exports.getParentDirPath = (panel) => {
|
export const getParentDirPath = (panel) => {
|
||||||
const path = DOM.getCurrentDirPath(panel);
|
const path = DOM.getCurrentDirPath(panel);
|
||||||
const dirName = DOM.getCurrentDirName() + '/';
|
const dirName = DOM.getCurrentDirName() + '/';
|
||||||
const index = path.lastIndexOf(dirName);
|
const index = path.lastIndexOf(dirName);
|
||||||
|
|
@ -130,7 +127,7 @@ module.exports.getParentDirPath = (panel) => {
|
||||||
/**
|
/**
|
||||||
* get not current direcotory path
|
* get not current direcotory path
|
||||||
*/
|
*/
|
||||||
module.exports.getNotCurrentDirPath = () => {
|
export const getNotCurrentDirPath = () => {
|
||||||
const panel = DOM.getPanel({
|
const panel = DOM.getPanel({
|
||||||
active: false,
|
active: false,
|
||||||
});
|
});
|
||||||
|
|
@ -143,14 +140,14 @@ module.exports.getNotCurrentDirPath = () => {
|
||||||
*
|
*
|
||||||
* @currentFile
|
* @currentFile
|
||||||
*/
|
*/
|
||||||
module.exports.getCurrentFile = () => {
|
export const getCurrentFile = () => {
|
||||||
return DOM.getByClass(CURRENT_FILE);
|
return DOM.getByClass(CURRENT_FILE);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* get current file by name
|
* get current file by name
|
||||||
*/
|
*/
|
||||||
module.exports.getCurrentByName = (name, panel = DOM.CurrentInfo.panel) => {
|
export const getCurrentByName = (name, panel = DOM.CurrentInfo.panel) => {
|
||||||
const dataName = 'js-file-' + btoa(encodeURI(encodeNBSP(name)));
|
const dataName = 'js-file-' + btoa(encodeURI(encodeNBSP(name)));
|
||||||
return DOM.getByDataName(dataName, panel);
|
return DOM.getByDataName(dataName, panel);
|
||||||
};
|
};
|
||||||
|
|
@ -172,7 +169,7 @@ function unsetCurrentFile(currentFile) {
|
||||||
/**
|
/**
|
||||||
* unified way to set current file
|
* unified way to set current file
|
||||||
*/
|
*/
|
||||||
module.exports.setCurrentFile = (currentFile, options) => {
|
export const setCurrentFile = (currentFile, options) => {
|
||||||
const o = options;
|
const o = options;
|
||||||
const currentFileWas = DOM.getCurrentFile();
|
const currentFileWas = DOM.getCurrentFile();
|
||||||
|
|
||||||
|
|
@ -196,7 +193,7 @@ module.exports.setCurrentFile = (currentFile, options) => {
|
||||||
name,
|
name,
|
||||||
path,
|
path,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
/* history could be present
|
/* history could be present
|
||||||
* but it should be false
|
* but it should be false
|
||||||
* to prevent default behavior
|
* to prevent default behavior
|
||||||
|
|
@ -219,7 +216,7 @@ module.exports.setCurrentFile = (currentFile, options) => {
|
||||||
return DOM;
|
return DOM;
|
||||||
};
|
};
|
||||||
|
|
||||||
this.setCurrentByName = (name) => {
|
export const setCurrentByName = (name) => {
|
||||||
const current = DOM.getCurrentByName(name);
|
const current = DOM.getCurrentByName(name);
|
||||||
return DOM.setCurrentFile(current);
|
return DOM.setCurrentFile(current);
|
||||||
};
|
};
|
||||||
|
|
@ -230,7 +227,7 @@ this.setCurrentByName = (name) => {
|
||||||
* @param layer - element
|
* @param layer - element
|
||||||
* @param - position {x, y}
|
* @param - position {x, y}
|
||||||
*/
|
*/
|
||||||
module.exports.getCurrentByPosition = ({x, y}) => {
|
export const getCurrentByPosition = ({x, y}) => {
|
||||||
const element = document.elementFromPoint(x, y);
|
const element = document.elementFromPoint(x, y);
|
||||||
|
|
||||||
const getEl = (el) => {
|
const getEl = (el) => {
|
||||||
|
|
@ -262,7 +259,7 @@ module.exports.getCurrentByPosition = ({x, y}) => {
|
||||||
*
|
*
|
||||||
* @param currentFile
|
* @param currentFile
|
||||||
*/
|
*/
|
||||||
module.exports.isCurrentFile = (currentFile) => {
|
export const isCurrentFile = (currentFile) => {
|
||||||
if (!currentFile)
|
if (!currentFile)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
|
@ -274,7 +271,7 @@ module.exports.isCurrentFile = (currentFile) => {
|
||||||
*
|
*
|
||||||
* @param name
|
* @param name
|
||||||
*/
|
*/
|
||||||
module.exports.setTitle = (name) => {
|
export const setTitle = (name) => {
|
||||||
if (!Title)
|
if (!Title)
|
||||||
Title = DOM.getByTag('title')[0] || createElement('title', {
|
Title = DOM.getByTag('title')[0] || createElement('title', {
|
||||||
innerHTML: name,
|
innerHTML: name,
|
||||||
|
|
@ -291,22 +288,21 @@ module.exports.setTitle = (name) => {
|
||||||
*
|
*
|
||||||
* @param currentFile
|
* @param currentFile
|
||||||
*/
|
*/
|
||||||
module.exports.isCurrentIsDir = (currentFile) => {
|
export const isCurrentIsDir = (currentFile) => {
|
||||||
const current = currentFile || DOM.getCurrentFile();
|
const current = currentFile || DOM.getCurrentFile();
|
||||||
const path = DOM.getCurrentPath(current);
|
const path = DOM.getCurrentPath(current);
|
||||||
const fileType = DOM.getCurrentType(current);
|
const fileType = DOM.getCurrentType(current);
|
||||||
|
|
||||||
const isZip = /\.zip$/.test(path);
|
const isZip = path.endsWith('.zip');
|
||||||
const isDir = /^directory(-link)?/.test(fileType);
|
const isDir = /^directory(-link)?/.test(fileType);
|
||||||
|
|
||||||
return isDir || isZip;
|
return isDir || isZip;
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports.getCurrentType = (currentFile) => {
|
export const getCurrentType = (currentFile) => {
|
||||||
const current = currentFile || DOM.getCurrentFile();
|
const current = currentFile || DOM.getCurrentFile();
|
||||||
const el = DOM.getByDataName('js-type', current);
|
const el = DOM.getByDataName('js-type', current);
|
||||||
const type = el
|
const type = el.className
|
||||||
.className
|
|
||||||
.split(' ')
|
.split(' ')
|
||||||
.pop();
|
.pop();
|
||||||
|
|
||||||
|
|
@ -1,20 +1,18 @@
|
||||||
'use strict';
|
import {test, stub} from 'supertape';
|
||||||
|
import {create} from 'auto-globals';
|
||||||
|
import wraptile from 'wraptile';
|
||||||
|
import * as currentFile from './current-file.mjs';
|
||||||
|
|
||||||
const {test, stub} = require('supertape');
|
|
||||||
|
|
||||||
const {create} = require('auto-globals');
|
|
||||||
const wraptile = require('wraptile');
|
|
||||||
const currentFile = require('./current-file');
|
|
||||||
const id = (a) => a;
|
const id = (a) => a;
|
||||||
|
|
||||||
const returns = wraptile(id);
|
const returns = wraptile(id);
|
||||||
const {_CURRENT_FILE} = currentFile;
|
const {_CURRENT_FILE} = currentFile;
|
||||||
|
|
||||||
test('current-file: setCurrentName: setAttribute', (t) => {
|
test('current-file: setCurrentName: setAttribute', (t) => {
|
||||||
const {DOM, CloudCmd} = global;
|
const {DOM, CloudCmd} = globalThis;
|
||||||
|
|
||||||
global.DOM = getDOM();
|
globalThis.DOM = getDOM();
|
||||||
global.CloudCmd = getCloudCmd();
|
globalThis.CloudCmd = getCloudCmd();
|
||||||
|
|
||||||
const current = create();
|
const current = create();
|
||||||
const {setAttribute} = current;
|
const {setAttribute} = current;
|
||||||
|
|
@ -23,17 +21,17 @@ test('current-file: setCurrentName: setAttribute', (t) => {
|
||||||
|
|
||||||
t.calledWith(setAttribute, ['data-name', 'js-file-aGVsbG8='], 'should call setAttribute');
|
t.calledWith(setAttribute, ['data-name', 'js-file-aGVsbG8='], 'should call setAttribute');
|
||||||
|
|
||||||
global.DOM = DOM;
|
globalThis.DOM = DOM;
|
||||||
global.CloudCmd = CloudCmd;
|
globalThis.CloudCmd = CloudCmd;
|
||||||
|
|
||||||
t.end();
|
t.end();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('current-file: setCurrentName: setAttribute: cyrillic', (t) => {
|
test('current-file: setCurrentName: setAttribute: cyrillic', (t) => {
|
||||||
const {DOM, CloudCmd} = global;
|
const {DOM, CloudCmd} = globalThis;
|
||||||
|
|
||||||
global.DOM = getDOM();
|
globalThis.DOM = getDOM();
|
||||||
global.CloudCmd = getCloudCmd();
|
globalThis.CloudCmd = getCloudCmd();
|
||||||
|
|
||||||
const current = create();
|
const current = create();
|
||||||
const {setAttribute} = current;
|
const {setAttribute} = current;
|
||||||
|
|
@ -42,8 +40,8 @@ test('current-file: setCurrentName: setAttribute: cyrillic', (t) => {
|
||||||
|
|
||||||
t.calledWith(setAttribute, ['data-name', 'js-file-JUQwJUIwJUQwJUI5'], 'should call setAttribute');
|
t.calledWith(setAttribute, ['data-name', 'js-file-JUQwJUIwJUQwJUI5'], 'should call setAttribute');
|
||||||
|
|
||||||
global.DOM = DOM;
|
globalThis.DOM = DOM;
|
||||||
global.CloudCmd = CloudCmd;
|
globalThis.CloudCmd = CloudCmd;
|
||||||
|
|
||||||
t.end();
|
t.end();
|
||||||
});
|
});
|
||||||
|
|
@ -59,12 +57,12 @@ test('current-file: getCurrentName', (t) => {
|
||||||
});
|
});
|
||||||
|
|
||||||
test('current-file: emit', (t) => {
|
test('current-file: emit', (t) => {
|
||||||
const {DOM, CloudCmd} = global;
|
const {DOM, CloudCmd} = globalThis;
|
||||||
|
|
||||||
const emit = stub();
|
const emit = stub();
|
||||||
|
|
||||||
global.DOM = getDOM();
|
globalThis.DOM = getDOM();
|
||||||
global.CloudCmd = getCloudCmd({
|
globalThis.CloudCmd = getCloudCmd({
|
||||||
emit,
|
emit,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -74,22 +72,22 @@ test('current-file: emit', (t) => {
|
||||||
|
|
||||||
t.calledWith(emit, ['current-file', current], 'should call emit');
|
t.calledWith(emit, ['current-file', current], 'should call emit');
|
||||||
|
|
||||||
global.DOM = DOM;
|
globalThis.DOM = DOM;
|
||||||
global.CloudCmd = CloudCmd;
|
globalThis.CloudCmd = CloudCmd;
|
||||||
|
|
||||||
t.end();
|
t.end();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('current-file: setCurrentName: return', (t) => {
|
test('current-file: setCurrentName: return', (t) => {
|
||||||
const {DOM, CloudCmd} = global;
|
const {DOM, CloudCmd} = globalThis;
|
||||||
|
|
||||||
const link = {};
|
const link = {};
|
||||||
|
|
||||||
global.DOM = getDOM({
|
globalThis.DOM = getDOM({
|
||||||
link,
|
link,
|
||||||
});
|
});
|
||||||
|
|
||||||
global.CloudCmd = getCloudCmd();
|
globalThis.CloudCmd = getCloudCmd();
|
||||||
|
|
||||||
const current = create();
|
const current = create();
|
||||||
|
|
||||||
|
|
@ -97,19 +95,19 @@ test('current-file: setCurrentName: return', (t) => {
|
||||||
|
|
||||||
t.equal(result, link, 'should return link');
|
t.equal(result, link, 'should return link');
|
||||||
|
|
||||||
global.DOM = DOM;
|
globalThis.DOM = DOM;
|
||||||
global.CloudCmd = CloudCmd;
|
globalThis.CloudCmd = CloudCmd;
|
||||||
|
|
||||||
t.end();
|
t.end();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('current-file: getParentDirPath: result', (t) => {
|
test('current-file: getParentDirPath: result', (t) => {
|
||||||
const {DOM} = global;
|
const {DOM} = globalThis;
|
||||||
|
|
||||||
const getCurrentDirPath = returns('/D/Films/+++favorite films/');
|
const getCurrentDirPath = returns('/D/Films/+++favorite films/');
|
||||||
const getCurrentDirName = returns('+++favorite films');
|
const getCurrentDirName = returns('+++favorite films');
|
||||||
|
|
||||||
global.DOM = getDOM({
|
globalThis.DOM = getDOM({
|
||||||
getCurrentDirPath,
|
getCurrentDirPath,
|
||||||
getCurrentDirName,
|
getCurrentDirName,
|
||||||
});
|
});
|
||||||
|
|
@ -117,55 +115,55 @@ test('current-file: getParentDirPath: result', (t) => {
|
||||||
const result = currentFile.getParentDirPath();
|
const result = currentFile.getParentDirPath();
|
||||||
const expected = '/D/Films/';
|
const expected = '/D/Films/';
|
||||||
|
|
||||||
global.DOM = DOM;
|
globalThis.DOM = DOM;
|
||||||
|
|
||||||
t.equal(result, expected, 'should return parent dir path');
|
t.equal(result, expected, 'should return parent dir path');
|
||||||
t.end();
|
t.end();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('current-file: isCurrentFile: no', (t) => {
|
test('current-file: isCurrentFile: no', (t) => {
|
||||||
const {DOM, CloudCmd} = global;
|
const {DOM, CloudCmd} = globalThis;
|
||||||
|
|
||||||
global.DOM = getDOM();
|
globalThis.DOM = getDOM();
|
||||||
global.CloudCmd = getCloudCmd();
|
globalThis.CloudCmd = getCloudCmd();
|
||||||
|
|
||||||
const result = currentFile.isCurrentFile();
|
const result = currentFile.isCurrentFile();
|
||||||
|
|
||||||
global.DOM = DOM;
|
globalThis.DOM = DOM;
|
||||||
global.CloudCmd = CloudCmd;
|
globalThis.CloudCmd = CloudCmd;
|
||||||
|
|
||||||
t.notOk(result);
|
t.notOk(result);
|
||||||
t.end();
|
t.end();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('current-file: isCurrentFile', (t) => {
|
test('current-file: isCurrentFile', (t) => {
|
||||||
const {DOM, CloudCmd} = global;
|
const {DOM, CloudCmd} = globalThis;
|
||||||
|
|
||||||
const isContainClass = stub();
|
const isContainClass = stub();
|
||||||
|
|
||||||
global.DOM = getDOM({
|
globalThis.DOM = getDOM({
|
||||||
isContainClass,
|
isContainClass,
|
||||||
});
|
});
|
||||||
|
|
||||||
global.CloudCmd = getCloudCmd();
|
globalThis.CloudCmd = getCloudCmd();
|
||||||
|
|
||||||
const current = {};
|
const current = {};
|
||||||
currentFile.isCurrentFile(current);
|
currentFile.isCurrentFile(current);
|
||||||
|
|
||||||
global.DOM = DOM;
|
globalThis.DOM = DOM;
|
||||||
global.CloudCmd = CloudCmd;
|
globalThis.CloudCmd = CloudCmd;
|
||||||
|
|
||||||
t.calledWith(isContainClass, [current, _CURRENT_FILE], 'should call isContainClass');
|
t.calledWith(isContainClass, [current, _CURRENT_FILE], 'should call isContainClass');
|
||||||
t.end();
|
t.end();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('current-file: getCurrentType', (t) => {
|
test('current-file: getCurrentType', (t) => {
|
||||||
const {DOM, CloudCmd} = global;
|
const {DOM, CloudCmd} = globalThis;
|
||||||
|
|
||||||
global.DOM = getDOM();
|
globalThis.DOM = getDOM();
|
||||||
global.CloudCmd = getCloudCmd();
|
globalThis.CloudCmd = getCloudCmd();
|
||||||
|
|
||||||
const {getByDataName} = global.DOM;
|
const {getByDataName} = globalThis.DOM;
|
||||||
|
|
||||||
getByDataName.returns({
|
getByDataName.returns({
|
||||||
className: 'mini-icon directory',
|
className: 'mini-icon directory',
|
||||||
|
|
@ -175,98 +173,96 @@ test('current-file: getCurrentType', (t) => {
|
||||||
|
|
||||||
currentFile.getCurrentType(current);
|
currentFile.getCurrentType(current);
|
||||||
|
|
||||||
global.DOM = DOM;
|
globalThis.DOM = DOM;
|
||||||
global.CloudCmd = CloudCmd;
|
globalThis.CloudCmd = CloudCmd;
|
||||||
|
|
||||||
t.calledWith(getByDataName, ['js-type', current]);
|
t.calledWith(getByDataName, ['js-type', current]);
|
||||||
t.end();
|
t.end();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('current-file: isCurrentIsDir: getCurrentType', (t) => {
|
test('current-file: isCurrentIsDir: getCurrentType', (t) => {
|
||||||
const {DOM, CloudCmd} = global;
|
const {DOM, CloudCmd} = globalThis;
|
||||||
|
|
||||||
global.DOM = getDOM();
|
globalThis.DOM = getDOM();
|
||||||
global.CloudCmd = getCloudCmd();
|
globalThis.CloudCmd = getCloudCmd();
|
||||||
|
|
||||||
const {getCurrentType} = global.DOM;
|
const {getCurrentType} = globalThis.DOM;
|
||||||
|
|
||||||
const current = create();
|
const current = create();
|
||||||
|
|
||||||
currentFile.isCurrentIsDir(current);
|
currentFile.isCurrentIsDir(current);
|
||||||
|
|
||||||
global.DOM = DOM;
|
globalThis.DOM = DOM;
|
||||||
global.CloudCmd = CloudCmd;
|
globalThis.CloudCmd = CloudCmd;
|
||||||
|
|
||||||
t.calledWith(getCurrentType, [current]);
|
t.calledWith(getCurrentType, [current]);
|
||||||
t.end();
|
t.end();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('current-file: isCurrentIsDir: directory', (t) => {
|
test('current-file: isCurrentIsDir: directory', (t) => {
|
||||||
const {DOM, CloudCmd} = global;
|
const {DOM, CloudCmd} = globalThis;
|
||||||
|
|
||||||
global.DOM = getDOM({
|
globalThis.DOM = getDOM({
|
||||||
getCurrentType: stub().returns('directory'),
|
getCurrentType: stub().returns('directory'),
|
||||||
});
|
});
|
||||||
|
|
||||||
global.CloudCmd = getCloudCmd();
|
globalThis.CloudCmd = getCloudCmd();
|
||||||
|
|
||||||
const current = create();
|
const current = create();
|
||||||
|
|
||||||
const result = currentFile.isCurrentIsDir(current);
|
const result = currentFile.isCurrentIsDir(current);
|
||||||
|
|
||||||
global.DOM = DOM;
|
globalThis.DOM = DOM;
|
||||||
global.CloudCmd = CloudCmd;
|
globalThis.CloudCmd = CloudCmd;
|
||||||
|
|
||||||
t.ok(result);
|
t.ok(result);
|
||||||
t.end();
|
t.end();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('current-file: isCurrentIsDir: directory-link', (t) => {
|
test('current-file: isCurrentIsDir: directory-link', (t) => {
|
||||||
const {DOM, CloudCmd} = global;
|
const {DOM, CloudCmd} = globalThis;
|
||||||
|
|
||||||
global.DOM = getDOM({
|
globalThis.DOM = getDOM({
|
||||||
getCurrentType: stub().returns('directory-link'),
|
getCurrentType: stub().returns('directory-link'),
|
||||||
});
|
});
|
||||||
|
|
||||||
global.CloudCmd = getCloudCmd();
|
globalThis.CloudCmd = getCloudCmd();
|
||||||
|
|
||||||
const current = create();
|
const current = create();
|
||||||
|
|
||||||
const result = currentFile.isCurrentIsDir(current);
|
const result = currentFile.isCurrentIsDir(current);
|
||||||
|
|
||||||
global.DOM = DOM;
|
globalThis.DOM = DOM;
|
||||||
global.CloudCmd = CloudCmd;
|
globalThis.CloudCmd = CloudCmd;
|
||||||
|
|
||||||
t.ok(result);
|
t.ok(result);
|
||||||
t.end();
|
t.end();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('current-file: isCurrentIsDir: file', (t) => {
|
test('current-file: isCurrentIsDir: file', (t) => {
|
||||||
const {DOM, CloudCmd} = global;
|
const {DOM, CloudCmd} = globalThis;
|
||||||
|
|
||||||
global.DOM = getDOM({
|
globalThis.DOM = getDOM({
|
||||||
getCurrentType: stub().returns('file'),
|
getCurrentType: stub().returns('file'),
|
||||||
});
|
});
|
||||||
|
|
||||||
global.CloudCmd = getCloudCmd();
|
globalThis.CloudCmd = getCloudCmd();
|
||||||
|
|
||||||
const current = create();
|
const current = create();
|
||||||
|
|
||||||
const result = currentFile.isCurrentIsDir(current);
|
const result = currentFile.isCurrentIsDir(current);
|
||||||
|
|
||||||
global.DOM = DOM;
|
globalThis.DOM = DOM;
|
||||||
global.CloudCmd = CloudCmd;
|
globalThis.CloudCmd = CloudCmd;
|
||||||
|
|
||||||
t.notOk(result);
|
t.notOk(result);
|
||||||
t.end();
|
t.end();
|
||||||
});
|
});
|
||||||
|
|
||||||
function getCloudCmd({emit} = {}) {
|
const getCloudCmd = ({emit} = {}) => ({
|
||||||
return {
|
prefix: '',
|
||||||
prefix: '',
|
emit: emit || stub(),
|
||||||
emit: emit || stub(),
|
});
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
test('current-file: parseNameAttribute', (t) => {
|
test('current-file: parseNameAttribute', (t) => {
|
||||||
const result = currentFile._parseNameAttribute('js-file-aGVsbG8mbmJzcDt3b3JsZA==');
|
const result = currentFile._parseNameAttribute('js-file-aGVsbG8mbmJzcDt3b3JsZA==');
|
||||||
|
|
@ -285,15 +281,17 @@ test('current-file: parseHrefAttribute', (t) => {
|
||||||
t.end();
|
t.end();
|
||||||
});
|
});
|
||||||
|
|
||||||
function getDOM({
|
function getDOM(overrides = {}) {
|
||||||
link = {},
|
const {
|
||||||
getCurrentDirPath = stub(),
|
link = {},
|
||||||
getCurrentDirName = stub(),
|
getCurrentDirPath = stub(),
|
||||||
getByDataName = stub(),
|
getCurrentDirName = stub(),
|
||||||
isContainClass = stub(),
|
getByDataName = stub(),
|
||||||
getCurrentType = stub(),
|
isContainClass = stub(),
|
||||||
getCurrentPath = stub(),
|
getCurrentType = stub(),
|
||||||
} = {}) {
|
getCurrentPath = stub().returns(''),
|
||||||
|
} = overrides;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
getCurrentDirPath,
|
getCurrentDirPath,
|
||||||
getCurrentDirName,
|
getCurrentDirName,
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const tryToCatch = require('try-to-catch');
|
const {tryToCatch} = require('try-to-catch');
|
||||||
|
|
||||||
const {
|
const {
|
||||||
alert,
|
alert,
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,8 @@
|
||||||
/* global CloudCmd */
|
/* global CloudCmd */
|
||||||
const philip = require('philip');
|
const philip = require('philip');
|
||||||
|
|
||||||
const Images = require('./images');
|
const Images = require('./images.mjs');
|
||||||
const {FS} = require('../../common/cloudfunc');
|
const {FS} = require('../../common/cloudfunc.mjs');
|
||||||
const DOM = require('.');
|
const DOM = require('.');
|
||||||
const Dialog = require('./dialog');
|
const Dialog = require('./dialog');
|
||||||
|
|
||||||
|
|
@ -63,14 +63,8 @@ module.exports = (items) => {
|
||||||
uploader.on('end', CloudCmd.refresh);
|
uploader.on('end', CloudCmd.refresh);
|
||||||
};
|
};
|
||||||
|
|
||||||
function percent(i, n, per = 100) {
|
const percent = (i, n, per = 100) => Math.round(i * per / n);
|
||||||
return Math.round(i * per / n);
|
|
||||||
}
|
|
||||||
|
|
||||||
function uploadFile(url, data) {
|
const uploadFile = (url, data) => DOM.load.put(url, data);
|
||||||
return DOM.load.put(url, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
function uploadDir(url) {
|
const uploadDir = (url) => DOM.load.put(`${url}?dir`);
|
||||||
return DOM.load.put(`${url}?dir`);
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
const test = require('supertape');
|
const test = require('supertape');
|
||||||
const {create} = require('auto-globals');
|
const {create} = require('auto-globals');
|
||||||
const tryCatch = require('try-catch');
|
const {tryCatch} = require('try-catch');
|
||||||
|
|
||||||
const {isContainClass} = require('./dom-tree');
|
const {isContainClass} = require('./dom-tree');
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,257 +0,0 @@
|
||||||
'use strict';
|
|
||||||
|
|
||||||
const itype = require('itype');
|
|
||||||
const EventStore = require('./event-store');
|
|
||||||
|
|
||||||
module.exports = new EventsProto();
|
|
||||||
|
|
||||||
function EventsProto() {
|
|
||||||
const Events = this;
|
|
||||||
|
|
||||||
const getEventOptions = (eventName) => {
|
|
||||||
if (eventName !== 'touchstart')
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return {
|
|
||||||
passive: true,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
function parseArgs(eventName, element, listener, callback) {
|
|
||||||
let isFunc;
|
|
||||||
const args = [
|
|
||||||
eventName,
|
|
||||||
element,
|
|
||||||
listener,
|
|
||||||
callback,
|
|
||||||
];
|
|
||||||
|
|
||||||
const EVENT_NAME = 1;
|
|
||||||
const ELEMENT = 0;
|
|
||||||
const type = itype(eventName);
|
|
||||||
|
|
||||||
switch(type) {
|
|
||||||
default:
|
|
||||||
if (!type.endsWith('element'))
|
|
||||||
throw Error(`unknown eventName: ${type}`);
|
|
||||||
|
|
||||||
parseArgs(args[EVENT_NAME], args[ELEMENT], listener, callback);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'string':
|
|
||||||
isFunc = itype.function(element);
|
|
||||||
|
|
||||||
if (isFunc) {
|
|
||||||
listener = element;
|
|
||||||
element = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!element)
|
|
||||||
element = window;
|
|
||||||
|
|
||||||
callback(element, [
|
|
||||||
eventName,
|
|
||||||
listener,
|
|
||||||
getEventOptions(eventName),
|
|
||||||
]);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'array':
|
|
||||||
|
|
||||||
for (const name of eventName) {
|
|
||||||
parseArgs(name, element, listener, callback);
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'object':
|
|
||||||
|
|
||||||
for (const name of Object.keys(eventName)) {
|
|
||||||
const eventListener = eventName[name];
|
|
||||||
|
|
||||||
parseArgs(name, element, eventListener, callback);
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* safe add event listener
|
|
||||||
*
|
|
||||||
* @param type
|
|
||||||
* @param element {document by default}
|
|
||||||
* @param listener
|
|
||||||
*/
|
|
||||||
this.add = (type, element, listener) => {
|
|
||||||
checkType(type);
|
|
||||||
|
|
||||||
parseArgs(type, element, listener, (element, args) => {
|
|
||||||
const [name, fn, options] = args;
|
|
||||||
|
|
||||||
element.addEventListener(name, fn, options);
|
|
||||||
EventStore.add(element, name, fn);
|
|
||||||
});
|
|
||||||
|
|
||||||
return Events;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* safe add event listener
|
|
||||||
*
|
|
||||||
* @param type
|
|
||||||
* @param listener
|
|
||||||
* @param element {document by default}
|
|
||||||
*/
|
|
||||||
this.addOnce = (type, element, listener) => {
|
|
||||||
const once = (event) => {
|
|
||||||
Events.remove(type, element, once);
|
|
||||||
listener(event);
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!listener) {
|
|
||||||
listener = element;
|
|
||||||
element = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.add(type, element, once);
|
|
||||||
|
|
||||||
return Events;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* safe remove event listener
|
|
||||||
*
|
|
||||||
* @param type
|
|
||||||
* @param listener
|
|
||||||
* @param element {document by default}
|
|
||||||
*/
|
|
||||||
this.remove = (type, element, listener) => {
|
|
||||||
checkType(type);
|
|
||||||
|
|
||||||
parseArgs(type, element, listener, (element, args) => {
|
|
||||||
element.removeEventListener(...args);
|
|
||||||
});
|
|
||||||
|
|
||||||
return Events;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* remove all added event listeners
|
|
||||||
*
|
|
||||||
* @param listener
|
|
||||||
*/
|
|
||||||
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 listener
|
|
||||||
*/
|
|
||||||
this.addKey = function(...argsArr) {
|
|
||||||
const name = 'keydown';
|
|
||||||
const args = [
|
|
||||||
name,
|
|
||||||
...argsArr,
|
|
||||||
];
|
|
||||||
|
|
||||||
return Events.add(...args);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* safe remove event click listener
|
|
||||||
*
|
|
||||||
* @param listener
|
|
||||||
*/
|
|
||||||
this.rmKey = function(...argsArr) {
|
|
||||||
const name = 'keydown';
|
|
||||||
const args = [
|
|
||||||
name,
|
|
||||||
...argsArr,
|
|
||||||
];
|
|
||||||
|
|
||||||
return Events.remove(...args);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* safe add event click listener
|
|
||||||
*
|
|
||||||
* @param listener
|
|
||||||
*/
|
|
||||||
this.addClick = function(...argsArr) {
|
|
||||||
const name = 'click';
|
|
||||||
const args = [
|
|
||||||
name,
|
|
||||||
...argsArr,
|
|
||||||
];
|
|
||||||
|
|
||||||
return Events.add(...args);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* safe remove event click listener
|
|
||||||
*
|
|
||||||
* @param listener
|
|
||||||
*/
|
|
||||||
this.rmClick = function(...argsArr) {
|
|
||||||
const name = 'click';
|
|
||||||
const args = [
|
|
||||||
name,
|
|
||||||
...argsArr,
|
|
||||||
];
|
|
||||||
|
|
||||||
return Events.remove(...args);
|
|
||||||
};
|
|
||||||
|
|
||||||
this.addContextMenu = function(...argsArr) {
|
|
||||||
const name = 'contextmenu';
|
|
||||||
const args = [
|
|
||||||
name,
|
|
||||||
...argsArr,
|
|
||||||
];
|
|
||||||
|
|
||||||
return Events.add(...args);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* safe add event click listener
|
|
||||||
*
|
|
||||||
* @param listener
|
|
||||||
*/
|
|
||||||
this.addError = function(...argsArr) {
|
|
||||||
const name = 'error';
|
|
||||||
const args = [
|
|
||||||
name,
|
|
||||||
...argsArr,
|
|
||||||
];
|
|
||||||
|
|
||||||
return Events.add(...args);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* safe add load click listener
|
|
||||||
*
|
|
||||||
* @param listener
|
|
||||||
*/
|
|
||||||
this.addLoad = function(...argsArr) {
|
|
||||||
const name = 'load';
|
|
||||||
const args = [
|
|
||||||
name,
|
|
||||||
...argsArr,
|
|
||||||
];
|
|
||||||
|
|
||||||
return Events.add(...args);
|
|
||||||
};
|
|
||||||
|
|
||||||
function checkType(type) {
|
|
||||||
if (!type)
|
|
||||||
throw Error('type could not be empty!');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
203
client/dom/events/index.mjs
Normal file
203
client/dom/events/index.mjs
Normal file
|
|
@ -0,0 +1,203 @@
|
||||||
|
import itype from 'itype';
|
||||||
|
import EventStore from './event-store.js';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* safe add event listener
|
||||||
|
*
|
||||||
|
* @param type
|
||||||
|
* @param element - document by default
|
||||||
|
* @param listener
|
||||||
|
*/
|
||||||
|
export const add = (type, element, listener) => {
|
||||||
|
checkType(type);
|
||||||
|
|
||||||
|
parseArgs(type, element, listener, (element, args) => {
|
||||||
|
const [name, fn, options] = args;
|
||||||
|
|
||||||
|
element.addEventListener(name, fn, options);
|
||||||
|
EventStore.add(element, name, fn);
|
||||||
|
});
|
||||||
|
|
||||||
|
return Events;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* safe add event listener
|
||||||
|
*
|
||||||
|
* @param type
|
||||||
|
* @param listener
|
||||||
|
* @param element - document by default
|
||||||
|
*/
|
||||||
|
export const addOnce = (type, element, listener) => {
|
||||||
|
const once = (event) => {
|
||||||
|
Events.remove(type, element, once);
|
||||||
|
listener(event);
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!listener) {
|
||||||
|
listener = element;
|
||||||
|
element = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
add(type, element, once);
|
||||||
|
|
||||||
|
return Events;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* safe remove event listener
|
||||||
|
*
|
||||||
|
* @param type
|
||||||
|
* @param listener
|
||||||
|
* @param element - document by default
|
||||||
|
*/
|
||||||
|
export const remove = (type, element, listener) => {
|
||||||
|
checkType(type);
|
||||||
|
|
||||||
|
parseArgs(type, element, listener, (element, args) => {
|
||||||
|
element.removeEventListener(...args);
|
||||||
|
});
|
||||||
|
|
||||||
|
return Events;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* remove all added event listeners
|
||||||
|
*/
|
||||||
|
export const removeAll = () => {
|
||||||
|
const events = EventStore.get();
|
||||||
|
|
||||||
|
for (const [el, name, fn] of events)
|
||||||
|
el.removeEventListener(name, fn);
|
||||||
|
|
||||||
|
EventStore.clear();
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* safe add event keydown listener
|
||||||
|
*
|
||||||
|
* @param args
|
||||||
|
*/
|
||||||
|
export const addKey = function(...args) {
|
||||||
|
return add('keydown', ...args);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* safe remove event click listener
|
||||||
|
*
|
||||||
|
* @param args
|
||||||
|
*/
|
||||||
|
export const rmKey = function(...args) {
|
||||||
|
return Events.remove('keydown', ...args);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* safe add event click listener
|
||||||
|
*/
|
||||||
|
export const addClick = function(...args) {
|
||||||
|
return Events.add('click', ...args);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* safe remove event click listener
|
||||||
|
*/
|
||||||
|
export const rmClick = function(...args) {
|
||||||
|
return remove('click', ...args);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const addContextMenu = function(...args) {
|
||||||
|
return add('contextmenu', ...args);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* safe add load listener
|
||||||
|
*/
|
||||||
|
export const addLoad = function(...args) {
|
||||||
|
return add('load', ...args);
|
||||||
|
};
|
||||||
|
|
||||||
|
function checkType(type) {
|
||||||
|
if (!type)
|
||||||
|
throw Error('type could not be empty!');
|
||||||
|
}
|
||||||
|
|
||||||
|
const getEventOptions = (eventName) => {
|
||||||
|
if (eventName !== 'touchstart')
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return {
|
||||||
|
passive: true,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
function parseArgs(eventName, element, listener, callback) {
|
||||||
|
let isFunc;
|
||||||
|
const args = [
|
||||||
|
eventName,
|
||||||
|
element,
|
||||||
|
listener,
|
||||||
|
callback,
|
||||||
|
];
|
||||||
|
|
||||||
|
const EVENT_NAME = 1;
|
||||||
|
const ELEMENT = 0;
|
||||||
|
const type = itype(eventName);
|
||||||
|
|
||||||
|
switch(type) {
|
||||||
|
default:
|
||||||
|
if (!type.endsWith('element'))
|
||||||
|
throw Error(`unknown eventName: ${type}`);
|
||||||
|
|
||||||
|
parseArgs(args[EVENT_NAME], args[ELEMENT], listener, callback);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'string':
|
||||||
|
isFunc = itype.function(element);
|
||||||
|
|
||||||
|
if (isFunc) {
|
||||||
|
listener = element;
|
||||||
|
element = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!element)
|
||||||
|
element = window;
|
||||||
|
|
||||||
|
callback(element, [
|
||||||
|
eventName,
|
||||||
|
listener,
|
||||||
|
getEventOptions(eventName),
|
||||||
|
]);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'array':
|
||||||
|
|
||||||
|
for (const name of eventName) {
|
||||||
|
parseArgs(name, element, listener, callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'object':
|
||||||
|
|
||||||
|
for (const name of Object.keys(eventName)) {
|
||||||
|
const eventListener = eventName[name];
|
||||||
|
|
||||||
|
parseArgs(name, element, eventListener, callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const Events = {
|
||||||
|
add,
|
||||||
|
addClick,
|
||||||
|
addContextMenu,
|
||||||
|
addKey,
|
||||||
|
addLoad,
|
||||||
|
addOnce,
|
||||||
|
remove,
|
||||||
|
removeAll,
|
||||||
|
rmClick,
|
||||||
|
rmKey,
|
||||||
|
};
|
||||||
|
|
@ -1,20 +1,14 @@
|
||||||
/* global DOM */
|
/* global DOM */
|
||||||
|
import createElement from '@cloudcmd/create-element';
|
||||||
'use strict';
|
|
||||||
|
|
||||||
const createElement = require('@cloudcmd/create-element');
|
|
||||||
|
|
||||||
const Images = module.exports;
|
|
||||||
|
|
||||||
const LOADING = 'loading';
|
const LOADING = 'loading';
|
||||||
const HIDDEN = 'hidden';
|
const HIDDEN = 'hidden';
|
||||||
const ERROR = 'error';
|
const ERROR = 'error';
|
||||||
|
|
||||||
function getLoadingType() {
|
const getLoadingType = () => isSVG() ? '-svg' : '-gif';
|
||||||
return isSVG() ? '-svg' : '-gif';
|
|
||||||
}
|
export const get = getElement;
|
||||||
|
|
||||||
module.exports.get = getElement;
|
|
||||||
/**
|
/**
|
||||||
* check SVG SMIL animation support
|
* check SVG SMIL animation support
|
||||||
*/
|
*/
|
||||||
|
|
@ -42,7 +36,7 @@ function getElement() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Функция создаёт картинку загрузки */
|
/* Функция создаёт картинку загрузки */
|
||||||
module.exports.loading = () => {
|
export const loading = () => {
|
||||||
const element = getElement();
|
const element = getElement();
|
||||||
const {classList} = element;
|
const {classList} = element;
|
||||||
const loadingImage = LOADING + getLoadingType();
|
const loadingImage = LOADING + getLoadingType();
|
||||||
|
|
@ -54,7 +48,7 @@ module.exports.loading = () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Функция создаёт картинку ошибки загрузки */
|
/* Функция создаёт картинку ошибки загрузки */
|
||||||
module.exports.error = () => {
|
export const error = () => {
|
||||||
const element = getElement();
|
const element = getElement();
|
||||||
const {classList} = element;
|
const {classList} = element;
|
||||||
const loadingImage = LOADING + getLoadingType();
|
const loadingImage = LOADING + getLoadingType();
|
||||||
|
|
@ -65,14 +59,21 @@ module.exports.error = () => {
|
||||||
return element;
|
return element;
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports.show = show;
|
show.load = show;
|
||||||
module.exports.show.load = show;
|
show.error = (text) => {
|
||||||
module.exports.show.error = error;
|
const image = Images.error();
|
||||||
|
|
||||||
|
DOM.show(image);
|
||||||
|
image.title = text;
|
||||||
|
|
||||||
|
return image;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function shows loading spinner
|
* Function shows loading spinner
|
||||||
* position = {top: true};
|
* position = {top: true};
|
||||||
*/
|
*/
|
||||||
function show(position, panel) {
|
export function show(position, panel) {
|
||||||
const image = Images.loading();
|
const image = Images.loading();
|
||||||
const parent = image.parentElement;
|
const parent = image.parentElement;
|
||||||
const refreshButton = DOM.getRefreshButton(panel);
|
const refreshButton = DOM.getRefreshButton(panel);
|
||||||
|
|
@ -98,19 +99,10 @@ function show(position, panel) {
|
||||||
return image;
|
return image;
|
||||||
}
|
}
|
||||||
|
|
||||||
function error(text) {
|
|
||||||
const image = Images.error();
|
|
||||||
|
|
||||||
DOM.show(image);
|
|
||||||
image.title = text;
|
|
||||||
|
|
||||||
return image;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* hide load image
|
* hide load image
|
||||||
*/
|
*/
|
||||||
module.exports.hide = () => {
|
export const hide = () => {
|
||||||
const element = Images.get();
|
const element = Images.get();
|
||||||
|
|
||||||
DOM.hide(element);
|
DOM.hide(element);
|
||||||
|
|
@ -118,7 +110,7 @@ module.exports.hide = () => {
|
||||||
return Images;
|
return Images;
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports.setProgress = (value, title) => {
|
export const setProgress = (value, title) => {
|
||||||
const DATA = 'data-progress';
|
const DATA = 'data-progress';
|
||||||
const element = Images.get();
|
const element = Images.get();
|
||||||
|
|
||||||
|
|
@ -133,7 +125,7 @@ module.exports.setProgress = (value, title) => {
|
||||||
return Images;
|
return Images;
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports.clearProgress = () => {
|
export const clearProgress = () => {
|
||||||
const DATA = 'data-progress';
|
const DATA = 'data-progress';
|
||||||
const element = Images.get();
|
const element = Images.get();
|
||||||
|
|
||||||
|
|
@ -145,3 +137,13 @@ module.exports.clearProgress = () => {
|
||||||
|
|
||||||
return Images;
|
return Images;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const Images = {
|
||||||
|
clearProgress,
|
||||||
|
setProgress,
|
||||||
|
show,
|
||||||
|
hide,
|
||||||
|
get,
|
||||||
|
error,
|
||||||
|
loading,
|
||||||
|
};
|
||||||
|
|
@ -3,12 +3,12 @@
|
||||||
/* global CloudCmd */
|
/* global CloudCmd */
|
||||||
const Util = require('../../common/util');
|
const Util = require('../../common/util');
|
||||||
|
|
||||||
const Images = require('./images');
|
const Images = require('./images.mjs');
|
||||||
const RESTful = require('./rest');
|
const RESTful = require('./rest');
|
||||||
const Storage = require('./storage');
|
const Storage = require('./storage');
|
||||||
const renameCurrent = require('./operations/rename-current');
|
const renameCurrent = require('./operations/rename-current');
|
||||||
|
|
||||||
const CurrentFile = require('./current-file');
|
const CurrentFile = require('./current-file.mjs');
|
||||||
const DOMTree = require('./dom-tree');
|
const DOMTree = require('./dom-tree');
|
||||||
|
|
||||||
const Cmd = module.exports;
|
const Cmd = module.exports;
|
||||||
|
|
@ -32,8 +32,8 @@ DOM.CurrentInfo = CurrentInfo;
|
||||||
module.exports = DOM;
|
module.exports = DOM;
|
||||||
|
|
||||||
DOM.uploadDirectory = require('./directory');
|
DOM.uploadDirectory = require('./directory');
|
||||||
DOM.Buffer = require('./buffer');
|
DOM.Buffer = require('./buffer.mjs');
|
||||||
DOM.Events = require('./events');
|
DOM.Events = require('#dom/events');
|
||||||
|
|
||||||
const loadRemote = require('./load-remote');
|
const loadRemote = require('./load-remote');
|
||||||
const selectByPattern = require('./select-by-pattern');
|
const selectByPattern = require('./select-by-pattern');
|
||||||
|
|
@ -416,7 +416,7 @@ module.exports.shrinkSelection = () => {
|
||||||
* setting history wrapper
|
* setting history wrapper
|
||||||
*/
|
*/
|
||||||
module.exports.setHistory = (data, title, url) => {
|
module.exports.setHistory = (data, title, url) => {
|
||||||
const ret = window.history;
|
const ret = globalThis.history;
|
||||||
const {prefix} = CloudCmd;
|
const {prefix} = CloudCmd;
|
||||||
|
|
||||||
url = prefix + url;
|
url = prefix + url;
|
||||||
|
|
@ -520,6 +520,11 @@ module.exports.getPanelPosition = (panel) => {
|
||||||
return panel.dataset.name.replace('js-', '');
|
return panel.dataset.name.replace('js-', '');
|
||||||
};
|
};
|
||||||
|
|
||||||
|
module.exports.getCSSVar = (name, {body = document.body} = {}) => {
|
||||||
|
const bodyStyle = getComputedStyle(body);
|
||||||
|
return bodyStyle.getPropertyValue(`--${name}`);
|
||||||
|
};
|
||||||
|
|
||||||
/** function getting panel active, or passive
|
/** function getting panel active, or passive
|
||||||
* @param options = {active: true}
|
* @param options = {active: true}
|
||||||
*/
|
*/
|
||||||
|
|
@ -549,7 +554,7 @@ module.exports.getPanel = (options) => {
|
||||||
* then always work with passive
|
* then always work with passive
|
||||||
* panel
|
* panel
|
||||||
*/
|
*/
|
||||||
if (window.innerWidth < CloudCmd.MIN_ONE_PANEL_WIDTH)
|
if (globalThis.innerWidth < CloudCmd.MIN_ONE_PANEL_WIDTH)
|
||||||
panel = DOM.getByDataName('js-left');
|
panel = DOM.getByDataName('js-left');
|
||||||
|
|
||||||
if (!panel)
|
if (!panel)
|
||||||
|
|
@ -724,17 +729,19 @@ module.exports.getPackerExt = (type) => {
|
||||||
return '.tar.gz';
|
return '.tar.gz';
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports.goToDirectory = async () => {
|
module.exports.goToDirectory = async (overrides = {}) => {
|
||||||
const msg = 'Go to directory:';
|
|
||||||
const {Dialog} = DOM;
|
const {Dialog} = DOM;
|
||||||
|
const {prompt = Dialog.prompt, changeDir = CloudCmd.changeDir} = overrides;
|
||||||
|
|
||||||
|
const msg = 'Go to directory:';
|
||||||
const {dirPath} = CurrentInfo;
|
const {dirPath} = CurrentInfo;
|
||||||
|
|
||||||
const [cancel, path = dirPath] = await Dialog.prompt(msg, dirPath);
|
const [cancel, path = dirPath] = await prompt(msg, dirPath);
|
||||||
|
|
||||||
if (cancel)
|
if (cancel)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
await CloudCmd.changeDir(path);
|
await changeDir(path);
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports.duplicatePanel = async () => {
|
module.exports.duplicatePanel = async () => {
|
||||||
|
|
|
||||||
|
|
@ -3,29 +3,54 @@
|
||||||
require('css-modules-require-hook/preset');
|
require('css-modules-require-hook/preset');
|
||||||
|
|
||||||
const {test, stub} = require('supertape');
|
const {test, stub} = require('supertape');
|
||||||
const mockRequire = require('mock-require');
|
const {getCSSVar, goToDirectory} = require('./index');
|
||||||
const {reRequire, stopAll} = mockRequire;
|
|
||||||
|
|
||||||
global.CloudCmd = {};
|
globalThis.CloudCmd = {};
|
||||||
|
|
||||||
test('cloudcmd: client: dom: goToDirectory', async (t) => {
|
test('cloudcmd: client: dom: goToDirectory', async (t) => {
|
||||||
const path = '';
|
const path = '';
|
||||||
const {CloudCmd} = global;
|
|
||||||
const changeDir = stub();
|
const changeDir = stub();
|
||||||
const prompt = stub().returns([null, path]);
|
const prompt = stub().returns([null, path]);
|
||||||
|
|
||||||
CloudCmd.changeDir = changeDir;
|
await goToDirectory({
|
||||||
|
|
||||||
mockRequire('./dialog', {
|
|
||||||
prompt,
|
prompt,
|
||||||
|
changeDir,
|
||||||
});
|
});
|
||||||
|
|
||||||
const {goToDirectory} = reRequire('.');
|
|
||||||
|
|
||||||
await goToDirectory();
|
|
||||||
|
|
||||||
stopAll();
|
|
||||||
|
|
||||||
t.calledWith(changeDir, [path]);
|
t.calledWith(changeDir, [path]);
|
||||||
t.end();
|
t.end();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('cloudcmd: client: dom: getCSSVar', (t) => {
|
||||||
|
const body = {};
|
||||||
|
const getPropertyValue = stub().returns(0);
|
||||||
|
|
||||||
|
globalThis.getComputedStyle = stub().returns({
|
||||||
|
getPropertyValue,
|
||||||
|
});
|
||||||
|
const result = getCSSVar('hello', {
|
||||||
|
body,
|
||||||
|
});
|
||||||
|
|
||||||
|
delete globalThis.getComputedStyle;
|
||||||
|
|
||||||
|
t.notOk(result);
|
||||||
|
t.end();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('cloudcmd: client: dom: getCSSVar: 1', (t) => {
|
||||||
|
const body = {};
|
||||||
|
const getPropertyValue = stub().returns(1);
|
||||||
|
|
||||||
|
globalThis.getComputedStyle = stub().returns({
|
||||||
|
getPropertyValue,
|
||||||
|
});
|
||||||
|
const result = getCSSVar('hello', {
|
||||||
|
body,
|
||||||
|
});
|
||||||
|
|
||||||
|
delete globalThis.getComputedStyle;
|
||||||
|
|
||||||
|
t.ok(result);
|
||||||
|
t.end();
|
||||||
|
});
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,14 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const {FS} = require('../../../common/cloudfunc');
|
const {FS} = require('../../../common/cloudfunc.mjs');
|
||||||
const sendRequest = require('./send-request');
|
const _sendRequest = require('./send-request');
|
||||||
|
|
||||||
const imgPosition = {
|
const imgPosition = {
|
||||||
top: true,
|
top: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports.delete = async (url, data) => {
|
module.exports.delete = async (url, data) => {
|
||||||
return await sendRequest({
|
return await _sendRequest({
|
||||||
method: 'DELETE',
|
method: 'DELETE',
|
||||||
url: FS + url,
|
url: FS + url,
|
||||||
data,
|
data,
|
||||||
|
|
@ -19,7 +19,7 @@ module.exports.delete = async (url, data) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports.patch = async (url, data) => {
|
module.exports.patch = async (url, data) => {
|
||||||
return await sendRequest({
|
return await _sendRequest({
|
||||||
method: 'PATCH',
|
method: 'PATCH',
|
||||||
url: FS + url,
|
url: FS + url,
|
||||||
data,
|
data,
|
||||||
|
|
@ -28,7 +28,7 @@ module.exports.patch = async (url, data) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports.write = async (url, data) => {
|
module.exports.write = async (url, data) => {
|
||||||
return await sendRequest({
|
return await _sendRequest({
|
||||||
method: 'PUT',
|
method: 'PUT',
|
||||||
url: FS + url,
|
url: FS + url,
|
||||||
data,
|
data,
|
||||||
|
|
@ -36,7 +36,11 @@ module.exports.write = async (url, data) => {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports.createDirectory = async (url) => {
|
module.exports.createDirectory = async (url, overrides = {}) => {
|
||||||
|
const {
|
||||||
|
sendRequest = _sendRequest,
|
||||||
|
} = overrides;
|
||||||
|
|
||||||
return await sendRequest({
|
return await sendRequest({
|
||||||
method: 'PUT',
|
method: 'PUT',
|
||||||
url: `${FS}${url}?dir`,
|
url: `${FS}${url}?dir`,
|
||||||
|
|
@ -47,7 +51,7 @@ module.exports.createDirectory = async (url) => {
|
||||||
module.exports.read = async (url, dataType = 'text') => {
|
module.exports.read = async (url, dataType = 'text') => {
|
||||||
const notLog = !url.includes('?');
|
const notLog = !url.includes('?');
|
||||||
|
|
||||||
return await sendRequest({
|
return await _sendRequest({
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
url: FS + url,
|
url: FS + url,
|
||||||
notLog,
|
notLog,
|
||||||
|
|
@ -56,7 +60,7 @@ module.exports.read = async (url, dataType = 'text') => {
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports.copy = async (from, to, names) => {
|
module.exports.copy = async (from, to, names) => {
|
||||||
return await sendRequest({
|
return await _sendRequest({
|
||||||
method: 'PUT',
|
method: 'PUT',
|
||||||
url: '/copy',
|
url: '/copy',
|
||||||
data: {
|
data: {
|
||||||
|
|
@ -69,7 +73,7 @@ module.exports.copy = async (from, to, names) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports.pack = async (data) => {
|
module.exports.pack = async (data) => {
|
||||||
return await sendRequest({
|
return await _sendRequest({
|
||||||
method: 'PUT',
|
method: 'PUT',
|
||||||
url: '/pack',
|
url: '/pack',
|
||||||
data,
|
data,
|
||||||
|
|
@ -77,7 +81,7 @@ module.exports.pack = async (data) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports.extract = async (data) => {
|
module.exports.extract = async (data) => {
|
||||||
return await sendRequest({
|
return await _sendRequest({
|
||||||
method: 'PUT',
|
method: 'PUT',
|
||||||
url: '/extract',
|
url: '/extract',
|
||||||
data,
|
data,
|
||||||
|
|
@ -85,7 +89,7 @@ module.exports.extract = async (data) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports.move = async (from, to, names) => {
|
module.exports.move = async (from, to, names) => {
|
||||||
return await sendRequest({
|
return await _sendRequest({
|
||||||
method: 'PUT',
|
method: 'PUT',
|
||||||
url: '/move',
|
url: '/move',
|
||||||
data: {
|
data: {
|
||||||
|
|
@ -98,7 +102,7 @@ module.exports.move = async (from, to, names) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports.rename = async (from, to) => {
|
module.exports.rename = async (from, to) => {
|
||||||
return await sendRequest({
|
return await _sendRequest({
|
||||||
method: 'PUT',
|
method: 'PUT',
|
||||||
url: '/rename',
|
url: '/rename',
|
||||||
data: {
|
data: {
|
||||||
|
|
@ -111,7 +115,7 @@ module.exports.rename = async (from, to) => {
|
||||||
|
|
||||||
module.exports.Config = {
|
module.exports.Config = {
|
||||||
read: async () => {
|
read: async () => {
|
||||||
return await sendRequest({
|
return await _sendRequest({
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
url: '/config',
|
url: '/config',
|
||||||
imgPosition,
|
imgPosition,
|
||||||
|
|
@ -120,7 +124,7 @@ module.exports.Config = {
|
||||||
},
|
},
|
||||||
|
|
||||||
write: async (data) => {
|
write: async (data) => {
|
||||||
return await sendRequest({
|
return await _sendRequest({
|
||||||
method: 'PATCH',
|
method: 'PATCH',
|
||||||
url: '/config',
|
url: '/config',
|
||||||
data,
|
data,
|
||||||
|
|
@ -131,7 +135,7 @@ module.exports.Config = {
|
||||||
|
|
||||||
module.exports.Markdown = {
|
module.exports.Markdown = {
|
||||||
read: async (url) => {
|
read: async (url) => {
|
||||||
return await sendRequest({
|
return await _sendRequest({
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
url: `/markdown${url}`,
|
url: `/markdown${url}`,
|
||||||
imgPosition,
|
imgPosition,
|
||||||
|
|
@ -140,7 +144,7 @@ module.exports.Markdown = {
|
||||||
},
|
},
|
||||||
|
|
||||||
render: async (data) => {
|
render: async (data) => {
|
||||||
return await sendRequest({
|
return await _sendRequest({
|
||||||
method: 'PUT',
|
method: 'PUT',
|
||||||
url: '/markdown',
|
url: '/markdown',
|
||||||
data,
|
data,
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,14 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const {test, stub} = require('supertape');
|
const {test, stub} = require('supertape');
|
||||||
|
const io = require('.');
|
||||||
const mockRequire = require('mock-require');
|
|
||||||
|
|
||||||
const {reRequire, stopAll} = mockRequire;
|
|
||||||
|
|
||||||
test('client: dom: io', (t) => {
|
test('client: dom: io', (t) => {
|
||||||
const sendRequest = stub();
|
const sendRequest = stub();
|
||||||
mockRequire('./send-request', sendRequest);
|
|
||||||
|
|
||||||
const io = reRequire('.');
|
io.createDirectory('/hello', {
|
||||||
|
sendRequest,
|
||||||
io.createDirectory('/hello');
|
});
|
||||||
|
|
||||||
const expected = {
|
const expected = {
|
||||||
imgPosition: {
|
imgPosition: {
|
||||||
|
|
@ -22,8 +18,6 @@ test('client: dom: io', (t) => {
|
||||||
url: '/fs/hello?dir',
|
url: '/fs/hello?dir',
|
||||||
};
|
};
|
||||||
|
|
||||||
stopAll();
|
|
||||||
|
|
||||||
t.calledWith(sendRequest, [expected]);
|
t.calledWith(sendRequest, [expected]);
|
||||||
t.end();
|
t.end();
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
/* global CloudCmd */
|
/* global CloudCmd */
|
||||||
const {promisify} = require('es6-promisify');
|
const {promisify} = require('es6-promisify');
|
||||||
|
|
||||||
const Images = require('../images');
|
const Images = require('../images.mjs');
|
||||||
const load = require('../load');
|
const load = require('../load');
|
||||||
|
|
||||||
module.exports = promisify((params, callback) => {
|
module.exports = promisify((params, callback) => {
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
const rendy = require('rendy');
|
const rendy = require('rendy');
|
||||||
const itype = require('itype');
|
const itype = require('itype');
|
||||||
const load = require('load.js');
|
const load = require('load.js');
|
||||||
const tryToCatch = require('try-to-catch');
|
const {tryToCatch} = require('try-to-catch');
|
||||||
|
|
||||||
const {findObjByNameInArr} = require('../../common/util');
|
const {findObjByNameInArr} = require('../../common/util');
|
||||||
|
|
||||||
|
|
@ -17,42 +17,40 @@ module.exports = (name, options, callback = options) => {
|
||||||
if (o.name && window[o.name])
|
if (o.name && window[o.name])
|
||||||
return callback();
|
return callback();
|
||||||
|
|
||||||
Files
|
Files.get('modules').then(async (modules) => {
|
||||||
.get('modules')
|
const online = config('online') && navigator.onLine;
|
||||||
.then(async (modules) => {
|
const module = findObjByNameInArr(modules.remote, name);
|
||||||
const online = config('online') && navigator.onLine;
|
|
||||||
const module = findObjByNameInArr(modules.remote, name);
|
|
||||||
|
|
||||||
const isArray = itype.array(module.local);
|
const isArray = itype.array(module.local);
|
||||||
const {version} = module;
|
const {version} = module;
|
||||||
|
|
||||||
let remoteTmpls;
|
let remoteTmpls;
|
||||||
let local;
|
let local;
|
||||||
|
|
||||||
if (isArray) {
|
if (isArray) {
|
||||||
remoteTmpls = module.remote;
|
remoteTmpls = module.remote;
|
||||||
local = module.local;
|
({local} = module);
|
||||||
} else {
|
} else {
|
||||||
remoteTmpls = [module.remote];
|
remoteTmpls = [module.remote];
|
||||||
local = [module.local];
|
local = [module.local];
|
||||||
}
|
}
|
||||||
|
|
||||||
const localURL = local.map((url) => prefix + url);
|
const localURL = local.map((url) => prefix + url);
|
||||||
|
|
||||||
const remoteURL = remoteTmpls.map((tmpl) => {
|
const remoteURL = remoteTmpls.map((tmpl) => {
|
||||||
return rendy(tmpl, {
|
return rendy(tmpl, {
|
||||||
version,
|
version,
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
if (online) {
|
|
||||||
const [e] = await tryToCatch(load.parallel, remoteURL);
|
|
||||||
|
|
||||||
if (!e)
|
|
||||||
return callback();
|
|
||||||
}
|
|
||||||
|
|
||||||
const [e] = await tryToCatch(load.parallel, localURL);
|
|
||||||
callback(e);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (online) {
|
||||||
|
const [e] = await tryToCatch(load.parallel, remoteURL);
|
||||||
|
|
||||||
|
if (!e)
|
||||||
|
return callback();
|
||||||
|
}
|
||||||
|
|
||||||
|
const [e] = await tryToCatch(load.parallel, localURL);
|
||||||
|
callback(e);
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ const itype = require('itype');
|
||||||
const jonny = require('jonny');
|
const jonny = require('jonny');
|
||||||
const Emitify = require('emitify');
|
const Emitify = require('emitify');
|
||||||
const exec = require('execon');
|
const exec = require('execon');
|
||||||
const Images = require('./images');
|
const Images = require('./images.mjs');
|
||||||
|
|
||||||
module.exports.getIdBySrc = getIdBySrc;
|
module.exports.getIdBySrc = getIdBySrc;
|
||||||
/**
|
/**
|
||||||
|
|
@ -63,7 +63,7 @@ module.exports.ajax = (params) => {
|
||||||
if (!isArrayBuf && isObject || isArray)
|
if (!isArrayBuf && isObject || isArray)
|
||||||
data = jonny.stringify(p.data);
|
data = jonny.stringify(p.data);
|
||||||
else
|
else
|
||||||
data = p.data;
|
({data} = p);
|
||||||
|
|
||||||
xhr.onreadystatechange = (event) => {
|
xhr.onreadystatechange = (event) => {
|
||||||
const xhr = event.target;
|
const xhr = event.target;
|
||||||
|
|
|
||||||
|
|
@ -3,21 +3,29 @@
|
||||||
/* global CloudCmd */
|
/* global CloudCmd */
|
||||||
const capitalize = require('just-capitalize');
|
const capitalize = require('just-capitalize');
|
||||||
|
|
||||||
const Dialog = require('../dialog');
|
const _Dialog = require('../dialog');
|
||||||
const Storage = require('../storage');
|
const Storage = require('../storage');
|
||||||
const RESTful = require('../rest');
|
const RESTful = require('../rest');
|
||||||
|
|
||||||
const {
|
const _currentFile = require('../current-file.mjs');
|
||||||
isCurrentFile,
|
|
||||||
getCurrentName,
|
|
||||||
getCurrentFile,
|
|
||||||
getCurrentByName,
|
|
||||||
getCurrentType,
|
|
||||||
getCurrentDirPath,
|
|
||||||
setCurrentName,
|
|
||||||
} = require('../current-file');
|
|
||||||
|
|
||||||
module.exports = async (current) => {
|
module.exports = async (current, overrides = {}) => {
|
||||||
|
const {
|
||||||
|
refresh = CloudCmd.refresh,
|
||||||
|
Dialog = _Dialog,
|
||||||
|
currentFile = _currentFile,
|
||||||
|
} = overrides;
|
||||||
|
|
||||||
|
const {
|
||||||
|
isCurrentFile,
|
||||||
|
getCurrentName,
|
||||||
|
getCurrentFile,
|
||||||
|
getCurrentByName,
|
||||||
|
getCurrentType,
|
||||||
|
getCurrentDirPath,
|
||||||
|
setCurrentName,
|
||||||
|
} = currentFile;
|
||||||
|
|
||||||
if (!isCurrentFile(current))
|
if (!isCurrentFile(current))
|
||||||
current = getCurrentFile();
|
current = getCurrentFile();
|
||||||
|
|
||||||
|
|
@ -58,5 +66,5 @@ module.exports = async (current) => {
|
||||||
setCurrentName(to, current);
|
setCurrentName(to, current);
|
||||||
|
|
||||||
Storage.remove(dirPath);
|
Storage.remove(dirPath);
|
||||||
CloudCmd.refresh();
|
refresh();
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -2,23 +2,20 @@
|
||||||
|
|
||||||
const {test, stub} = require('supertape');
|
const {test, stub} = require('supertape');
|
||||||
|
|
||||||
const mockRequire = require('mock-require');
|
const renameCurrent = require('./rename-current');
|
||||||
|
|
||||||
const {reRequire, stopAll} = mockRequire;
|
|
||||||
|
|
||||||
test('cloudcmd: client: dom: renameCurrent: isCurrentFile', async (t) => {
|
test('cloudcmd: client: dom: renameCurrent: isCurrentFile', async (t) => {
|
||||||
const current = {};
|
const current = {};
|
||||||
const isCurrentFile = stub();
|
const isCurrentFile = stub();
|
||||||
|
|
||||||
mockRequire('../dialog', stubDialog());
|
const currentFile = stubCurrentFile({
|
||||||
mockRequire('../current-file', stubCurrentFile({
|
|
||||||
isCurrentFile,
|
isCurrentFile,
|
||||||
}));
|
});
|
||||||
|
|
||||||
const renameCurrent = reRequire('./rename-current');
|
await renameCurrent(current, {
|
||||||
await renameCurrent(current);
|
Dialog: stubDialog(),
|
||||||
|
currentFile,
|
||||||
stopAll();
|
});
|
||||||
|
|
||||||
t.calledWith(isCurrentFile, [current], 'should call isCurrentFile');
|
t.calledWith(isCurrentFile, [current], 'should call isCurrentFile');
|
||||||
t.end();
|
t.end();
|
||||||
|
|
@ -27,11 +24,6 @@ test('cloudcmd: client: dom: renameCurrent: isCurrentFile', async (t) => {
|
||||||
test('cloudcmd: client: dom: renameCurrent: file exist', async (t) => {
|
test('cloudcmd: client: dom: renameCurrent: file exist', async (t) => {
|
||||||
const current = {};
|
const current = {};
|
||||||
const name = 'hello';
|
const name = 'hello';
|
||||||
const {CloudCmd} = global;
|
|
||||||
|
|
||||||
global.CloudCmd = {
|
|
||||||
refresh: stub(),
|
|
||||||
};
|
|
||||||
|
|
||||||
const prompt = stub().returns([null, name]);
|
const prompt = stub().returns([null, name]);
|
||||||
const confirm = stub().returns([true]);
|
const confirm = stub().returns([true]);
|
||||||
|
|
@ -39,25 +31,23 @@ test('cloudcmd: client: dom: renameCurrent: file exist', async (t) => {
|
||||||
const getCurrentByName = stub().returns(current);
|
const getCurrentByName = stub().returns(current);
|
||||||
const getCurrentType = stub().returns('directory');
|
const getCurrentType = stub().returns('directory');
|
||||||
|
|
||||||
mockRequire('../dialog', stubDialog({
|
const Dialog = stubDialog({
|
||||||
confirm,
|
confirm,
|
||||||
prompt,
|
prompt,
|
||||||
}));
|
});
|
||||||
|
|
||||||
mockRequire('../current-file', stubCurrentFile({
|
const currentFile = stubCurrentFile({
|
||||||
getCurrentByName,
|
getCurrentByName,
|
||||||
getCurrentType,
|
getCurrentType,
|
||||||
}));
|
});
|
||||||
|
|
||||||
const renameCurrent = reRequire('./rename-current');
|
await renameCurrent(null, {
|
||||||
await renameCurrent();
|
Dialog,
|
||||||
|
currentFile,
|
||||||
|
});
|
||||||
|
|
||||||
const expected = 'Directory "hello" already exists. Proceed?';
|
const expected = 'Directory "hello" already exists. Proceed?';
|
||||||
|
|
||||||
global.CloudCmd = CloudCmd;
|
|
||||||
|
|
||||||
stopAll();
|
|
||||||
|
|
||||||
t.calledWith(confirm, [expected], 'should call confirm');
|
t.calledWith(confirm, [expected], 'should call confirm');
|
||||||
t.end();
|
t.end();
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const tryToCatch = require('try-to-catch');
|
const {tryToCatch} = require('try-to-catch');
|
||||||
|
|
||||||
const {encode} = require('../../common/entity');
|
const {encode} = require('../../common/entity');
|
||||||
|
|
||||||
const Images = require('./images');
|
const Images = require('./images.mjs');
|
||||||
const IO = require('./io');
|
const IO = require('./io');
|
||||||
const Dialog = require('./dialog');
|
const Dialog = require('./dialog');
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,58 +7,58 @@ const storage = require('./storage');
|
||||||
const {stringify} = JSON;
|
const {stringify} = JSON;
|
||||||
|
|
||||||
test('cloudcmd: client: storage: set', async (t) => {
|
test('cloudcmd: client: storage: set', async (t) => {
|
||||||
const {localStorage} = global;
|
const {localStorage} = globalThis;
|
||||||
const setItem = stub();
|
const setItem = stub();
|
||||||
|
|
||||||
global.localStorage = {
|
globalThis.localStorage = {
|
||||||
setItem,
|
setItem,
|
||||||
};
|
};
|
||||||
|
|
||||||
await storage.set('hello', 'world');
|
await storage.set('hello', 'world');
|
||||||
global.localStorage = localStorage;
|
globalThis.localStorage = localStorage;
|
||||||
|
|
||||||
t.calledWith(setItem, ['hello', 'world'], 'should call setItem');
|
t.calledWith(setItem, ['hello', 'world'], 'should call setItem');
|
||||||
t.end();
|
t.end();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('cloudcmd: client: storage: get', async (t) => {
|
test('cloudcmd: client: storage: get', async (t) => {
|
||||||
const {localStorage} = global;
|
const {localStorage} = globalThis;
|
||||||
const getItem = stub().returns('world');
|
const getItem = stub().returns('world');
|
||||||
|
|
||||||
global.localStorage = {
|
globalThis.localStorage = {
|
||||||
getItem,
|
getItem,
|
||||||
};
|
};
|
||||||
|
|
||||||
const result = await storage.get('hello');
|
const result = await storage.get('hello');
|
||||||
|
|
||||||
global.localStorage = localStorage;
|
globalThis.localStorage = localStorage;
|
||||||
|
|
||||||
t.equal(result, 'world');
|
t.equal(result, 'world');
|
||||||
t.end();
|
t.end();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('cloudcmd: client: storage: getJson', async (t) => {
|
test('cloudcmd: client: storage: getJson', async (t) => {
|
||||||
const {localStorage} = global;
|
const {localStorage} = globalThis;
|
||||||
const expected = {
|
const expected = {
|
||||||
hello: 'world',
|
hello: 'world',
|
||||||
};
|
};
|
||||||
|
|
||||||
const getItem = stub().returns(stringify(expected));
|
const getItem = stub().returns(stringify(expected));
|
||||||
|
|
||||||
global.localStorage = {
|
globalThis.localStorage = {
|
||||||
getItem,
|
getItem,
|
||||||
};
|
};
|
||||||
|
|
||||||
const result = await storage.getJson('hello');
|
const result = await storage.getJson('hello');
|
||||||
|
|
||||||
global.localStorage = localStorage;
|
globalThis.localStorage = localStorage;
|
||||||
|
|
||||||
t.deepEqual(result, expected);
|
t.deepEqual(result, expected);
|
||||||
t.end();
|
t.end();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('cloudcmd: client: storage: setJson', async (t) => {
|
test('cloudcmd: client: storage: setJson', async (t) => {
|
||||||
const {localStorage} = global;
|
const {localStorage} = globalThis;
|
||||||
const data = {
|
const data = {
|
||||||
hello: 'world',
|
hello: 'world',
|
||||||
};
|
};
|
||||||
|
|
@ -66,42 +66,42 @@ test('cloudcmd: client: storage: setJson', async (t) => {
|
||||||
const expected = stringify(data);
|
const expected = stringify(data);
|
||||||
const setItem = stub();
|
const setItem = stub();
|
||||||
|
|
||||||
global.localStorage = {
|
globalThis.localStorage = {
|
||||||
setItem,
|
setItem,
|
||||||
};
|
};
|
||||||
|
|
||||||
await storage.setJson('hello', data);
|
await storage.setJson('hello', data);
|
||||||
global.localStorage = localStorage;
|
globalThis.localStorage = localStorage;
|
||||||
|
|
||||||
t.calledWith(setItem, ['hello', expected]);
|
t.calledWith(setItem, ['hello', expected]);
|
||||||
t.end();
|
t.end();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('cloudcmd: client: storage: remove', async (t) => {
|
test('cloudcmd: client: storage: remove', async (t) => {
|
||||||
const {localStorage} = global;
|
const {localStorage} = globalThis;
|
||||||
const removeItem = stub();
|
const removeItem = stub();
|
||||||
|
|
||||||
global.localStorage = {
|
globalThis.localStorage = {
|
||||||
removeItem,
|
removeItem,
|
||||||
};
|
};
|
||||||
|
|
||||||
await storage.remove('hello');
|
await storage.remove('hello');
|
||||||
global.localStorage = localStorage;
|
globalThis.localStorage = localStorage;
|
||||||
|
|
||||||
t.calledWith(removeItem, ['hello'], 'should call removeItem');
|
t.calledWith(removeItem, ['hello'], 'should call removeItem');
|
||||||
t.end();
|
t.end();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('cloudcmd: client: storage: clear', async (t) => {
|
test('cloudcmd: client: storage: clear', async (t) => {
|
||||||
const {localStorage} = global;
|
const {localStorage} = globalThis;
|
||||||
const clear = stub();
|
const clear = stub();
|
||||||
|
|
||||||
global.localStorage = {
|
globalThis.localStorage = {
|
||||||
clear,
|
clear,
|
||||||
};
|
};
|
||||||
|
|
||||||
await storage.clear();
|
await storage.clear();
|
||||||
global.localStorage = localStorage;
|
globalThis.localStorage = localStorage;
|
||||||
|
|
||||||
t.calledWithNoArgs(clear, 'should call clear');
|
t.calledWithNoArgs(clear, 'should call clear');
|
||||||
t.end();
|
t.end();
|
||||||
|
|
|
||||||
|
|
@ -5,10 +5,10 @@ const {eachSeries} = require('execon');
|
||||||
const wraptile = require('wraptile');
|
const wraptile = require('wraptile');
|
||||||
|
|
||||||
const load = require('./load');
|
const load = require('./load');
|
||||||
const Images = require('./images');
|
const Images = require('./images.mjs');
|
||||||
const {alert} = require('./dialog');
|
const {alert} = require('./dialog');
|
||||||
|
|
||||||
const {FS} = require('../../common/cloudfunc');
|
const {FS} = require('../../common/cloudfunc.mjs');
|
||||||
|
|
||||||
const {getCurrentDirPath: getPathWhenRootEmpty} = require('.');
|
const {getCurrentDirPath: getPathWhenRootEmpty} = require('.');
|
||||||
const loadFile = wraptile(_loadFile);
|
const loadFile = wraptile(_loadFile);
|
||||||
|
|
@ -61,7 +61,7 @@ function _loadFile(dir, n, file, callback) {
|
||||||
.on('progress', (count) => {
|
.on('progress', (count) => {
|
||||||
const max = step(n);
|
const max = step(n);
|
||||||
const value = (i - 1) * max + percent(count, 100, max);
|
const value = (i - 1) * max + percent(count, 100, max);
|
||||||
|
|
||||||
Images.show.load('top');
|
Images.show.load('top');
|
||||||
Images.setProgress(Math.round(value));
|
Images.setProgress(Math.round(value));
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -1,47 +0,0 @@
|
||||||
'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;
|
|
||||||
};
|
|
||||||
44
client/get-json-from-file-table.mjs
Normal file
44
client/get-json-from-file-table.mjs
Normal file
|
|
@ -0,0 +1,44 @@
|
||||||
|
/* 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,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
@ -1,22 +1,17 @@
|
||||||
'use strict';
|
|
||||||
|
|
||||||
/* global CloudCmd, DOM */
|
/* global CloudCmd, DOM */
|
||||||
const clipboard = require('@cloudcmd/clipboard');
|
import clipboard from '@cloudcmd/clipboard';
|
||||||
const fullstore = require('fullstore');
|
import {fullstore} from 'fullstore';
|
||||||
|
import * as Events from '#dom/events';
|
||||||
|
import * as Buffer from '../dom/buffer.mjs';
|
||||||
|
import KEY from './key.js';
|
||||||
|
import _vim from './vim/index.js';
|
||||||
|
import setCurrentByChar from './set-current-by-char.js';
|
||||||
|
import {createBinder} from './binder.js';
|
||||||
|
|
||||||
const Buffer = require('../dom/buffer');
|
|
||||||
const Events = require('../dom/events');
|
|
||||||
const KEY = require('./key');
|
|
||||||
|
|
||||||
const vim = require('./vim');
|
|
||||||
const setCurrentByChar = require('./set-current-by-char');
|
|
||||||
const {createBinder} = require('./binder');
|
|
||||||
|
|
||||||
const Info = DOM.CurrentInfo;
|
|
||||||
const Chars = fullstore();
|
const Chars = fullstore();
|
||||||
|
|
||||||
const toggleVim = (keyCode) => {
|
const toggleVim = (keyCode, overrides = {}) => {
|
||||||
const {_config, config} = CloudCmd;
|
const {_config, config} = overrides;
|
||||||
|
|
||||||
if (keyCode === KEY.ESC)
|
if (keyCode === KEY.ESC)
|
||||||
_config('vim', !config('vim'));
|
_config('vim', !config('vim'));
|
||||||
|
|
@ -29,13 +24,16 @@ Chars([]);
|
||||||
const {assign} = Object;
|
const {assign} = Object;
|
||||||
const binder = createBinder();
|
const binder = createBinder();
|
||||||
|
|
||||||
module.exports = assign(binder, KEY);
|
const bind = () => {
|
||||||
module.exports.bind = () => {
|
|
||||||
Events.addKey(listener, true);
|
Events.addKey(listener, true);
|
||||||
binder.setBind();
|
binder.setBind();
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports._listener = listener;
|
export const Key = assign(binder, KEY, {
|
||||||
|
bind,
|
||||||
|
});
|
||||||
|
|
||||||
|
export const _listener = listener;
|
||||||
|
|
||||||
function getChar(event) {
|
function getChar(event) {
|
||||||
/*
|
/*
|
||||||
|
|
@ -55,7 +53,14 @@ function getChar(event) {
|
||||||
return [symbol, char];
|
return [symbol, char];
|
||||||
}
|
}
|
||||||
|
|
||||||
async function listener(event) {
|
async function listener(event, overrides = {}) {
|
||||||
|
const {
|
||||||
|
config = CloudCmd.config,
|
||||||
|
_config = CloudCmd._config,
|
||||||
|
switchKey = _switchKey,
|
||||||
|
vim = _vim,
|
||||||
|
} = overrides;
|
||||||
|
|
||||||
const {keyCode} = event;
|
const {keyCode} = event;
|
||||||
|
|
||||||
// strange chrome bug calles listener twice
|
// strange chrome bug calles listener twice
|
||||||
|
|
@ -74,8 +79,12 @@ async function listener(event) {
|
||||||
if (!binder.isBind())
|
if (!binder.isBind())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
toggleVim(keyCode);
|
toggleVim(keyCode, {
|
||||||
const isVim = CloudCmd.config('vim');
|
config,
|
||||||
|
_config,
|
||||||
|
});
|
||||||
|
|
||||||
|
const isVim = config('vim');
|
||||||
|
|
||||||
if (!isVim && !isNumpad && !alt && !ctrl && !meta && (isBetween || symbol))
|
if (!isVim && !isNumpad && !alt && !ctrl && !meta && (isBetween || symbol))
|
||||||
return setCurrentByChar(char, Chars);
|
return setCurrentByChar(char, Chars);
|
||||||
|
|
@ -112,7 +121,8 @@ function fromCharCode(keyIdentifier) {
|
||||||
return String.fromCharCode(hex);
|
return String.fromCharCode(hex);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function switchKey(event) {
|
async function _switchKey(event) {
|
||||||
|
const Info = DOM.CurrentInfo;
|
||||||
let i;
|
let i;
|
||||||
let isSelected;
|
let isSelected;
|
||||||
let prev;
|
let prev;
|
||||||
|
|
@ -509,6 +519,18 @@ async function switchKey(event) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case KEY.DOT:
|
||||||
|
if (meta && shift) {
|
||||||
|
const showDotFiles = !CloudCmd.config('showDotFiles');
|
||||||
|
CloudCmd._config('showDotFiles', showDotFiles);
|
||||||
|
CloudCmd.refresh();
|
||||||
|
await DOM.RESTful.Config.write({
|
||||||
|
showDotFiles,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -3,27 +3,23 @@
|
||||||
require('css-modules-require-hook/preset');
|
require('css-modules-require-hook/preset');
|
||||||
|
|
||||||
const autoGlobals = require('auto-globals');
|
const autoGlobals = require('auto-globals');
|
||||||
const mockRequire = require('mock-require');
|
|
||||||
const supertape = require('supertape');
|
const supertape = require('supertape');
|
||||||
|
|
||||||
const {ESC} = require('./key');
|
const {ESC} = require('./key');
|
||||||
|
|
||||||
|
const {Key, _listener} = require('./index.mjs');
|
||||||
|
|
||||||
const {getDOM, getCloudCmd} = require('./vim/globals.fixture');
|
const {getDOM, getCloudCmd} = require('./vim/globals.fixture');
|
||||||
const test = autoGlobals(supertape);
|
const test = autoGlobals(supertape);
|
||||||
const {reRequire, stopAll} = mockRequire;
|
|
||||||
const {stub} = supertape;
|
const {stub} = supertape;
|
||||||
|
|
||||||
global.DOM = getDOM();
|
globalThis.DOM = getDOM();
|
||||||
global.CloudCmd = getCloudCmd();
|
globalThis.CloudCmd = getCloudCmd();
|
||||||
|
|
||||||
test('cloudcmd: client: key: enable vim', async (t) => {
|
test('cloudcmd: client: key: enable vim', async (t) => {
|
||||||
const vim = stub();
|
const vim = stub();
|
||||||
const {CloudCmd} = global;
|
const config = stub().returns(true);
|
||||||
const {config} = CloudCmd;
|
const _config = stub();
|
||||||
|
|
||||||
CloudCmd.config = stub().returns(true);
|
|
||||||
CloudCmd._config = stub();
|
|
||||||
mockRequire('./vim', vim);
|
|
||||||
const {_listener, setBind} = reRequire('.');
|
|
||||||
|
|
||||||
const event = {
|
const event = {
|
||||||
keyCode: ESC,
|
keyCode: ESC,
|
||||||
|
|
@ -31,11 +27,14 @@ test('cloudcmd: client: key: enable vim', async (t) => {
|
||||||
altKey: false,
|
altKey: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
setBind();
|
Key.setBind();
|
||||||
await _listener(event);
|
|
||||||
|
|
||||||
CloudCmd.config = config;
|
await _listener(event, {
|
||||||
stopAll();
|
vim,
|
||||||
|
config,
|
||||||
|
_config,
|
||||||
|
switchKey: stub(),
|
||||||
|
});
|
||||||
|
|
||||||
t.calledWith(vim, ['Escape', event]);
|
t.calledWith(vim, ['Escape', event]);
|
||||||
t.end();
|
t.end();
|
||||||
|
|
@ -43,25 +42,20 @@ test('cloudcmd: client: key: enable vim', async (t) => {
|
||||||
|
|
||||||
test('cloudcmd: client: key: disable vim', async (t) => {
|
test('cloudcmd: client: key: disable vim', async (t) => {
|
||||||
const _config = stub();
|
const _config = stub();
|
||||||
|
const config = stub();
|
||||||
const event = {
|
const event = {
|
||||||
keyCode: ESC,
|
keyCode: ESC,
|
||||||
key: 'Escape',
|
key: 'Escape',
|
||||||
altKey: false,
|
altKey: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
const {CloudCmd} = global;
|
Key.setBind();
|
||||||
const {config} = CloudCmd;
|
await _listener(event, {
|
||||||
|
config,
|
||||||
|
_config,
|
||||||
|
switchKey: stub(),
|
||||||
|
});
|
||||||
|
|
||||||
global.CloudCmd.config = _config;
|
t.calledWith(_config, ['vim', true]);
|
||||||
global.CloudCmd._config = _config;
|
|
||||||
|
|
||||||
const {_listener, setBind} = reRequire('.');
|
|
||||||
|
|
||||||
setBind();
|
|
||||||
await _listener(event);
|
|
||||||
|
|
||||||
CloudCmd.config = config;
|
|
||||||
|
|
||||||
t.calledWith(_config, ['vim']);
|
|
||||||
t.end();
|
t.end();
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -3,9 +3,9 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const {escapeRegExp} = require('../../common/util');
|
const {escapeRegExp} = require('../../common/util');
|
||||||
const Info = DOM.CurrentInfo;
|
|
||||||
|
|
||||||
module.exports = function setCurrentByChar(char, charStore) {
|
module.exports = function setCurrentByChar(char, charStore) {
|
||||||
|
const Info = DOM.CurrentInfo;
|
||||||
let firstByName;
|
let firstByName;
|
||||||
let skipCount = 0;
|
let skipCount = 0;
|
||||||
let setted = false;
|
let setted = false;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const fullstore = require('fullstore');
|
const {fullstore} = require('fullstore');
|
||||||
const limier = require('limier');
|
const limier = require('limier');
|
||||||
|
|
||||||
const searchStore = fullstore([]);
|
const searchStore = fullstore([]);
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ const dir = './';
|
||||||
|
|
||||||
const {getDOM} = require('./globals.fixture');
|
const {getDOM} = require('./globals.fixture');
|
||||||
|
|
||||||
global.DOM = getDOM();
|
globalThis.DOM = getDOM();
|
||||||
|
|
||||||
const {_next, _previous} = require(`${dir}find`);
|
const {_next, _previous} = require(`${dir}find`);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,31 +9,43 @@ const {
|
||||||
selectFileNotParent,
|
selectFileNotParent,
|
||||||
} = require('./set-current');
|
} = require('./set-current');
|
||||||
|
|
||||||
const {Dialog} = DOM;
|
module.exports = (key, event, overrides = {}) => {
|
||||||
|
const defaults = {
|
||||||
const DEPS = {
|
...globalThis.DOM,
|
||||||
...DOM,
|
...globalThis.CloudCmd,
|
||||||
...CloudCmd,
|
};
|
||||||
};
|
|
||||||
|
const deps = {
|
||||||
module.exports = async (key, event, deps = DEPS) => {
|
...defaults,
|
||||||
|
...overrides,
|
||||||
|
};
|
||||||
|
|
||||||
const operations = getOperations(event, deps);
|
const operations = getOperations(event, deps);
|
||||||
await vim(key, operations);
|
|
||||||
|
vim(key, operations, deps);
|
||||||
};
|
};
|
||||||
|
|
||||||
const getOperations = (event, deps) => {
|
const getOperations = (event, deps) => {
|
||||||
const {
|
const {
|
||||||
Info = DOM.CurrentInfo,
|
Info = globalThis.DOM.CurrentInfo,
|
||||||
|
CloudCmd = globalThis.CloudCmd,
|
||||||
Operation,
|
Operation,
|
||||||
unselectFiles,
|
unselectFiles,
|
||||||
setCurrentFile,
|
setCurrentFile,
|
||||||
setCurrentByName,
|
setCurrentByName,
|
||||||
getCurrentName,
|
getCurrentName,
|
||||||
|
prompt = globalThis.DOM.Dialog.prompt,
|
||||||
|
preventDefault = event?.preventDefault?.bind(event),
|
||||||
|
|
||||||
toggleSelectedFile,
|
toggleSelectedFile,
|
||||||
Buffer = {},
|
Buffer = {},
|
||||||
|
createFindNext = _createFindNext,
|
||||||
} = deps;
|
} = deps;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
findNext: createFindNext({
|
||||||
|
setCurrentByName,
|
||||||
|
}),
|
||||||
escape: unselectFiles,
|
escape: unselectFiles,
|
||||||
|
|
||||||
remove: () => {
|
remove: () => {
|
||||||
|
|
@ -99,8 +111,8 @@ const getOperations = (event, deps) => {
|
||||||
},
|
},
|
||||||
|
|
||||||
find: async () => {
|
find: async () => {
|
||||||
event.preventDefault();
|
preventDefault();
|
||||||
const [, value] = await Dialog.prompt('Find', '');
|
const [, value] = await prompt('Find', '');
|
||||||
|
|
||||||
if (!value)
|
if (!value)
|
||||||
return;
|
return;
|
||||||
|
|
@ -111,11 +123,6 @@ const getOperations = (event, deps) => {
|
||||||
setCurrentByName(result);
|
setCurrentByName(result);
|
||||||
},
|
},
|
||||||
|
|
||||||
findNext: () => {
|
|
||||||
const name = finder.findNext();
|
|
||||||
setCurrentByName(name);
|
|
||||||
},
|
|
||||||
|
|
||||||
findPrevious: () => {
|
findPrevious: () => {
|
||||||
const name = finder.findPrevious();
|
const name = finder.findPrevious();
|
||||||
setCurrentByName(name);
|
setCurrentByName(name);
|
||||||
|
|
@ -124,3 +131,10 @@ const getOperations = (event, deps) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports.selectFile = selectFileNotParent;
|
module.exports.selectFile = selectFileNotParent;
|
||||||
|
|
||||||
|
const _createFindNext = (overrides = {}) => () => {
|
||||||
|
const {setCurrentByName} = overrides;
|
||||||
|
const name = finder.findNext();
|
||||||
|
|
||||||
|
setCurrentByName(name);
|
||||||
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const {join} = require('path');
|
const {join} = require('node:path');
|
||||||
const {test, stub} = require('supertape');
|
const {test, stub} = require('supertape');
|
||||||
const mockRequire = require('mock-require');
|
const mockRequire = require('mock-require');
|
||||||
|
|
||||||
|
|
@ -10,13 +10,13 @@ const pathVim = join(dir, 'vim');
|
||||||
|
|
||||||
const {getDOM, getCloudCmd} = require('./globals.fixture');
|
const {getDOM, getCloudCmd} = require('./globals.fixture');
|
||||||
|
|
||||||
global.DOM = getDOM();
|
globalThis.DOM = getDOM();
|
||||||
global.CloudCmd = getCloudCmd();
|
globalThis.CloudCmd = getCloudCmd();
|
||||||
|
|
||||||
const vim = require(pathVim);
|
const vim = require('./index.js');
|
||||||
|
|
||||||
const {assign} = Object;
|
const {assign} = Object;
|
||||||
const {DOM} = global;
|
const {DOM} = globalThis;
|
||||||
const {Buffer} = DOM;
|
const {Buffer} = DOM;
|
||||||
const pathFind = join(dir, 'vim', 'find');
|
const pathFind = join(dir, 'vim', 'find');
|
||||||
const {reRequire, stopAll} = mockRequire;
|
const {reRequire, stopAll} = mockRequire;
|
||||||
|
|
@ -520,15 +520,26 @@ test('cloudcmd: client: key: Enter', async (t) => {
|
||||||
test('cloudcmd: client: key: /', (t) => {
|
test('cloudcmd: client: key: /', (t) => {
|
||||||
const preventDefault = stub();
|
const preventDefault = stub();
|
||||||
const element = {};
|
const element = {};
|
||||||
|
const Info = {
|
||||||
|
element,
|
||||||
|
files: [],
|
||||||
|
};
|
||||||
|
|
||||||
DOM.CurrentInfo.element = element;
|
const getCurrentName = stub().returns('');
|
||||||
DOM.getCurrentName = () => '';
|
|
||||||
|
|
||||||
vim('/', {
|
const event = {
|
||||||
preventDefault,
|
preventDefault,
|
||||||
|
};
|
||||||
|
|
||||||
|
const prompt = stub().returns([]);
|
||||||
|
|
||||||
|
vim('/', event, {
|
||||||
|
getCurrentName,
|
||||||
|
Info,
|
||||||
|
prompt,
|
||||||
});
|
});
|
||||||
|
|
||||||
t.calledWithNoArgs(preventDefault, 'should call preventDefault');
|
t.calledWithNoArgs(preventDefault);
|
||||||
t.end();
|
t.end();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -559,17 +570,13 @@ test('cloudcmd: client: find', (t) => {
|
||||||
|
|
||||||
test('cloudcmd: client: key: n', (t) => {
|
test('cloudcmd: client: key: n', (t) => {
|
||||||
const findNext = stub();
|
const findNext = stub();
|
||||||
|
const createFindNext = stub().returns(findNext);
|
||||||
|
|
||||||
mockRequire(pathFind, {
|
|
||||||
findNext,
|
|
||||||
});
|
|
||||||
|
|
||||||
const vim = reRequire(pathVim);
|
|
||||||
const event = {};
|
const event = {};
|
||||||
|
|
||||||
vim('n', event);
|
vim('n', event, {
|
||||||
|
createFindNext,
|
||||||
stopAll();
|
});
|
||||||
|
|
||||||
t.calledWithNoArgs(findNext, 'should call findNext');
|
t.calledWithNoArgs(findNext, 'should call findNext');
|
||||||
t.end();
|
t.end();
|
||||||
|
|
@ -595,7 +602,7 @@ test('cloudcmd: client: key: N', (t) => {
|
||||||
|
|
||||||
test('cloudcmd: client: key: make directory', async (t) => {
|
test('cloudcmd: client: key: make directory', async (t) => {
|
||||||
const vim = reRequire(pathVim);
|
const vim = reRequire(pathVim);
|
||||||
const {DOM} = global;
|
const {DOM} = globalThis;
|
||||||
|
|
||||||
assign(DOM, {
|
assign(DOM, {
|
||||||
promptNewDir: stub(),
|
promptNewDir: stub(),
|
||||||
|
|
@ -615,7 +622,7 @@ test('cloudcmd: client: key: make directory', async (t) => {
|
||||||
|
|
||||||
test('cloudcmd: client: key: make file', (t) => {
|
test('cloudcmd: client: key: make file', (t) => {
|
||||||
const vim = reRequire(pathVim);
|
const vim = reRequire(pathVim);
|
||||||
const {DOM} = global;
|
const {DOM} = globalThis;
|
||||||
|
|
||||||
assign(DOM, {
|
assign(DOM, {
|
||||||
promptNewFile: stub(),
|
promptNewFile: stub(),
|
||||||
|
|
@ -634,28 +641,30 @@ test('cloudcmd: client: key: make file', (t) => {
|
||||||
});
|
});
|
||||||
|
|
||||||
test('cloudcmd: client: vim: terminal', (t) => {
|
test('cloudcmd: client: vim: terminal', (t) => {
|
||||||
const {CloudCmd} = global;
|
const CloudCmd = {
|
||||||
|
|
||||||
assign(CloudCmd, {
|
|
||||||
Terminal: {
|
Terminal: {
|
||||||
show: stub(),
|
show: stub(),
|
||||||
},
|
},
|
||||||
});
|
};
|
||||||
|
|
||||||
const event = {};
|
const event = {};
|
||||||
|
|
||||||
vim('t', event);
|
vim('t', event, {
|
||||||
vim('t', event);
|
CloudCmd,
|
||||||
|
});
|
||||||
|
vim('t', event, {
|
||||||
|
CloudCmd,
|
||||||
|
});
|
||||||
|
|
||||||
t.calledWithNoArgs(CloudCmd.Terminal.show);
|
t.calledWithNoArgs(CloudCmd.Terminal.show);
|
||||||
t.end();
|
t.end();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('cloudcmd: client: vim: edit', async (t) => {
|
test('cloudcmd: client: vim: edit', async (t) => {
|
||||||
global.DOM = getDOM();
|
globalThis.DOM = getDOM();
|
||||||
global.CloudCmd = getCloudCmd();
|
globalThis.CloudCmd = getCloudCmd();
|
||||||
|
|
||||||
const {CloudCmd} = global;
|
const {CloudCmd} = globalThis;
|
||||||
|
|
||||||
assign(CloudCmd, {
|
assign(CloudCmd, {
|
||||||
EditFileVim: {
|
EditFileVim: {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const fullstore = require('fullstore');
|
const {fullstore} = require('fullstore');
|
||||||
const store = fullstore('');
|
const store = fullstore('');
|
||||||
const visual = fullstore(false);
|
const visual = fullstore(false);
|
||||||
|
|
||||||
|
|
@ -21,7 +21,7 @@ const rmFirst = (a) => {
|
||||||
|
|
||||||
const noop = () => {};
|
const noop = () => {};
|
||||||
|
|
||||||
module.exports = (key, operations) => {
|
module.exports = (key, operations = {}) => {
|
||||||
const prevStore = store();
|
const prevStore = store();
|
||||||
const isVisual = visual();
|
const isVisual = visual();
|
||||||
const value = store(prevStore.concat(key));
|
const value = store(prevStore.concat(key));
|
||||||
|
|
@ -169,6 +169,9 @@ module.exports = (key, operations) => {
|
||||||
findPrevious();
|
findPrevious();
|
||||||
return end();
|
return end();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (key === ' ')
|
||||||
|
return end();
|
||||||
};
|
};
|
||||||
|
|
||||||
function handleDelete(prevStore) {
|
function handleDelete(prevStore) {
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,24 @@ test('vim: no operations', (t) => {
|
||||||
t.end();
|
t.end();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('vim: space', (t) => {
|
||||||
|
const moveNext = stub();
|
||||||
|
|
||||||
|
vim(' ');
|
||||||
|
vim('j', {
|
||||||
|
moveNext,
|
||||||
|
});
|
||||||
|
|
||||||
|
const args = [{
|
||||||
|
count: 1,
|
||||||
|
isDelete: false,
|
||||||
|
isVisual: false,
|
||||||
|
}];
|
||||||
|
|
||||||
|
t.calledWith(moveNext, args);
|
||||||
|
t.end();
|
||||||
|
});
|
||||||
|
|
||||||
test('vim: ^', (t) => {
|
test('vim: ^', (t) => {
|
||||||
const movePrevious = stub();
|
const movePrevious = stub();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,12 +5,13 @@
|
||||||
const exec = require('execon');
|
const exec = require('execon');
|
||||||
const itype = require('itype');
|
const itype = require('itype');
|
||||||
const currify = require('currify');
|
const currify = require('currify');
|
||||||
const tryToCatch = require('try-to-catch');
|
const {tryToCatch} = require('try-to-catch');
|
||||||
const clipboard = require('@cloudcmd/clipboard');
|
const clipboard = require('@cloudcmd/clipboard');
|
||||||
|
|
||||||
const getRange = require('./get-range');
|
const getRange = require('./get-range');
|
||||||
const uploadFiles = require('../dom/upload-files');
|
const uploadFiles = require('../dom/upload-files');
|
||||||
const {FS} = require('../../common/cloudfunc');
|
const {FS} = require('../../common/cloudfunc.mjs');
|
||||||
|
const Events = require('#dom/events');
|
||||||
|
|
||||||
const getIndex = currify(require('./get-index'));
|
const getIndex = currify(require('./get-index'));
|
||||||
|
|
||||||
|
|
@ -29,10 +30,8 @@ module.exports.init = async () => {
|
||||||
]);
|
]);
|
||||||
};
|
};
|
||||||
|
|
||||||
CloudCmd.Listeners = module.exports;
|
|
||||||
|
|
||||||
const unselect = (event) => {
|
const unselect = (event) => {
|
||||||
const isMac = /Mac/.test(window.navigator.platform);
|
const isMac = /Mac/.test(globalThis.navigator.platform);
|
||||||
const {
|
const {
|
||||||
shiftKey,
|
shiftKey,
|
||||||
metaKey,
|
metaKey,
|
||||||
|
|
@ -50,12 +49,9 @@ const execAll = currify((funcs, event) => {
|
||||||
fn(event);
|
fn(event);
|
||||||
});
|
});
|
||||||
|
|
||||||
const Info = DOM.CurrentInfo;
|
|
||||||
const {Events} = DOM;
|
|
||||||
|
|
||||||
const EventsFiles = {
|
const EventsFiles = {
|
||||||
mousedown: exec.with(execIfNotUL, setCurrentFileByEvent),
|
mousedown: exec.with(execIfNotUL, setCurrentFileByEvent),
|
||||||
click: execAll([onClick, unselect]),
|
click: execAll([onClick, exec.with(execIfNotMobile, unselect)]),
|
||||||
dragstart: exec.with(execIfNotUL, onDragStart),
|
dragstart: exec.with(execIfNotUL, onDragStart),
|
||||||
dblclick: exec.with(execIfNotUL, onDblClick),
|
dblclick: exec.with(execIfNotUL, onDblClick),
|
||||||
touchstart: exec.with(execIfNotUL, onTouch),
|
touchstart: exec.with(execIfNotUL, onTouch),
|
||||||
|
|
@ -111,8 +107,10 @@ module.exports.initKeysPanel = () => {
|
||||||
if (!keysElement)
|
if (!keysElement)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Events.addClick(keysElement, ({target}) => {
|
Events.addClick(keysElement, (event) => {
|
||||||
|
const {target} = event;
|
||||||
const {id} = target;
|
const {id} = target;
|
||||||
|
|
||||||
const operation = (name) => {
|
const operation = (name) => {
|
||||||
const {Operation} = CloudCmd;
|
const {Operation} = CloudCmd;
|
||||||
|
|
||||||
|
|
@ -128,7 +126,10 @@ module.exports.initKeysPanel = () => {
|
||||||
'f6': operation('move'),
|
'f6': operation('move'),
|
||||||
'f7': DOM.promptNewDir,
|
'f7': DOM.promptNewDir,
|
||||||
'f8': operation('delete'),
|
'f8': operation('delete'),
|
||||||
'f9': CloudCmd.Menu.show,
|
'f9': () => {
|
||||||
|
event.stopPropagation();
|
||||||
|
CloudCmd.Menu.show();
|
||||||
|
},
|
||||||
'f10': CloudCmd.Config.show,
|
'f10': CloudCmd.Config.show,
|
||||||
'~': CloudCmd.Konsole.show,
|
'~': CloudCmd.Konsole.show,
|
||||||
'shift~': CloudCmd.Terminal.show,
|
'shift~': CloudCmd.Terminal.show,
|
||||||
|
|
@ -162,6 +163,7 @@ function getPathListener(panel) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function isNoCurrent(panel) {
|
function isNoCurrent(panel) {
|
||||||
|
const Info = DOM.CurrentInfo;
|
||||||
const infoPanel = Info.panel;
|
const infoPanel = Info.panel;
|
||||||
|
|
||||||
if (!infoPanel)
|
if (!infoPanel)
|
||||||
|
|
@ -186,6 +188,7 @@ function decodePath(path) {
|
||||||
}
|
}
|
||||||
|
|
||||||
async function onPathElementClick(panel, event) {
|
async function onPathElementClick(panel, event) {
|
||||||
|
const Info = DOM.CurrentInfo;
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
|
||||||
const element = event.target;
|
const element = event.target;
|
||||||
|
|
@ -215,12 +218,18 @@ async function onPathElementClick(panel, event) {
|
||||||
|
|
||||||
function copyPath(el) {
|
function copyPath(el) {
|
||||||
clipboard
|
clipboard
|
||||||
.writeText(el
|
.writeText(el.parentElement.title)
|
||||||
.parentElement.title)
|
|
||||||
.then(CloudCmd.log)
|
.then(CloudCmd.log)
|
||||||
.catch(CloudCmd.log);
|
.catch(CloudCmd.log);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function execIfNotMobile(callback, event) {
|
||||||
|
const isMobile = DOM.getCSSVar('is-mobile');
|
||||||
|
|
||||||
|
if (!isMobile)
|
||||||
|
callback(event);
|
||||||
|
}
|
||||||
|
|
||||||
function execIfNotUL(callback, event) {
|
function execIfNotUL(callback, event) {
|
||||||
const {target} = event;
|
const {target} = event;
|
||||||
const {tagName} = target;
|
const {tagName} = target;
|
||||||
|
|
@ -235,14 +244,14 @@ function onClick(event) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function toggleSelect(key, files) {
|
function toggleSelect(key, files) {
|
||||||
const isMac = /Mac/.test(window.navigator.platform);
|
const isMac = /Mac/.test(globalThis.navigator.platform);
|
||||||
|
|
||||||
if (!key)
|
if (!key)
|
||||||
throw Error('key should not be undefined!');
|
throw Error('key should not be undefined!');
|
||||||
|
|
||||||
const [file] = files;
|
const [file] = files;
|
||||||
|
|
||||||
if (isMac && key.meta || key.ctrl)
|
if (isMac && key.meta)
|
||||||
return DOM.toggleSelectedFile(file);
|
return DOM.toggleSelectedFile(file);
|
||||||
|
|
||||||
if (key.shift)
|
if (key.shift)
|
||||||
|
|
@ -250,6 +259,7 @@ function toggleSelect(key, files) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function changePanel(element) {
|
function changePanel(element) {
|
||||||
|
const Info = DOM.CurrentInfo;
|
||||||
const {panel} = Info;
|
const {panel} = Info;
|
||||||
const files = DOM.getByDataName('js-files', panel);
|
const files = DOM.getByDataName('js-files', panel);
|
||||||
const ul = getULElement(element);
|
const ul = getULElement(element);
|
||||||
|
|
@ -291,6 +301,7 @@ async function onTouch(event) {
|
||||||
* in Chrome (HTML5)
|
* in Chrome (HTML5)
|
||||||
*/
|
*/
|
||||||
function onDragStart(event) {
|
function onDragStart(event) {
|
||||||
|
const Info = DOM.CurrentInfo;
|
||||||
const {prefixURL} = CloudCmd;
|
const {prefixURL} = CloudCmd;
|
||||||
const element = getLIElement(event.target);
|
const element = getLIElement(event.target);
|
||||||
const {isDir} = Info;
|
const {isDir} = Info;
|
||||||
|
|
@ -327,6 +338,7 @@ function getULElement(element) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function setCurrentFileByEvent(event) {
|
function setCurrentFileByEvent(event) {
|
||||||
|
const Info = DOM.CurrentInfo;
|
||||||
const BUTTON_LEFT = 0;
|
const BUTTON_LEFT = 0;
|
||||||
|
|
||||||
const key = {
|
const key = {
|
||||||
|
|
@ -415,7 +427,7 @@ function dragndrop() {
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* In Mac OS Chrome dropEffect = 'none'
|
* In macOS Chrome dropEffect = 'none'
|
||||||
* so drop do not firing up when try
|
* so drop do not firing up when try
|
||||||
* to upload file from download bar
|
* to upload file from download bar
|
||||||
*/
|
*/
|
||||||
|
|
@ -440,7 +452,7 @@ function dragndrop() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function unload() {
|
function unload() {
|
||||||
DOM.Events.add(['unload', 'beforeunload'], (event) => {
|
Events.add(['unload', 'beforeunload'], (event) => {
|
||||||
const {Key} = CloudCmd;
|
const {Key} = CloudCmd;
|
||||||
const isBind = Key?.isBind();
|
const isBind = Key?.isBind();
|
||||||
|
|
||||||
|
|
@ -469,7 +481,8 @@ function pop() {
|
||||||
|
|
||||||
function resize() {
|
function resize() {
|
||||||
Events.add('resize', () => {
|
Events.add('resize', () => {
|
||||||
const is = window.innerWidth < CloudCmd.MIN_ONE_PANEL_WIDTH;
|
const Info = DOM.CurrentInfo;
|
||||||
|
const is = globalThis.innerWidth < CloudCmd.MIN_ONE_PANEL_WIDTH;
|
||||||
|
|
||||||
if (!is)
|
if (!is)
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,16 @@
|
||||||
'use strict';
|
|
||||||
|
|
||||||
/* global CloudCmd */
|
/* global CloudCmd */
|
||||||
const exec = require('execon');
|
import exec from 'execon';
|
||||||
const tryToCatch = require('try-to-catch');
|
import {tryToCatch} from 'try-to-catch';
|
||||||
const loadJS = require('load.js').js;
|
import {js as loadJS} from 'load.js';
|
||||||
|
import pascalCase from 'just-pascal-case';
|
||||||
|
|
||||||
const pascalCase = require('just-pascal-case');
|
|
||||||
const noJS = (a) => a.replace(/.js$/, '');
|
const noJS = (a) => a.replace(/.js$/, '');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* function load modules
|
* function load modules
|
||||||
* @params = {name, path, func, dobefore, arg}
|
* @params = {name, path, func, dobefore, arg}
|
||||||
*/
|
*/
|
||||||
module.exports = function loadModule(params) {
|
export const loadModule = (params) => {
|
||||||
if (!params)
|
if (!params)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
@ -51,7 +49,7 @@ module.exports = function loadModule(params) {
|
||||||
const [e, a] = await tryToCatch(m);
|
const [e, a] = await tryToCatch(m);
|
||||||
|
|
||||||
if (e)
|
if (e)
|
||||||
return console.error(e);
|
return;
|
||||||
|
|
||||||
return await a.show(...args);
|
return await a.show(...args);
|
||||||
};
|
};
|
||||||
|
|
@ -9,7 +9,7 @@ const load = require('load.js');
|
||||||
const {ajax} = require('../dom/load');
|
const {ajax} = require('../dom/load');
|
||||||
|
|
||||||
const Files = require('../dom/files');
|
const Files = require('../dom/files');
|
||||||
const Images = require('../dom/images');
|
const Images = require('../dom/images.mjs');
|
||||||
const {log} = CloudCmd;
|
const {log} = CloudCmd;
|
||||||
|
|
||||||
const upload = currify(_upload);
|
const upload = currify(_upload);
|
||||||
|
|
|
||||||
|
|
@ -8,16 +8,16 @@ const currify = require('currify');
|
||||||
const wraptile = require('wraptile');
|
const wraptile = require('wraptile');
|
||||||
const squad = require('squad');
|
const squad = require('squad');
|
||||||
const {promisify} = require('es6-promisify');
|
const {promisify} = require('es6-promisify');
|
||||||
const tryToCatch = require('try-to-catch');
|
const {tryToCatch} = require('try-to-catch');
|
||||||
const load = require('load.js');
|
const load = require('load.js');
|
||||||
const createElement = require('@cloudcmd/create-element');
|
const createElement = require('@cloudcmd/create-element');
|
||||||
|
|
||||||
const input = require('./input');
|
const input = require('./input');
|
||||||
const Images = require('../../dom/images');
|
const Images = require('../../dom/images.mjs');
|
||||||
const Events = require('../../dom/events');
|
const Events = require('#dom/events');
|
||||||
const Files = require('../../dom/files');
|
const Files = require('../../dom/files');
|
||||||
|
|
||||||
const {getTitle} = require('../../../common/cloudfunc');
|
const {getTitle} = require('../../../common/cloudfunc.mjs');
|
||||||
const {Dialog, setTitle} = DOM;
|
const {Dialog, setTitle} = DOM;
|
||||||
|
|
||||||
const Name = 'Config';
|
const Name = 'Config';
|
||||||
|
|
@ -52,12 +52,12 @@ module.exports.init = async () => {
|
||||||
|
|
||||||
showLoad();
|
showLoad();
|
||||||
|
|
||||||
const {prefix} = CloudCmd;
|
const {DIR_DIST} = CloudCmd;
|
||||||
|
|
||||||
[Template] = await Promise.all([
|
[Template] = await Promise.all([
|
||||||
Files.get('config-tmpl'),
|
Files.get('config-tmpl'),
|
||||||
loadSocket(),
|
loadSocket(),
|
||||||
loadCSS(`${prefix}/dist/config.css`),
|
loadCSS(`${DIR_DIST}/config.css`),
|
||||||
CloudCmd.View(),
|
CloudCmd.View(),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
|
@ -135,15 +135,19 @@ async function fillTemplate() {
|
||||||
|
|
||||||
const {
|
const {
|
||||||
editor,
|
editor,
|
||||||
|
menu,
|
||||||
packer,
|
packer,
|
||||||
columns,
|
columns,
|
||||||
|
theme,
|
||||||
configAuth,
|
configAuth,
|
||||||
...obj
|
...obj
|
||||||
} = input.convert(config);
|
} = input.convert(config);
|
||||||
|
|
||||||
|
obj[`${menu}-selected`] = 'selected';
|
||||||
obj[`${editor}-selected`] = 'selected';
|
obj[`${editor}-selected`] = 'selected';
|
||||||
obj[`${packer}-selected`] = 'selected';
|
obj[`${packer}-selected`] = 'selected';
|
||||||
obj[`${columns}-selected`] = 'selected';
|
obj[`${columns}-selected`] = 'selected';
|
||||||
|
obj[`${theme}-selected`] = 'selected';
|
||||||
obj.configAuth = configAuth ? '' : 'hidden';
|
obj.configAuth = configAuth ? '' : 'hidden';
|
||||||
|
|
||||||
const innerHTML = rendy(Template, obj);
|
const innerHTML = rendy(Template, obj);
|
||||||
|
|
@ -223,7 +227,8 @@ function onAuthChange(checked) {
|
||||||
const elUsername = input.getElementByName('username', Element);
|
const elUsername = input.getElementByName('username', Element);
|
||||||
const elPassword = input.getElementByName('password', Element);
|
const elPassword = input.getElementByName('password', Element);
|
||||||
|
|
||||||
elUsername.disabled = elPassword.disabled = !checked;
|
elUsername.disabled = !checked;
|
||||||
|
elPassword.disabled = !checked;
|
||||||
}
|
}
|
||||||
|
|
||||||
function onNameChange(name) {
|
function onNameChange(name) {
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@
|
||||||
CloudCmd.Contact = exports;
|
CloudCmd.Contact = exports;
|
||||||
|
|
||||||
const olark = require('@cloudcmd/olark');
|
const olark = require('@cloudcmd/olark');
|
||||||
const Images = require('../dom/images');
|
const Images = require('../dom/images.mjs');
|
||||||
|
|
||||||
const {Events} = DOM;
|
const {Events} = DOM;
|
||||||
const {Key} = CloudCmd;
|
const {Key} = CloudCmd;
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
/* global CloudCmd */
|
/* global CloudCmd */
|
||||||
CloudCmd.EditFileVim = exports;
|
CloudCmd.EditFileVim = exports;
|
||||||
|
|
||||||
const Events = require('../dom/events');
|
const Events = require('#dom/events');
|
||||||
|
|
||||||
const {Key} = CloudCmd;
|
const {Key} = CloudCmd;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
CloudCmd.EditFile = exports;
|
CloudCmd.EditFile = exports;
|
||||||
|
|
||||||
const Format = require('format-io');
|
const Format = require('format-io');
|
||||||
const fullstore = require('fullstore');
|
const {fullstore} = require('fullstore');
|
||||||
const exec = require('execon');
|
const exec = require('execon');
|
||||||
const supermenu = require('supermenu');
|
const supermenu = require('supermenu');
|
||||||
|
|
||||||
|
|
@ -61,8 +61,7 @@ module.exports.show = async (options) => {
|
||||||
|
|
||||||
Images.show.load();
|
Images.show.load();
|
||||||
|
|
||||||
CloudCmd
|
CloudCmd.Edit
|
||||||
.Edit
|
|
||||||
.getEditor()
|
.getEditor()
|
||||||
.setOption('keyMap', 'default');
|
.setOption('keyMap', 'default');
|
||||||
|
|
||||||
|
|
@ -78,8 +77,7 @@ module.exports.show = async (options) => {
|
||||||
|
|
||||||
setMsgChanged(name);
|
setMsgChanged(name);
|
||||||
|
|
||||||
CloudCmd
|
CloudCmd.Edit
|
||||||
.Edit
|
|
||||||
.getEditor()
|
.getEditor()
|
||||||
.setValueFirst(path, data)
|
.setValueFirst(path, data)
|
||||||
.setModeForPath(name)
|
.setModeForPath(name)
|
||||||
|
|
@ -131,8 +129,7 @@ function setMenu(event) {
|
||||||
},
|
},
|
||||||
|
|
||||||
afterClick: () => {
|
afterClick: () => {
|
||||||
CloudCmd
|
CloudCmd.Edit
|
||||||
.Edit
|
|
||||||
.getEditor()
|
.getEditor()
|
||||||
.focus();
|
.focus();
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
/* global CloudCmd */
|
/* global CloudCmd */
|
||||||
CloudCmd.EditNamesVim = exports;
|
CloudCmd.EditNamesVim = exports;
|
||||||
|
|
||||||
const Events = require('../dom/events');
|
const Events = require('#dom/events');
|
||||||
const {Key} = CloudCmd;
|
const {Key} = CloudCmd;
|
||||||
|
|
||||||
const ConfigView = {
|
const ConfigView = {
|
||||||
|
|
@ -21,8 +21,7 @@ module.exports.init = async () => {
|
||||||
module.exports.show = () => {
|
module.exports.show = () => {
|
||||||
Events.addKey(listener);
|
Events.addKey(listener);
|
||||||
|
|
||||||
CloudCmd
|
CloudCmd.EditNames
|
||||||
.EditNames
|
|
||||||
.show(ConfigView)
|
.show(ConfigView)
|
||||||
.getEditor()
|
.getEditor()
|
||||||
.setKeyMap('vim');
|
.setKeyMap('vim');
|
||||||
|
|
|
||||||
|
|
@ -1,21 +1,17 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
const {tryToCatch} = require('try-to-catch');
|
||||||
|
|
||||||
/* global CloudCmd, DOM */
|
/* global CloudCmd, DOM */
|
||||||
CloudCmd.EditNames = exports;
|
CloudCmd.EditNames = exports;
|
||||||
|
|
||||||
const currify = require('currify');
|
|
||||||
const exec = require('execon');
|
const exec = require('execon');
|
||||||
const supermenu = require('supermenu');
|
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 Info = DOM.CurrentInfo;
|
||||||
const {Dialog} = DOM;
|
const {Dialog} = DOM;
|
||||||
|
|
||||||
const refresh = currify(_refresh);
|
|
||||||
const rename = currify(_rename);
|
|
||||||
|
|
||||||
let Menu;
|
let Menu;
|
||||||
|
|
||||||
const ConfigView = {
|
const ConfigView = {
|
||||||
|
|
@ -44,8 +40,7 @@ module.exports.show = (options) => {
|
||||||
|
|
||||||
DOM.Events.addKey(keyListener);
|
DOM.Events.addKey(keyListener);
|
||||||
|
|
||||||
CloudCmd
|
CloudCmd.Edit
|
||||||
.Edit
|
|
||||||
.getEditor()
|
.getEditor()
|
||||||
.setValueFirst('edit-names', names)
|
.setValueFirst('edit-names', names)
|
||||||
.setMode()
|
.setMode()
|
||||||
|
|
@ -63,9 +58,9 @@ async function keyListener(event) {
|
||||||
const ctrlMeta = ctrl || meta;
|
const ctrlMeta = ctrl || meta;
|
||||||
const {Key} = CloudCmd;
|
const {Key} = CloudCmd;
|
||||||
|
|
||||||
if (ctrlMeta && event.keyCode === Key.S)
|
if (ctrlMeta && event.keyCode === Key.S) {
|
||||||
hide();
|
hide();
|
||||||
else if (ctrlMeta && event.keyCode === Key.P) {
|
} else if (ctrlMeta && event.keyCode === Key.P) {
|
||||||
const [, pattern] = await Dialog.prompt('Apply pattern:', '[n][e]');
|
const [, pattern] = await Dialog.prompt('Apply pattern:', '[n][e]');
|
||||||
pattern && applyPattern(pattern);
|
pattern && applyPattern(pattern);
|
||||||
}
|
}
|
||||||
|
|
@ -94,7 +89,7 @@ function setListeners() {
|
||||||
DOM.Events.addOnce('contextmenu', element, setMenu);
|
DOM.Events.addOnce('contextmenu', element, setMenu);
|
||||||
}
|
}
|
||||||
|
|
||||||
function applyNames() {
|
async function applyNames() {
|
||||||
const dir = Info.dirPath;
|
const dir = Info.dirPath;
|
||||||
const from = getActiveNames();
|
const from = getActiveNames();
|
||||||
const nameIndex = from.indexOf(Info.name);
|
const nameIndex = from.indexOf(Info.name);
|
||||||
|
|
@ -106,18 +101,18 @@ function applyNames() {
|
||||||
|
|
||||||
const root = CloudCmd.config('root');
|
const root = CloudCmd.config('root');
|
||||||
|
|
||||||
Promise
|
const response = rename(dir, from, to, root);
|
||||||
.resolve(root)
|
const [error] = await tryToCatch(refresh, to, nameIndex, response);
|
||||||
.then(rename(dir, from, to))
|
|
||||||
.then(refresh(to, nameIndex))
|
if (error)
|
||||||
.catch(alert);
|
alert(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
function _refresh(to, nameIndex, res) {
|
function refresh(to, nameIndex, res) {
|
||||||
if (res.status === 404)
|
if (res.status === 404) {
|
||||||
return res
|
const error = res.text();
|
||||||
.text()
|
throw error;
|
||||||
.then(reject);
|
}
|
||||||
|
|
||||||
const currentName = to[nameIndex];
|
const currentName = to[nameIndex];
|
||||||
|
|
||||||
|
|
@ -133,7 +128,7 @@ function getDir(root, dir) {
|
||||||
return root + dir;
|
return root + dir;
|
||||||
}
|
}
|
||||||
|
|
||||||
function _rename(path, from, to, root) {
|
function rename(path, from, to, root) {
|
||||||
const dir = getDir(root, path);
|
const dir = getDir(root, path);
|
||||||
const {prefix} = CloudCmd;
|
const {prefix} = CloudCmd;
|
||||||
|
|
||||||
|
|
@ -173,8 +168,8 @@ function setMenu(event) {
|
||||||
};
|
};
|
||||||
|
|
||||||
const menuData = {
|
const menuData = {
|
||||||
'Save Ctrl+S': () => {
|
'Save Ctrl+S': async () => {
|
||||||
applyNames();
|
await applyNames();
|
||||||
hide();
|
hide();
|
||||||
},
|
},
|
||||||
'Go To Line Ctrl+G': () => {
|
'Go To Line Ctrl+G': () => {
|
||||||
|
|
@ -215,6 +210,7 @@ async function isChanged() {
|
||||||
if (!editor.isChanged())
|
if (!editor.isChanged())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const [, names] = await Dialog.confirm(msg);
|
const [cancel] = await Dialog.confirm(msg);
|
||||||
names && applyNames();
|
|
||||||
|
!cancel && await applyNames();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,12 +5,13 @@
|
||||||
const montag = require('montag');
|
const montag = require('montag');
|
||||||
|
|
||||||
const {promisify} = require('es6-promisify');
|
const {promisify} = require('es6-promisify');
|
||||||
const tryToCatch = require('try-to-catch');
|
const {tryToCatch} = require('try-to-catch');
|
||||||
const createElement = require('@cloudcmd/create-element');
|
const createElement = require('@cloudcmd/create-element');
|
||||||
const load = require('load.js');
|
const load = require('load.js');
|
||||||
const {MAX_FILE_SIZE: maxSize} = require('../../common/cloudfunc');
|
const {MAX_FILE_SIZE: maxSize} = require('../../common/cloudfunc.mjs');
|
||||||
|
|
||||||
const {time, timeEnd} = require('../../common/util');
|
const {time, timeEnd} = require('../../common/util');
|
||||||
|
const getEditor = () => editor;
|
||||||
const isFn = (a) => typeof a === 'function';
|
const isFn = (a) => typeof a === 'function';
|
||||||
const loadJS = load.js;
|
const loadJS = load.js;
|
||||||
|
|
||||||
|
|
@ -91,10 +92,6 @@ module.exports.show = (options) => {
|
||||||
|
|
||||||
module.exports.getEditor = getEditor;
|
module.exports.getEditor = getEditor;
|
||||||
|
|
||||||
function getEditor() {
|
|
||||||
return editor;
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports.getElement = () => Element;
|
module.exports.getElement = () => Element;
|
||||||
|
|
||||||
module.exports.hide = () => {
|
module.exports.hide = () => {
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
/* global CloudCmd */
|
/* global CloudCmd */
|
||||||
CloudCmd.Help = exports;
|
CloudCmd.Help = exports;
|
||||||
|
|
||||||
const Images = require('../dom/images');
|
const Images = require('../dom/images.mjs');
|
||||||
|
|
||||||
module.exports.init = () => {
|
module.exports.init = () => {
|
||||||
Images.show.load('top');
|
Images.show.load('top');
|
||||||
|
|
|
||||||
|
|
@ -8,11 +8,11 @@ CloudCmd.Konsole = exports;
|
||||||
|
|
||||||
const exec = require('execon');
|
const exec = require('execon');
|
||||||
const currify = require('currify');
|
const currify = require('currify');
|
||||||
const tryToCatch = require('try-to-catch');
|
const {tryToCatch} = require('try-to-catch');
|
||||||
const loadJS = require('load.js').js;
|
const loadJS = require('load.js').js;
|
||||||
const createElement = require('@cloudcmd/create-element');
|
const createElement = require('@cloudcmd/create-element');
|
||||||
|
|
||||||
const Images = require('../dom/images');
|
const Images = require('../dom/images.mjs');
|
||||||
const {Dialog, CurrentInfo: Info} = DOM;
|
const {Dialog, CurrentInfo: Info} = DOM;
|
||||||
|
|
||||||
const rmLastSlash = (a) => a.replace(/\/$/, '') || '/';
|
const rmLastSlash = (a) => a.replace(/\/$/, '') || '/';
|
||||||
|
|
@ -46,22 +46,18 @@ module.exports.clear = () => {
|
||||||
konsole.clear();
|
konsole.clear();
|
||||||
};
|
};
|
||||||
|
|
||||||
function getPrefix() {
|
const getPrefix = () => CloudCmd.prefix + '/console';
|
||||||
return CloudCmd.prefix + '/console';
|
|
||||||
}
|
|
||||||
|
|
||||||
function getPrefixSocket() {
|
function getPrefixSocket() {
|
||||||
return CloudCmd.prefixSocket + '/console';
|
return CloudCmd.prefixSocket + '/console';
|
||||||
}
|
}
|
||||||
|
|
||||||
function getEnv() {
|
const getEnv = () => ({
|
||||||
return {
|
ACTIVE_DIR: DOM.getCurrentDirPath.bind(DOM),
|
||||||
ACTIVE_DIR: DOM.getCurrentDirPath.bind(DOM),
|
PASSIVE_DIR: DOM.getNotCurrentDirPath.bind(DOM),
|
||||||
PASSIVE_DIR: DOM.getNotCurrentDirPath.bind(DOM),
|
CURRENT_NAME: DOM.getCurrentName.bind(DOM),
|
||||||
CURRENT_NAME: DOM.getCurrentName.bind(DOM),
|
CURRENT_PATH: () => Info.path,
|
||||||
CURRENT_PATH: () => Info.path,
|
});
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
async function onPath(path) {
|
async function onPath(path) {
|
||||||
if (Info.dirPath === path)
|
if (Info.dirPath === path)
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ CloudCmd.Markdown = exports;
|
||||||
|
|
||||||
const createElement = require('@cloudcmd/create-element');
|
const createElement = require('@cloudcmd/create-element');
|
||||||
|
|
||||||
const Images = require('../dom/images');
|
const Images = require('../dom/images.mjs');
|
||||||
const {Markdown} = require('../dom/rest');
|
const {Markdown} = require('../dom/rest');
|
||||||
const {alert} = require('../dom/dialog');
|
const {alert} = require('../dom/dialog');
|
||||||
|
|
||||||
|
|
|
||||||
30
client/modules/menu/cloudmenu.mjs
Normal file
30
client/modules/menu/cloudmenu.mjs
Normal file
|
|
@ -0,0 +1,30 @@
|
||||||
|
import supermenu from 'supermenu';
|
||||||
|
|
||||||
|
const noop = () => {};
|
||||||
|
const {CloudCmd} = globalThis;
|
||||||
|
|
||||||
|
export const createCloudMenu = async (fm, options, menuData) => {
|
||||||
|
const createMenu = await loadMenu();
|
||||||
|
const menu = await createMenu(fm, options, menuData);
|
||||||
|
|
||||||
|
menu.addContextMenuListener = menu.addContextMenuListener || noop;
|
||||||
|
|
||||||
|
return menu;
|
||||||
|
};
|
||||||
|
|
||||||
|
async function loadMenu() {
|
||||||
|
if (CloudCmd.config('menu') === 'aleman') {
|
||||||
|
const {host, protocol} = globalThis.location;
|
||||||
|
const url = `${protocol}//${host}/node_modules/aleman/menu/menu.js`;
|
||||||
|
const {createMenu} = await import(/* webpackIgnore: true */url);
|
||||||
|
|
||||||
|
return createMenu;
|
||||||
|
}
|
||||||
|
|
||||||
|
return createSupermenu;
|
||||||
|
}
|
||||||
|
|
||||||
|
function createSupermenu(name, options, menuData) {
|
||||||
|
const element = document.querySelector('[data-name="js-fm"]');
|
||||||
|
return supermenu(element, options, menuData);
|
||||||
|
}
|
||||||
|
|
@ -4,12 +4,11 @@
|
||||||
|
|
||||||
const exec = require('execon');
|
const exec = require('execon');
|
||||||
const wrap = require('wraptile');
|
const wrap = require('wraptile');
|
||||||
const supermenu = require('supermenu');
|
|
||||||
const createElement = require('@cloudcmd/create-element');
|
const createElement = require('@cloudcmd/create-element');
|
||||||
|
|
||||||
const {FS} = require('../../common/cloudfunc');
|
const {FS} = require('../../../common/cloudfunc.mjs');
|
||||||
const {getIdBySrc} = require('../dom/load');
|
const {getIdBySrc} = require('../../dom/load');
|
||||||
const RESTful = require('../dom/rest');
|
const RESTful = require('../../dom/rest');
|
||||||
|
|
||||||
const {config, Key} = CloudCmd;
|
const {config, Key} = CloudCmd;
|
||||||
|
|
||||||
|
|
@ -32,7 +31,7 @@ module.exports.ENABLED = false;
|
||||||
|
|
||||||
CloudCmd.Menu = exports;
|
CloudCmd.Menu = exports;
|
||||||
|
|
||||||
module.exports.init = () => {
|
module.exports.init = async () => {
|
||||||
const {isAuth, menuDataFile} = getFileMenuData();
|
const {isAuth, menuDataFile} = getFileMenuData();
|
||||||
|
|
||||||
const fm = DOM.getFM();
|
const fm = DOM.getFM();
|
||||||
|
|
@ -46,8 +45,12 @@ module.exports.init = () => {
|
||||||
type: 'file',
|
type: 'file',
|
||||||
});
|
});
|
||||||
|
|
||||||
MenuContext = supermenu(fm, options, menuData);
|
const {createCloudMenu} = await import('./cloudmenu.mjs');
|
||||||
MenuContextFile = supermenu(fm, optionsFile, menuDataFile);
|
|
||||||
|
const {name} = fm.dataset;
|
||||||
|
|
||||||
|
MenuContext = await createCloudMenu(name, options, menuData);
|
||||||
|
MenuContextFile = await createCloudMenu(name, optionsFile, menuDataFile);
|
||||||
|
|
||||||
MenuContext.addContextMenuListener();
|
MenuContext.addContextMenuListener();
|
||||||
MenuContextFile.addContextMenuListener();
|
MenuContextFile.addContextMenuListener();
|
||||||
|
|
@ -106,7 +109,9 @@ function getOptions({type}) {
|
||||||
|
|
||||||
const options = {
|
const options = {
|
||||||
icon: true,
|
icon: true,
|
||||||
|
infiniteScroll: false,
|
||||||
beforeClose: Key.setBind,
|
beforeClose: Key.setBind,
|
||||||
|
beforeHide: Key.setBind,
|
||||||
beforeShow: exec.with(beforeShow, func),
|
beforeShow: exec.with(beforeShow, func),
|
||||||
beforeClick,
|
beforeClick,
|
||||||
name,
|
name,
|
||||||
|
|
@ -126,6 +131,7 @@ function getMenuData(isAuth) {
|
||||||
CloudCmd.Upload.show();
|
CloudCmd.Upload.show();
|
||||||
},
|
},
|
||||||
'Upload From Cloud': uploadFromCloud,
|
'Upload From Cloud': uploadFromCloud,
|
||||||
|
'Toggle File Selection': DOM.toggleSelectedFile,
|
||||||
'(Un)Select All': DOM.toggleAllSelectedFiles,
|
'(Un)Select All': DOM.toggleAllSelectedFiles,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -197,14 +203,25 @@ function isPath(x, y) {
|
||||||
const el = document.elementFromPoint(x, y);
|
const el = document.elementFromPoint(x, y);
|
||||||
const elements = panel.querySelectorAll('[data-name="js-path"] *');
|
const elements = panel.querySelectorAll('[data-name="js-path"] *');
|
||||||
|
|
||||||
return ~[].indexOf.call(elements, el);
|
return !~[].indexOf.call(elements, el);
|
||||||
}
|
}
|
||||||
|
|
||||||
function beforeShow(callback, params) {
|
function beforeShow(callback, params) {
|
||||||
const {name} = params;
|
Key.unsetBind();
|
||||||
|
|
||||||
|
const {
|
||||||
|
name,
|
||||||
|
position = {
|
||||||
|
x: params.x,
|
||||||
|
y: params.y,
|
||||||
|
},
|
||||||
|
} = params;
|
||||||
|
|
||||||
|
const {x, y} = position;
|
||||||
|
|
||||||
const el = DOM.getCurrentByPosition({
|
const el = DOM.getCurrentByPosition({
|
||||||
x: params.x,
|
x,
|
||||||
y: params.y,
|
y,
|
||||||
});
|
});
|
||||||
|
|
||||||
const menuName = getMenuNameByEl(el);
|
const menuName = getMenuNameByEl(el);
|
||||||
|
|
@ -220,14 +237,12 @@ function beforeShow(callback, params) {
|
||||||
exec(callback);
|
exec(callback);
|
||||||
|
|
||||||
if (isShow)
|
if (isShow)
|
||||||
isShow = isPath(params.x, params.y);
|
isShow = isPath(x, y);
|
||||||
|
|
||||||
return isShow;
|
return isShow;
|
||||||
}
|
}
|
||||||
|
|
||||||
function beforeClick(name) {
|
const beforeClick = (name) => MenuShowedName !== name;
|
||||||
return MenuShowedName !== name;
|
|
||||||
}
|
|
||||||
|
|
||||||
async function _uploadTo(nameModule) {
|
async function _uploadTo(nameModule) {
|
||||||
const [error, data] = await Info.getData();
|
const [error, data] = await Info.getData();
|
||||||
|
|
@ -277,6 +292,7 @@ function download(type) {
|
||||||
const path = DOM.getCurrentPath(file);
|
const path = DOM.getCurrentPath(file);
|
||||||
|
|
||||||
CloudCmd.log(`downloading file ${path}...`);
|
CloudCmd.log(`downloading file ${path}...`);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* if we send ajax request -
|
* if we send ajax request -
|
||||||
* no need in hash so we escape #
|
* no need in hash so we escape #
|
||||||
|
|
@ -327,13 +343,12 @@ function listener(event) {
|
||||||
const key = event.keyCode;
|
const key = event.keyCode;
|
||||||
const isBind = Key.isBind();
|
const isBind = Key.isBind();
|
||||||
|
|
||||||
if (!isBind)
|
if (key === ESC) {
|
||||||
return;
|
Key.setBind();
|
||||||
|
|
||||||
if (key === ESC)
|
|
||||||
return hide();
|
return hide();
|
||||||
|
}
|
||||||
|
|
||||||
if (key === F9) {
|
if (isBind && key === F9) {
|
||||||
const position = getCurrentPosition();
|
const position = getCurrentPosition();
|
||||||
MenuContext.show(position.x, position.y);
|
MenuContext.show(position.x, position.y);
|
||||||
|
|
||||||
|
|
@ -1,28 +1,20 @@
|
||||||
/* global CloudCmd */
|
import currify from 'currify';
|
||||||
/* global Util */
|
import wraptile from 'wraptile';
|
||||||
/* global DOM */
|
import {promisify} from 'es6-promisify';
|
||||||
/* global fileop */
|
import exec from 'execon';
|
||||||
|
import load from 'load.js';
|
||||||
|
import {tryToCatch} from 'try-to-catch';
|
||||||
|
import {encode} from '../../../common/entity.js';
|
||||||
|
import removeExtension from './remove-extension.js';
|
||||||
|
import {setListeners} from './set-listeners.mjs';
|
||||||
|
import getNextCurrentName from './get-next-current-name.js';
|
||||||
|
|
||||||
'use strict';
|
const {DOM, CloudCmd} = globalThis;
|
||||||
|
|
||||||
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 removeQuery = (a) => a.replace(/\?.*/, '');
|
||||||
|
|
||||||
const Name = 'Operation';
|
const Name = 'Operation';
|
||||||
|
|
||||||
CloudCmd[Name] = exports;
|
|
||||||
|
|
||||||
const {config} = CloudCmd;
|
const {config} = CloudCmd;
|
||||||
const {Dialog, Images} = DOM;
|
const {Dialog, Images} = DOM;
|
||||||
|
|
||||||
|
|
@ -53,7 +45,7 @@ const noFilesCheck = () => {
|
||||||
return is;
|
return is;
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports.init = promisify((callback) => {
|
export const init = promisify((callback) => {
|
||||||
showLoad();
|
showLoad();
|
||||||
|
|
||||||
exec.series([
|
exec.series([
|
||||||
|
|
@ -92,7 +84,7 @@ const onConnect = currify((fn, operator) => {
|
||||||
async function initOperations(prefix, socketPrefix, fn) {
|
async function initOperations(prefix, socketPrefix, fn) {
|
||||||
socketPrefix = `${socketPrefix}/fileop`;
|
socketPrefix = `${socketPrefix}/fileop`;
|
||||||
|
|
||||||
const operator = await fileop({
|
const operator = await globalThis.fileop({
|
||||||
prefix,
|
prefix,
|
||||||
socketPrefix,
|
socketPrefix,
|
||||||
});
|
});
|
||||||
|
|
@ -198,11 +190,11 @@ function getPacker(type) {
|
||||||
return packTarFn;
|
return packTarFn;
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports.hide = () => {
|
export const hide = () => {
|
||||||
CloudCmd.View.hide();
|
CloudCmd.View.hide();
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports.show = (operation, data) => {
|
export const show = (operation, data) => {
|
||||||
if (!Loaded)
|
if (!Loaded)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
@ -343,10 +335,13 @@ async function _processFiles(options, data) {
|
||||||
let names = [];
|
let names = [];
|
||||||
|
|
||||||
if (data) {
|
if (data) {
|
||||||
from = data.from;
|
({
|
||||||
to = data.to;
|
from,
|
||||||
names = data.names;
|
to,
|
||||||
panel = Info.panel;
|
names,
|
||||||
|
} = data);
|
||||||
|
|
||||||
|
({panel} = Info);
|
||||||
} else {
|
} else {
|
||||||
from = Info.dirPath;
|
from = Info.dirPath;
|
||||||
to = DOM.getNotCurrentDirPath();
|
to = DOM.getNotCurrentDirPath();
|
||||||
|
|
@ -502,8 +497,14 @@ async function prompt(msg, to, names) {
|
||||||
return await Dialog.prompt(msg, to);
|
return await Dialog.prompt(msg, to);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
globalThis.CloudCmd[Name] = {
|
||||||
|
init,
|
||||||
|
hide,
|
||||||
|
show,
|
||||||
|
};
|
||||||
|
|
||||||
async function loadAll() {
|
async function loadAll() {
|
||||||
const {prefix} = CloudCmd;
|
const {prefix} = globalThis.CloudCmd;
|
||||||
const file = `${prefix}/fileop/fileop.js`;
|
const file = `${prefix}/fileop/fileop.js`;
|
||||||
|
|
||||||
const [error] = await tryToCatch(load.js, file);
|
const [error] = await tryToCatch(load.js, file);
|
||||||
|
|
@ -9,10 +9,10 @@ module.exports = (name) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
function getExtension(name) {
|
function getExtension(name) {
|
||||||
if (/\.tar\.gz$/.test(name))
|
if (name.endsWith('.tar.gz'))
|
||||||
return '.tar.gz';
|
return '.tar.gz';
|
||||||
|
|
||||||
if (/\.tar\.bz2$/.test(name))
|
if (name.endsWith('.tar.bz2'))
|
||||||
return '.tar.bz2';
|
return '.tar.bz2';
|
||||||
|
|
||||||
return getExt(name);
|
return getExt(name);
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,11 @@
|
||||||
'use strict';
|
|
||||||
|
|
||||||
/* global DOM */
|
/* global DOM */
|
||||||
const forEachKey = require('for-each-key');
|
import forEachKey from 'for-each-key';
|
||||||
|
import wraptile from 'wraptile';
|
||||||
const wraptile = require('wraptile');
|
import format from './format.js';
|
||||||
const format = require('./format');
|
|
||||||
|
|
||||||
const {Dialog, Images} = DOM;
|
const {Dialog, Images} = DOM;
|
||||||
|
|
||||||
module.exports = (options) => (emitter) => {
|
export const setListeners = (options) => (emitter) => {
|
||||||
const {
|
const {
|
||||||
operation,
|
operation,
|
||||||
callback,
|
callback,
|
||||||
|
|
@ -43,10 +40,13 @@ module.exports = (options) => (emitter) => {
|
||||||
operation,
|
operation,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
let noProgress = true;
|
||||||
|
|
||||||
const listeners = {
|
const listeners = {
|
||||||
progress: (value) => {
|
progress: (value) => {
|
||||||
done = value === 100;
|
done = value === 100;
|
||||||
progress.setProgress(value);
|
progress.setProgress(value);
|
||||||
|
noProgress = false;
|
||||||
},
|
},
|
||||||
|
|
||||||
end: () => {
|
end: () => {
|
||||||
|
|
@ -54,7 +54,7 @@ module.exports = (options) => (emitter) => {
|
||||||
forEachKey(removeListener, listeners);
|
forEachKey(removeListener, listeners);
|
||||||
progress.remove();
|
progress.remove();
|
||||||
|
|
||||||
if (lastError || done)
|
if (lastError || done || noProgress)
|
||||||
callback();
|
callback();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
@ -1,10 +1,20 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
/* global DOM */
|
|
||||||
require('domtokenlist-shim');
|
require('domtokenlist-shim');
|
||||||
|
|
||||||
const scrollIntoViewIfNeeded = require('scroll-into-view-if-needed').default;
|
const _scrollIntoViewIfNeeded = require('scroll-into-view-if-needed');
|
||||||
|
|
||||||
DOM.scrollIntoViewIfNeeded = (el) => scrollIntoViewIfNeeded(el, {
|
globalThis.DOM = globalThis.DOM || {};
|
||||||
block: 'nearest',
|
|
||||||
});
|
const scrollIntoViewIfNeeded = (el, overrides = {}) => {
|
||||||
|
const {
|
||||||
|
scroll = _scrollIntoViewIfNeeded,
|
||||||
|
} = overrides;
|
||||||
|
|
||||||
|
return scroll(el, {
|
||||||
|
block: 'nearest',
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
globalThis.DOM.scrollIntoViewIfNeeded = scrollIntoViewIfNeeded;
|
||||||
|
module.exports.scrollIntoViewIfNeeded = scrollIntoViewIfNeeded;
|
||||||
|
|
|
||||||
|
|
@ -1,33 +1,21 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const {test, stub} = require('supertape');
|
const {test, stub} = require('supertape');
|
||||||
|
const {scrollIntoViewIfNeeded} = require('./polyfill');
|
||||||
const mockRequire = require('mock-require');
|
|
||||||
|
|
||||||
const {stopAll} = mockRequire;
|
|
||||||
|
|
||||||
test('cloudcmd: client: polyfill: scrollIntoViewIfNeaded', (t) => {
|
test('cloudcmd: client: polyfill: scrollIntoViewIfNeaded', (t) => {
|
||||||
const {DOM} = global;
|
|
||||||
const scroll = stub();
|
const scroll = stub();
|
||||||
const el = {};
|
const el = {};
|
||||||
|
|
||||||
global.DOM = {};
|
scrollIntoViewIfNeeded(el, {
|
||||||
|
scroll,
|
||||||
mockRequire('scroll-into-view-if-needed', {
|
|
||||||
default: scroll,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
mockRequire.reRequire('./polyfill');
|
const args = [
|
||||||
|
el, {
|
||||||
global.DOM.scrollIntoViewIfNeeded(el);
|
block: 'nearest',
|
||||||
mockRequire.stop('scroll-into-view-if-neaded');
|
},
|
||||||
global.DOM = DOM;
|
];
|
||||||
|
|
||||||
const args = [el, {
|
|
||||||
block: 'nearest',
|
|
||||||
}];
|
|
||||||
|
|
||||||
stopAll();
|
|
||||||
|
|
||||||
t.calledWith(scroll, args, 'should call scrollIntoViewIfNeaded');
|
t.calledWith(scroll, args, 'should call scrollIntoViewIfNeaded');
|
||||||
t.end();
|
t.end();
|
||||||
|
|
|
||||||
|
|
@ -2,15 +2,15 @@
|
||||||
|
|
||||||
/* global CloudCmd, gritty */
|
/* global CloudCmd, gritty */
|
||||||
const {promisify} = require('es6-promisify');
|
const {promisify} = require('es6-promisify');
|
||||||
const tryToCatch = require('try-to-catch');
|
const {tryToCatch} = require('try-to-catch');
|
||||||
const fullstore = require('fullstore');
|
const {fullstore} = require('fullstore');
|
||||||
|
|
||||||
require('../../css/terminal.css');
|
require('../../css/terminal.css');
|
||||||
|
|
||||||
const exec = require('execon');
|
const exec = require('execon');
|
||||||
const load = require('load.js');
|
const load = require('load.js');
|
||||||
const DOM = require('../dom');
|
const DOM = require('../dom');
|
||||||
const Images = require('../dom/images');
|
const Images = require('../dom/images.mjs');
|
||||||
|
|
||||||
const {Dialog} = DOM;
|
const {Dialog} = DOM;
|
||||||
const {Key, config} = CloudCmd;
|
const {Key, config} = CloudCmd;
|
||||||
|
|
@ -33,7 +33,7 @@ const loadAll = async () => {
|
||||||
const [e] = await tryToCatch(load.parallel, [js, css]);
|
const [e] = await tryToCatch(load.parallel, [js, css]);
|
||||||
|
|
||||||
if (e) {
|
if (e) {
|
||||||
const src = e.target.src.replace(window.location.href, '');
|
const src = e.target.src.replace(globalThis.location.href, '');
|
||||||
return Dialog.alert(`file ${src} could not be loaded`);
|
return Dialog.alert(`file ${src} could not be loaded`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -75,22 +75,18 @@ function hide() {
|
||||||
CloudCmd.View.hide();
|
CloudCmd.View.hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
function getPrefix() {
|
const getPrefix = () => CloudCmd.prefix + '/gritty';
|
||||||
return CloudCmd.prefix + '/gritty';
|
|
||||||
}
|
|
||||||
|
|
||||||
function getPrefixSocket() {
|
function getPrefixSocket() {
|
||||||
return CloudCmd.prefixSocket + '/gritty';
|
return CloudCmd.prefixSocket + '/gritty';
|
||||||
}
|
}
|
||||||
|
|
||||||
function getEnv() {
|
const getEnv = () => ({
|
||||||
return {
|
ACTIVE_DIR: DOM.getCurrentDirPath,
|
||||||
ACTIVE_DIR: DOM.getCurrentDirPath,
|
PASSIVE_DIR: DOM.getNotCurrentDirPath,
|
||||||
PASSIVE_DIR: DOM.getNotCurrentDirPath,
|
CURRENT_NAME: DOM.getCurrentName,
|
||||||
CURRENT_NAME: DOM.getCurrentName,
|
CURRENT_PATH: DOM.getCurrentPath,
|
||||||
CURRENT_PATH: DOM.getCurrentPath,
|
});
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function create(createOptions) {
|
function create(createOptions) {
|
||||||
const {
|
const {
|
||||||
|
|
|
||||||
|
|
@ -2,14 +2,14 @@
|
||||||
|
|
||||||
/* global CloudCmd */
|
/* global CloudCmd */
|
||||||
/* global gritty */
|
/* global gritty */
|
||||||
const tryToCatch = require('try-to-catch');
|
const {tryToCatch} = require('try-to-catch');
|
||||||
|
|
||||||
require('../../css/terminal.css');
|
require('../../css/terminal.css');
|
||||||
|
|
||||||
const exec = require('execon');
|
const exec = require('execon');
|
||||||
const load = require('load.js');
|
const load = require('load.js');
|
||||||
const DOM = require('../dom');
|
const DOM = require('../dom');
|
||||||
const Images = require('../dom/images');
|
const Images = require('../dom/images.mjs');
|
||||||
|
|
||||||
const loadParallel = load.parallel;
|
const loadParallel = load.parallel;
|
||||||
|
|
||||||
|
|
@ -32,7 +32,7 @@ const loadAll = async () => {
|
||||||
const [e] = await tryToCatch(loadParallel, [js, css]);
|
const [e] = await tryToCatch(loadParallel, [js, css]);
|
||||||
|
|
||||||
if (e) {
|
if (e) {
|
||||||
const src = e.target.src.replace(window.location.href, '');
|
const src = e.target.src.replace(globalThis.location.href, '');
|
||||||
return Dialog.alert(`file ${src} could not be loaded`);
|
return Dialog.alert(`file ${src} could not be loaded`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -57,22 +57,18 @@ function hide() {
|
||||||
CloudCmd.View.hide();
|
CloudCmd.View.hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
function getPrefix() {
|
const getPrefix = () => CloudCmd.prefix + '/gritty';
|
||||||
return CloudCmd.prefix + '/gritty';
|
|
||||||
}
|
|
||||||
|
|
||||||
function getPrefixSocket() {
|
function getPrefixSocket() {
|
||||||
return CloudCmd.prefixSocket + '/gritty';
|
return CloudCmd.prefixSocket + '/gritty';
|
||||||
}
|
}
|
||||||
|
|
||||||
function getEnv() {
|
const getEnv = () => ({
|
||||||
return {
|
ACTIVE_DIR: DOM.getCurrentDirPath,
|
||||||
ACTIVE_DIR: DOM.getCurrentDirPath,
|
PASSIVE_DIR: DOM.getNotCurrentDirPath,
|
||||||
PASSIVE_DIR: DOM.getNotCurrentDirPath,
|
CURRENT_NAME: DOM.getCurrentName,
|
||||||
CURRENT_NAME: DOM.getCurrentName,
|
CURRENT_PATH: DOM.getCurrentPath,
|
||||||
CURRENT_PATH: DOM.getCurrentPath,
|
});
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function create() {
|
function create() {
|
||||||
const options = {
|
const options = {
|
||||||
|
|
|
||||||
|
|
@ -4,10 +4,10 @@
|
||||||
|
|
||||||
CloudCmd.Upload = exports;
|
CloudCmd.Upload = exports;
|
||||||
|
|
||||||
const Files = require('../dom/files');
|
|
||||||
const Images = require('../dom/images');
|
|
||||||
const uploadFiles = require('../dom/upload-files');
|
|
||||||
const createElement = require('@cloudcmd/create-element');
|
const createElement = require('@cloudcmd/create-element');
|
||||||
|
const Files = require('../dom/files');
|
||||||
|
const Images = require('../dom/images.mjs');
|
||||||
|
const uploadFiles = require('../dom/upload-files');
|
||||||
|
|
||||||
module.exports.init = async () => {
|
module.exports.init = async () => {
|
||||||
Images.show.load('top');
|
Images.show.load('top');
|
||||||
|
|
|
||||||
|
|
@ -5,14 +5,14 @@ require('../../../css/user-menu.css');
|
||||||
|
|
||||||
const currify = require('currify');
|
const currify = require('currify');
|
||||||
const wraptile = require('wraptile');
|
const wraptile = require('wraptile');
|
||||||
const fullstore = require('fullstore');
|
const {fullstore} = require('fullstore');
|
||||||
const load = require('load.js');
|
const load = require('load.js');
|
||||||
const createElement = require('@cloudcmd/create-element');
|
const createElement = require('@cloudcmd/create-element');
|
||||||
const tryCatch = require('try-catch');
|
const {tryCatch} = require('try-catch');
|
||||||
const tryToCatch = require('try-to-catch');
|
const {tryToCatch} = require('try-to-catch');
|
||||||
const {codeFrameColumns} = require('@babel/code-frame');
|
const {codeFrameColumns} = require('@babel/code-frame');
|
||||||
|
|
||||||
const Images = require('../../dom/images');
|
const Images = require('../../dom/images.mjs');
|
||||||
const Dialog = require('../../dom/dialog');
|
const Dialog = require('../../dom/dialog');
|
||||||
const getUserMenu = require('./get-user-menu');
|
const getUserMenu = require('./get-user-menu');
|
||||||
const navigate = require('./navigate');
|
const navigate = require('./navigate');
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const fullstore = require('fullstore');
|
const {fullstore} = require('fullstore');
|
||||||
|
|
||||||
const {
|
const {
|
||||||
J,
|
J,
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ const testRegExp = currify((name, reg) => reg.test(name));
|
||||||
const getRegExp = (ext) => RegExp(`\\.${ext}$`, 'i');
|
const getRegExp = (ext) => RegExp(`\\.${ext}$`, 'i');
|
||||||
|
|
||||||
const isPDF = (a) => /\.pdf$/i.test(a);
|
const isPDF = (a) => /\.pdf$/i.test(a);
|
||||||
const isHTML = (a) => /\.html$/.test(a);
|
const isHTML = (a) => a.endsWith('.html');
|
||||||
const isMarkdown = (a) => /.\.md$/.test(a);
|
const isMarkdown = (a) => /.\.md$/.test(a);
|
||||||
|
|
||||||
module.exports = (name) => {
|
module.exports = (name) => {
|
||||||
|
|
@ -45,9 +45,7 @@ function isMedia(name) {
|
||||||
return isAudio(name) || isVideo(name);
|
return isAudio(name) || isVideo(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
function isAudio(name) {
|
const isAudio = (name) => /\.(mp3|ogg|m4a)$/i.test(name);
|
||||||
return /\.(mp3|ogg|m4a)$/i.test(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
function isVideo(name) {
|
function isVideo(name) {
|
||||||
return /\.(mp4|avi|webm)$/i.test(name);
|
return /\.(mp4|avi|webm)$/i.test(name);
|
||||||
|
|
|
||||||
|
|
@ -2,19 +2,22 @@
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
const CloudCmd = globalThis.CloudCmd || {};
|
||||||
|
const DOM = globalThis.DOM || {};
|
||||||
|
|
||||||
require('../../../css/view.css');
|
require('../../../css/view.css');
|
||||||
|
|
||||||
const rendy = require('rendy');
|
const rendy = require('rendy');
|
||||||
const currify = require('currify');
|
const currify = require('currify');
|
||||||
const wraptile = require('wraptile');
|
const wraptile = require('wraptile');
|
||||||
const tryToCatch = require('try-to-catch');
|
const {tryToCatch} = require('try-to-catch');
|
||||||
const load = require('load.js');
|
const load = require('load.js');
|
||||||
|
|
||||||
const modal = require('@cloudcmd/modal');
|
const _modal = require('@cloudcmd/modal');
|
||||||
const createElement = require('@cloudcmd/create-element');
|
const _createElement = require('@cloudcmd/create-element');
|
||||||
|
|
||||||
const {time} = require('../../../common/util');
|
const {time} = require('../../../common/util');
|
||||||
const {FS} = require('../../../common/cloudfunc');
|
const {FS} = require('../../../common/cloudfunc.mjs');
|
||||||
|
|
||||||
const {
|
const {
|
||||||
isImage,
|
isImage,
|
||||||
|
|
@ -23,8 +26,8 @@ const {
|
||||||
} = require('./types');
|
} = require('./types');
|
||||||
|
|
||||||
const Files = require('../../dom/files');
|
const Files = require('../../dom/files');
|
||||||
const Events = require('../../dom/events');
|
const Events = require('#dom/events');
|
||||||
const Images = require('../../dom/images');
|
const Images = require('../../dom/images.mjs');
|
||||||
|
|
||||||
const {encode} = require('../../../common/entity');
|
const {encode} = require('../../../common/entity');
|
||||||
const isString = (a) => typeof a === 'string';
|
const isString = (a) => typeof a === 'string';
|
||||||
|
|
@ -55,7 +58,10 @@ CloudCmd[Name] = module.exports;
|
||||||
|
|
||||||
const Info = DOM.CurrentInfo;
|
const Info = DOM.CurrentInfo;
|
||||||
const {Key} = CloudCmd;
|
const {Key} = CloudCmd;
|
||||||
const basename = (a) => a.split('/').pop();
|
|
||||||
|
const basename = (a) => a
|
||||||
|
.split('/')
|
||||||
|
.pop();
|
||||||
|
|
||||||
let El;
|
let El;
|
||||||
let TemplateAudio;
|
let TemplateAudio;
|
||||||
|
|
@ -110,7 +116,7 @@ async function show(data, options = {}) {
|
||||||
if (!options || options.bindKeys !== false)
|
if (!options || options.bindKeys !== false)
|
||||||
Events.addKey(listener);
|
Events.addKey(listener);
|
||||||
|
|
||||||
El = createElement('div', {
|
El = _createElement('div', {
|
||||||
className: 'view',
|
className: 'view',
|
||||||
notAppend: true,
|
notAppend: true,
|
||||||
});
|
});
|
||||||
|
|
@ -123,7 +129,7 @@ async function show(data, options = {}) {
|
||||||
else
|
else
|
||||||
El.append(data);
|
El.append(data);
|
||||||
|
|
||||||
modal.open(El, initConfig(options));
|
_modal.open(El, initConfig(options));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -154,7 +160,11 @@ async function show(data, options = {}) {
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports._createIframe = createIframe;
|
module.exports._createIframe = createIframe;
|
||||||
function createIframe(src) {
|
function createIframe(src, overrides = {}) {
|
||||||
|
const {
|
||||||
|
createElement = _createElement,
|
||||||
|
} = overrides;
|
||||||
|
|
||||||
const element = createElement('iframe', {
|
const element = createElement('iframe', {
|
||||||
src,
|
src,
|
||||||
width: '100%',
|
width: '100%',
|
||||||
|
|
@ -169,7 +179,8 @@ function createIframe(src) {
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports._viewHtml = viewHtml;
|
module.exports._viewHtml = viewHtml;
|
||||||
function viewHtml(src) {
|
function viewHtml(src, overrides = {}) {
|
||||||
|
const {modal = _modal} = overrides;
|
||||||
modal.open(createIframe(src), Config);
|
modal.open(createIframe(src), Config);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -181,7 +192,7 @@ function viewPDF(src) {
|
||||||
if (CloudCmd.config('showFileName'))
|
if (CloudCmd.config('showFileName'))
|
||||||
options.title = Info.name;
|
options.title = Info.name;
|
||||||
|
|
||||||
modal.open(element, options);
|
_modal.open(element, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function viewMedia(path) {
|
async function viewMedia(path) {
|
||||||
|
|
@ -202,7 +213,7 @@ async function viewMedia(path) {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
modal.open(element, allConfig);
|
_modal.open(element, allConfig);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function viewFile() {
|
async function viewFile() {
|
||||||
|
|
@ -218,7 +229,7 @@ async function viewFile() {
|
||||||
options.title = Info.name;
|
options.title = Info.name;
|
||||||
|
|
||||||
El.append(element);
|
El.append(element);
|
||||||
modal.open(El, options);
|
_modal.open(El, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
const copy = (a) => assign({}, a);
|
const copy = (a) => assign({}, a);
|
||||||
|
|
@ -250,7 +261,7 @@ function initConfig(options) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function hide() {
|
function hide() {
|
||||||
modal.close();
|
_modal.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
function viewImage(path, prefixURL) {
|
function viewImage(path, prefixURL) {
|
||||||
|
|
@ -260,8 +271,7 @@ function viewImage(path, prefixURL) {
|
||||||
title: encode(basename(path)),
|
title: encode(basename(path)),
|
||||||
});
|
});
|
||||||
|
|
||||||
const names = Info
|
const names = Info.files
|
||||||
.files
|
|
||||||
.map(DOM.getCurrentPath)
|
.map(DOM.getCurrentPath)
|
||||||
.filter(isSupportedImage);
|
.filter(isSupportedImage);
|
||||||
|
|
||||||
|
|
@ -284,7 +294,7 @@ function viewImage(path, prefixURL) {
|
||||||
...imageConfig,
|
...imageConfig,
|
||||||
};
|
};
|
||||||
|
|
||||||
modal.open(titles, config);
|
_modal.open(titles, config);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getMediaElement(src) {
|
async function getMediaElement(src) {
|
||||||
|
|
@ -309,7 +319,7 @@ async function getMediaElement(src) {
|
||||||
name,
|
name,
|
||||||
});
|
});
|
||||||
|
|
||||||
const element = createElement('div', {
|
const element = _createElement('div', {
|
||||||
innerHTML,
|
innerHTML,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -321,10 +331,6 @@ function check(src) {
|
||||||
throw Error('src should be a string!');
|
throw Error('src should be a string!');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* function loads css and js of FancyBox
|
|
||||||
* @callback - executes, when everything loaded
|
|
||||||
*/
|
|
||||||
async function loadAll() {
|
async function loadAll() {
|
||||||
const {DIR_DIST} = CloudCmd;
|
const {DIR_DIST} = CloudCmd;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,22 +3,20 @@
|
||||||
require('css-modules-require-hook/preset');
|
require('css-modules-require-hook/preset');
|
||||||
|
|
||||||
const autoGlobals = require('auto-globals');
|
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 test = autoGlobals(require('supertape'));
|
||||||
const {reRequire, stopAll} = mockRequire;
|
const {
|
||||||
|
_initConfig,
|
||||||
|
_viewHtml,
|
||||||
|
_Config,
|
||||||
|
_createIframe,
|
||||||
|
} = require('.');
|
||||||
|
|
||||||
test('cloudcmd: client: view: initConfig', (t) => {
|
test('cloudcmd: client: view: initConfig', (t) => {
|
||||||
let config;
|
let config;
|
||||||
let i = 0;
|
let i = 0;
|
||||||
|
|
||||||
const {CloudCmd, DOM} = global;
|
|
||||||
|
|
||||||
global.CloudCmd = {};
|
|
||||||
global.DOM = {};
|
|
||||||
|
|
||||||
const {_initConfig} = reRequire('.');
|
|
||||||
|
|
||||||
const afterClose = () => ++i;
|
const afterClose = () => ++i;
|
||||||
const options = {
|
const options = {
|
||||||
afterClose,
|
afterClose,
|
||||||
|
|
@ -30,54 +28,32 @@ test('cloudcmd: client: view: initConfig', (t) => {
|
||||||
config = _initConfig(options);
|
config = _initConfig(options);
|
||||||
config.afterClose();
|
config.afterClose();
|
||||||
|
|
||||||
global.CloudCmd = CloudCmd;
|
|
||||||
global.DOM = DOM;
|
|
||||||
|
|
||||||
t.equal(i, 2, 'should not change default config');
|
t.equal(i, 2, 'should not change default config');
|
||||||
t.end();
|
t.end();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('cloudcmd: client: view: initConfig: no options', (t) => {
|
test('cloudcmd: client: view: initConfig: no options', (t) => {
|
||||||
const {CloudCmd, DOM} = global;
|
|
||||||
|
|
||||||
global.CloudCmd = {};
|
|
||||||
global.DOM = {};
|
|
||||||
|
|
||||||
const {_initConfig} = reRequire('.');
|
|
||||||
const config = _initConfig();
|
const config = _initConfig();
|
||||||
|
|
||||||
global.CloudCmd = CloudCmd;
|
|
||||||
global.DOM = DOM;
|
|
||||||
|
|
||||||
t.equal(typeof config, 'object');
|
t.equal(typeof config, 'object');
|
||||||
t.end();
|
t.end();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('cloudcmd: client: view: html', (t) => {
|
test('cloudcmd: client: view: html', (t) => {
|
||||||
const {CloudCmd, DOM} = global;
|
|
||||||
|
|
||||||
global.CloudCmd = {};
|
|
||||||
global.DOM = {};
|
|
||||||
const open = stub();
|
const open = stub();
|
||||||
|
const modal = {
|
||||||
mockRequire('@cloudcmd/modal', {
|
|
||||||
open,
|
open,
|
||||||
});
|
};
|
||||||
|
|
||||||
const {_viewHtml, _Config} = reRequire('.');
|
|
||||||
|
|
||||||
const src = '/hello.html';
|
const src = '/hello.html';
|
||||||
|
|
||||||
_viewHtml(src);
|
_viewHtml(src, {
|
||||||
|
modal,
|
||||||
global.CloudCmd = CloudCmd;
|
});
|
||||||
global.DOM = DOM;
|
|
||||||
|
|
||||||
const [first] = open.args;
|
const [first] = open.args;
|
||||||
const [arg] = first;
|
const [arg] = first;
|
||||||
|
|
||||||
stopAll();
|
|
||||||
|
|
||||||
t.deepEqual(first, [arg, _Config]);
|
t.deepEqual(first, [arg, _Config]);
|
||||||
t.end();
|
t.end();
|
||||||
});
|
});
|
||||||
|
|
@ -89,12 +65,11 @@ test('cloudcmd: client: view: createIframe', (t) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const createElement = stub().returns(el);
|
const createElement = stub().returns(el);
|
||||||
|
|
||||||
mockRequire('@cloudcmd/create-element', createElement);
|
|
||||||
const {_createIframe} = reRequire('.');
|
|
||||||
|
|
||||||
const src = '/hello.html';
|
const src = '/hello.html';
|
||||||
_createIframe(src);
|
|
||||||
|
_createIframe(src, {
|
||||||
|
createElement,
|
||||||
|
});
|
||||||
|
|
||||||
const expected = {
|
const expected = {
|
||||||
src,
|
src,
|
||||||
|
|
@ -102,8 +77,6 @@ test('cloudcmd: client: view: createIframe', (t) => {
|
||||||
width: '100%',
|
width: '100%',
|
||||||
};
|
};
|
||||||
|
|
||||||
stopAll();
|
|
||||||
|
|
||||||
t.calledWith(createElement, ['iframe', expected]);
|
t.calledWith(createElement, ['iframe', expected]);
|
||||||
t.end();
|
t.end();
|
||||||
});
|
});
|
||||||
|
|
@ -116,13 +89,10 @@ test('cloudcmd: client: view: createIframe: returns', (t) => {
|
||||||
|
|
||||||
const createElement = stub().returns(el);
|
const createElement = stub().returns(el);
|
||||||
|
|
||||||
mockRequire('@cloudcmd/create-element', createElement);
|
|
||||||
const {_createIframe} = reRequire('.');
|
|
||||||
|
|
||||||
const src = '/hello.html';
|
const src = '/hello.html';
|
||||||
const result = _createIframe(src);
|
const result = _createIframe(src, {
|
||||||
|
createElement,
|
||||||
stopAll();
|
});
|
||||||
|
|
||||||
t.equal(result, el);
|
t.equal(result, el);
|
||||||
t.end();
|
t.end();
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,13 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const {extname} = require('path');
|
const {extname} = require('node:path');
|
||||||
const currify = require('currify');
|
const currify = require('currify');
|
||||||
|
const isAudio = (name) => /\.(mp3|ogg|m4a)$/i.test(name);
|
||||||
const testRegExp = currify((name, reg) => reg.test(name));
|
const testRegExp = currify((name, reg) => reg.test(name));
|
||||||
const getRegExp = (ext) => RegExp(`\\.${ext}$`, 'i');
|
const getRegExp = (ext) => RegExp(`\\.${ext}$`, 'i');
|
||||||
|
|
||||||
const isPDF = (a) => /\.pdf$/i.test(a);
|
const isPDF = (a) => /\.pdf$/i.test(a);
|
||||||
const isHTML = (a) => /\.html$/.test(a);
|
const isHTML = (a) => a.endsWith('.html');
|
||||||
const isMarkdown = (a) => /.\.md$/.test(a);
|
const isMarkdown = (a) => /.\.md$/.test(a);
|
||||||
|
|
||||||
module.exports.getType = async (path) => {
|
module.exports.getType = async (path) => {
|
||||||
|
|
@ -53,9 +54,6 @@ function isMedia(name) {
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports.isAudio = isAudio;
|
module.exports.isAudio = isAudio;
|
||||||
function isAudio(name) {
|
|
||||||
return /\.(mp3|ogg|m4a)$/i.test(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
function isVideo(name) {
|
function isVideo(name) {
|
||||||
return /\.(mp4|avi|webm)$/i.test(name);
|
return /\.(mp4|avi|webm)$/i.test(name);
|
||||||
|
|
|
||||||
|
|
@ -22,12 +22,9 @@ test('cloudcmd: client: view: types: detectType', async (t) => {
|
||||||
headers: [],
|
headers: [],
|
||||||
});
|
});
|
||||||
|
|
||||||
const originalFetch = global.fetch;
|
globalThis.fetch = fetch;
|
||||||
|
|
||||||
global.fetch = fetch;
|
|
||||||
await _detectType('/hello');
|
await _detectType('/hello');
|
||||||
|
|
||||||
global.fetch = originalFetch;
|
|
||||||
const expected = ['/hello', {
|
const expected = ['/hello', {
|
||||||
method: 'HEAD',
|
method: 'HEAD',
|
||||||
}];
|
}];
|
||||||
|
|
@ -37,17 +34,13 @@ test('cloudcmd: client: view: types: detectType', async (t) => {
|
||||||
});
|
});
|
||||||
|
|
||||||
test('cloudcmd: client: view: types: detectType: found', async (t) => {
|
test('cloudcmd: client: view: types: detectType: found', async (t) => {
|
||||||
const originalFetch = global.fetch;
|
globalThis.fetch = stub().returns({
|
||||||
|
|
||||||
global.fetch = stub().returns({
|
|
||||||
headers: [
|
headers: [
|
||||||
['content-type', 'image/png'],
|
['content-type', 'image/png'],
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
const result = await _detectType('/hello');
|
const result = await _detectType('/hello');
|
||||||
|
|
||||||
global.fetch = originalFetch;
|
|
||||||
|
|
||||||
t.equal(result, '.png');
|
t.equal(result, '.png');
|
||||||
t.end();
|
t.end();
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -1,34 +0,0 @@
|
||||||
'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 = sort[position] = name;
|
|
||||||
|
|
||||||
const noCurrent = position !== Info.panelPosition;
|
|
||||||
|
|
||||||
CloudCmd.refresh({
|
|
||||||
panel,
|
|
||||||
noCurrent,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
36
client/sort.mjs
Normal file
36
client/sort.mjs
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
/* 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,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const tryToCatch = require('try-to-catch');
|
const {tryToCatch} = require('try-to-catch');
|
||||||
|
|
||||||
module.exports.registerSW = registerSW;
|
module.exports.registerSW = registerSW;
|
||||||
module.exports.unregisterSW = unregisterSW;
|
module.exports.unregisterSW = unregisterSW;
|
||||||
|
|
|
||||||
|
|
@ -3,14 +3,18 @@
|
||||||
const autoGlobals = require('auto-globals');
|
const autoGlobals = require('auto-globals');
|
||||||
const tape = require('supertape');
|
const tape = require('supertape');
|
||||||
|
|
||||||
const stub = require('@cloudcmd/stub');
|
const {stub} = require('@cloudcmd/stub');
|
||||||
|
|
||||||
|
const {tryCatch} = require('try-catch');
|
||||||
|
const {
|
||||||
|
listenSW,
|
||||||
|
registerSW,
|
||||||
|
unregisterSW,
|
||||||
|
} = require('./register');
|
||||||
|
|
||||||
const tryCatch = require('try-catch');
|
|
||||||
const {reRequire} = require('mock-require');
|
|
||||||
const test = autoGlobals(tape);
|
const test = autoGlobals(tape);
|
||||||
|
|
||||||
test('sw: listen', (t) => {
|
test('sw: listen', (t) => {
|
||||||
const {listenSW} = reRequire('./register');
|
|
||||||
const addEventListener = stub();
|
const addEventListener = stub();
|
||||||
const sw = {
|
const sw = {
|
||||||
addEventListener,
|
addEventListener,
|
||||||
|
|
@ -23,7 +27,6 @@ test('sw: listen', (t) => {
|
||||||
});
|
});
|
||||||
|
|
||||||
test('sw: lesten: no sw', (t) => {
|
test('sw: lesten: no sw', (t) => {
|
||||||
const {listenSW} = reRequire('./register');
|
|
||||||
const [e] = tryCatch(listenSW, null, 'hello', 'world');
|
const [e] = tryCatch(listenSW, null, 'hello', 'world');
|
||||||
|
|
||||||
t.notOk(e, 'should not throw');
|
t.notOk(e, 'should not throw');
|
||||||
|
|
@ -31,8 +34,6 @@ test('sw: lesten: no sw', (t) => {
|
||||||
});
|
});
|
||||||
|
|
||||||
test('sw: register: registerSW: no serviceWorker', async (t, {navigator}) => {
|
test('sw: register: registerSW: no serviceWorker', async (t, {navigator}) => {
|
||||||
const {registerSW} = reRequire('./register');
|
|
||||||
|
|
||||||
delete navigator.serviceWorker;
|
delete navigator.serviceWorker;
|
||||||
|
|
||||||
await registerSW();
|
await registerSW();
|
||||||
|
|
@ -46,8 +47,6 @@ test('sw: register: registerSW: no https', async (t, {location, navigator}) => {
|
||||||
|
|
||||||
location.protocol = 'http:';
|
location.protocol = 'http:';
|
||||||
|
|
||||||
const {registerSW} = reRequire('./register');
|
|
||||||
|
|
||||||
await registerSW();
|
await registerSW();
|
||||||
|
|
||||||
t.notCalled(register, 'should not call register');
|
t.notCalled(register, 'should not call register');
|
||||||
|
|
@ -62,8 +61,6 @@ test('sw: register: registerSW: http', async (t, {location, navigator}) => {
|
||||||
|
|
||||||
const {register} = navigator.serviceWorker;
|
const {register} = navigator.serviceWorker;
|
||||||
|
|
||||||
const {registerSW} = reRequire('./register');
|
|
||||||
|
|
||||||
await registerSW();
|
await registerSW();
|
||||||
|
|
||||||
t.notCalled(register, 'should not call register');
|
t.notCalled(register, 'should not call register');
|
||||||
|
|
@ -79,8 +76,6 @@ test('sw: register: registerSW: https self-signed', async (t, {location, navigat
|
||||||
const {register} = navigator.serviceWorker;
|
const {register} = navigator.serviceWorker;
|
||||||
register.throws(Error('Cannot register service worker!'));
|
register.throws(Error('Cannot register service worker!'));
|
||||||
|
|
||||||
const {registerSW} = reRequire('./register');
|
|
||||||
|
|
||||||
const result = await registerSW();
|
const result = await registerSW();
|
||||||
|
|
||||||
t.notOk(result, 'should not throw');
|
t.notOk(result, 'should not throw');
|
||||||
|
|
@ -91,8 +86,6 @@ test('sw: register: registerSW', async (t, {location, navigator}) => {
|
||||||
location.hostname = 'localhost';
|
location.hostname = 'localhost';
|
||||||
|
|
||||||
const {register} = navigator.serviceWorker;
|
const {register} = navigator.serviceWorker;
|
||||||
const {registerSW} = reRequire('./register');
|
|
||||||
|
|
||||||
await registerSW('/hello');
|
await registerSW('/hello');
|
||||||
|
|
||||||
t.calledWith(register, ['/hello/sw.js'], 'should call register');
|
t.calledWith(register, ['/hello/sw.js'], 'should call register');
|
||||||
|
|
@ -107,8 +100,6 @@ test('sw: register: unregisterSW', async (t, {location, navigator}) => {
|
||||||
|
|
||||||
register.returns(serviceWorker);
|
register.returns(serviceWorker);
|
||||||
|
|
||||||
const {unregisterSW} = reRequire('./register');
|
|
||||||
|
|
||||||
await unregisterSW('/hello');
|
await unregisterSW('/hello');
|
||||||
|
|
||||||
t.calledWith(register, ['/hello/sw.js'], 'should call register');
|
t.calledWith(register, ['/hello/sw.js'], 'should call register');
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const process = require('process');
|
const process = require('node:process');
|
||||||
const codegen = require('codegen.macro');
|
const codegen = require('codegen.macro');
|
||||||
const tryToCatch = require('try-to-catch');
|
const {tryToCatch} = require('try-to-catch');
|
||||||
const currify = require('currify');
|
const currify = require('currify');
|
||||||
|
|
||||||
const isDev = process.env.NODE_ENV === 'development';
|
const isDev = process.env.NODE_ENV === 'development';
|
||||||
|
|
@ -50,14 +50,14 @@ const getRequest = (a, request) => {
|
||||||
return createRequest('/');
|
return createRequest('/');
|
||||||
};
|
};
|
||||||
|
|
||||||
self.addEventListener('install', wait(onInstall));
|
globalThis.addEventListener('install', wait(onInstall));
|
||||||
self.addEventListener('fetch', respondWith(onFetch));
|
globalThis.addEventListener('fetch', respondWith(onFetch));
|
||||||
self.addEventListener('activate', wait(onActivate));
|
globalThis.addEventListener('activate', wait(onActivate));
|
||||||
|
|
||||||
async function onActivate() {
|
async function onActivate() {
|
||||||
console.info(`cloudcmd: sw: activate: ${NAME}`);
|
console.info(`cloudcmd: sw: activate: ${NAME}`);
|
||||||
|
|
||||||
await self.clients.claim();
|
await globalThis.clients.claim();
|
||||||
const keys = await caches.keys();
|
const keys = await caches.keys();
|
||||||
const deleteCache = caches.delete.bind(caches);
|
const deleteCache = caches.delete.bind(caches);
|
||||||
|
|
||||||
|
|
@ -67,7 +67,7 @@ async function onActivate() {
|
||||||
async function onInstall() {
|
async function onInstall() {
|
||||||
console.info(`cloudcmd: sw: install: ${NAME}`);
|
console.info(`cloudcmd: sw: install: ${NAME}`);
|
||||||
|
|
||||||
await self.skipWaiting();
|
await globalThis.skipWaiting();
|
||||||
}
|
}
|
||||||
|
|
||||||
async function onFetch(event) {
|
async function onFetch(event) {
|
||||||
|
|
|
||||||
|
|
@ -1,19 +0,0 @@
|
||||||
'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');
|
|
||||||
};
|
|
||||||
|
|
@ -1,53 +0,0 @@
|
||||||
'use strict';
|
|
||||||
|
|
||||||
const {test, stub} = require('supertape');
|
|
||||||
|
|
||||||
const {btoa, atob} = require('./base64');
|
|
||||||
|
|
||||||
test('btoa: browser', (t) => {
|
|
||||||
const btoaOriginal = global.btoa;
|
|
||||||
const str = 'hello';
|
|
||||||
|
|
||||||
global.btoa = stub();
|
|
||||||
|
|
||||||
btoa(str);
|
|
||||||
|
|
||||||
t.calledWith(global.btoa, [str], 'should call global.btoa');
|
|
||||||
t.end();
|
|
||||||
|
|
||||||
global.btoa = btoaOriginal;
|
|
||||||
});
|
|
||||||
|
|
||||||
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 str = 'hello';
|
|
||||||
|
|
||||||
global.atob = stub();
|
|
||||||
|
|
||||||
atob(str);
|
|
||||||
|
|
||||||
t.calledWith(global.atob, [str], 'should call global.btoa');
|
|
||||||
t.end();
|
|
||||||
|
|
||||||
global.atob = atobOriginal;
|
|
||||||
});
|
|
||||||
|
|
||||||
test('atob: node', (t) => {
|
|
||||||
const str = 'aGVsbG8=';
|
|
||||||
const expected = 'hello';
|
|
||||||
|
|
||||||
const result = atob(str);
|
|
||||||
|
|
||||||
t.equal(result, expected, 'should encode base64');
|
|
||||||
t.end();
|
|
||||||
});
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const tryToCatch = require('try-to-catch');
|
const {promisify} = require('node:util');
|
||||||
|
const {tryToCatch} = require('try-to-catch');
|
||||||
|
|
||||||
const {test, stub} = require('supertape');
|
const {test, stub} = require('supertape');
|
||||||
|
|
||||||
const callbackify = require('./callbackify');
|
const callbackify = require('./callbackify');
|
||||||
const {promisify} = require('util');
|
|
||||||
|
|
||||||
test('cloudcmd: common: callbackify: error', async (t) => {
|
test('cloudcmd: common: callbackify: error', async (t) => {
|
||||||
const promise = stub().rejects(Error('hello'));
|
const promise = stub().rejects(Error('hello'));
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue