diff --git a/.babelrc b/.babelrc deleted file mode 100644 index 8fe27f8f..00000000 --- a/.babelrc +++ /dev/null @@ -1,9 +0,0 @@ -{ - "presets": [ - "es2015" - ], - "plugins": [ - "transform-object-assign" - ] -} - diff --git a/.babelrc.json b/.babelrc.json new file mode 100644 index 00000000..33d70c39 --- /dev/null +++ b/.babelrc.json @@ -0,0 +1,9 @@ +{ + "presets": [ + "@babel/preset-env" + ], + "plugins": [ + "module:babel-plugin-macros", + "@babel/plugin-transform-optional-chaining" + ] +} diff --git a/.bowerrc b/.bowerrc deleted file mode 100644 index 0ab1766a..00000000 --- a/.bowerrc +++ /dev/null @@ -1,3 +0,0 @@ -{ - "directory" : "modules" -} \ No newline at end of file diff --git a/.browserslistrc b/.browserslistrc new file mode 100644 index 00000000..bde9f522 --- /dev/null +++ b/.browserslistrc @@ -0,0 +1,4 @@ +last 2 Chrome versions +last 2 Safari versions +Firefox ESR +not dead diff --git a/.cloudcmd.menu.js b/.cloudcmd.menu.js new file mode 100644 index 00000000..0e0126b6 --- /dev/null +++ b/.cloudcmd.menu.js @@ -0,0 +1,31 @@ +export default { + 'F2 - Rename File': renameCurrent, + 'L - Lint': run('npm run lint'), + 'F - Fix Lint': run('npm run fix:lint'), + 'T - Test': run('npm run test'), + 'C - Coverage': run('npm run coverage'), + 'D - Build Dev': run('npm run build:client:dev'), + 'P - Build Prod': run('npm run build:client'), +}; + +async function renameCurrent(DOM) { + await DOM.renameCurrent(); +} + +function run(command) { + return async ({CloudCmd, DOM}) => { + const {TerminalRun, config} = CloudCmd; + + const {CurrentInfo} = DOM; + const {dirPath} = CurrentInfo; + + const cwd = config('root') + dirPath; + + return await TerminalRun.show({ + cwd, + command, + closeMessage: 'Press any key to close Terminal', + autoClose: false, + }); + }; +} diff --git a/.dockerignore b/.dockerignore index 430fc4eb..1c9d9d9a 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,24 +1,23 @@ +.* +*.spec.js node_modules npm-debug.log* coverage +test +manifest.yml +app.json +bower.json +yarn-error.log +yarn.lock +now.json -modules/jquery/dist -modules/jquery/external -modules/jquery/src +docker -!modules/jquery/dist/jquery.min.js +webpack.config.js +cssnano.config.js -modules/fancybox/lib/ -modules/fancybox/demo -modules/fancybox/sprite.psd - -modules/execon +bin/release.js client -legacy server_ -.nyc_output - -*.swp - diff --git a/.editorconfig b/.editorconfig index 09fa9422..439abfd0 100644 --- a/.editorconfig +++ b/.editorconfig @@ -9,7 +9,7 @@ root = true charset = utf-8 end_of_line = lf insert_final_newline = true -trim_trailing_whitespace = true +trim_trailing_whitespace = false indent_style = space indent_size = 4 diff --git a/.eslintrc b/.eslintrc deleted file mode 100644 index eb6279f1..00000000 --- a/.eslintrc +++ /dev/null @@ -1,17 +0,0 @@ -{ - "env": { - "es6": true, - "node": true, - "browser": true - }, - "parserOptions": { - "ecmaVersion": 6, - "sourceType": "module" - }, - "rules": { - "indent": ["error", 4], - "semi": "error", - "no-use-before-define": ["error", "nofunc"] - }, - "extends": ["eslint:recommended"] -} diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 00000000..9fdb6d3c --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1,3 @@ +github: coderaiser +open_collective: cloudcmd +ko_fi: coderaiser diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md deleted file mode 100644 index 6cc34cc8..00000000 --- a/.github/ISSUE_TEMPLATE.md +++ /dev/null @@ -1,12 +0,0 @@ - - -* **Version** (`cloudcmd -v`): -* **Node Version** `node -v`: -* **OS** (`uname -a` on Linux): -* **Browser name/version**: -* **Used Command Line Parameters**: -* **Changed Config**: - diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 00000000..5c1e7460 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -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. diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 00000000..5f41e73a --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -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. diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 00000000..549a8874 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -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. diff --git a/.github/ISSUE_TEMPLATE/issue_template.md b/.github/ISSUE_TEMPLATE/issue_template.md new file mode 100644 index 00000000..17bf5831 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/issue_template.md @@ -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** diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 98b1f1ad..fb62bd82 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -4,6 +4,5 @@ about something, just do as best as you're able. --> - [ ] commit message named according to [Contributing Guide](https://github.com/coderaiser/cloudcmd/blob/master/CONTRIBUTING.md "Contributting Guide") -- [ ] `npm run codestyle` is OK +- [ ] `npm run fix:lint` is OK - [ ] `npm test` is OK - diff --git a/.github/workflows/docker-io.yml b/.github/workflows/docker-io.yml new file mode 100644 index 00000000..8cbeb042 --- /dev/null +++ b/.github/workflows/docker-io.yml @@ -0,0 +1,60 @@ +name: Docker IO +permissions: + contents: write +on: + - push +jobs: + buildx: + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + steps: + - name: Checkout + uses: actions/checkout@v5 + - uses: oven-sh/setup-bun@v2 + with: + bun-version: latest + - name: Use Node.js 24.x + uses: actions/setup-node@v6 + with: + node-version: 24.x + - name: Install Redrun + run: bun i redrun -g --no-save + - name: NPM Install + run: bun i --no-save + - name: Lint + run: redrun lint + - name: Build + id: build + run: | + redrun build + VERSION=$(grep '"version":' package.json -m1 | cut -d\" -f4) + echo "version=$VERSION" >> $GITHUB_OUTPUT + - name: Set up QEMU + uses: docker/setup-qemu-action@v4 + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v4 + - name: Login to DockerHub + uses: docker/login-action@v4 + with: + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_TOKEN }} + - name: Login to GitHub Container Registry + uses: docker/login-action@v4 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + - name: Build and push io-image + uses: docker/build-push-action@v7 + with: + context: . + file: docker/Dockerfile.io + platforms: linux/amd64,linux/arm64 + push: true + tags: | + coderaiser/cloudcmd:io + coderaiser/cloudcmd:${{ steps.build.outputs.version }}-io + ghcr.io/${{ github.repository }}-io + ghcr.io/${{ github.repository }}:${{ steps.build.outputs.version }}-io diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml new file mode 100644 index 00000000..5c81d368 --- /dev/null +++ b/.github/workflows/docker.yml @@ -0,0 +1,88 @@ +name: Docker CI +permissions: + contents: write +on: + push: + tags: + - "*" +jobs: + buildx: + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + steps: + - name: Checkout + uses: actions/checkout@v5 + - uses: oven-sh/setup-bun@v2 + with: + bun-version: latest + - name: Use Node.js 22.x + uses: actions/setup-node@v6 + with: + node-version: 22.x + - name: Install Redrun + run: bun i redrun -g --no-save + - name: NPM Install + run: bun i --no-save + - name: Lint + run: redrun lint + - name: Build + id: build + run: | + redrun build + VERSION=$(grep '"version":' package.json -m1 | cut -d\" -f4) + echo "version=$VERSION" >> $GITHUB_OUTPUT + - name: Set up QEMU + uses: docker/setup-qemu-action@v4 + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v4 + - name: Login to DockerHub + uses: docker/login-action@v4 + with: + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_TOKEN }} + - name: Login to GitHub Container Registry + uses: docker/login-action@v4 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + - name: Build and push base-image + uses: docker/build-push-action@v7 + with: + context: . + file: docker/Dockerfile + platforms: linux/amd64,linux/arm64 + push: true + tags: | + coderaiser/cloudcmd:latest + 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 + uses: docker/build-push-action@v7 + with: + context: . + file: docker/Dockerfile.alpine + platforms: linux/amd64,linux/arm64 + push: true + tags: | + coderaiser/cloudcmd:alpine + coderaiser/cloudcmd:latest-alpine + coderaiser/cloudcmd:${{ steps.build.outputs.version }}-alpine + ghcr.io/${{ github.repository }}:latest-alpine + ghcr.io/${{ github.repository }}:${{ steps.build.outputs.version }}-alpine + - name: Build and push slim-image + uses: docker/build-push-action@v7 + with: + context: . + file: docker/Dockerfile.slim + platforms: linux/amd64,linux/arm64 + push: true + tags: | + coderaiser/cloudcmd:slim + coderaiser/cloudcmd:latest-slim + coderaiser/cloudcmd:${{ steps.build.outputs.version }}-slim + ghcr.io/${{ github.repository }}-slim + ghcr.io/${{ github.repository }}:${{ steps.build.outputs.version }}-slim diff --git a/.github/workflows/nodejs.yml b/.github/workflows/nodejs.yml new file mode 100644 index 00000000..429e5568 --- /dev/null +++ b/.github/workflows/nodejs.yml @@ -0,0 +1,53 @@ +name: Node CI +on: + - push +permissions: + contents: write +jobs: + build: + runs-on: ubuntu-latest + env: + NAME: cloudcmd + strategy: + matrix: + node-version: + - 22.x + - 24.x + - 26.x + steps: + - uses: actions/checkout@v5 + - uses: oven-sh/setup-bun@v2 + with: + bun-version: latest + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v6 + with: + node-version: ${{ matrix.node-version }} + - name: Install Redrun + run: bun i redrun madrun -g --no-save + - name: Install + run: bun i --no-save + - name: Init Madrun + run: madrun --init + - name: Lint + run: redrun fix:lint + - name: Typos + uses: coderaiser/typos.ai@v1.1.8 + with: + key: ${{ secrets.TYPOS_AI_KEY }} + - name: Commit fixes + uses: EndBug/add-and-commit@v10 + continue-on-error: true + with: + message: "chore: ${{ env.NAME }}: actions: lint ☘️" + - name: Build + run: redrun build + - name: Test + run: redrun test + - name: Coverage + run: redrun coverage coverage:report + - name: Coveralls + uses: coverallsapp/github-action@v2 + continue-on-error: true + with: + github-token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.gitignore b/.gitignore index 929f2110..6aa86aa9 100644 --- a/.gitignore +++ b/.gitignore @@ -1,30 +1,17 @@ -node_modules -npm-debug.log* -coverage - -modules/jquery/dist -modules/jquery/external -modules/jquery/src - -!modules/jquery/dist/jquery.min.js - -modules/fancybox/lib/ -modules/fancybox/demo -modules/fancybox/sprite.psd -modules/fancybox/*.json -modules/fancybox/gulpfile.js -modules/jquery-mousewheel - -modules/execon -modules/emitify - -legacy -server_ +*.swp +*.log +*.lock .nyc_output +.DS_Store +.idea -*.swp +package-lock.json +npm-debug.log* +node_modules +coverage +modules/execon +modules/emitify dist dist-dev - diff --git a/.jscsrc b/.jscsrc deleted file mode 100644 index 917a1a86..00000000 --- a/.jscsrc +++ /dev/null @@ -1,20 +0,0 @@ -{ - "preset": "crockford", - "requireSpaceAfterKeywords": false, - "requireCapitalizedConstructors": false, - "requireMultipleVarDecl": false, - "disallowTrailingWhitespace": "ignoreEmptyLines", - "disallowTrailingComma": false, - "disallowDanglingUnderscores": false, - "validateIndentation": false, - "requireCurlyBraces": false, - "requireVarDeclFirst": false, - "requireSpacesInAnonymousFunctionExpression": { - "beforeOpeningCurlyBrace": true - }, - "excludeFiles": [ - "node_modules/**", - "modules/**", - "bower_components/**" - ] -} diff --git a/.jshintrc b/.jshintrc deleted file mode 100644 index 34199ac1..00000000 --- a/.jshintrc +++ /dev/null @@ -1,24 +0,0 @@ -{ - "esversion": 6, - "unused" : true, - "bitwise" : false, - "browser" : true, - "devel" : true, - "eqeqeq" : true, - "jquery" : false, - "newcap" : false, - "noarg" : true, - "node" : true, - "noempty" : true, - "nonew" : true, - "strict" : true, - "undef" : true, - "evil" : true, - "expr" : true, - "quotmark": "single", - "validthis": true, - "-W024": true, - "-W120": true, - "-W079": true, - "-W138": true -} diff --git a/.madrun.js b/.madrun.js new file mode 100644 index 00000000..efa8ce98 --- /dev/null +++ b/.madrun.js @@ -0,0 +1,62 @@ +import {run, cutEnv} from 'madrun'; +import {defineEnv} from 'supertape/env'; + +const testEnv = defineEnv({ + timeout: 7000, + css: true, +}); + +const buildEnv = { + NODE_ENV: 'production', +}; + +export default { + 'start': () => 'node bin/cloudcmd.js', + 'start:dev': async () => await run('start', null, { + NODE_ENV: 'development', + }), + 'build:start': () => run(['build:client', 'start']), + 'build:start:dev': () => run([ + 'build:client:dev', + 'start:dev', + ]), + 'lint:all': () => run('lint:progress'), + 'lint': () => 'redlint fix; putout .', + 'lint:progress': () => run('lint', '-f progress'), + 'watch:lint': () => 'nodemon -w client -w server -w test -w common -w .webpack -x "putout -s"', + 'fresh:lint': () => run('lint', '--fresh'), + 'lint:fresh': () => run('lint', '--fresh'), + 'fix:lint': async () => `putout --fix . && redlint fix`, + 'lint:stream': () => run('lint', '-f stream'), + 'test': () => [testEnv, `tape '{test}/**/*.js' '{bin,client,static,common,server}/**/*.spec.js' -f fail`], + 'test:e2e': () => `tape 'test-e2e/**/*.js'`, + 'test:client': () => `tape 'test/client/**/*.js'`, + 'test:server': () => `tape 'test/**/*.js' 'server/**/*.spec.js' 'common/**/*.spec.js'`, + 'wisdom': async () => await run(['lint:all', 'build', 'test'], null, { + CI: 1, + }), + 'wisdom:type': () => 'bin/release.js', + 'coverage': async () => [testEnv, `c8 ${await cutEnv('test')}`], + 'coverage:report': () => 'c8 report --reporter=lcov', + 'report': () => 'c8 report --reporter=lcov', + '6to5': () => [buildEnv, 'rspack build --config rspack.config.js'], + '6to5:client': () => run('6to5', '--mode production'), + '6to5:client:dev': async () => await run('6to5', '--mode development', { + NODE_ENV: 'development', + }), + 'pre6to5:client': () => 'rimraf dist', + 'pre6to5:client:dev': () => 'rimraf dist-dev', + 'watch:client': () => run('6to5:client', '--watch'), + 'watch:client:dev': () => run('6to5:client:dev', '--watch'), + 'watch:server': () => 'nodemon bin/cloudcmd.js', + 'watch:test': async () => [testEnv, `nodemon -w client -w server -w test -w common -x ${await cutEnv('test')}`], + 'watch:test:client': async () => `nodemon -w client -w test/client -x ${await run('test:client')}`, + 'watch:test:server': async () => `nodemon -w client -w test/client -x ${await run('test:server')}`, + 'watch:coverage': async () => [testEnv, `nodemon -w server -w test -w common -x ${await cutEnv('coverage')}`], + 'watch:fix:lint': async () => `nodemon -w client -w server -w test -w common -x '${await run('fix:lint')}'`, + 'build': async () => run('6to5:*'), + 'build:dev': async () => run('build:client:dev'), + 'build:client': () => run('6to5:client'), + 'build:client:dev': () => run('6to5:client:dev'), + 'heroku-postbuild': () => run('6to5:client'), +}; diff --git a/.npmignore b/.npmignore index 1e077fb0..b83b5923 100644 --- a/.npmignore +++ b/.npmignore @@ -1,34 +1,29 @@ +*.spec.* +*.config.* +*.fixture.js* +*.ai +*.cdr +*.eps +*.log +*.lock + .* + manifest.yml -Dockerfile* docker-compose.yml -shell -test -coverage - -modules/jquery/dist -modules/jquery/external -modules/jquery/src - -!modules/jquery/dist/jquery.min.js - -modules/fancybox/lib/ -modules/fancybox/demo -modules/fancybox/sprite.psd - -modules/execon -modules/emitify - +now.json app.json -circle.yml - -bin/release.js -bin/legacy.js - -client - -legacy/bin/release.js -legacy/bin/legacy.js - +bower.json +deno.json +bin/release.* +img/logo/cloudcmd-hq.png webpack.config.js +docker +test* +fixture +fixture-* +coverage +css +html +client diff --git a/.nycrc.json b/.nycrc.json new file mode 100644 index 00000000..1fe174f3 --- /dev/null +++ b/.nycrc.json @@ -0,0 +1,15 @@ +{ + "checkCoverage": false, + "all": false, + "exclude": [ + "**/*.spec.js", + "**/*.*.js", + "**/*.config.*", + "**/fixture", + "**/test/**" + ], + "branches": 100, + "lines": 100, + "functions": 100, + "statements": 100 +} diff --git a/.putout.json b/.putout.json new file mode 100644 index 00000000..7154775a --- /dev/null +++ b/.putout.json @@ -0,0 +1,60 @@ +{ + "plugins": ["cloudcmd"], + "ignore": [ + "*.md", + "app.json", + "fontello.json", + "html", + "fixture*" + ], + "rules": { + "package-json/add-type": "off" + }, + "match": { + ".filesystem.json": { + "nodejs/rename-file-cjs-to-js": "off" + }, + "base64": { + "types/convert-typeof-to-is-type": "off" + }, + "*.md": { + "nodejs/convert-commonjs-to-esm": "on" + }, + ".webpack": { + "webpack": "on" + }, + "server": { + "nodejs/remove-process-exit": "on" + }, + "server/{server,exit}.js": { + "nodejs/remove-process-exit": "off" + }, + "server/{server,exit,terminal,distribute/log}.{js,mjs}": { + "remove-console": "off" + }, + "client/{client,cloudcmd,load-module}.{js,mjs}": { + "remove-console": "off" + }, + "client": { + "nodejs": "off" + }, + "client/sw": { + "remove-console": "off" + }, + "test/common/cloudfunc.js": { + "remove-console": "off" + }, + "storage.js": { + "promises/remove-useless-async": "off" + }, + "docker.yml": { + "github/set-node-versions": "off" + }, + "vim.js": { + "merge-duplicate-functions": "off" + }, + "common": { + "nodejs/declare": "off" + } + } +} diff --git a/.rspack/css.js b/.rspack/css.js new file mode 100644 index 00000000..10d28250 --- /dev/null +++ b/.rspack/css.js @@ -0,0 +1,38 @@ +import {env} from 'node:process'; +import {rspack} from '@rspack/core'; + +const {CssExtractRspackPlugin} = rspack; +const isDev = env.NODE_ENV === 'development'; + +const plugins = [ + new CssExtractRspackPlugin({ + filename: '[name].css', + }), +]; + +const rules = [{ + test: /\.css$/i, + use: [CssExtractRspackPlugin.loader, { + loader: 'css-loader', + options: { + url: true, + }, + }], +}, { + test: /\.(png|gif|svg|woff|woff2|eot|ttf)$/, + type: 'asset/inline', +}]; + +export default { + mode: isDev ? 'development' : 'production', + plugins, + module: { + rules, + }, + optimization: { + minimize: !isDev, + minimizer: [ + new rspack.LightningCssMinimizerRspackPlugin(), + ], + }, +}; diff --git a/.rspack/html.js b/.rspack/html.js new file mode 100644 index 00000000..e90038ac --- /dev/null +++ b/.rspack/html.js @@ -0,0 +1,36 @@ +import {env} from 'node:process'; +import HtmlWebpackPlugin from 'html-webpack-plugin'; + +const isDev = env.NODE_ENV === 'development'; + +export const plugins = [ + new HtmlWebpackPlugin({ + inject: false, + template: 'html/index.html', + minify: !isDev && getMinifyHtmlOptions(), + }), +]; + +function getMinifyHtmlOptions() { + return { + removeComments: true, + removeCommentsFromCDATA: true, + removeCDATASectionsFromCDATA: true, + collapseWhitespace: true, + collapseBooleanAttributes: true, + removeAttributeQuotes: true, + removeRedundantAttributes: true, + useShortDoctype: true, + removeEmptyAttributes: true, + /* оставляем, поскольку у нас + * в элемент fm генерируеться + * таблица файлов + */ + removeEmptyElements: false, + removeOptionalTags: true, + removeScriptTypeAttributes: true, + removeStyleLinkTypeAttributes: true, + + minifyJS: true, + }; +} diff --git a/.rspack/js.js b/.rspack/js.js new file mode 100644 index 00000000..251d85f6 --- /dev/null +++ b/.rspack/js.js @@ -0,0 +1,173 @@ +import {resolve, sep} from 'node:path'; +import {fileURLToPath} from 'node:url'; +import {env} from 'node:process'; +import {rspack} from '@rspack/core'; + +const resolveModule = (a) => fileURLToPath(import.meta.resolve(a)); + +const { + EnvironmentPlugin, + NormalModuleReplacementPlugin, + ProvidePlugin, +} = rspack; + +const modules = './modules'; +const dirModules = './client/modules'; +const dirCss = './css'; +const dirThemes = `${dirCss}/themes`; +const dirColumns = `${dirCss}/columns`; +const dir = './client'; +const {NODE_ENV} = env; +const isDev = NODE_ENV === 'development'; + +const rootDir = new URL('..', import.meta.url).pathname; +const dist = resolve(rootDir, 'dist'); +const distDev = resolve(rootDir, 'dist-dev'); +const devtool = isDev ? 'eval' : 'source-map'; + +const noParse = (a) => a.endsWith('.spec.js'); + +// codegen.macro is a babel-macro (build-time codegen), not supported by +// Rspack's native SWC transform, so client/sw/sw.js (the only file that +// uses it) keeps going through babel-loader. Everything else uses +// Rspack's built-in SWC loader, which is the main source of the speedup. +const rules = [{ + test: /sw\/sw\.js$/, + exclude: /node_modules/, + loader: 'babel-loader', +}, { + test: /\.[mc]?js$/, + exclude: [/node_modules/, /sw\/sw\.js$/], + loader: 'builtin:swc-loader', + options: { + jsc: { + parser: { + syntax: 'ecmascript', + }, + }, + env: { + targets: 'defaults', + }, + }, +}]; + +const plugins = [ + new NormalModuleReplacementPlugin(/^node:/, (resource) => { + resource.request = resource.request.replace(/^node:/, ''); + }), + new NormalModuleReplacementPlugin(/^putout$/, '@putout/bundle'), + new EnvironmentPlugin({ + NODE_ENV, + }), + new ProvidePlugin({ + process: 'process/browser', + }), +]; + +const splitChunks = { + 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', + 'columns/name-size-time', + 'columns/name-size-date-time', + ]; + + return !lazyChunks.includes(chunk.name); + }, + minChunks: 1, + enforce: true, + priority: -1, + reuseExistingChunk: true, + }, + }, +}; + +export default { + resolve: { + symlinks: false, + alias: { + 'node:process': 'process', + 'node:path': 'path', + }, + fallback: { + path: resolveModule('path-browserify'), + process: resolveModule('process/browser'), + util: resolveModule('util'), + }, + }, + devtool, + optimization: { + splitChunks, + }, + entry: { + '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`, + 'columns/name-size-date-time': `${dirColumns}/name-size-date-time.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.js`, + [`${modules}/edit`]: `${dirModules}/edit.js`, + [`${modules}/edit-file`]: `${dirModules}/edit-file.js`, + [`${modules}/edit-file-vim`]: `${dirModules}/edit-file-vim.js`, + [`${modules}/edit-names`]: `${dirModules}/edit-names.js`, + [`${modules}/edit-names-vim`]: `${dirModules}/edit-names-vim.js`, + [`${modules}/menu`]: `${dirModules}/menu/index.js`, + [`${modules}/view`]: `${dirModules}/view/index.js`, + [`${modules}/help`]: `${dirModules}/help.js`, + [`${modules}/markdown`]: `${dirModules}/markdown.js`, + [`${modules}/config`]: `${dirModules}/config/index.js`, + [`${modules}/contact`]: `${dirModules}/contact.js`, + [`${modules}/upload`]: `${dirModules}/upload.js`, + [`${modules}/operation`]: `${dirModules}/operation/index.js`, + [`${modules}/konsole`]: `${dirModules}/konsole.js`, + [`${modules}/terminal`]: `${dirModules}/terminal.js`, + [`${modules}/terminal-run`]: `${dirModules}/terminal-run.js`, + [`${modules}/cloud`]: `${dirModules}/cloud.js`, + [`${modules}/user-menu`]: `${dirModules}/user-menu/index.js`, + [`${modules}/polyfill`]: `${dirModules}/polyfill.js`, + [`${modules}/command-line`]: `${dirModules}/command-line.js`, + }, + output: { + filename: '[name].js', + path: isDev ? distDev : dist, + pathinfo: isDev, + devtoolModuleFilenameTemplate, + publicPath: '/dist/', + }, + module: { + rules, + noParse, + }, + plugins, + performance: { + maxEntrypointSize: 800_000, + maxAssetSize: 600_000, + }, +}; + +function devtoolModuleFilenameTemplate(info) { + const resource = info.absoluteResourcePath.replace(rootDir + sep, ''); + return `file://cloudcmd/${resource}`; +} diff --git a/.stylelintrc.yml b/.stylelintrc.yml deleted file mode 100644 index a3e39ca7..00000000 --- a/.stylelintrc.yml +++ /dev/null @@ -1,15 +0,0 @@ -extends: stylelint-config-standard -rules: - indentation: 4 - declaration-block-trailing-semicolon: always - declaration-colon-space-before: null - selector-list-comma-newline-after: null - comment-empty-line-before: null - number-leading-zero: null - number-no-trailing-zeros: null - string-quotes: single - function-url-quotes: never - no-eol-whitespace: null - font-family-name-quotes: always-unless-keyword - rule-empty-line-before: null - diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 628a53c1..00000000 --- a/.travis.yml +++ /dev/null @@ -1,17 +0,0 @@ -language: node_js -node_js: - - 7 - - 6 - -script: - - npm run codestyle - - npm run 6to5:client:dev - - npm run coverage && npm run report - -notifications: - email: - on_success: never - on_failure: change - -sudo: false - diff --git a/.typos.toml b/.typos.toml new file mode 100644 index 00000000..dc8af253 --- /dev/null +++ b/.typos.toml @@ -0,0 +1,2 @@ +[files] +extend-exclude = ["ChangeLog"] diff --git a/.yaspellerrc b/.yaspellerrc index e6c4bc80..7e29119e 100644 --- a/.yaspellerrc +++ b/.yaspellerrc @@ -10,6 +10,7 @@ ".md" ], "dictionary":[ + "CloudCmd", "Dev", "Dropbox", "Deepword", @@ -20,17 +21,24 @@ "Heroku", "Iptables", "JitSu", + "Node", + "IO", "Olena", "TarZak", "Termux", "Zalitok", "WebSocket", + "auth", + "autostart", + "binded", "cd", "cloudcmd", "coderaiser", "com", - "dev", "deepword", + "dev", + "destructuring", + "dropbox", "dword", "edward", "favicon", @@ -38,17 +46,27 @@ "gz", "io", "js", + "linux", + "maintainers", + "markdown", + "microservice", "minification", "mouseup", + "named", "nginx", + "npm", "or io", + "patreon", + "rc", "refactor", + "sexualized", "sslPort", "unselect", "util", "v0", "v1", "v2", - "yml" + "yml", + "systemd" ] } diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 00000000..0e2522dd --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,46 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. + +## Our Standards + +Examples of behavior that contributes to creating a positive environment include: + +- Using welcoming and inclusive language +- Being respectful of differing viewpoints and experiences +- Gracefully accepting constructive criticism +- Focusing on what is best for the community +- Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +- The use of sexualized language or imagery and unwelcome sexual attention or advances +- Trolling, insulting/derogatory comments, and personal or political attacks +- Public or private harassment +- Publishing others' private information, such as a physical or electronic address, without explicit permission +- Other conduct which could reasonably be considered inappropriate in a professional setting + +## Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. + +## Scope + +This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] + +[homepage]: http://contributor-covenant.org +[version]: http://contributor-covenant.org/version/1/4/ diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c7c9b914..b6b6b4ef 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,27 +1,30 @@ -Commit ---------------- +## Commit + Format of the commit message: **type(scope) subject** **Type**: -- feature(scope) subject -- fix(scope) subject -- docs(scope) subject -- refactor(scope) subject -- test(scope) subject -- chore(scope) subject + +- feature: scope: subject +- fix: scope: subject +- docs: scope: subject +- refactor: scope: subject +- test: scope: subject +- chore: scope: subject **Scope**: Scope could be anything specifying place of the commit change. For example util, console, view, edit, style etc... **Subject text**: + - use imperative, present tense: “change” not “changed” nor “changes” - don't capitalize first letter - no dot (.) at the end -**Message body**: + **Message body**: - just as in use imperative, present tense: “change” not “changed” nor “changes” - includes motivation for the change and contrasts with previous behavior **Examples**: -- [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: style: .name{width}: 37% -> 35%](https://github.com/coderaiser/cloudcmd/commit/94b0642e3990c17b3a0ee3efeb75f343e1e7c050) +- [fix: console: dispatch: focus -> mouseup](https://github.com/coderaiser/cloudcmd/commit/f41ec5058d1411e86a881f8e8077e0572e0409ec) diff --git a/ChangeLog b/ChangeLog index 39f228f8..c5e0fbca 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,3601 @@ +2026.06.15, v19.19.1 + +feature: +- 78b206e0 client: key: Ctrl + L -> Ctrl + Shift + L: Log out (#466) +- b1492885 docker: io: NPM_CONFIG_PACKAGE_LOCK=false +- 76d7bf4d docker: typos, shellcheck: add + +2026.05.26, v19.19.0 + +feature: +- 4ee38db6 client: view: flac: add support + +2026.05.26, v19.18.1 + +feature: +- 40ecef5e cloudcmd: ratelimit: X-Forwarded-For (#437) + +2026.05.26, v19.18.0 + +fix: +- 161bede8 client: menu: @putout/bundle@5.5. +- 447d990f cloudcmd: server: rest: sendError + +feature: +- 5d9628ce cloudcmd: rate limit: add support (#437) +- 2be395e6 cloudcmd: get rid of manifest: 401 basic auth + +2026.05.17, v19.17.0 + +fix: +- d96f6c46 css: query: hide time on mobile +- e7c55e05 docker: io: XDG_CONFIG_HOME + +feature: +- ae1ca0f8 cloudcmd: cssnano-preset-default v8.0.1 +- 94d5096a style: owner, mode: improve +- 807f8346 cloudcmd: superc8 v12.6.0 +- 67a95722 docker: io: cline: add +- 68eacb91 qword: add +- 4acd294b docker: io: tmux +- 05c80043 cloudcmd: @supertape/loader-css v1.0.0 +- 800a6545 cloudcmd: eslint-plugin-n v18.0.1 +- a985bb36 cloudcmd: supertape v13.0.0 +- 4315ec61 docker: io XDG_CONFIG_HOME: /etc -> /usr/local/etc + +2026.05.03, v19.16.0 + +feature: +- d82d0335 client: vim: rr for rename file +- acfa27cf docker: io: nvchad: add +- 14f009f8 docker: io: bash-completion: add +- c6c60146 docker: io: f4 +- 9a6b8935 docker: io: GOPATH +- a9bc22ce cloudcmd: operation: rm useless checks +- 36bacfe9 cloudcmd: client: key: vim: cc, mm +- 591da25c cloudcmd: ponse v8.0.0 +- 1e1b073c docker: io: /usr/src/cloudcmd -> /usr/local/share/cloudcmd + +2026.04.28, v19.15.0 + +feature: +- 9d97343b cloudcmd: operation: rm useless checks +- 46a88cfa cloudcmd: client: key: vim: cc, mm + +2026.04.28, v19.14.0 + +feature: +- 36a8b641 cloudcmd: ponse v8.0.0 +- 1c263c18 docker: io: /usr/src/cloudcmd -> /usr/local/share/cloudcmd +- ea7b828c docker: io: ubuntu: resolute +- cd6c11ac docker: io: far2l +- c4beeec6 docker: io: gdu: add + +2026.04.21, v19.13.1 + +feature: +- d5cd11e8 cloudcmd: montag v2.0.1 +- dc94d2db docker: io: add latest git version +- 1637beee docker: io: /usr/local/src -> /usr/local/share +- b1bc4e73 Docker: io: pv +- 7c0dca60 docker: io: git: master + +2026.04.15, v19.13.0 + +fix: +- 48693d9e docker: io: XDG_CACHE_HOME + +feature: +- 4b2395c5 cloudcmd: Ctrl + L: logout +- 977a8aaa docker: io: strace: add +- 7d0098fd docker: io: XDG_CACHE_HOME=/tmp/cache +- a89e901b actions: docker: io: add + +2026.04.12, v19.12.5 + +feature: +- 1cfc1a6f docker: io: only amd64 + +2026.04.12, v19.12.4 + +feature: +- 3c2b5658 docker: io: haskell +- d37f8cd3 docker: io: palabra: node + +2026.04.12, v19.12.3 + +feature: +- cb6cabd4 docker: io: PALABRA_DIR + +2026.04.11, v19.12.2 + +feature: +- 2ce11fa2 docker: io: get rid of haskell: to slow install +- aa741232 docker: io: rizin, yara + +2026.04.09, v19.12.1 + +feature: +- 5bd03215 docker: io: add PREFIX + +2026.04.09, v19.12.0 + +feature: +- 13b15b7b docker: io: palabra + +2026.04.07, v19.11.14 + +feature: +- a31beab0 docker: io: rustup env + +2026.04.07, v19.11.13 + +feature: +- 6a08479a docker: io: BUN_INSTALL + +2026.04.06, v19.11.12 + +feature: +- 46c65554 docker: io: npm_config_cache + +2026.04.06, v19.11.11 + +feature: +- ae2ce388 docker: io: $DENO_DIR + +2026.04.06, v19.11.10 + +feature: +- 12ea14ac docker: io: nvm: node + +2026.04.06, v19.11.9 + +feature: +- ea96d13f docker: io: net-tools + +2026.04.06, v19.11.8 + +feature: +- 5c08565f docker: io: debian -> ubuntu + +2026.04.05, v19.11.7 + +feature: +- 36cdef37 docker: io: bookworm + +2026.04.05, v19.11.6 + +feature: +- 845f9bd1 cloudcmd: gritty v10.2.0 + +2026.04.05, v19.11.5 + +feature: +- f9c513cc docker: io: hexyl: add + +2026.04.04, v19.11.4 + +feature: +- e7347d25 docker: io: neovim: apt -> github + +2026.04.04, v19.11.3 + +feature: +- 9970ff76 docker: io: btop +- 4395a471 docker: io: $PATH: add $HOME/.local/bin + +2026.04.04, v19.11.2 + +feature: +- c40ae8e4 docker: io: htop +- f463c5c5 docker: io: aptitude: add +- d1032f09 docker: io: remove unused + +2026.04.04, v19.11.1 + +feature: +- 7787bfc2 cloudcmd: user-menu: runFromCDN + +2026.04.04, v19.11.0 + +feature: +- 32f89d38 cloudcmd: user-menu: root + +2026.04.04, v19.10.2 + +feature: +- df4fb517 cloudcmd: aleman v2.0.1 + +2026.04.03, v19.10.1 + +feature: +- ceb7ef4f docker: io: keep /var/lib/apt/lists + +2026.04.02, v19.10.0 + +fix: +- d12e7bd0 distribute: fix event listener leak on socket disconnect (#462) + +2026.04.02, v19.9.24 + +feature: +- c4d26c6a docker: io: apt-get upgrade +- 9ddb8c29 docker: io: get rid of nix +- e4d7d441 docker: io: nix + +2026.04.01, v19.9.23 + +feature: +- 5a3413ce docker: io: nix + +2026.03.31, v19.9.22 + +feature: +- b4345ed4 docker: io: DENO_DIR + +2026.03.31, v19.9.21 + +fix: +- 5c6a9a95 css: columns: name: 40% -> 35% + +2026.03.30, v19.9.20 + +feature: +- cd0b5554 iocmd: io: nvm + +2026.03.30, v19.9.19 + +feature: +- 6a52b11e docker: io: go, rust + +2026.03.30, v19.9.18 + +feature: +- 738059f2 docker: io: fzf +- 3fc8932f docker: io: less, el_GR + +2026.03.30, v19.9.17 + +feature: +- cf424d6c docker: io: command-not-found update + +2026.03.29, v19.9.16 + +feature: +- 19347a2b docker: io: add command-not-found + +2026.03.29, v19.9.15 + +feature: +- ee170552 docker: io: ubuntu +- e04c4594 docker: io: net-tools: add + +2026.03.29, v19.9.14 + +fix: +- 6c7709be docker: io: PS1 + +2026.03.29, v19.9.13 + +fix: +- 439b3710 bin: currify +- e4182841 docker: io: xterm-256color + +2026.03.29, v19.9.12 + +feature: +- 811a47fd cloudcmd: bin: get rid of require + +2026.03.29, v19.9.11 + +feature: +- 1f95f188 cloudcmd: get rid of simport + +2026.03.29, v19.9.10 + +feature: +- f0deb323 docker: io: add ja_JP.UTF-8 + +2026.03.29, v19.9.9 + +fix: +- f671f798 docker: io: PS1 environment variable in Dockerfile + +feature: +- cc7f9dc7 docker: io: use ubuntu + +2026.03.28, v19.9.8 + +feature: +- 4d1cd8cd docker: io: ffmpeg +- 54b56fdc cloudcmd: vim: ESC: use only to enable, do not use to disable + +2026.03.27, v19.9.7 + +feature: +- 110908e2 docker: io: apt-get + +2026.03.26, v19.9.6 + +feature: +- 6450a2f8 docker: io: add UTF-8 + +2026.03.26, v19.9.5 + +fix: +- e761cacb columns: name-size-date-time: 20% -> 19% + +2026.03.26, v19.9.4 + +feature: +- 69498ed6 docker: io: pull.rebase by default + +2026.03.24, v19.9.3 + +feature: +- 8763788b docker: io: healthcheck + +2026.03.23, v19.9.2 + +feature: +- 09a02074 docker: io: git config: add +- c448eaa4 docker: io: buni + +2026.03.23, v19.9.1 + +fix: +- 6e5318fa client: modules: config: input: quote + +2026.03.23, v19.9.0 + +feature: +- a1216cdd cloudcmd: add ability to hide port configuration + +2026.03.23, v19.8.15 + +feature: +- 68b2aa78 docker: io: cloudcmd_vim + +2026.03.23, v19.8.14 + +fix: +- 665ed9c2 docker: io: get back port + +2026.03.23, v19.8.13 + +feature: +- 618a5615 docker: io: PS1 + +2026.03.23, v19.8.12 + +feature: +- 556b0150 docker: io: PS1 + +2026.03.23, v19.8.11 + +fix: +- 97672ef5 docker: io: apt-get install -> apt-get + +feature: +- 67f27d84 docker: io: bun, deno + +2026.03.23, v19.8.10 + +feature: +- 025b005e docker: io: add PS1 + +2026.03.23, v19.8.9 + +fix: +- b052cf22 cloudcmd: no time available: --.--.---- -> --:--:-- (#461) + +2026.03.23, v19.8.8 + +feature: +- 02dbe56d server: user-menu: when error send it + +2026.03.23, v19.8.7 + +feature: +- ecc76e8b docker: io: renamify-cli, runny, redfork + +2026.03.23, v19.8.6 + +fix: +- 53c072ab @putout/plugin-cloudcmd: devDependencies -> dependnecies + +feature: +- 4b9922bf docker: /usr/src: app -> cloudcmd + +2026.03.23, v19.8.5 + +fix: +- 56fc8b83 docker: gritty + +2026.03.22, v19.8.4 + +feature: +- 5000227e docker: vim nvim + +2026.03.22, v19.8.3 + +fix: +- 01677e6a docker: io: slim -> io + +feature: +- 7e35c606 docker: io: curl wget + +2026.03.22, v19.8.2 + +feature: +- e5b221f7 docker: io: add + +2026.03.22, v19.8.1 + +feature: +- 708a4c6b docker: slim: add +- 80613f46 docker: slim: add + +2026.03.20, v19.8.0 + +fix: +- 59037f2c cloudcmd: bin: --show-config + +feature: +- 10934b3a cloudcmd: add ability to show modification time (#230) + +2026.03.18, v19.7.1 + +feature: +- b0c1d36c cloudcmd: @cloudcmd/fileop v9.0.7 (#460) + +2026.03.17, v19.7.0 + +feature: +- daf83875 cloudfunc: override date format (#459) + +2026.03.17, v19.6.9 + +feature: +- b28a070a cloudcmd: redzip v4.6.1 +- 43c5a011 cloudcmd: css-minimizer-webpack-plugin v8.0.0 +- 15dcae5c cloudcmd: webpack-cli v7.0.2 +- 5976da81 cloudcmd: @cloudcmd/fileop v9.0.5 +- 37cb83f2 cloudcmd: redzip v4.6.0 + +2026.02.27, v19.6.8 + +feature: +- 15fab514 cloudcmd: copymitter v10.3.0 (#458) + +2026.02.26, v19.6.7 + +feature: +- 68c7d0be cloudcmd: onezip v7.0.0 + +2026.02.26, v19.6.6 + +feature: +- 3987cc82 cloudcmd: redzip v4.5.1 (#457) + +2026.02.26, v19.6.5 + +feature: +- 964ae989 cloudcmd: redzip v4.5.0 (#457) + +2026.02.25, v19.6.4 + +feature: +- a66eeda3 cloudcmd: copymitter v10.2.0 (coderaiser/cloudcmd#457) +- 4340533a cloudcmd: c8 v11.0.0 +- 0857711f cloudcmd: redzip v4.2.0 (#457) + +2026.02.24, v19.6.3 + +feature: +- 2234f1b4 cloudcmd: redzip v4.2.0 (#475) + +2026.02.24, v19.6.2 + +feature: +- 321a54dd cloudcmd: @cloudcmd/fileop v9.0.2 (#457) + +2026.02.24, v19.6.1 + +feature: +- 7c5ac408 cloudcmd: @cloudcmd/fileop v9.0.1 (#457) + +2026.02.21, v19.6.0 + +feature: +- 6d19bf2e common: object.omit -> omit + +2026.02.18, v19.5.1 + +feature: +- 6e1cf4ef cloudcmd: supermenu v5.0.0 + +2026.02.18, v19.5.0 + +feature: +- b20539ef common: entity: encode {,} +- 7ef134f4 cloudcmd: rendy v5.0.0 + +2026.02.18, v19.4.1 + +feature: +- 1e18d513 cloudcmd: @cloudcmd/fileop v9.0.0 + +2026.02.18, v19.4.0 + +fix: +- 45cf9baf menu: prefix (#456) + +feature: +- 3e647290 cloudcmd: redlint v6.0.0 +- 800ed012 cloudcmd: putout v42.0.5 +- 525c17d4 cloudcmd: madrun v13.0.0 +- 44247499 cloudcmd: eslint-plugin-putout v31.0.0 + +2026.02.15, v19.3.9 + +feature: +- 9ffe3ef1 cloudcmd: copymitter v10.0.0 (#457) + +2026.02.15, v19.3.8 + +fix: +- d274a2b3 spinner (#456) + +2026.02.13, v19.3.7 + +feature: +- 8fd79a27 cloudcmd: win32 v8.0.0 + +2026.02.12, v19.3.6 + +feature: +- ac94eccd cloudcmd: konsole: named +- 144e4a34 cloudcmd: gritty v10.0.0 +- 938f9e76 cloudcmd: console-io v15.0.1 + +2026.02.08, v19.3.5 + +feature: +- fb40bd9c rm cssnano: has no sense for spinner, option disabled by default (https://svgo.dev/docs/plugins/convertPathData/) +- 76125be9 cloudcmd: eslint v10.0.0 + +2026.02.06, v19.3.4 + +feature: +- 66a08c7f cloudcmd: deepword v11.0.0 + +2026.02.05, v19.3.3 + +feature: +- 4a5a56f4 cloudcmd: dword v16.0.0 + +2026.02.04, v19.3.2 + +fix: +- 99d8435e cloudcmd: exports +- a266c145 cloudcmd: default -> named +- 6e3ba271 Closing X in editor disappeared (#455) + +feature: +- 30f42e94 cloudcmd: restafary v13.0.1 +- f84ce853 cloudcmd: edward v16.0.0 + +2026.02.03, v19.3.1 + +fix: +- 5661bc4f Closing X in editor disappeared (#455) + +2026.02.03, v19.3.0 + +feature: +- 4533a25c cloudcmd: migrate to ESM +- e8a81c49 client: dom: events: migrate to ESM +- 071141bc client: terminal-run: migrate to ESM + +2026.02.03, v19.2.0 + +feature: +- bb32f7c4 client: dom: migrate to ESM +- 457c83db client: migrate to ESM +- f8a941bd client: modules: markdown: migrate to ESM +- 9d6cffaf client: polifyll: migrate to ESM +- 5b704d06 client: edit-names: migrate to ESM +- 2c2ca8eb client: edit-file: migrate to ESM +- c9f57c5f client: modules: edit-file-vim: migrate to ESM +- 327ac9de client: modules: help: migrate to ESM +- dc34ee87 cloudcmd: @putout/plugin-cloudcmd v5.0.0 +- 3cd3695b client: modules: edit-names-vim: migrate to ESM +- dfcbfd63 client: modules: terminal: migrate to ESM + +2026.02.02, v19.1.21 + +feature: +- e3ad330e client: konsole: migrate to ESM +- 983fd9af client: edit: migrate to ESM +- ebabad94 common: entity: migrate to ESM +- c3b71653 client: dom: images -> #images +- 8cad7514 common: cloudfunc -> #common/cloudfunc +- 1f174870 client: view: migrate to ESM +- 7173f6cb cloudcmd: smalltalk v5.0.0 + +2026.01.31, v19.1.20 + +feature: +- c1014c9c client: dom: operations: rename-current: migrate to ESM +- 2e486f8b cloudcmd: restafary v13.0.0 +- 6addb29f cloudcmd: redzip v4.0.0 + +2026.01.30, v19.1.19 + +feature: +- 2a0feac7 cloudcmd: @cloudcmd/modal v4.0.0 + +2026.01.30, v19.1.18 + +feature: +- 73fa4961 client: modules: user-menu: migrate to ESM +- ebfdf8c0 client: modules: operation: migrate to ESM +- ad683171 client: modules: menu: migrate to ESM +- 0054cfa3 client: dom: load-remote: migrate to ESM +- e4d0ece0 client: dom: rest: migrate to ESM +- c704ffe4 client: dom: storage: migrate to ESM +- 5182cb81 client: modules: upload: migrate to ESM +- 9543f1ad client: dom: upload-files: migrate to ESM + +2026.01.29, v19.1.17 + +feature: +- f9c28319 client: dom: migrate to ESM +- 9d2c4e4a client: dom: cmd: move out +- 5a2aa70f client: dom: simplify require +- dee50a85 client: dom: files: migrate to ESM +- 23c0d770 client: dom: dom-tree: migrate to ESM +- cf2c6415 client: directory: migrate to ESM +- 0eb802e7 client: dom: dialog: migrate to ESM + +2026.01.28, v19.1.16 + +fix: +- 4c242631 css: spinner: do not minify svg + +2026.01.28, v19.1.15 + +feature: +- 265c0b49 client: key: vim: migrate to ESM +- 3bc49f02 client: set-current-by-char: migrate to ESM + +2026.01.28, v19.1.14 + +feature: +- f8a63b5a client: key: binder: migrate to ESM +- 2cc97f33 client: cloud: migrate to ESM + +2026.01.27, v19.1.13 + +feature: +- 41b5a96f client: load: migrate to ESM + +2026.01.27, v19.1.12 + +feature: +- 27a52d33 client: sw: migrate to ESM +- 6b049d95 client: sw: register: migrate to ESM + +2026.01.25, v19.1.11 + +feature: +- f849b842 client: listeners: migrate to ESM +- 091f9017 client: listeners: simplify +- 3c1a82e7 client: key: view: get rid of mock-require + +2026.01.25, v19.1.10 + +feature: +- dc5867b0 client: key: vim: get rid of mock-require +- 77b70b21 cloudcmd: aleman v2.0.0 + +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 + +feature: +- aca4119f cloudcmd: inly v5.0.0 + +2024.02.01, v17.0.2 + +feature: +- 5324a41a cloudcmd: supertape v10.0.0 +- d453a1b2 cloudcmd: onezip v6.0.1 +- 71b915be cloudcmd: @cloudcmd/fileop v8.0.0 + +2024.01.25, v17.0.1 + +feature: +- d79a5776 cloudcmd: putout v35.0.0 +- 8d92aa91 cloudcmd: package-json v9.0.0 +- 5ab5576e cloudcmd: open v10.0.3 +- c5cfe68c cloudcmd: c8 v9.1.0 + +2023.12.12, v17.0.0 + +feature: +- 154e3b07 cloudcmd: find-up v7.0.0 +- a02d288d cloudcmd: @putout/babel v2.0.0 +- 3314f9b9 drop support of node < 18 +- a6afa205 cloudcmd: supertape v9.0.0 +- e600c05d cloudcmd: eslint-plugin-putout v22.0.0 +- 99c00954 cloudcmd: madrun v10.0.0 +- afdf7434 cloudcmd: putout v34.0.7 + +2023.12.08, v16.18.0 + +feature: +- 4462f269 cloudcmd: markdown-it v14.0.0 +- 0cc76bd4 cloudcmd: philip v3.0.0: decrease bundle size +- 656ebd87 client: move out set-current + +2023.12.04, v16.17.9 + +fix: +- fb2d0814 github actions + +2023.12.04, v16.17.8 + +feature: +- 93aa7278 yaspeller: rm +- af9c916e cloudcmd: eslint-plugin-putout v21.0.2 +- 01dccbfd cloudcmd: putout v33.13.3 + +2023.10.12, v16.17.7 + +feature: +- 7857fb72 package: rendy v4.1.3 + +2023.09.22, v16.17.6 + +feature: +- 570cb8c0 package: nodemon v3.0.1 +- 828d10a8 package: rimraf v5.0.1 +- 88908b35 package: eslint-plugin-putout v20.0.0 +- 93f4a07e package: putout v32.0.6 +- a5f93523 github actions: use bun + +2023.09.06, v16.17.5 + +feature: +- 3b0941bc actions: docker/login-action@v2 (#396) + +2023.09.05, v16.17.4 + +feature: +- 35dedfdf github: update docker actions (#396) + +2023.09.05, v16.17.3 + +feature: +- 3c93b29b github: docker/build-push-action v4 (#396) + +2023.09.04, v16.17.2 + +fix: +- 621f52da docker + +2023.09.04, v16.17.1 + +fix: +- eb3f037a docker: bun -> node + +2023.09.04, v16.17.0 + +feature: +- 224e5397 docker: use bun instead of node +- 4b9267f3 package: edward v14.2.0 + +2023.08.10, v16.16.3 + +feature: +- 354c137d package: console-io v14.0.0 + +2023.08.09, v16.16.2 + +feature: +- e353fff7 package: redzip v3.0.0 + +2023.08.07, v16.16.1 + +feature: +- d63169cc package: @putout/babel v1.0.5 +- bb9276be package: eslint-plugin-putout v19.0.3 +- 9aed5f75 package: putout v31.0.3 + +2023.07.09, v16.16.0 + +feature: +- c4f56c59 package: memfs v4.2.0 +- 0e663e1d package: @putout/plugin-cloudcmd v3.1.1 +- ff9265b7 package: c8 v8.0.0 +- 22aa337a package: eslint-plugin-n v16.0.1 +- 13350b55 package: eslint-plugin-putout v18.0.0 +- ce196abf package: putout v30.1.1 + +2023.05.17, v16.15.0 + +feature: +- a1bf40bd package: open v9.1.0 +- ef608853 client: self signed certs on Chrome (#393) + +2023.03.21, v16.14.1 + +feature: +- b336a472 package: eslint-plugin-putout v17.1.0 +- 019e15b8 package: @cloudcmd/fileop v7.0.0 +- 64354300 package: copymitter v8.0.1 +- 27437880 package: @cloudcmd/move-files v7.0.0 + +2023.03.08, v16.14.0 + +feature: +- 6b22b241 package: putout v29.0.3 + +2023.01.30, v16.13.1 + +feature: +- client: add DIR_DIST +- client: DIRCLIENT -> DIR_CLIENT + +2023.01.29, v16.13.0 + +feature: +- client: key: vim: open editor with 'e' +- client: vim: add ability to show terminal with 'tt' + +2023.01.29, v16.12.0 + +feature: +- client: vim: add ability to create directory with 'md', and create file with 'mf' + +2023.01.22, v16.11.0 + +fix: +- lint: eslint-plugin-node -> eslint-plugin-n + +feature: +- user-menu: add support of mov +- client: user-menu: navigate: add support of \D + [JK] to speed up vim navigation + +2023.01.19, v16.10.0 + +fix: +- lint: eslint-plugin-node -> eslint-plugin-n + +feature: +- client: user-menu: navigate: add support of \D + [JK] to speed up vim navigation + +2023.01.18, v16.9.1 + +fix: +- static: user-menu: convert flac to mp3 + +2023.01.17, v16.9.0 + +feature: +- package: scroll-into-view-if-needed v3.0.4 +- package: tar-stream v3.0.0 +- static: user-menu: add recipes from Cookbook + +2023.01.16, v16.8.0 + +feature: +- package: @putout/plugin-cloudcmd v2.0.0: CloudCmd.loadDir() -> CloudCmd.changeDir()' + +2023.01.15, v16.7.0 + +feature: +- package: @cloudcmd/modal v3.0.0: add ability to not set cursor when close the modal +- package: auto-globals v3.0.0 +- package: rimraf v4.0.5 +- user-menu: rm border + +2022.10.20, v16.6.1 + +feature: +- package: package-json v8.1.0 +- package: supertape v8.1.0 +- package: putout v28.0.0 + +2022.10.09, v16.6.0 + +feature: +- package: @cloudcmd/fileop v6.0.0 +- package: @cloudcmd/move-files v6.0.0 +- package: copymitter v7.0.0 + +2022.08.06, v16.5.0 + +feature: +- client: add Command Line +- package: add funding +- (package) gritty v7.0.0 + +2022.07.20, v16.4.1 + +feature: +- (package) eslint-plugin-n v15.2.4 +- (package) putout v27.0.1 +- (package) eslint-plugin-putout v16.0.0 + + +2022.07.11, v16.4.0 + +feature: +- (cloudcmd) env: add ability to pass 0 and 1 + + +2022.07.02, v16.3.1 + +fix: +- (client) cloudcmd: rm window.Emitify + + +2022.07.01, v16.3.0 + +feature: +- (cloudcmd) terminal-run: return -1, when not load + + +2022.06.17, v16.2.0 + +feature: +- (package) markdown-it v13.0.1 +- (cloudcmd) server: convert to ESM +- (package) thread-it v2.0.0 + + +2022.05.12, v16.1.1 + +feature: +- (package) edward v14.0.0 +- (package) putout v26.0.1 + + +2022.04.23, v16.1.0 + +feature: +- (cloudcmd) improve support of NBSP + + +2022.04.22, v16.0.1 + +feature: +- (package) dword v14.0.0 +- (package) restafary v11.0.0 +- (package) @cloudcmd/stub v4.0.1 +- (package) win32 v7.0.0 +- (package) eslint-plugin-putout v14.4.0 + + +2022.02.19, v16.0.0 + +feature: +- (cloudcmd) drop support of node < 16 +- (package) supertape v7.1.0 +- (package) eslint-plugin-putout v13.11.0 +- (package) madrun v9.0.0 +- (package) putout v25.0.1 + +2022.01.20, v15.9.15 + +fix: +- (css) icons (#368) + +2022.01.13, v15.9.14 + +fix: +- (cloudcmd) client: edit-names in vim mode +- (docker) images: make dockerfiles use node:lts-buster and node:lts-buster-slim for alpine (#363) +- (docker) images: make dockerfiles use node:lts-buster-slim as base image (#357) +feature: +- (package) eslint-plugin-putout v13.0.1 +- (package) putout v24.0.2 + +2021.12.23, v15.9.13 + +feature: +- (package) putout v23.0.0 + +2021.12.16, v15.9.12 + +fix: +- (client) loadDir: history enabled by default + +2021.12.09, v15.9.11 + +fix: +- (client) load: Upload stuck for zero byte files (#359) + +2021.12.04, v15.9.10 + +fix: +- (client) operation: move and copy not working (#358) +feature: +- (package) eslint-plugin-putout v12.2.0 + +2021.11.22, v15.9.9 + +feature: +- (package) putout v22.0.2 +- (package) yargs-parser v21.0.0 +- (package) yaspeller v8.0.0 +- (package) eslint-plugin-putout v11.1.0 +- (package) putout v21.1.2 +- (package) eslint v8.0.1 +- (package) eslint-plugin-putout v10.3.0 +- (package) find-up v6.1.0 +- (package) putout v20.5.1 +- (package) supertape v6.9.1 +- (package) eslint-plugin-putout v9.0.1 + +2021.08.09, v15.9.8 + +fix: +- (cloudcmd) args: snake case -> camelCase: yargs strip dashed + + +2021.06.27, v15.9.7 + +fix: +- (config) rm broadcast: cannot change config +- (view) close modals using ESC + +feature: +- (package) package-json v7.0.0 +- (config) add more descriptive titles + + +2021.06.13, v15.9.6 + +feature: +- (package) @cloudcmd/move-files v5.0.0 + + +2021.06.08, v15.9.5 + +fix: +- (load) put: replace #: single -> multiple +- (server) user-menu: e.message -> errorFind.message + +feature: +- (package) eslint-plugin-putout v8.0.1 +- (package) es6-promisify v7.0.0 +- (package) putout v18.0.1 +- (package) putout v17.0.0 + + +2021.04.05, v15.9.4 +feature: +- (package) socket.io-client v4.0.1 +- (package) open v8.0.5 +- (package) putout v16.4.0 + +2021.03.17, v15.9.3 + +fix: +- (cloudcmd) Docker latest-alpine (15.9.2) stopped with errors (#337) + + +2021.03.16, v15.9.2 + +fix: +- (route) unable to navigate between folders (#333) + +feature: +- (package) open v8.0.2 +- (package) socket.io-client v4.0.0 +- (package) socket.io v4.0.0 + + +2021.03.01, v15.9.1 + +feature: +- (cloudcmd) icons: add archive icon for small screens +- (cloudcmd) add archive-link image + + +2021.03.01, v15.9.0 + +feature: +- feature(cloudcmd) add archive icon +- feature(client) rm unused loadCurrentTime +- feature(package) win32 v6.0.0 +- feature(package) redzip v2.0.0 + + + +2021.02.27, v15.8.1 + +feature: +- (package) restafary v9.7.0 (#330) + + +2021.02.23, v15.8.0 + +feature: +- (cloudcmd) add ability to suggest option, when wrong provided +- (package) supertape v5.0.0 + + +2021.02.21, v15.7.1 + +fix: +- (cloudcmd) prefix env has no effect (#328) + + +2021.02.19, v15.7.0 + +fix: +- chore(github-actions) add ability to autofix lint + +feature: +- (package) @cloudcmd/move-files v4.0.0 +- (package) putout v15.0.0 +- (package) copymitter v6.0.0 +- (package) @cloudcmd/olark v3.0.2 +- (client) view: unknown file type: method: GET -> HEAD: speed up + + +2021.02.03, v15.6.0 + +feature: +- (client) view: add ability to detect file type when extension is missing (coderaiser/cloudcmd#287) + + +2021.02.02, v15.5.2 + +fix: +- (client) view: isAudio (#322) + + +2021.01.31, v15.5.1 + +fix: +- (cloudcmd) cannot create a directory (#319) + + +2021.01.30, v15.5.0 + +feature: +- (package) style-loader v2.0.0 +- (cloudcmd) improve error handling when viewing or editing a file +- (package) putout v14.0.0 +- (package) eslint-plugin-putout v7.0.0 + + +2021.01.26, v15.4.4 + +feature: +- (package) win32 v5.1.11 + + +2021.01.25, v15.4.3 + +feature: +- (package) restbox v3.0.0 +- (package) ponse v6.0.0 +- (package) files-io v4.0.0 + + +2021.01.21, v15.4.2 + +feature: +- (package) mellow v3.0.0 +- (route) tokenize -> wraptile + + +2021.01.20, v15.4.1 + +feature: +- (route) redzip -> win32 (#317) + + +2021.01.19, v15.4.0 + +feature: +- (cloudcmd) add abilit to parse markdown inside zip archives + + +2021.01.19, v15.3.4 + +fix: +- (docker) images: change alpine images to be part of master image (#316) +- (dom) bug in Firefox with Imagus extension enabled: change getCurrentName to read from `data-name` instead of `title` (#313) + +feature: +- (package) deepword v8.0.0 +- (package) console-io v13.0.0 +- (package) edward v13.0.0 +- (docker) add support of multi-arch builds (#291) + + +2021.01.18, v15.3.3 + +fix: +- (dom) bug in Firefox with Imagus extension enabled: change getCurrentName to read from `data-name` instead of `title` (#313) +- (client) dom: goToDirectory + + +2021.01.18, v15.3.2 + +fix: +- (client) dom: goToDirectory + + +2021.01.17, v15.3.1 + +fix: +- (view) view html, pdf + +feature: +- (package) dword v13.0.0 +- (modules) socket.io v3.1.0 + + +2021.01.17, v15.3.0 + +feature: +- (client) improve vim support: Esc - toggle vim support in editors +- (client) view: add ability to view raw files using Shift + F3 +- (client) view: show markdown without shift +- (key) add ability to toggle global vim config on the time of session + + +2021.01.16, v15.2.0 + +fix: +- (server) distribute: simplify colors + +feature: +- (cloudcmd) add ability to open html files using F3 +- (cloudcmd) add ability to toggle vim hotkes using Esc +- (package) @cloudcmd/fileop v5.0.0 + + +2021.01.07, v15.1.0 + +feature: +- (cloudcmd) add ability to read zip files like directories (#309) + + +2021.01.05, v15.0.4 + +feature: +- (package) flop v9.0.0 +- (package) restafary v9.0.1 + + +2021.01.05, v15.0.3 + +fix: +- (cloudcmd) validateRoot: import -> simport: forEachKey is not a function (#311) + +feature: +- (package) onezip v5.0.0 +- (package) socket.io v3.0.5 (socketio/socket.io#3720) + + +2020.12.31, v15.0.2 + +fix: +- (cloudcmd) criton: crash when password set (#310) + + +2020.12.30, v15.0.1 + +fix: +- (cloudcmd) css: media query for screen size with width more then 1600 (cloudcmd/console-io#6) +- (cloudcmd) client: build: optional chaining +- (cloudcmd) drop support of node < 14 + +feature: +- (package) putout v13.0.0 + + +2020.12.28, v15.0.0 + +fix: +- (cloudcmd) app, help: remove duplicate keys +- chore(cloudcmd) menu: add lint, :lint, test, coverage +- (cloudcmd) importListen prevent server from start (#295) + +feature: +- (package) auto-globals v2.0.0 +- (cloudcmd) convert to EcmaScriptModules +- (package) supertape v4.1.0 +- (package) supertape v3.10.0 +- (package) babel-plugin-macros v3.0.0 +- (package) putout v12.0.0 +- (package) supertape v3.1.3 +- (package) madrun v8.0.0 +- (package) gritty v6.0.0 +- (package) console-io v12.0.0 +- (package) socket.io-client v3.0.1 +- (package) socket.io v3.0.1 +- (package) putout v11.0.2 +- (package) eslint-plugin-putout v6.0.0 +- (package) markdown-it v12.0.0 +- (package) putout v10.0.0 +- (package) gritty v5.0.0 +- (distribute) import: do not import if env variable set +- (package) drop support of node < 12 +- (package) table v6.0.1 + + +2020.08.21, v14.9.3 + +fix: +- (client) dom: buffer: get, set -> getJson, setJson (#295) + +feature: +- (storage) rm unused removeMatch + + +2020.08.19, v14.9.2 + +fix: +- (cloudcmd) client: edit: json files (#294) + + +2020.08.16, v14.9.1 + +feature: +- (cloudcmd) add IO.createDirectory (https://github.com/coderaiser/putout/commit/b54b5486f438804120df261dafa8e6985201a4eb) + + +2020.08.14, v14.9.0 + +feature: +- (key) vim: add ability to navigate to next and previous using w and b +- (key) vim: add ability to navigate using to first and last file using ^ and $ + + +2020.08.14, v14.8.0 + +feature: +- (cloudcmd) IO.cp -> IO.copy +- (cloudcmd) IO.mv -> IO.move +- (package) find-up v5.0.0 + + +2020.08.11, v14.7.2 + +fix: +- (client) key: F3: search appears + + +2020.08.11, v14.7.1 + +fix: +- (view) init config: copy + + +2020.08.10, v14.7.0 + +fix: +- (client) user menu: click on user menu title +- test(cloudcmd) test/server/prefixer -> server/prefixer + +feature: +- (cloudcmd) rest: add rename +- (rest) mv: improved user errors +- (client) io: promisify -> async +- (package) webpack-merge v5.0.8 +- (package) eslint-plugin-putout v5.0.0 +- (package) putout v9.0.0 +- (package) madrun v7.0.0 + + +2020.05.20, v14.6.0 + +feature: +- (package) markdown-it v11.0.0 +- (cloudcmd) client: add ability to handle existing file while rename (#289) +- (package) supertape v2.0.0 +- (package) @cloudcmd/stub v3.0.0 + + +2020.05.06, v14.5.1 + +fix: +- (docker) alpine + + +2020.05.04, v14.5.0 + +fix: +- (user-menu) choose using Enter + +feature: +- (package) eslint v7.0.0 +- (package) eslint-plugin-putout v4.0.0 +- (package) putout v8.0.0 +- (package) madrun v6.0.0 +- (client) directory: add abily to show progress dialog on upload + + +2020.04.27, v14.4.0 + +feature: +- (user-menu) add ability to run selected items without showing dialog + + +2020.04.13, v14.3.10 + +fix: +- (util) getRegExp: multiple dots +- (cloudcmd) crash on check for update (#286) + +feature: +- (package) yaspeller v7.0.0 + + +2020.04.10, v14.3.9 + +fix: +- (docker) node -> node:lts (#280) +- (env) UPPER_CASE first, and then lower_case (#283) + +feature: +- (cloudcmd) promise -> async + + +2020.04.04, v14.3.8 + +feature: +- (client) ajaxLoad: callback -> promise +- (get-json-from-file-table) mv out from client + + +2020.04.03, v14.3.7 + +fix: +- (client) dom: getCurrentType + +feature: +- (package) chalk v4.0.0 + + +2020.03.31, v14.3.6 + +fix: +- (cloudcmd) directoryStorage + + +2020.03.25, v14.3.5 + +feature: +- (package) fullstore v3.0.0 +- (package) html-webpack-plugin v4.0.1 +- (package) codegen.macro v4.0.0 +- (package) url-loader v4.0.0 + + +2020.03.03, v14.3.4 + +feature: +- (package) readjson v2.0.1 +- (package) tryrequire v3.0.0 +- (package) flop v8.0.0 +- (package) writejson v3.0.0 +- (package) try-to-catch v3.0.0 +- (package) try-catch v3.0.0 + + +2020.02.23, v14.3.3 + +feature: +- (key) vim: split DOM and vim + + +2020.02.21, v14.3.2 + +feature: +- (package) serve-once v2.0.0 +- (package) edward v12.0.0 +- (package) dword v12.0.0 +- (package) ponse v5.0.0 + + +2020.02.21, v14.3.1 + +feature: +- (package) supermenu v4.0.1 +- (package) stylelint-config-standard v20.0.0 +- (package) http-auth v4.1.2 + + +2020.01.29, v14.3.0 + +feature: +- (listeners) improve file select with ctrl + click (#269) +- (docker) add Dockerfile for arm based clients such as rpi (#268) +- (package) @cloudcmd/clipboard v2.0.0 +- (package) stylelint v13.0.0 +- (package) emitify v4.0.1 +- (package) nyc v15.0.0 +- (package) eslint-plugin-node v11.0.0 + + +2019.12.21, v14.2.1 + +feature: +- (package) for-each-key v2.0.0 +- (package) jonny v3.0.0 +- (package) jaguar v6.0.0 +- (package) ponse v4.0.0 +- (package) ponse v3.5.1 +- (package) memfs v3.0.1 +- (package) url-loader v3.0.0 +- (package) nodemon v2.0.1 +- (package) stylelint v12.0.0 + + +2019.11.15, v14.2.0 + +feature: +- (cloudcmd) add CLOUDCMD_PREFIX +- (package) chalk v3.0.0 +- (package) eslint-plugin-putout v3.0.0 +- (package) madrun v5.0.0 +- (package) putout v7.0.0 +- (package) madrun v4.0.0 +- (package) try-to-catch v2.0.0 + + +2019.10.16, v14.1.2 + +fix: +- (madrun) client test command: test:client command (#260) + +feature: +- (package) @cloudcmd/fileop v4.0.0 +- (package) inly v4.0.0 +- (package) onezip v4.0.0 +- (package) open v7.0.0 +- (package) multi-rename v2.0.0 +- (package) shortdate v2.0.0 + + +2019.10.09, v14.1.1 + +feature: +- (package) @cloudcmd/fileop v3.0.0 +- (package) @cloudcmd/move-files v3.0.0 +- (package) copymitter v5.0.0 + + +2019.10.02, v14.1.0 + +feature: +- (view) add support of webm (#256) + + +2019.09.25, v14.0.2 + +fix: +- (client) change directory with enabled dirStorage (#255) + + +2019.09.25, v14.0.1 + +fix: +- (cloudcmd) wrong editor root on multi instance + +feature: +- (package) deepword v7.0.0 +- (cloudcmd) rm now (zeit/micro/issues/377) + + +2019.09.22, v14.0.0 + +feature: +- (operation) show progress bar on first operation (#253) +- (package) pullout v4.0.0 +- (package) console-io v11.0.0 +- (package) flop v7.0.0 +- (package) restbox v2.0.0 +- (package) restafary v8.0.0 +- (package) nomine v4.0.0 +- (cloudcmd) drop support of node < 10 +- (cloudcmd) remove --progress option, make always enabled + + +2019.09.21, v13.4.2 + +fix: +- (terminal) on -> onKey + + +2019.09.20, v13.4.1 + +feature: +- (package) @cloudcmd/olark v3.0.0 +- (package) format-io v2.0.0 +- (package) limier v3.0.0 +- (package) currify v4.0.0 +- (package) limier v2.0.1 +- (package) load.js v3.0.0 +- (package) @cloudcmd/create-element v2.0.0 +- (package) supermenu v3.0.0 +- (package) smalltalk v4.0.0 +- (package) @cloudcmd/modal v2.0.0 +- (package) putout v6.0.0 +- (package) stylelint-config-standard v19.0.0 +- (package) stylelint v11.0.0 +- (package) markdown-it v10.0.0 +- (package) rm version-io +- (package) fullstore v2.0.2 +- (package) wraptile v3.0.0 +- (package) rendy v3.0.0 +- (package) eslint-plugin-node v10.0.0 +- (package) restafary v7.0.0 + + +2019.09.03, v13.4.0 + +feature: +- (view) add support of pdf +- (package) madrun v3.0.1 + + +2019.08.28, v13.3.0 + +fix: +- feature(client) remove legacy suffix, use modules as is +- (client) rm additional dialog +- (user-menu) putout path +- (edit-names) hide +- (vim) find + +feature: +- (cloudcmd) decrease bundle size: disable convertion to es5 +- (client) remove legacy suffix, use modules as is +- (package) es6-promisify v6.0.2 +- (menu) rm mute: has no sense with new ponse headers +- (markdown) move out parse to worker + + +2019.08.22, v13.2.1 + +fix: +- (buffer) copy, cut +- (key) chrome event double pass +- (user-menu) processing menu item run error + +feature: +- (user-menu) rm path + + +2019.08.20, v13.2.0 + +fix: +- (menu) autoplay on download in firefox +- (dom) getCurrentData + +feature: +- (user-menu) improve error handling +- (package) eslint-plugin-putout v2.0.0 + + +2019.08.16, v13.1.0 + +fix: +- (user-menu) hide load on error +- (key) keys block + +feature: +- (cloudcmd) add ability to remember position of current file on reload +- (madrun) disable web workers, while testing +- (user-menu) speed up user menu parsing with help of worker threads +- (user-menu) add ability to used EcmaScript Modules, improve error handling +- (server) add compress: speed up client side load + + +2019.08.14, v13.0.1 + +fix: +- (cloudcmd) rm --user-menu: always enabled + +feature: +- (package) rimraf v3.0.0 + + +2019.08.14, v13.0.0 + +fix: +- (set-listeners) can not continue first error operation error +- (view) getMediaElement: play video/audio + +feature: +- (cloudcmd) only user menu on f2 +- (cloudcmd) remove plugins +- (package) putout v5.2.1 +- (package) style-loader v1.0.0 + + +2019.08.02, v12.6.3 + +fix: +- (operation) first copy after startup fails (close #251) +- (key) chrome keydown event double pass +- (client) load +- (cloudcmd) server start when importListen enabled + +feature: +- (cloudcmd) simplify lint +- (package) markdown-it v9.0.0 +- (package) deepmerge v4.0.0 +- (package) yaspeller v6.0.0 +- (package) css-loader v3.0.0 +- (babel) remove unused @babel/plugin-syntax-dynamic-import +- (cloudcmd) rm Promise polyfill +- (package) rm Object.assign polyfill + + +2019.06.06, v12.6.2 + +fix: +- (cloudcmd) config: save -> write (#247) + +feature: +- (package) remove file-loader +- (package) url-loader v2.0.0 + + +2019.06.04, v12.6.1 + +fix: +- (config) configManager: totally move away from singletone + + +2019.05.31, v12.6.0 + +feature: +- (config-manager) add (#208) +- (package) add support of cwd in TerminalRun with help of gritty v4.7.0 +- (user-menu) add ability to ignore private methods + + +2019.05.28, v12.5.0 + +feature: +- (user-menu) add Compare Directories (#220) + + +2019.05.27, v12.4.0 + +fix: +- (terminal-run) resolve before close + +feature: +- (terminal-run) add ability to resolve exit code + + +2019.05.24, v12.3.2 + +fix: +- (user-menu) F1 and F keys overlapping +- (select-by-pattern) crash + + +2019.05.24, v12.3.1 + +fix: +- (cloudcmd) copy + + +2019.05.24, v12.3.0 + +fix: +- (user-menu) prefix (#244) +- (dom) renameCurrent: try-to-promise RESTful.mv + +feature: +- (user-menu) hide scroll when small amount of items +- (user-menu) add ability to run in mobile devices +- (upload) improve style +- (user-menu) imrove error output +- (user-menu) add default user menu +- (dialog) cancel -> tryToCatch +- (user-menu) add default option: create user menu +- (user-menu) add error handling +- (user-menu) add ability to navigate with j, k +- (cloudcmd) deprecate plugins + + +2019.05.13, v12.2.0 + +fix: +- feature(npmignore) add fixture.json +- (operation) set-listeners: alert: noCancel -> cancel +- (cloudcmd) different title + +feature: +- (key) add ability to rename file with Shift + F6 +- (user-menu) add (#221) +- (package) clean-css-loader v2.0.0 +- (package) edward v11.0.0 +- (npmignore) add fixture.json +- (package) dword v11.0.0 +- (package) smalltalk v3.4.0 +- (package) eslint v6.0.0-alpha +- (package) eslint-plugin-node v9.0.1 +- (config) speed up load: series -> parallel +- (cloudcmd) avoid service worker reoload scripts in dev mode +- (package) putout v4.23.0 +- (package) nyc v14.0.0 + + +2019.04.15, v12.1.0 + +fix: +- (heroku) app: add "}" (#236) + +feature: +- (edit-names) add bulk rename (#231) +- (package) stylelint v10.0.0 + + +2019.04.04, v12.0.2 + +fix: +- (listeners) any touch open file (#235) + + +2019.04.04, v12.0.1 + +fix: +- (listeners) unable to navigate into folders (#235) + + +2019.04.01, v12.0.0 + +fix: +- feature(cloudcmd) split prefix and prefixSocket finally + +feature: +- (cloudcmd) drop support of beautify, minify +- (cloudcmd) improved progress of file operations +- (cloudcmd) split prefix and prefixSocket finally +- (cloudcmd) view file on double click or enter +- (cloudcmd) add ability to change directory using F3 + + +2019.03.27, v11.8.6 + +fix: +- (operation) progress +- (terminal) rm IntersectionObserver handling (xtermjs/xterm.js#1929) + +feature: +- (package) opn -> open v6.0.0 +- (package) remove @babel/plugin-proposal-object-rest-spread + + +2019.02.20, v11.8.5 + +fix: +- (plugins) set content-type (#230) + +feature: +- (package) putout v4.0.0 +- (package) madrun v2.0.0 + + +2019.02.15, v11.8.4 + +fix: +- (terminal) chrome does not display anything on first open (#214) +- (rest) can not read ###files (#223) +- (help) add --terminal-auto-restart +- (cloudcmd) read root from custom config (#224) +- refactor(view) viewImage: href, prefixURL -> prefixURL +- docs(help) improve English translation of HELP.md (#211) + +feature: +- (package) tar-stream v2.0.0 +- (package) redrun -> madrun +- (package) unionfs v4.0.0 +- (package) package-json v6.0.0 +- (package) add @putout/eslint-config +- (package) tape -> supertape +- (package) add putout +- (package) add eslint-plugin-tape +- (package) file-loader v3.0.1 +- (package) css-loader v2.0.1 +- (package) kebabToCamelCase -> just-pascal-case +- (package) deepmerge v3.0.0 + + +2018.12.04, v11.8.3 + +fix: +- test(export) defaultConfig: prefix +- (edit) prefix (#207) +- feature(package) :lint: add eslint-remove-line + +feature: +- (modules) socket.io v2.2.0 +- (package) clear-module -> mock-require +- (package) auto-globals v1.7.0 +- (package) fix:lint: add eslint-remove-line +- (cloudcmd) sinon, sinon-called-with-diff -> @cloudcmd/stub + + +2018.11.22, v11.8.2 + +fix: +- (Dockerfile) WORKDIR (#182) + + +2018.11.14, v11.8.1 + +fix: +- (validate) corruption of config when root not found + +feature: +- (package) pullout v3.0.0 +- (validate) root: do not validate dropbox root + + +2018.11.09, v11.8.0 + +fix: +- (dialog) noFiles: reject on close + +feature: +- (package) add dropbox support +- (server) add graceful shutdown +- (package) sinon-called-with-diff v3.0.0 + + +2018.11.01, v11.7.1 + +fix: +- (cloudcmd) register service worker on http connection (#203) +- refactor(cloudcmd) PREFIX -> prefix +- docs(help) example: prefix -> express mount point + +feature: +- (package) criton v2.0.0 +- (package) eslint-plugin-node v8.0.0 + + +2018.10.25, v11.7.0 + +fix: +- feature(cloudcmd) add ability to set prefix for web sockets connections with --prefix-socket (#200) + +feature: +- (cloudcmd) add ability to set prefix for web sockets connections with --prefix-socket (#200) +- (package) deepword v5.0.0 +- (package) dword v9.0.0 +- (package) edward v9.0.0 +- (package) console-io v10.0.0 +- (package) ponse v3.0.0 +- (package) files-io v3.0.0 + + +2018.10.23, v11.6.0 + +feature: +- (cloudcmd) add support of express mounting point (#200) + + +2018.10.23, v11.5.4 + +fix: +- docs(changelog) rm + +feature: +- (package) supermenu v2.1.2 +- (npmignore) add ai, cdr, eps + + +2018.10.19, v11.5.3 + +feature: +- (package) console-io v9.0.0 +- (npmignore) add fixture + + +2018.10.19, v11.5.2 + +fix: +- (server) open error: exit -> warning (#196, #197, #198) + + +2018.10.17, v11.5.1 + +fix: +- (contact) load + +feature: +- (olark) bower -> npm + + +2018.10.16, v11.5.0 + +feature: +- (config) add ability to remove auth change from config with help of --config-auth flag + + +2018.10.16, v11.4.1 + +fix: +- (Docker) cloudcmd_open false (#197) + +feature: +- (package) sinon v7.0.0 + + +2018.10.12, v11.4.0 + +feature: +- (cloudcmd) add env variable CLOUDCMD_OPEN + + +2018.10.12, v11.3.1 + +fix: +- (server) crash on open error (#196) + +feature: +- (cloudcmd) add unhandledRejection listener +- (exit) add ability to receive error as argument + + +2018.10.11, v11.3.0 + +feature: +- (img) add file-link, directory-link +- (cloudcmd) show size as for links +- (cloudcmd) readify: add support of links +- (package) nomine v3.0.0 +- (package) restafary v5.0.0 +- (package) flop v6.0.0 +- (package) currify v3.0.0 + + +2018.10.04, v11.2.3 + +feature: +- (package) rm unused join-io +- (package) apart v2.0.0 +- (server) callback -> await + + +2018.09.28, v11.2.2 + +fix: +- (cloudcmd) prefix with leading slash (#195) + + +2018.09.28, v11.2.1 + +fix: +- (sw) cache favicon.ico from root (#194) + +feature: +- (package) onezip v3.0.0 + + +2018.09.28, v11.2.0 + +feature: +- (package) inly v3.0.0 +- (package) jaguar v5.0.0 +- (cloudcmd) add --terminal-auto-restart + + +2018.09.27, v11.1.0 + +feature: +- (package) redrun v7.0.0 +- (package) @cloudcmd/read-files-sync v2.0.0 +- (cloudcmd) --terminal-command: command to run in terminal (shell by default) +- (package) gritty v4.0.0 +- (package) console-io v8.0.0 + + +2018.09.26, v11.0.0 + +feature: +- (package) babel-eslint v10.0.0 +- (package) deepword v4.0.0 +- (package) edward v8.0.0 +- (package) dword v8.0.0 +- (package) restafary v4.0.0 +- (package) flop v5.0.0 +- (package) @cloudcmd/fileop v2.0.0 +- (package) @cloudcmd/move-files v2.0.1 +- (package) copymitter v4.0.2: add ability to copy symlinks (#191) +- (config) disable online by default +- (config) enable open by default +- (package) set engine to node v8.0.0 LTS +- (package) package-json v5.0.0 +- (server) drop support of VCAP_APP_PORT +- (cloudcmd) showUpdateInfo: rm rendy +- (package) squad v3.0.0 + + +2018.09.21, v10.8.2 + +fix: +- (distribute) export: config +- (sw) register: null -> stub + + +2018.09.20, v10.8.1 + +fix: +- (view) change elements position when open image + + +2018.09.19, v10.8.0 + +feature: +- (package) load -> load.js + @cloudcmd/create/element +- (cloudcmd) rm jquery + + +2018.09.14, v10.7.0 + +fix: +- (cloudcmd) onUpdateFound: doubled prefix for cloudcmd.common.js (#188) + +feature: +- (view) fancybox -> @cloudcmd/modal + + +2018.09.10, v10.6.0 + +fix: +- (view) title: xss +- (sw) navigation error + +feature: +- (events) add ability to remove all added listeners +- (cloudcmd) add ability update cloudcmd without page reload +- (cloudcmd) add --show-file-name to add file name title in view and edit (#183) + + +2018.09.08, v10.5.3 + +fix: +- (webpack) css: font resource ignores prefix setting (#185) +- (sw) no auth dialog when serve by service worker +- (sw) http auth + +feature: +- (package) babel-loader v8.0.0 +- (package) babel v7.0.0 +- (package) table v5.0.2 +- (package) style-loader v0.23.0 +- (package) nyc v13.0.1 +- (package) babel-eslint v9.0.0 + + +2018.08.25, v10.5.2 + +fix: +- (konsole) try to load console.js when console is disabled + + +2018.08.25, v10.5.1 + +fix: +- (log) makeColor: mac os + +feature: +- (export) add config send log + + +2018.08.23, v10.5.0 + +fix: +- (edit-file) multiple f4 +- (config) init: load when configDialog disabled +- (name-size-date) .name width +- (listeners) isNoCurrent: can not go to root when root is empty +- (client) parallel -> series: route + +feature: +- (distribute) add ability to import config from remote export server +- (package) file-loader v2.0.0 +- (package) watch:lint:server +- (package) add watch:test:server +- (package) yaspeller v5.0.0 +- (package) style-loader v0.22.0 +- (package) serviceworker-webpack-plugin v1.0.1 + + +2018.07.18, v10.4.1 + +fix: +- (img) loading: svg minify + + +2018.07.17, v10.4.0 + +fix: +- (sw) cache of 401 +- (polyfill) scrollIntoViewIfNeeded in firefox + +feature: +- (package) engines: node v4.5.0 +- (package) eslint-plugin-node v7.0.0 +- (package) @cloudcmd/clipboard v1.0.2 +- (package) rm unused html-webpack-exclude-assets-plugin +- (package) gritty v3.0.0 +- (package) optimize-css-assets-webpack-plugin v5.0.0 +- (package) @cloudcmd/clipboard v1.0.1 +- (package) clear-module v3.0.0 +- (package) smalltalk v3.1.0 +- (package) css-loader v1.0.0 +- (Dockerfile) mhart/alpine-node -> node:alpine + + +2018.07.02, v10.3.2 + +fix: +- (terminal) prevent init when config disabled +- (operation) next current file after delete +- (key) vim: do not react on navigation after view hide + +feature: +- (package) codegen.macro v3.0.0 + + +2018.06.25, v10.3.1 + +fix: +- (npmignore) rm dist*/modules + +feature: +- (package) eslint v5.0.0 + + +2018.06.22, v10.3.0 + +fix: +- (operation) set next file current when can not delete + +feature: +- (webpack) minimize service worker size +- (terminal) move out terminal.css from view.css +- (package) fast-async v7.0.6 +- (cloudcmd) import -> load.js +- (load-module) add + + +2018.06.21, v10.2.3 + +fix: +- (cloudcmd) env variables override (#179) +- (sw) register when prefix changed + +feature: +- (upload-files) add ability to show error message +- (gitignore) add jquery-mouse-wheel + + +2018.06.15, v10.2.2 + +fix: +- (config) set file mode permissions to readable only by current user (#61) + + +2018.06.13, v10.2.1 + +fix: +- (style) .fm: scrolling on ios + +feature: +- (dom) touchstart: set passive listener +- (package) format-io v1.0.0 +- (package) add domtokenlist-shim from npm +- (polyfill) add scroll-into-view-if-needed polyfill from npm + + +2018.06.11, v10.2.0 + +feature: +- (cloudcmd) add ability to set current file closer to removed files +- (client) add ability to clear localStorage on logOut +- (package) sinon v6.0.0 + + +2018.06.09, v10.1.2 + +fix: +- (dom) saveDataToStorage, getDataFromStorage: localStorage option check (#177) + + +2018.06.08, v10.1.1 + +fix: +- (menu) initial position + + +2018.06.07, v10.1.0 + +fix: +- (operation) deleteSilent: refresh: on error -> always +- (edit-file-vim) check is file changed on close +- (sw) "only-if-cached" can be set only with "same-origin" mode + +feature: +- (edit-names-vim) add +- (package) pullout v2.0.0 + + +2018.06.04, v10.0.3 + +fix: +- (index) zoom on tap +- (client) logout: servicer worker: unregister + +feature: +- (package) webpack-cli v3.0.1 +- (rest) add memory info +- (package) babel v7 +- (package) nyc v12.0.1 +- (cloudcmd) pullout/legacy -> pullout +- (package) nomine v2.0.0 + + +2018.05.29, v10.0.2 + +fix: +- (listeners) copyPath +- (font) copy path + + +2018.05.29, v10.0.1 + +fix: +- (font) terminal icon + + +2018.05.25, v10.0.0 + +feature: +- (cloudcmd) --one-panel-mode -> --one-file-panel +- (cloudcmd) clear storage -> copy path (#173) +- (config) rm option: htmlDialogs +- (cloudcmd) add service worker +- (config) rm option: cache +- (cloudcmd) rm option: localStorage + + +2018.05.24, v9.6.0 + +fix: +- (docker) node v10.1 +- (current-file) getParrentDirPath: path contains "+++" + +feature: +- (cloudcmd) rm global window.exec +- (package) rm vulnerable fresh-require +- (package) rm vulnerable nsp +- (terminal) set fontFamily +- (modules) socket.io v2.1.1 + + +2018.05.15, v9.5.0 + +fix: +- (server) mv: rename file +- (cloudcmd) choose +- (konsole) Ctrl + P: paste current directory path +- (operation) set moveFn to RESTful.mv on disconnect + +feature: +- (cloudcmd) deprecate localStorage +- (key) add ability to copy path with help of Ctrl + p +- (env) return boolean only +- (cloudcmd) move out dist from route + + +2018.05.08, v9.4.0 + +fix: +- (name-size) margin-right: 0 + +feature: +- (cloudcmd) deprecate --one-panel-mode in favour --one-file-panel +- (cloudcmd) add ability to show progress on move (#157) +- (package) rm checkup +- (package) wraptile v2.0.0 +- (package) ponse v2.0.0 +- (package) onezip v2.0.0 +- (package) jaguar v4.0.0 +- (package) files-io v2.0.0 +- (package) inly v2.0.0 + + +2018.05.01, v9.3.2 + +fix: +- (cloudcmd) cyrillic symbols in names +- (operation) update file list after error on copy + +feature: +- (package) clean-css-loader v1.0.1 +- (package) copymitter v3.0.0: improved copy accuracy (#157) + + +2018.04.30, v9.3.1 + +fix: +- (listeners) onPathElementClick: empty space (#171) + +feature: +- (package) sinon v5.0.1 +- (travis) node_js: add 10 +- (docker) node v10 + + +2018.04.27, v9.3.0 + +feature: +- (package) smalltalk: bower -> npm +- (modules) menu-io -> supermenu +- (package) rendy v2.0.0 + + +2018.04.25, v9.2.0 + +fix: +- (client) when password changed console and terminal can not authenticate when auth enabled + +feature: +- (cloudcmd) add ability to use not only alphabet and number symbols (#167) + + +2018.04.23, v9.1.6 + +fix: +- (cloudfunc) XSS vulnerability: html in file name: allows executing malicious javascript code in the user's browser + +feature: +- (entity) add " +- (package) add prewisdom + + +2018.04.19, v9.1.5 + +fix: +- (terminal) rows and cols +- (wepback) js: devtoolModuleFilenameTemplate +- (now) files: add .webpack + +feature: +- (package) style-loader v0.21.0 +- (travis) node_js: rm 6 + + +2018.04.17, v9.1.4 + +fix: +- (download) download files with "#" in name (#80) + + +2018.04.16, v9.1.3 + +fix: +- (view) showImage: left key button in image view (#164) +- (edit-file-vim) Shift + Esc: task manager + + +2018.04.12, v9.1.2 + +fix: +- (operations) for-each-key v1.0.1: update file list after removing file + +feature: +- (webpack) deepmerge -> webpack-merge +- (webpack) split config to: js, html and css + + +2018.04.10, v9.1.1 + +fix: +- (columns) name-size in firefox (#162) + +feature: +- (package) add for-each-key from npm +- (modules) socket.io v2.1.0 + + +2018.04.02, v9.1.0 + +fix: +- (client) authCheck: can not connect via web sockets when auth disabled (#160) + +feature: +- (cloudcmd) add --cache cli option + + +2018.03.30, v9.0.0 + +fix: +- (cloudcmd) --no-prefix +- (client) goToParentDir +- (query) portrait on iphone 6 firefox + +feature: +- (cloudcmd) showKeysPanel -> keysPanel +- (package) dword v7.0.0 +- (package) deepword v3.0.0 +- (package) edward v7.0.0 +- (package) console-io v7.0.0 +- (cloudcmd) drop support of gritty < v2 +- (config) auth +- (cloudcmd) spero, ishtar, salam, remedy, omnes -> fileop +- (for-each-key) add +- (package) html-webpack-exclude-assets-plugin v0.0.7 +- (query) add support if iphone 6 landscape + + +2018.03.24, v8.5.2 + +fix: +- (cloudcmd) rm redundant dir 1 + + +2018.03.24, v8.5.1 + +fix: +- (operation) progress of copy/move (#155) + + +2018.03.20, v8.5.0 + +fix: +- (rest) jonny: node v4 support + +feature: +- (cloudcmd) add --sync-console-path +- (package) console-io v6.0.1 +- (package) html-webpack-exclude-assets-plugin v0.0.6 +- (package) html-webpack-plugin v3.0.7 +- (cloudcmd) add emitter +- (package) os-homedir -> os.homedir + + +2018.03.16, v8.4.1 + +fix: +- (rest) moveFiles: could not rename (#150) + + +2018.03.14, v8.4.0 + +feature: +- (name-size-date) improve view +- (columns) add name-size (#139) +- (package) redrun v6.0.0 +- (package) url-loader v1.0.1 +- (app) add CLOUDCMD_COLUMNS + + +2018.03.02, v8.3.0 + +fix: +- (route) buildIndex: getIndexPath +- (listeners) pop: change #hash + +feature: +- (cloudcmd) --columns: add ability to set visible columns (#146) +- (package) html-webpack-plugin v3.0.4 +- (package) limier v2.0.0 +- (package) webpack v4.0.0 +- (package) rm jscs, jshint +- (package) jonny v2.0.3 +- (package) flop v4.0.0 +- (package) add mock-require, clear-module + + +2018.02.19, v8.2.2 + +fix: +- (directory) upload files with help of dragndrop when root directory is empty (#145) + +feature: +- (package) stylelint v9.0.0 +- (package) squad v2.0.0 +- (package) sinon-called-with-diff v2.0.0 +- (package) tryrequire v2.0.1 +- (package) try-catch v2.0.0 +- (package) eslint-plugin-node v6.0.0 +- (package) es6-promisify v6.0.0 +- (package) style-loader v0.20.1 + + +2018.01.23, v8.2.1 + +fix: +- (operation) paste files when current file is ".." (#142) + +feature: +- (bower) jquery v3.3.1 + + +2018.01.16, v8.2.0 + +fix: +- (config) showConfig +- (now) add quotes + +feature: +- (config) username, password: add autocomplete +- (config) div -> form +- (package) mock-require v3.0.1 + + +2017.12.08, v8.1.3 + +fix: +- (view) Info.files -> Info +- (config) patch +- (fancybox) _afterZoomIn: hide + +feature: +- (edit-file-vim) setOption -> setKeyMap +- (package) stylelint-config-standard v18.0.0 +- (package) nsp v3.1.0 + + +2017.10.23, v8.1.2 + +fix: +- (operation) update panel after error on delete files +- (operation) noFilesCheck: false positive: files selected but current is ".." + + +2017.10.19, v8.1.1 + +fix: +- (menu) when click on ".." show full menu + +feature: +- (bower) smalltalk v2.5.1 +- (package) lint:js:eslint:client -> lint:client + + +2017.10.19, v8.1.0 + +fix: +- (menu) when click on ".." show full menu +- (menu) show menu on F9 when current is ".." +- (menu) title: Menu -> Cloud Commander +- (menu) uploadTo: when error - do nothing, everything already done + +feature: +- (package) lint:js:eslint:client -> lint:client +- (cloud) filepicker v2 +- (client) log: return str + + +2017.10.13, v8.0.5 + +feature: +- (polyfill) clean up old polyfills +- (events) rm unused dispatch + + +2017.10.10, v8.0.4 + +feature: +- (package) deepmerge v2.0.0 +- (bower) smalltalk v2.5.0 + + +2017.10.06, v8.0.3 + +fix: +- (operation) deleted file do not disappear + + +2017.10.06, v8.0.2 + +fix: +- (operation) delete: check no files after ask + +feature: +- (package) url-loader v0.6.1 +- (package) style-loader v0.19.0 + + +2017.10.02, v8.0.1 + +fix: +- (package) get back file-loader + + +2017.10.02, v8.0.0 + +feature: +- (cloudcmd) middleware: password: plain -> encrypted (#136) +- (package) coveralls v3.0.0 + + +2017.09.29, v7.9.0 + +feature: +- (cloudcmd) add --confirm-move +- (cloudcmd) add --confirm-copy +- (template) add: read all templates on start +- (package) sinon v4.0.0 + + +2017.09.25, v7.8.0 + +feature: +- (listeners) add ability to move files via shift + drag + + +2017.09.22, v7.7.3 + +feature: +- (bower) smalltalk v2.4.2 + + +2017.09.22, v7.7.2 + +feature: +- (package) spead up directory upload: philip: bower -> npm + + +2017.09.18, v7.7.1 + +fix: +- (operation) RESTful.remove -> RESTful.delete (#132) + +feature: +- (package) babel-preset-2015 -> babel-preset-env + + +2017.09.12, v7.7.0 + +feature: +- (cloudcmd) add support of CLOUDCMD_VIM env variable + + +2017.09.11, v7.6.0 + +feature: +- (vim) add find support with: "/", "n" and "N" +- (package) yaspeller v4.0.0 + + +2017.09.08, v7.5.2 + +fix: +- (config) vim: "false" -> false + + +2017.09.08, v7.5.1 + +fix: +- (config) vim enabled by default +- (cloudcmd) --vim + + +2017.09.08, v7.5.0 + +feature: +- (vim) add hot keys +- (key) add ability to extract archives with Alt + F9 +- (key) add ability to pack files with Alt + F5 + + +2017.09.04, v7.4.0 + +feature: +- (key) add ability to extract archives with Alt + F9 +- (key) add ability to pack files with Alt + F5 +- (package) docker:rm-old: --cam -> -P +- (package) scripts: wisdom:type: add support of wisdom 6 +- (package) docker:rm-old: --parallel -> --calm +- (package) wisdom: rm docker:rm-old + + +2017.08.29, v7.3.2 + +fix: +- (operation) pack in old packer type after changin packer without reload + +feature: +- (appveyor) add terminal +- (cloudcmd) add now demo + + +2017.08.14, v7.3.1 + +fix: +- (cloudcmd) empty string in CLOUDCMD_NAME and CLOUDCMD_ROOT + + +2017.08.14, v7.3.0 + +feature: +- (cloudcmd) add support of CLOUDCMD_ONE_PANEL_MODE (#64) +- (cloudcmd) add support of CLOUDCMD_ROOT (#64) +- (travis) add node v8 condition +- (cloudcmd) add ability to build docker images with help of travis + + +2017.08.11, v7.2.2 + +fix: +- (route) buildIndex: no index.html + +feature: +- (Dockerfile) set package-lock false +- (dockerignore) yarn-error +- (package) sinon v3.0.0 + + +2017.07.31, v7.2.1 + +fix: +- (config) aditional panel +- (view) no scrallbar on help +- (package) docker:push:latest: add (#127) + + +2017.07.28, v7.2.0 + +feature: +- (cloudcmd) add support of env variable CLOUDCMD_CONSOLE +- (contact) add ability to hide contact button with --no-contact (#125) + + +2017.07.27, v7.1.1 + +fix: +- (view) config: additional panel at the bottom +- (view) terminal: set .view height + + +2017.07.27, v7.1.0 + +fix: +- (route) showKeysPanel +- (config) additional bar: .view: rm height: 100% +- (view) key binding after click outside the modal window + +feature: +- (cloudcmd) --name: add ability to set tab name in web browser +- (Dockerfile) decrease image size: clean npm cache after install +- (gitignore) add yarn-error.log +- (package) stylelint-config-standard v17.0.0 +- (package) stylelint v8.0.0 + + +2017.07.14, v7.0.2 + +fix: +- (cloudcmd) node v4 support: currify, pullout +- (cloudcmd) socket.io: support of node < 4 (#121) + +feature: +- (package) deepword v2.0.0 +- (package) dword v6.0.0 +- (package) edward v6.0.0 +- (package) restafary v3.0.0 +- (package) remedy v3.0.0 +- (gitignore) add yarn.lock +- (package) flop v3.0.0 +- (package) join-io v2.0.0 +- (package) add eslint-plugin-node +- (package) console-io v5.0.0 +- (npmignore) add css, html +- (auth) add currify +- (cloudcmd) require es2015 versions of packages +- (package) opn v5.1.0 +- (package) http-auth v3.2.3 +- (package) package-json v4.0.1 +- (package) chalk v2.0.1 +- (cloudcmd) rm support of node.js < 4.0.0 +- (cloudcmd) rm config option: minify +- (route) rm minify +- (package) extract-text-webpack-plugin v3.0.0 +- (package) socket.io v2.0.3 + + +2017.07.12, v7.0.1 + +fix: +- (cloudcmd) node v4 support: currify, pullout + +feature: +- (package) console-io v5.0.0 +- (npmignore) add css, html + + +2017.07.12, v7.0.0 + +feature: +- (auth) add currify +- (cloudcmd) require es2015 versions of packages +- (package) opn v5.1.0 +- (package) http-auth v3.2.3 +- (package) package-json v4.0.1 +- (package) chalk v2.0.1 +- (cloudcmd) rm support of node.js < 4.0.0 +- (cloudcmd) rm config option: minify +- (route) rm minify +- (package) extract-text-webpack-plugin v3.0.0 + + +2017.07.14, v6.15.5 + +fix: +- (cloudcmd) socket.io: support of node < 4 (#121) + + +2017.07.10, v6.15.4 + +feature: +- (bower) smalltalk v2.4.1 (#117) +- (package) ishtar v2.0.0 +- (package) remedy v2.0.0 +- (package) spero v2.0.0 +- (package) rm mollify +- (css) add minification build step +- (webpack) loaders -> rules +- (package) dword v5.0.0 +- (package) edward v5.0.0 +- (package) console-io v4.0.0 + + +2017.06.26, v6.15.3 + +fix: +- (client) save directory path and file list to storage when dirStorage disabled +- (view) show: close view on ESC + + +2017.06.22, v6.15.2 + +fix: +- (konsole) when disabled error occures on second call +- (config) when disabled error occures on second call +- (terminal) when disabled, error occures on second call + +feature: +- (package) heroku-postbuild -> heroku-postbuild, postheroku-postbuild +- (package) webpack v3.0.0 + + +2017.06.14, v6.15.1 + +fix: +- (client) rigth -> right +- (client) baseInit: init both panels in OnePanelMode (#116) +- (Dockerfile) ENTRYPOINT: command -> executable + +feature: +- (modules) socket.io v2.0.3 +- (package) eslint v4.0.0 +- (app) add auth env variables + + +2017.06.06, v6.15.0 + +fix: +- (cloudcmd) editor: choose -> env + +feature: +- (show-config) add ability to show config values with --show-config +- (cloudcmd) add CLOUDCMD_USERNAME +- (cloudcmd) add CLOUDCMD_PASSWORD +- (help) add CLOUDCMD_AUTH +- (modules) socket.io v2.0.2 +- (package) nyc v11.0.2 +- (gitignore) add package-lock.json +- (package) docker:rm: add -f: force +- (travis) node_js: 7 -> 8 +- (dockerignore) reduce size of image +- (package) scripts: docker:tag +- (npmignore) add bower.json, manifest.yml +- (Dockerfile) Entrypoint: set absolute: add ability to override WorkDir + + +2017.05.25, v6.14.4 + +fix: +- (package) put fullstore in dependencies + +feature: +- (bower) smalltalk v2.4.0 +- (package) rm unused version-io + + +2017.05.22, v6.14.3 + +fix: +- (client) dirStorage: save date + +feature: +- (bower) philip v1.3.7 +- (cloudcmd) store -> fullstore + + +2017.05.18, v6.14.2 + +fix: +- (edit-file) show editor when access denied + + +2017.05.18, v6.14.1 + +feature: +- (edit-file-vim) add ability to reuse edit-file: minimize file size + + 2017.05.17, v6.14.0 fix: @@ -3168,7 +6766,7 @@ fix: - (rest) onDelete: func(null, body) -> func - (rest) onStat: add var - (cloudcmd) change index path -- (server) start: url -> URL +- (server) start: url -> PREFIX - (server) start: SSLPort -> sslPort - (server) start: Port -> port - (dom) getCurrentDirPath: "," -> ";" @@ -4180,7 +7778,7 @@ with clicks on files. - Removed allowed from cache property in config. - Added ability to hide "Upload To" menu item if -no storage modules setted up in modules.json. +no storage modules set up in modules.json. - From now any file minifying only if last modified time was changed. @@ -4386,7 +7984,7 @@ in any position in anyLoadOnLoad function. - Added chainable to Cache object in DOM. - Changed default ip to null so IP would be geted from -config.json only if it setted up. +config.json only if it set up. - Fixed bug with starting node from other then projects dir. @@ -4695,7 +8293,7 @@ time was possible. - Fixed bug with undefined size on root directory of Cloud Commander. Now Cloud Commander writes size 0, if can't get size, and besides will -setted b char: "0b". +set b char: "0b". - Added supporting of Russian language in directory names. diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index ef4f0767..00000000 --- a/Dockerfile +++ /dev/null @@ -1,20 +0,0 @@ -FROM node -MAINTAINER Coderaiser - -RUN mkdir -p /usr/src/app -WORKDIR /usr/src/app - -COPY package.json /usr/src/app/ - -RUN npm install --production && \ - npm i gritty - -COPY . /usr/src/app - -ENV cloudcmd_terminal true -ENV cloudcmd_terminal_path gritty - -EXPOSE 8000 - -ENTRYPOINT ["bin/cloudcmd.js"] - diff --git a/Dockerfile.alpine b/Dockerfile.alpine deleted file mode 100644 index 1ae6021d..00000000 --- a/Dockerfile.alpine +++ /dev/null @@ -1,24 +0,0 @@ -FROM mhart/alpine-node -MAINTAINER Coderaiser - -RUN mkdir -p /usr/src/app -WORKDIR /usr/src/app - -COPY package.json /usr/src/app/ - -RUN npm install --production && \ - apk update && \ - apk add --no-cache bash make g++ python && \ - npm i gritty && \ - apk del make g++ python && \ - rm -rf /usr/include /tmp/* /var/cache/apk/* - -COPY . /usr/src/app - -ENV cloudcmd_terminal true -ENV cloudcmd_terminal_path gritty - -EXPOSE 8000 - -ENTRYPOINT ["bin/cloudcmd.js"] - diff --git a/HELP.md b/HELP.md index ff176d9a..2967f0d0 100644 --- a/HELP.md +++ b/HELP.md @@ -1,190 +1,282 @@ -# Cloud Commander v6.14.0 +# Cloud Commander v19.19.1 -### [Main][MainURL] [Blog][BlogURL] Live(![Heroku][Heroku_LIVE_IMG] [Heroku][HerokuURL]) +### [Main][MainURL] [Blog][BlogURL] [Demo][DemoURL] [Deploy](#deploy) -[MainURL]: http://cloudcmd.io "Main" -[BlogURL]: http://blog.cloudcmd.io "Blog" -[HerokuURL]: http://cloudcmd.herokuapp.com/ "Heroku" -[HEROKU_LIVE_IMG]: https://status-io.cloudcmd.io/host/cloudcmd.herokuapp.com/img/txt.png "Heroku" +[MainURL]: https://cloudcmd.io "Main" +[BlogURL]: https://blog.cloudcmd.io "Blog" +[SupportURL]: https://patreon.com/coderaiser "Patreon" +[DemoURL]: https://cloudcmd-zdp6.onrender.com/ +[DWORD]: https://github.com/cloudcmd/dword "Editor based on CodeMirror" +[EDWARD]: https://github.com/cloudcmd/edward "Editor based on Ace" +[DEEPWORD]: https://github.com/cloudcmd/deepword "Editor based on Monaco" +[QWORD]: https://github.com/cloudcmd/qword "Editor based on CodeMirror 6" +[EDWARD_KEYS]: https://github.com/cloudcmd/edward/#hot-keys "Edward Hot keys" +[TERMUX]: https://termux.com "Termux" +[INLY]: https://github.com/coderaiser/node-inly "Extract archive" -[DWORD]: https://github.com/cloudcmd/dword "Editor based on CodeMirror" -[EDWARD]: https://github.com/cloudcmd/edward "Editor based on Ace" -[DEEPWORD]: https://github.com/cloudcmd/deepword "Editor based on Monaco" -[EDWARD_KEYS]: https://github.com/cloudcmd/edward/#hot-keys "Edward Hot keys" -[TERMUX]: https://termux.com "Termux" -[INLY]: https://github.com/coderaiser/node-inly "Extract archive" -**Cloud Commander** is an orthodox web file manager with console and editor. Will help you manage the server and work with files, directories and programs in browser from any computer, mobile or tablet. +[DeployInstaPodsIMG]: https://img.shields.io/badge/deploy%20on-InstaPods-blue +[DeployInstaPodsURL]: https://app.instapods.com/dashboard/pods/create?app=cloudcmd&ref=cloudcmd -![Cloud Commander](/img/logo/cloudcmd.png "Cloud Commander") +**Cloud Commander** is a file manager for the web. It includes a command-line console and a text editor. Cloud Commander helps you manage your server and work with files, directories and programs in a web browser from any computer, mobile or tablet. -Benefits ---------------- +![Cloud Commander](https://cloudcmd.io/img/logo/cloudcmd.png "Cloud Commander") -- Open Source (**MIT License**). +## Benefits + +- Open source (**MIT License**). - Has 2 classic panels. - Optional **authorization**. -- Client works in web browser. +- Client works in a web browser. - Server works on **Windows**, **Linux**, **Mac OS** and **Android** (with help of [Termux][TERMUX]). -- Could be used local or remotely. -- Adapting to screen size. -- **3 built-in editors** with support of **syntax highlighting**: [Dword][DWORD], [Edward][EDWARD] and [Deepword][DEEPWORD]. -- [Console](https://github.com/cloudcmd/console "Console") with support of default OS command line. +- Can be used local or remotely. +- Adapts to screen size. +- **3 built-in editors** with support of **syntax highlighting**: [Dword][DWORD], [Edward][EDWARD] [Deepword][DEEPWORD] and [Qword][QWORD]. +- [Console](https://github.com/cloudcmd/console "Console") with support of the default OS command line. - Written in **JavaScript/Node.js**. - Built-in archives pack: **zip** and **tar.gz**. - Built-in archives extract: **zip**, **tar**, **gz**, **bz2**, **.tar.gz** and **.tar.bz2** (with help of [inly][INLY]). -Install ---------------- +## Installation -The installation of file manager is very simple. +Installation is very simple: -- install latest version of [node.js](https://nodejs.org/ "node.js"). -- install `cloudcmd` via `npm` with: +- Install the latest version of [node.js](https://nodejs.org/ "node.js"). +- Install `cloudcmd` via `npm` with: ```sh npm i cloudcmd -g ``` -When in trouble use: +When in trouble, use: ```sh npm i cloudcmd -g --force ``` -Start ---------------- -For starting just type in console: +## Usage + +To start the server, just run the global *npm* binary from your terminal: ```sh cloudcmd ``` -Cloud Commander supports command line parameters: +Cloud Commander supports the following command-line parameters: -|Parameter |Operation -|:------------------------------|:------------------------------ -| `-h, --help` | display help and exit -| `-v, --version` | display version and exit -| `-s, --save` | save configuration -| `-o, --online` | load scripts from remote servers -| `-a, --auth` | enable authorization -| `-u, --username` | set username -| `-p, --password` | set password -| `-c, --config` | configuration file path -| `--editor` | set editor: "dword", "edward" or "deepword" -| `--packer` | set packer: "tar" or "zip" -| `--root` | set root directory -| `--prefix` | set url prefix -| `--port` | set port number -| `--minify` | enable minification -| `--progress` | show progress of file operations -| `--html-dialogs` | use html dialogs -| `--open` | open web browser when server started -| `--one-panel-mode` | set one panel mode - `--config-dialog` | enable config dialog - `--console` | enable console - `--terminal` | enable terminal - `--terminal-path` | set terminal path -| `--no-server` | do not start server -| `--no-auth` | disable authorization -| `--no-online` | load scripts from local server -| `--no-open` | do not open web browser when server started -| `--no-minify` | disable minification -| `--no-progress` | do not show progress of file operations -| `--no-html-dialogs` | do not use html dialogs -| `--no-one-panel-mode` | unset one panel mode -| `--no-config-dialog` | disable config dialog -| `--no-console` | disable console -| `--no-terminal` | disable terminal +| Parameter |Operation +|:-----------------------------|:------------------------------ +| `-h, --help` | display help and exit +| `-v, --version` | display version and exit +| `-s, --save` | save configuration +| `-o, --online` | load scripts from remote servers +| `-a, --auth` | enable authorization +| `-u, --username` | set username +| `-p, --password` | set password +| `-c, --config` | configuration file path +| `--show-config` | show config values +| `--show-dot-files` | show dot files +| `--show-file-name` | show file name in view and edit +| `--editor` | set editor: "dword", "edward" or "deepword" +| `--packer` | set packer: "tar" or "zip" +| `--root` | set root directory +| `--prefix` | set url prefix +| `--prefix-socket` | set prefix for url connection +| `--port` | set port number +| `--confirm-copy` | confirm copy +| `--confirm-move` | confirm move +| `--open` | open web browser when server starts +| `--name` | set tab name in web browser +| `--menu` | set menu: "supermenu" or "aleman" +| `--one-file-panel` | show one file panel +| `--keys-panel` | show keys panel +| `--contact` | enable contact +| `--config-dialog` | enable config dialog +| `--config-auth` | enable auth change in config dialog +| `--config-port` | enable port change in config dialog +| `--console` | enable console +| `--sync-console-path` | sync console path +| `--terminal` | enable terminal +| `--terminal-path` | set terminal path +| `--terminal-command` | set command to run in terminal (shell by default) +| `--terminal-auto-restart` | restart command on exit +| `--vim` | enable vim hot keys +| `--columns` | set visible columns +| `--theme` | set theme 'light' or 'dark'" +| `--export` | enable export of config through a server +| `--export-token` | authorization token used by export server +| `--import` | enable import of config +| `--import-token` | authorization token used to connect to export server +| `--import-url` | url of an import server +| `--import-listen` | enable listen on config updates from import server +| `--dropbox` | enable dropbox integration +| `--dropbox-token` | set dropbox token +| `--log` | enable logging +| `--no-show-config` | do not show config values +| `--no-server` | do not start server +| `--no-auth` | disable authorization +| `--no-online` | load scripts from local server +| `--no-open` | do not open web browser when server started +| `--no-name` | set default tab name in web browser +| `--no-keys-panel` | hide keys panel +| `--no-one-file-panel` | show two file panels +| `--no-confirm-copy` | do not confirm copy +| `--no-confirm-move` | do not confirm move +| `--no-config-dialog` | disable config dialog +| `--no-config-auth` | disable auth change in config dialog +| `--no-config-port` | disable port change in config dialog +| `--no-console` | disable console +| `--no-sync-console-path` | do not sync console path +| `--no-contact` | disable contact +| `--no-terminal` | disable terminal +| `--no-terminal-command` | set default shell to run in terminal +| `--no-terminal-auto-restart` | do not restart command on exit +| `--no-vim` | disable vim hot keys +| `--no-themes` | set default visible themes +| `--no-export` | disable export config through a server +| `--no-import` | disable import of config +| `--no-import-listen` | disable listen on config updates from import server +| `--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 -If no parameters given Cloud Commander reads information from `~/.cloudcmd.json` and use -port from it (`8000` default). if port variables `PORT` or `VCAP_APP_PORT` isn't exist. +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 use, type in address bar of your browser: +To begin using the web client, go to this PREFIX in your browser: ``` http://localhost:8000 ``` -Update ---------------- -If you installed Cloud Commander with `npm`, stop application and -re-install it: +## Updating the app + +If you installed Cloud Commander with `npm`, stop the server. Then, reinstall it with: ```sh npm install cloudcmd -g ``` -Then start it again, clear cache of your browser and reload page. +Then, start the server again with `cloudcmd` and reload the page. -Hot keys ---------------- +## Hot keys -|Key |Operation -|:----------------------|:-------------------------------------------- -| `F1` | help -| `F2` | rename -| `F3` | view -| `Shift + F3` | view as `markdown` -| `F4` | edit -| `Shift + F4` | edit in `vim` mode -| `F5` | copy -| `F6` | rename/move -| `F7` | new directory -| `Shift + F7` | new file -| `F8`, `Delete` | remove -| `Shift + Delete` | remove without prompt -| `F9` | menu -| `F10` | config -| `*` | select/unselect all -| `+` | expand selection -| `-` | shrink selection -| `Ctrl + x` | cut to buffer -| `Ctrl + с` | copy to buffer -| `Ctrl + v` | paste from buffer -| `Ctrl + z` | clear buffer -| `Ctrl + r` | refresh -| `Ctrl + d` | clear local storage -| `Ctrl + a` | select all files in a panel -| `Ctrl + m` | rename selected files -| `Ctrl + u` | swap panels -| `Ctrl + F3` | sort by name -| `Ctrl + F5` | sort by date -| `Ctrl + F6` | sort by size -| `Up`, `Down`, `Enter` | file system navigation -| `Alt + Left/Right` | show content of directory under cursor in target panel -| `Alt + g` | go to directory -| `Ctrl + \` | go to the root directory -| `Tab` | move via panels -| `Page Up` | up on one page -| `Page Down` | down on one page -| `Home` | to begin of list -| `End` | to end of list -| `Space` | select current file (and get size of directory) -| `Insert` | select current file (and move to next) -| `F9` | context menu -| `~` | console -| `Ctrl + Click` | open file on new tab +| Key |Operation +|:---------------------|:-------------------------------------------- +| `F1` | help +| `F2` | show `user menu` +| `F3` | view, change directory +| `Shift + F3` | view raw file, change directory +| `F4` | edit +| `F5` | copy +| `Alt` + `F5` | pack +| `F6` | rename/move +| `Shift` + `F6` | rename current file +| `F7` | new directory +| `Shift + F7` | new file +| `F8`, `Delete` | remove +| `Shift + Delete` | remove without prompt +| `F9` | menu +| `Alt` + `F9` | extract +| `F10` | config +| `*` | select/unselect all +| `+` | expand selection +| `-` | shrink selection +| `:` | open Command Line +| `Ctrl + X` | cut to buffer +| `Ctrl + C` | copy to buffer +| `Ctrl + V` | paste from buffer +| `Ctrl + Z` | clear buffer +| `Ctrl + P` | copy path +| `Ctrl + R` | refresh +| `Ctrl + D` | clear local storage +| `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 + U` | swap panels +| `Ctrl + F3` | sort by name +| `Ctrl + F5` | sort by date +| `Ctrl + F6` | sort by size +| `Ctrl + Shift + L` | logout +| `Ctrl + Command + .` | show/hide dot files +| `Up` | move cursor up +| `Down` | move cursor down +| `Enter` | change directory/view file +| `Alt + Left/Right` | show content of directory under cursor in target panel +| `Alt + G` | go to directory +| `Ctrl + \` | go to the root directory +| `Tab` | move via panels +| `Page Up` | up on one page +| `Page Down` | down on one page +| `Home` | to begin of list +| `End` | to end of list +| `Space` | select current file (and get size of directory) +| `Insert` | select current file (and move to next) +| `F9` | context menu +| `~` | console +| `Esc` | toggle vim hotkeys (`file manager`, `editor`) + +### Vim + +When the `--vim` option is provided, or the configuration parameter `vim` is set, the following hotkeys become available: + +| Key |Operation +|:------------|:-------------------------------------------- +| `j` | navigate to next file +| `k` | navigate to previous file +| `dd` | remove current file +| `G` or `$` | navigate to bottom file +| `gg` or `^` | navigate to top file +| `v` | visual mode +| `y` | copy (selected in visual mode files) +| `p` | paste files +| `Esc` | unselect all +| `/` | find file in current directory +| `n` | navigate to next found file +| `N` | navigate to previous found file +| `md` | make directory +| `mf` | make file +| `tt` | show terminal +| `e` | edit file +| `cc` | copy +| `mm` | move +| `rr` | rename file + +Commands can be joined, for example: + +- `5j` will navigate **5** files below current; +- `d5j` will remove next **5** files; +- `dG` will remove all files from current to bottom; + +## Drag and drop + +These file operations are accessible with "drag and drop". + +| Drag Mouse Button | Key | Origin | Destination |Operation +|:------------------|:----------|:----------|:--------------|:------------------ +| Left | | Panel | Panel | copy files +| Left | `Shift` | Panel | Panel | rename/move files +| Left | | Panel | Desktop | download files +| Left | | Desktop | Panel | upload files + +## View -View ---------------- ![View](/img/screen/view.png "View") ### Features + - View images. - View text files. -- Playing audio. -- Playing video. +- Play audio. +- Play video. -### Hot keys +### Hotkeys |Key |Operation |:----------------------|:-------------------------------------------- | `F3` | open | `Esc` | close -Edit ---------------- +## Edit + ![Edit](/img/screen/edit.png "Edit") ### Hot keys @@ -192,13 +284,13 @@ Edit |Key |Operation |:----------------------|:-------------------------------------------- | `F4` | open -| `Shift + F4` | open in `vim` mode +| `Shift + F4` | open in "vim" mode | `Esc` | close -For more details see [Edward hot keys][EDWARD_KEYS]. +For more details see [Edward hotkeys][EDWARD_KEYS]. + +## Console -Console ---------------- ![Console](/img/screen/console.png "Console") ### Hot keys @@ -206,24 +298,24 @@ Console |Key |Operation |:----------------------|:-------------------------------------------- | `~` | open -| `Ctrl + p` | paste path of current directory +| `Ctrl + P` | paste path of current directory | `Esc` | close For more details see [console hot keys](https://github.com/cloudcmd/console#hot-keys "Console Hot Keys"). -Terminal ---------------- +## Terminal + ![Terminal](/img/screen/terminal.png "Terminal") ### Install -`Terminal` disabled and not installed by default. To use it you should install [gritty](https://github.com/cloudcmd/gritty "Gritty") with: +The terminal is disabled and not installed by default. To use it, you should install [gritty](https://github.com/cloudcmd/gritty "Gritty") with: ```sh npm i gritty -g ``` -And then set the path of a terminal with: +and then set the path for the terminal with: ```sh cloudcmd --terminal --terminal-path `gritty --path` --save @@ -231,17 +323,18 @@ cloudcmd --terminal --terminal-path `gritty --path` --save ### Windows -On Windows you need to install `windows-build-tools` before: +If you can't install `gritty` on Windows, try to install `windows-build-tools` first: ```sh -npm install --global windows-build-tools +npm install windows-build-tools -g ``` -Then get path of a `gritty` with: +Then get the path of `gritty` with: ```sh gritty --path ``` + It will returns something like: ```sh @@ -254,34 +347,33 @@ Set this path as `--terminal-path` with: cloudcmd --save --terminal --terminal-path "C:\Users\coderaiser\AppData\Roaming\npm\node_modules\gritty" ``` -After that you can use `terminal` in the same way as a `console`. +After that, you can use Cloud Commander's terminal in the same way as a normal shell console. -### Hot keys +### Hotkeys |Key |Operation |:----------------------|:-------------------------------------------- | `Shift` + `~` | open | `Shift` + `Esc` | close -Environment Variables ---------------- +## Environment Variables -Every program executed in `console` or `terminal` has these `environment` variables: +Every program executed in Cloud Commander's terminal has these environment variables: - `ACTIVE_DIR` - directory that contains cursor - `PASSIVE_DIR` - directory with no cursor - `CURRENT_NAME` - name of a file under cursor - `CURRENT_PATH` - path to file under cursor -On `Unix` you can use it this way: +On Unix, you can use it this way: ```sh ~> echo $CURRENT_PATH /home/coderaiser/cloudcmd/bin/cloudcmd.js ``` -Config ---------------- +## Configuration + ![Config](/img/screen/config.png "Config") ### Hot keys @@ -291,56 +383,261 @@ Config | `F10` | open | `Esc` | close -When you change one of options file `~/.cloudcmd.json` would be saved. -It could be edited manually with any text editor. -Here is description of options: +When you change any options, the `~/.cloudcmd.json` file is automatically updated. +It can also be edited manually with any text editor. +Here's a description of all options: -```js +```json { - "auth" : false, /* enable http authentication */ - "username" : "root", /* username for authentication */ - "password" : "toor", /* password hash in sha-1 for authentication*/ - "algo" : "sha512WithRSAEncryption", /* cryptographic algorithm */ - "editor" : "edward", /* default, could be "dword" or "edward" */ - "packer" : "tar", /* default, could be "tar" or "zip" */ - "diff" : true, /* when save - send patch, not whole file */ - "zip" : true, /* zip text before send / unzip before save */ - "localStorage" : true, /* local storage */ - "buffer" : true, /* buffer for copying files */ - "dirStorage" : true, /* store directory listing to localStorage */ - "minify" : false, /* minification of js,css,html and img */ - "online" : true, /* load js files from cdn or local path */ - "open" : false /* open web browser when server started */ - "cache" : true, /* add cache-control */ - "showKeysPanel" : true, /* show classic panel with buttons of keys */ - "port" : 8000, /* http port */ - "ip" : null, /* ip or null(default) */ - "root" : "/", /* root directory */ - "prefix" : "", /* url prefix */ - "progress" : true, /* show progress of file operations */ - "htmlDialogs" : true, /* use html dialogs */ - "onePanelMode" : false, /* set one panel mode */ - "configDialog" : true, /* enable config dialog */ - "console" : true, /* enable console */ - "terminal" : false, /* disable terminal */ - "terminalPath" : '', /* path of a terminal */ + "name": "", // set tab name in web browser + "auth": false, // enable http authentication + "username": "root", // username for authentication + "password": "toor", // password hash for authentication + "algo": "sha512WithRSAEncryption", // cryptographic algorithm + "editor": "edward", // default, could be "dword" or "edward" + "packer": "tar", // default, could be "tar" or "zip" + "diff": true, // when save - send patch, not whole file + "zip": true, // zip text before send / unzip before save + "buffer": true, // buffer for copying files + "dirStorage": true, // store directory listing + "online": false, // do not load js files from cdn + "open": true, // open web browser when server started + "oneFilePanel": false, // show one file panel + "keysPanel": true, // show classic panel with buttons of keys + "port": 8000, // http port + "ip": null, // ip or null(default) + "root": "/", // root directory + "prefix": "", // url prefix + "prefixSocket": "", // prefix for socket connection + "confirmCopy": true, // confirm copy + "confirmMove": true, // confirm move + "showConfig": false, // show config at startup + "showDotFiles": true, // show dot files + "showFileName": false, // do not show file name in view and edit + "contact": true, // enable contact + "configDialog": true, // enable config dialog + "configAuth": true, // enable auth change in config dialog + "console": true, // enable console + "syncConsolePath": false, // do not sync console path + "terminal": false, // disable terminal + "terminalPath": "", // path of a terminal + "terminalCommand": "", // set command to run in terminal + "terminalAutoRestart": true, // restart command on exit + "vim": false, // disable vim hot keys + "themes": "name-size-date-owner-mode", // set visible themes + "export": false, // enable export of config through a server + "exportToken": "root", // token used by export server + "import": false, // enable import of config + "import-url": "http://localhost:8000", // url of an export server + "importToken": "root", // token used to connect to export server + "importListen": false, // listen on config updates + "dropbox": false, // disable dropbox integration + "dropboxToken": "", // unset dropbox token + "log": true // logging } ``` ### Environment Variables -Some config options can be overridden with `environment variables` such: +Some config options can be overridden with environment variables, such as: +- `CLOUDCMD_NAME` - set tab name in web browser +- `CLOUDCMD_OPEN` - open web browser when server started - `CLOUDCMD_EDITOR` - set editor +- `CLOUDCMD_COLUMNS` - set visible themes +- `CLOUDCMD_THEME` - set themes "light" or "dark" +- `CLOUDCMD_MENU` - set menu "supermenu" or "aleman" +- `CLOUDCMD_CONTACT` - enable contact +- `CLOUDCMD_CONFIG_DIALOG` - enable config dialog +- `CLOUDCMD_CONFIG_AUTH` - enable auth change in config dialog +- `CLOUDCMD_CONFIG_PORT` - enable port change in config dialog +- `CLOUDCMD_CONSOLE` - enable console +- `CLOUDCMD_SYNC_CONSOLE_PATH` - sync console path - `CLOUDCMD_TERMINAL` - enable terminal - `CLOUDCMD_TERMINAL_PATH` - set terminal path -- `CLOUDCMD_CONFIG_DIALOG` - enable config dialog +- `CLOUDCMD_TERMINAL_COMMAND` - set command to run in terminal (shell by default) +- `CLOUDCMD_TERMINAL_AUTO_RESTART` - restart command on exit +- `CLOUDCMD_KEYS_PANEL` - show keys panel +- `CLOUDCMD_ONE_FILE_PANEL` - show one file panel +- `CLOUDCMD_AUTH` - enable authentication +- `CLOUDCMD_USERNAME` - set username +- `CLOUDCMD_PASSWORD` - set password +- `CLOUDCMD_PREFIX` - set url prefix +- `CLOUDCMD_ROOT` - set root directory +- `CLOUDCMD_VIM` - enable vim hot keys +- `CLOUDCMD_CONFIRM_COPY` - confirm copy +- `CLOUDCMD_CONFIRM_MOVE` - confirm move +- `CLOUDCMD_SHOW_FILE_NAME` - show file name in view and edit +- `CLOUDCMD_EXPORT` - enable export of config through a server +- `CLOUDCMD_EXPORT_TOKEN` - authorization token used by export server +- `CLOUDCMD_IMPORT` - enable import of config +- `CLOUDCMD_IMPORT_TOKEN` - authorization token used to connect to export server +- `CLOUDCMD_IMPORT_URL` - url of an import server +- `CLOUDCMD_IMPORT_LISTEN` - enable listen on config updates from import server + +### User Menu + +When you press `F2` Cloud Commander will read a file `.cloudcmd.menu.js` by walking up parent directories, if can't read it will try to read `~/.cloudcmd.menu.js`. + +Let's consider example `user menu` works file: + +```js +const RENAME_FILE = 'Rename file'; + +export default { + '__settings': { + select: [RENAME_FILE], + run: false, + }, + [`F2 - ${RENAME_FILE}`]: async ({DOM}) => { + await DOM.renameCurrent(); + }, + 'D - Build Dev': async ({CloudCmd}) => { + await CloudCmd.TerminalRun.show({ + command: 'npm run build:client:dev', + autoClose: false, // optional + closeMessage: 'Press any button to close Terminal', // optional + }); + + await CloudCmd.refresh(); + }, + 'P - Build Prod': async ({CloudCmd}) => { + await CloudCmd.TerminalRun.show({ + command: 'npm run build:client', + autoClose: true, // optional + }); + + await CloudCmd.refresh(); + }, + 'C - Create User Menu File': async ({DOM, CloudCmd}) => { + const {CurrentInfo} = DOM; + + const {dirPath} = CurrentInfo; + const path = `${dirPath}.cloudcmd.menu.js`; + const {prefix} = CloudCmd; + + const data = await readDefaultMenu({ + prefix, + }); + + await createDefaultMenu({ + path, + data, + DOM, + CloudCmd, + }); + }, +}; + +async function createDefaultMenu({path, data, DOM, CloudCmd}) { + const {IO} = DOM; + + await IO.write(path, data); + await CloudCmd.refresh(); + + DOM.setCurrentByName('.cloudcmd.menu.js'); + + await CloudCmd.EditFile.show(); +} + +async function readDefaultMenu({prefix}) { + const res = await fetch(`${prefix}/api/v1/user-menu/default`); + const data = await res.text(); + + return data; +} +``` + +You will have ability to run one of this 3 commands with help of double click, enter, or binded key (`F2`, `D` or `P` in this example). Also you can run commands in terminal, or execute any built-in function of `Cloud Commander` extended it's interface. You can find more examples in [User Menu Cookbook](https://github.com/coderaiser/cloudcmd/wiki/User-Menu-Cookbook). + +#### User Menu API + +Here you can find `API` that can be used in **User Menu**. **DOM** and **CloudCmd** two main objects you receive in arguments list using destructuring. + +**DOM** contains all base functions of `Cloud Commander` (rename, remove, download etc); + +- `renameCurrent` - shows renames current file dialog, and does renaming. + +**CloudCmd** contains all modules (`Terminal`, `View`, `Edit`, `Config`, `Console` etc); + +- `TerminalRun` - module that shows `Terminal` with a `command` from options and closes terminal when everything is done. + +**IO** Files API + +- `rename(from, to)` - rename `from` into `to` +- `move(from, to, names)` - rename files with a `names` `from` into `to`; +- `copy(from, to, names)` - copy files with a `names` `from` into `to`; +- `createDirectory(path)` - create directory with a `path`; + +### Distribute + +Being able to configure Cloud Commander remotely opens the doors to using it as microservice, and that's what the "distribute" options set out to do. + +There is an **export server** and an **import client**, which are enabled with `--export` and `--import` respectively. There is a "token", which should be the same in `--import-token` and `--export-token`. To use the *import client*, you should provide `--import-url` to the client so it can connect to an *export server*. + +There are two ways that the *import client* can receive configuration from an *export server*: + +- full config at startup (default) +- get every updated option (with help of the `--import-listen` flag) + +#### An example - using the "distribute" options to get configuration from a remote instance: + +Here's an *export server*: + +``` +coderaiser@cloudcmd:~$ cloudcmd --port 1234 --export --export-token=cloudcmd +``` + +...and an *import client*: + +``` +coderaiser@cloudcmd:~$ cloudcmd --name importer --port 4321 --import-url http://127.0.0.1:1234 --import-token=cloudcmd --no-server --save +``` + +Here's the log output from the *export server*: + +``` +url: http://localhost:1234/ +2018.08.23 13:41:45 -> export: try to auth from importer [127.0.0.1:4321] +2018.08.23 13:41:45 -> export: connected to importer [127.0.0.1:4321] +2018.08.23 13:41:45 -> export: config send to importer [127.0.0.1:4321] +2018.08.23 13:41:45 -> export: disconnected importer [127.0.0.1:4321] +``` + +...and the log output from the *import client*: + +``` +2018.08.23 13:47:36 -> import: try to auth to http://127.0.0.1:1234 +2018.08.23 13:47:36 -> import: connected to http://127.0.0.1:1234 +2018.08.23 13:47:36 -> import: config received from http://127.0.0.1:1234 +2018.08.23 13:47:36 -> import: disconnected from http://127.0.0.1:1234 +``` + +When the *import client* uses `--import-listen`, a persistent connection is used, and the *client* receives live updates from the *import server*. + +The *export server* omits the following configuration fields: + +- `auth` +- `username` +- `password` +- `algo` +- `name` +- `ip` +- `port` +- `root` +- `import` +- `importUrl` +- `importToken` +- `export` +- `exportToken` +- `log` +- `configDialog` + +## Menu -Menu ---------------- ![Menu](/img/screen/menu.png "Menu") -Right mouse click button shows context menu with items: +Right-mouse click to show a context menu with these items: - View - Edit @@ -361,22 +658,30 @@ Right mouse click button shows context menu with items: ### Hot keys -|Key |Operation -|:----------------------|:-------------------------------------------- -| `F9` | open -| `Esc` | close +| Key | Operation | +|:-------------|:------------------------| +| `F9` | open | +| `Esc` | close | +| `Up`, `j` | move cursor up | +| `Down`, `k` | move cursor down | +| `Left`, `h` | close submenu | +| `Right`, `l` | open submenu | +| `G` or `$` | navigate to bottom | +| `gg` or `^` | navigate to top | -One panel mode ---------------- -Cloud Commander could work in one panel mode when screen size can not accommodate second panel or via `--one-panel-mode` options flag. -It could happen when mobile device, tablet or small window size used to work with file manager. +Commands can be joined, for example: -![One panel mode](/img/screen/one-panel-mode.png "One panel mode") +- `5j` will navigate **5** items below current; -Using as Middleware ---------------- +## One file panel -Cloud Commander could be used as middleware for `node.js` applications based on [socket.io](http://socket.io "Socket.IO") and [express](http://expressjs.com "Express"): +Cloud Commander can work in one panel mode when your screen size can't accommodate a second panel (such as on mobile or tablet), or via the `--one-file-panel` options flag. + +![One file panel](/img/screen/one-file-panel.png "One file panel") + +## Using as middleware + +Cloud Commander can be used as middleware for `node.js` applications based on [socket.io](http://socket.io "Socket.IO") and [express](http://expressjs.com "Express"): Init `package.json`: @@ -393,56 +698,142 @@ npm i cloudcmd express socket.io -S And create `index.js`: ```js -const http = require('http'); -const cloudcmd = require('cloudcmd'); -const io = require('socket.io'); -const app = require('express')(); +import http from 'node:http'; +import {cloudcmd} from 'cloudcmd'; +import {Server} from 'socket.io'; +import express from 'express'; +const app = express(); const port = 1337; -const prefix = '/cloudcmd'; +const prefix = '/'; const server = http.createServer(app); -const socket = io.listen(server, { - path: `${prefix}/socket.io` +const socket = new Server(server, { + path: `${prefix}socket.io`, }); const config = { - prefix /* base URL or function which returns base URL (optional) */ + name: 'cloudcmd :)', }; -const plugins = [ - __dirname + '/plugin.js' -]; - const filePicker = { data: { FilePicker: { - key: 'key' - } - } + key: 'key', + }, + }, }; // override option from json/modules.json -const modules = {filePicker}; +const modules = { + filePicker, +}; -app.use(cloudcmd({ - socket, /* used by Config, Edit (optional) and Console (required) */ - config, /* config data (optional) */ - plugins, /* optional */ - modules, /* optional */ +const { + createConfigManager, + configPath, +} = cloudcmd; + +const configManager = createConfigManager({ + configPath, +}); + +app.use(prefix, cloudcmd({ + socket, // used by Config, Edit (optional) and Console (required) + config, // config data (optional) + modules, // optional + configManager, // optional })); server.listen(port); ``` -And you are ready to go. +Here is example with two `Config Managers`: -Server ---------------- -Standard practices say no non-root process gets to talk to -the Internet on a port less than 1024. Anyway I suggest you -to start Cloud Commander as non-root. How it could be solved? -There is a couple easy and fast ways. One of them is port forwarding. +```js +import http from 'node:http'; +import cloudcmd from 'cloudcmd'; +import {Server} from 'socket.io'; +import express from 'express'; + +const app = express(); +const port = 8000; +const prefix1 = '/1'; +const prefix2 = '/2'; + +const {createConfigManager} = cloudcmd; + +const server = http.createServer(app); +const socket1 = new Server(server, { + path: `${prefix1}/socket.io`, +}); + +const socket2 = new Server(server, { + path: `${prefix2}/socket.io`, +}); + +const configManager1 = createConfigManager(); + +configManager1('name', '1'); + +const configManager2 = createConfigManager(); +configManager2('name', '2'); + +app.use(prefix1, cloudcmd({ + socket: socket1, + configManager: configManager1, +})); + +app.use(prefix2, cloudcmd({ + socket: socket2, + configManager: configManager2, +})); + +server.listen(port); +``` + +If you want to enable authorization, you can pass credentials to Cloud Commander with a config. To generate a password, you can install `criton` with `npm i criton --save`, and use it (or any other way) to generate a hash of a password. + +```js +import criton from 'criton'; + +const algo = 'sha512WithRSAEncryption'; + +// default +// you can generate a hash dynamically +const password = criton('root', algo); + +// or use a pregenerated hash as well +'2b64f2e..ca5d9a9'; + +const auth = true; +const username = 'root'; + +const config = { + algo, // optional + auth, + username, + password, +}; +``` + +Now you're ready to go! + +## Authorization + +`~/.cloudcmd.json` contains [password hash](https://github.com/coderaiser/cloudcmd/blob/v11.8.3/json/config.json#L5) because of security reason, if someone steal your config, he wouldn't know your password, because hash is [very strong](https://github.com/coderaiser/cloudcmd/blob/v11.8.3/json/config.json#L6) and can be customized. + +You should never write your password as plain text to `~/.cloudcmd.json`, you can generate password using `cloudcmd` itself: + +``` +cloudcmd --username name --password password --auth --save --no-server +``` + +This command will create hash of your password and write it to `~/.cloudcmd.json`. + +## Server + +Standard practices dictate that no non-root process get to talk to the internet on a port less than 1024. Despite this, **I suggest you start Cloud Commander as a non-root process**. How can we get around this limitation? There's a couple of fast & easy ways. One of them is port forwarding: ### Iptables @@ -455,15 +846,15 @@ iptables -t nat -A PREROUTING -p tcp --dport 443 -j REDIRECT --to-ports 4430 iptables -t nat -L # look rules after ``` -You should see something like this ( **8000** and **4430** should be in config as **port** and **sslPort** ) +You should see something like this (**8000** and **4430** should be in config as **port** and **sslPort**) ```sh target prot opt source destination REDIRECT tcp -- anywhere anywhere tcp dpt:http redir ports 8000 REDIRECT tcp -- anywhere anywhere tcp dpt:https redir ports 4430 ``` -If you would want to get things back just clear rules ( **1** and **2** it's rule numbers, -in your list they could differ). + +If you would want to get things back just clear rules (rule numbers **1** and **2**; in your list they could differ). ```sh iptables -t nat -D PREROUTING 2 @@ -471,14 +862,15 @@ iptables -t nat -D PREROUTING 1 ``` ### nginx -Get [nginx](http://nginx.org/ "nginx"). On Linux it could be done this way: + +Get [nginx](http://nginx.org/ "nginx"). On Linux, you can run: ```sh sudo apt-get install nginx #for ubuntu and debian ``` -Then make host file **/etc/nginx/sites-available/io.cloudcmd.io** -( *io.cloudcmd.io* is your domain name) with content: +Then, make a host file **/etc/nginx/sites-available/io.cloudcmd.io** +(where, for example, *io.cloudcmd.io* is your domain name) with these contents: ```sh server { @@ -492,7 +884,7 @@ server { } ``` -If you want add **SSL**, add a couple lines to server block: +**If you want add SSL**, add a couple lines to the `server` block: ```sh server { @@ -509,7 +901,7 @@ server { } ``` -For WebSocket support (nginx >= v1.3.13) modify server block: +For WebSocket support, (nginx >= v1.3.13) modify the `server` block like so: ```sh location / { @@ -521,8 +913,7 @@ For WebSocket support (nginx >= v1.3.13) modify server block: } ``` - -If you need redirection from **http** to **https**, it's simple: +If you need redirection from **http** to **https**, simply use: ```sh server { @@ -534,30 +925,29 @@ server { ``` ```sh -# create symlink of this file +# create a symlink of this file ln -s ./sites-available/io.cloudcmd.io ./sites-enabled # restart nginx /etc/init.d/nginx restart ``` -Deploy ---------------- -`Cloud Commander` could be easily deployed to [Heroku](https://heroku.com/deploy?template=https://github.com/coderaiser/cloudcmd "Deploy to Heroku"). +## Deploy -[![Deploy to Heroku](https://www.herokucdn.com/deploy/button.png "Deploy to Heroku")]( https://heroku.com/deploy?template=https://github.com/coderaiser/cloudcmd) +`Cloud Commander` can be easily deployed to [InstaPods][DeployInstaPodsURL]. After deploy you receive email with credentials. -Docker ---------------- -`Cloud Commander` could be used as [docker container](https://hub.docker.com/r/coderaiser/cloudcmd/ "Docker container") this way: +[![Deploy on InstaPods](https://instapods.com/deploy-button.svg)](https://app.instapods.com/dashboard/pods/create?app=cloudcmd&ref=cloudcmd) + +## Docker + +`Cloud Commander` can be used as [docker container](https://hub.docker.com/r/coderaiser/cloudcmd/ "Docker container") like so: ```sh -docker run -v ~:/root -v /:/mnt/fs -t -p 8000:8000 coderaiser/cloudcmd +docker run -t --rm -v ~:/root -v /:/mnt/fs -w=/root -p 8000:8000 coderaiser/cloudcmd ``` -Config would be read from home directory, hosts root file system would be mount to `/mnt/fs`, -`8000` port would be exposed to hosts port. +Configuration will be read from the home directory, the host's root file system will be mounted to `/mnt/fs`, and port `8000` port will exposed to the host's port. -Also you could use [docker compose](https://docs.docker.com/compose/ "Docker Compose") with `docker-compose.yml`: +Also, you can use [docker compose](https://docs.docker.com/compose/ "Docker Compose") with `docker-compose.yml`: ```yml version: '2' @@ -571,23 +961,601 @@ services: image: coderaiser/cloudcmd ``` -When you create this file run: +When you create this file, run: ```sh docker-compose up ``` -Get involved ---------------- +# Dropbox -There is a lot ways to be involved in `Cloud Commander` development: +Dropbox support is integrated into Cloud Commander, and you can switch from your local file system to a Dropbox account. +All you need to do is set `--dropbox` option and [generate a dropbox token](https://blogs.dropbox.com/developers/2014/05/generate-an-access-token-for-your-own-account/) for your account. -- if you find a bug or got idea to share [create issue](https://github.com/coderaiser/cloudcmd/issues/new "Create issue"); -- if you fixed a bug, typo or implemented new feature [create pull request](https://github.com/coderaiser/cloudcmd/compare "Create pull request"); -- if you know languages you can help with [site translations](https://github.com/coderaiser/cloudcmd/wiki "Cloud Commander community wiki"); +This could look like this: -Version history ---------------- +```sh +cloudcmd --dropbox --dropbox-token your-dropbox-token +``` + +While using Dropbox remember that there is no remote support for the console/terminal. Seeing the progress of file operations is also not supported. There's only basic support, but you can do the following things with files and directories: + +- create +- remove +- rename/move +- view +- edit + +## Automatically start cloudcmd on boot for `systemd` + +First, locate the command to run cloudcmd + +```sh +which cloudcmd +``` + +take note of the result and create a systemd entry by executing + +```sh +sudo nano /etc/systemd/system/cloudcmd.service +``` + +and use this template + +``` +[Unit] +Description = Cloud Commander + +[Service] +TimeoutStartSec = 0 +Restart = always +ExecStart = THE RESULT OF which cloudcmd WE'VE EXECUTED EARLIER +User = YOUR_USER + +[Install] +WantedBy = multi-user.target +``` + +Don't forget to change the line for `ExecStart` and `User` + +Save the changes and exit editor. + +You may now enable cloudcmd and set it to autostart on boot by running: + +```sh +sudo systemctl enable --now cloudcmd +``` + +## Automatically start cloudcmd on boot for `FreeBSD` + +First, locate the command to run cloudcmd + +``` +which cloudcmd +``` + +take note of the result and create a rc script + +``` +vi /usr/local/etc/rc.d/cloudcmd +``` + +and use this template + +``` +!/bin/sh +# +# PROVIDE: cloudcmd +# REQUIRE: LOGIN +# KEYWORD: shutdown + +# Author: IhatemyISP (ihatemyisp.net) +# Version: 1.0.0 + +# Description: +# This script runs Cloud Commander as a service under the supplied user on boot + +# 1) Place file in /usr/local/etc/rc.d/ +# 2) Add cloudcmd_enable="YES" to /etc/rc.conf +# 3) (Optional) To run as non-root, add cloudcmd_runAs="user" to /etc/rc.conf +# 4) (Optional) To pass Cloud Commander args, add cloudcmd_args="" to /etc/rc.conf + +# Freebsd rc library +. /etc/rc.subr + +# General Info +name="cloudcmd" # Safe name of program +program_name="cloudcmd" # Name of exec +title="CloudCommander" # Title to display in top/htop + +# RC.config vars +load_rc_config $name # Loading rc config vars +: ${cloudcmd_enable="NO"} # Default: Do not enable Cloud Commander +: ${cloudcmd_runAs="root"} # Default: Run Cloud Commander as root + +# Freebsd Setup +rcvar=cloudcmd_enable # Enables the rc.conf YES/NO flag +pidfile="/var/run/${program_name}.pid" # PID file location + +# Env Setup +export HOME=$( getent passwd "$cloudcmd_runAs" | cut -d: -f6 ) # Gets the home directory of the runAs user + +# Command Setup +exec_path="/usr/local/bin/${program_name}" # Path to the cloudcmd exec, /usr/local/bin/ when installed globally +output_file="/var/log/${program_name}.log" # Path to Cloud Commander output file + +# Command +command="/usr/sbin/daemon" +command_args="-r -t ${title} -u ${cloudcmd_runAs} -o ${output_file} -P ${pidfile} ${exec_path} ${cloudcmd_args}" + +# Loading Config +load_rc_config ${name} +run_rc_command "$1" +``` + +Enable autostart + +``` +echo cloudcmd_enable="YES" >> /etc/rc.conf +``` + +(Optional) Set user to run Cloud Commander as (default is root) + +``` +echo cloudcmd_runAs="user" >> /etc/rc.conf +``` + +Start the service (or just reboot) + +``` +service cloudcmd start +``` + +## Get involved + +There are a lot of ways to be involved in `Cloud Commander` development: + +- support project on patreon: https://patreon.com/coderaiser; +- if you find a bug or have an idea to share, [create an issue](https://github.com/coderaiser/cloudcmd/issues/new "Create issue"); +- if you fixed a bug, typo or implemented a new feature, [create a pull request](https://github.com/coderaiser/cloudcmd/compare "Create pull request"); +- if you know a language not currently translated, or would like to improve an existing translation, you can help with [site translations](https://github.com/coderaiser/cloudcmd/wiki "Cloud Commander community wiki"); + +## Version history + +- *2026.06.15*, **[v19.19.1](//github.com/coderaiser/cloudcmd/releases/tag/v19.19.1)** +- *2026.05.26*, **[v19.19.0](//github.com/coderaiser/cloudcmd/releases/tag/v19.19.0)** +- *2026.05.26*, **[v19.18.1](//github.com/coderaiser/cloudcmd/releases/tag/v19.18.1)** +- *2026.05.26*, **[v19.18.0](//github.com/coderaiser/cloudcmd/releases/tag/v19.18.0)** +- *2026.05.17*, **[v19.17.0](//github.com/coderaiser/cloudcmd/releases/tag/v19.17.0)** +- *2026.05.03*, **[v19.16.0](//github.com/coderaiser/cloudcmd/releases/tag/v19.16.0)** +- *2026.04.28*, **[v19.15.0](//github.com/coderaiser/cloudcmd/releases/tag/v19.15.0)** +- *2026.04.28*, **[v19.14.0](//github.com/coderaiser/cloudcmd/releases/tag/v19.14.0)** +- *2026.04.21*, **[v19.13.1](//github.com/coderaiser/cloudcmd/releases/tag/v19.13.1)** +- *2026.04.15*, **[v19.13.0](//github.com/coderaiser/cloudcmd/releases/tag/v19.13.0)** +- *2026.04.12*, **[v19.12.5](//github.com/coderaiser/cloudcmd/releases/tag/v19.12.5)** +- *2026.04.12*, **[v19.12.4](//github.com/coderaiser/cloudcmd/releases/tag/v19.12.4)** +- *2026.04.12*, **[v19.12.3](//github.com/coderaiser/cloudcmd/releases/tag/v19.12.3)** +- *2026.04.11*, **[v19.12.2](//github.com/coderaiser/cloudcmd/releases/tag/v19.12.2)** +- *2026.04.09*, **[v19.12.1](//github.com/coderaiser/cloudcmd/releases/tag/v19.12.1)** +- *2026.04.09*, **[v19.12.0](//github.com/coderaiser/cloudcmd/releases/tag/v19.12.0)** +- *2026.04.07*, **[v19.11.14](//github.com/coderaiser/cloudcmd/releases/tag/v19.11.14)** +- *2026.04.07*, **[v19.11.13](//github.com/coderaiser/cloudcmd/releases/tag/v19.11.13)** +- *2026.04.06*, **[v19.11.12](//github.com/coderaiser/cloudcmd/releases/tag/v19.11.12)** +- *2026.04.06*, **[v19.11.11](//github.com/coderaiser/cloudcmd/releases/tag/v19.11.11)** +- *2026.04.06*, **[v19.11.10](//github.com/coderaiser/cloudcmd/releases/tag/v19.11.10)** +- *2026.04.06*, **[v19.11.9](//github.com/coderaiser/cloudcmd/releases/tag/v19.11.9)** +- *2026.04.06*, **[v19.11.8](//github.com/coderaiser/cloudcmd/releases/tag/v19.11.8)** +- *2026.04.05*, **[v19.11.7](//github.com/coderaiser/cloudcmd/releases/tag/v19.11.7)** +- *2026.04.05*, **[v19.11.6](//github.com/coderaiser/cloudcmd/releases/tag/v19.11.6)** +- *2026.04.05*, **[v19.11.5](//github.com/coderaiser/cloudcmd/releases/tag/v19.11.5)** +- *2026.04.04*, **[v19.11.4](//github.com/coderaiser/cloudcmd/releases/tag/v19.11.4)** +- *2026.04.04*, **[v19.11.3](//github.com/coderaiser/cloudcmd/releases/tag/v19.11.3)** +- *2026.04.04*, **[v19.11.2](//github.com/coderaiser/cloudcmd/releases/tag/v19.11.2)** +- *2026.04.04*, **[v19.11.1](//github.com/coderaiser/cloudcmd/releases/tag/v19.11.1)** +- *2026.04.04*, **[v19.11.0](//github.com/coderaiser/cloudcmd/releases/tag/v19.11.0)** +- *2026.04.04*, **[v19.10.2](//github.com/coderaiser/cloudcmd/releases/tag/v19.10.2)** +- *2026.04.03*, **[v19.10.1](//github.com/coderaiser/cloudcmd/releases/tag/v19.10.1)** +- *2026.04.02*, **[v19.10.0](//github.com/coderaiser/cloudcmd/releases/tag/v19.10.0)** +- *2026.04.02*, **[v19.9.24](//github.com/coderaiser/cloudcmd/releases/tag/v19.9.24)** +- *2026.04.01*, **[v19.9.23](//github.com/coderaiser/cloudcmd/releases/tag/v19.9.23)** +- *2026.03.31*, **[v19.9.22](//github.com/coderaiser/cloudcmd/releases/tag/v19.9.22)** +- *2026.03.31*, **[v19.9.21](//github.com/coderaiser/cloudcmd/releases/tag/v19.9.21)** +- *2026.03.30*, **[v19.9.20](//github.com/coderaiser/cloudcmd/releases/tag/v19.9.20)** +- *2026.03.30*, **[v19.9.19](//github.com/coderaiser/cloudcmd/releases/tag/v19.9.19)** +- *2026.03.30*, **[v19.9.18](//github.com/coderaiser/cloudcmd/releases/tag/v19.9.18)** +- *2026.03.30*, **[v19.9.17](//github.com/coderaiser/cloudcmd/releases/tag/v19.9.17)** +- *2026.03.29*, **[v19.9.16](//github.com/coderaiser/cloudcmd/releases/tag/v19.9.16)** +- *2026.03.29*, **[v19.9.15](//github.com/coderaiser/cloudcmd/releases/tag/v19.9.15)** +- *2026.03.29*, **[v19.9.14](//github.com/coderaiser/cloudcmd/releases/tag/v19.9.14)** +- *2026.03.29*, **[v19.9.13](//github.com/coderaiser/cloudcmd/releases/tag/v19.9.13)** +- *2026.03.29*, **[v19.9.12](//github.com/coderaiser/cloudcmd/releases/tag/v19.9.12)** +- *2026.03.29*, **[v19.9.11](//github.com/coderaiser/cloudcmd/releases/tag/v19.9.11)** +- *2026.03.29*, **[v19.9.10](//github.com/coderaiser/cloudcmd/releases/tag/v19.9.10)** +- *2026.03.29*, **[v19.9.9](//github.com/coderaiser/cloudcmd/releases/tag/v19.9.9)** +- *2026.03.28*, **[v19.9.8](//github.com/coderaiser/cloudcmd/releases/tag/v19.9.8)** +- *2026.03.27*, **[v19.9.7](//github.com/coderaiser/cloudcmd/releases/tag/v19.9.7)** +- *2026.03.26*, **[v19.9.6](//github.com/coderaiser/cloudcmd/releases/tag/v19.9.6)** +- *2026.03.26*, **[v19.9.5](//github.com/coderaiser/cloudcmd/releases/tag/v19.9.5)** +- *2026.03.26*, **[v19.9.4](//github.com/coderaiser/cloudcmd/releases/tag/v19.9.4)** +- *2026.03.24*, **[v19.9.3](//github.com/coderaiser/cloudcmd/releases/tag/v19.9.3)** +- *2026.03.23*, **[v19.9.2](//github.com/coderaiser/cloudcmd/releases/tag/v19.9.2)** +- *2026.03.23*, **[v19.9.1](//github.com/coderaiser/cloudcmd/releases/tag/v19.9.1)** +- *2026.03.23*, **[v19.9.0](//github.com/coderaiser/cloudcmd/releases/tag/v19.9.0)** +- *2026.03.23*, **[v19.8.15](//github.com/coderaiser/cloudcmd/releases/tag/v19.8.15)** +- *2026.03.23*, **[v19.8.14](//github.com/coderaiser/cloudcmd/releases/tag/v19.8.14)** +- *2026.03.23*, **[v19.8.13](//github.com/coderaiser/cloudcmd/releases/tag/v19.8.13)** +- *2026.03.23*, **[v19.8.12](//github.com/coderaiser/cloudcmd/releases/tag/v19.8.12)** +- *2026.03.23*, **[v19.8.11](//github.com/coderaiser/cloudcmd/releases/tag/v19.8.11)** +- *2026.03.23*, **[v19.8.10](//github.com/coderaiser/cloudcmd/releases/tag/v19.8.10)** +- *2026.03.23*, **[v19.8.9](//github.com/coderaiser/cloudcmd/releases/tag/v19.8.9)** +- *2026.03.23*, **[v19.8.8](//github.com/coderaiser/cloudcmd/releases/tag/v19.8.8)** +- *2026.03.23*, **[v19.8.7](//github.com/coderaiser/cloudcmd/releases/tag/v19.8.7)** +- *2026.03.23*, **[v19.8.6](//github.com/coderaiser/cloudcmd/releases/tag/v19.8.6)** +- *2026.03.23*, **[v19.8.5](//github.com/coderaiser/cloudcmd/releases/tag/v19.8.5)** +- *2026.03.22*, **[v19.8.4](//github.com/coderaiser/cloudcmd/releases/tag/v19.8.4)** +- *2026.03.22*, **[v19.8.3](//github.com/coderaiser/cloudcmd/releases/tag/v19.8.3)** +- *2026.03.22*, **[v19.8.2](//github.com/coderaiser/cloudcmd/releases/tag/v19.8.2)** +- *2026.03.22*, **[v19.8.1](//github.com/coderaiser/cloudcmd/releases/tag/v19.8.1)** +- *2026.03.20*, **[v19.8.0](//github.com/coderaiser/cloudcmd/releases/tag/v19.8.0)** +- *2026.03.18*, **[v19.7.1](//github.com/coderaiser/cloudcmd/releases/tag/v19.7.1)** +- *2026.03.17*, **[v19.7.0](//github.com/coderaiser/cloudcmd/releases/tag/v19.7.0)** +- *2026.03.17*, **[v19.6.9](//github.com/coderaiser/cloudcmd/releases/tag/v19.6.9)** +- *2026.02.27*, **[v19.6.8](//github.com/coderaiser/cloudcmd/releases/tag/v19.6.8)** +- *2026.02.26*, **[v19.6.7](//github.com/coderaiser/cloudcmd/releases/tag/v19.6.7)** +- *2026.02.26*, **[v19.6.6](//github.com/coderaiser/cloudcmd/releases/tag/v19.6.6)** +- *2026.02.26*, **[v19.6.5](//github.com/coderaiser/cloudcmd/releases/tag/v19.6.5)** +- *2026.02.25*, **[v19.6.4](//github.com/coderaiser/cloudcmd/releases/tag/v19.6.4)** +- *2026.02.24*, **[v19.6.3](//github.com/coderaiser/cloudcmd/releases/tag/v19.6.3)** +- *2026.02.24*, **[v19.6.2](//github.com/coderaiser/cloudcmd/releases/tag/v19.6.2)** +- *2026.02.24*, **[v19.6.1](//github.com/coderaiser/cloudcmd/releases/tag/v19.6.1)** +- *2026.02.21*, **[v19.6.0](//github.com/coderaiser/cloudcmd/releases/tag/v19.6.0)** +- *2026.02.18*, **[v19.5.1](//github.com/coderaiser/cloudcmd/releases/tag/v19.5.1)** +- *2026.02.18*, **[v19.5.0](//github.com/coderaiser/cloudcmd/releases/tag/v19.5.0)** +- *2026.02.18*, **[v19.4.1](//github.com/coderaiser/cloudcmd/releases/tag/v19.4.1)** +- *2026.02.18*, **[v19.4.0](//github.com/coderaiser/cloudcmd/releases/tag/v19.4.0)** +- *2026.02.15*, **[v19.3.9](//github.com/coderaiser/cloudcmd/releases/tag/v19.3.9)** +- *2026.02.15*, **[v19.3.8](//github.com/coderaiser/cloudcmd/releases/tag/v19.3.8)** +- *2026.02.13*, **[v19.3.7](//github.com/coderaiser/cloudcmd/releases/tag/v19.3.7)** +- *2026.02.12*, **[v19.3.6](//github.com/coderaiser/cloudcmd/releases/tag/v19.3.6)** +- *2026.02.08*, **[v19.3.5](//github.com/coderaiser/cloudcmd/releases/tag/v19.3.5)** +- *2026.02.06*, **[v19.3.4](//github.com/coderaiser/cloudcmd/releases/tag/v19.3.4)** +- *2026.02.05*, **[v19.3.3](//github.com/coderaiser/cloudcmd/releases/tag/v19.3.3)** +- *2026.02.04*, **[v19.3.2](//github.com/coderaiser/cloudcmd/releases/tag/v19.3.2)** +- *2026.02.03*, **[v19.3.1](//github.com/coderaiser/cloudcmd/releases/tag/v19.3.1)** +- *2026.02.03*, **[v19.3.0](//github.com/coderaiser/cloudcmd/releases/tag/v19.3.0)** +- *2026.02.03*, **[v19.2.0](//github.com/coderaiser/cloudcmd/releases/tag/v19.2.0)** +- *2026.02.02*, **[v19.1.21](//github.com/coderaiser/cloudcmd/releases/tag/v19.1.21)** +- *2026.01.31*, **[v19.1.20](//github.com/coderaiser/cloudcmd/releases/tag/v19.1.20)** +- *2026.01.30*, **[v19.1.19](//github.com/coderaiser/cloudcmd/releases/tag/v19.1.19)** +- *2026.01.30*, **[v19.1.18](//github.com/coderaiser/cloudcmd/releases/tag/v19.1.18)** +- *2026.01.29*, **[v19.1.17](//github.com/coderaiser/cloudcmd/releases/tag/v19.1.17)** +- *2026.01.28*, **[v19.1.16](//github.com/coderaiser/cloudcmd/releases/tag/v19.1.16)** +- *2026.01.28*, **[v19.1.15](//github.com/coderaiser/cloudcmd/releases/tag/v19.1.15)** +- *2026.01.28*, **[v19.1.14](//github.com/coderaiser/cloudcmd/releases/tag/v19.1.14)** +- *2026.01.27*, **[v19.1.13](//github.com/coderaiser/cloudcmd/releases/tag/v19.1.13)** +- *2026.01.27*, **[v19.1.12](//github.com/coderaiser/cloudcmd/releases/tag/v19.1.12)** +- *2026.01.25*, **[v19.1.11](//github.com/coderaiser/cloudcmd/releases/tag/v19.1.11)** +- *2026.01.25*, **[v19.1.10](//github.com/coderaiser/cloudcmd/releases/tag/v19.1.10)** +- *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.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)** +- *2023.12.12*, **[v17.0.0](//github.com/coderaiser/cloudcmd/releases/tag/v17.0.0)** +- *2023.12.08*, **[v16.18.0](//github.com/coderaiser/cloudcmd/releases/tag/v16.18.0)** +- *2023.12.04*, **[v16.17.9](//github.com/coderaiser/cloudcmd/releases/tag/v16.17.9)** +- *2023.12.04*, **[v16.17.8](//github.com/coderaiser/cloudcmd/releases/tag/v16.17.8)** +- *2023.10.12*, **[v16.17.7](//github.com/coderaiser/cloudcmd/releases/tag/v16.17.7)** +- *2023.09.22*, **[v16.17.6](//github.com/coderaiser/cloudcmd/releases/tag/v16.17.6)** +- *2023.09.06*, **[v16.17.5](//github.com/coderaiser/cloudcmd/releases/tag/v16.17.5)** +- *2023.09.05*, **[v16.17.4](//github.com/coderaiser/cloudcmd/releases/tag/v16.17.4)** +- *2023.09.05*, **[v16.17.3](//github.com/coderaiser/cloudcmd/releases/tag/v16.17.3)** +- *2023.09.04*, **[v16.17.2](//github.com/coderaiser/cloudcmd/releases/tag/v16.17.2)** +- *2023.09.04*, **[v16.17.1](//github.com/coderaiser/cloudcmd/releases/tag/v16.17.1)** +- *2023.09.04*, **[v16.17.0](//github.com/coderaiser/cloudcmd/releases/tag/v16.17.0)** +- *2023.08.10*, **[v16.16.3](//github.com/coderaiser/cloudcmd/releases/tag/v16.16.3)** +- *2023.08.09*, **[v16.16.2](//github.com/coderaiser/cloudcmd/releases/tag/v16.16.2)** +- *2023.08.07*, **[v16.16.1](//github.com/coderaiser/cloudcmd/releases/tag/v16.16.1)** +- *2023.07.09*, **[v16.16.0](//github.com/coderaiser/cloudcmd/releases/tag/v16.16.0)** +- *2023.05.17*, **[v16.15.0](//github.com/coderaiser/cloudcmd/releases/tag/v16.15.0)** +- *2023.03.21*, **[v16.14.1](//github.com/coderaiser/cloudcmd/releases/tag/v16.14.1)** +- *2023.03.08*, **[v16.14.0](//github.com/coderaiser/cloudcmd/releases/tag/v16.14.0)** +- *2023.01.30*, **[v16.13.1](//github.com/coderaiser/cloudcmd/releases/tag/v16.13.1)** +- *2023.01.29*, **[v16.13.0](//github.com/coderaiser/cloudcmd/releases/tag/v16.13.0)** +- *2023.01.29*, **[v16.12.0](//github.com/coderaiser/cloudcmd/releases/tag/v16.12.0)** +- *2023.01.22*, **[v16.11.0](//github.com/coderaiser/cloudcmd/releases/tag/v16.11.0)** +- *2023.01.19*, **[v16.10.0](//github.com/coderaiser/cloudcmd/releases/tag/v16.10.0)** +- *2023.01.18*, **[v16.9.1](//github.com/coderaiser/cloudcmd/releases/tag/v16.9.1)** +- *2023.01.17*, **[v16.9.0](//github.com/coderaiser/cloudcmd/releases/tag/v16.9.0)** +- *2023.01.16*, **[v16.8.0](//github.com/coderaiser/cloudcmd/releases/tag/v16.8.0)** +- *2023.01.15*, **[v16.7.0](//github.com/coderaiser/cloudcmd/releases/tag/v16.7.0)** +- *2022.10.20*, **[v16.6.1](//github.com/coderaiser/cloudcmd/releases/tag/v16.6.1)** +- *2022.10.09*, **[v16.6.0](//github.com/coderaiser/cloudcmd/releases/tag/v16.6.0)** +- *2022.08.06*, **[v16.5.0](//github.com/coderaiser/cloudcmd/releases/tag/v16.5.0)** +- *2022.07.20*, **[v16.4.1](//github.com/coderaiser/cloudcmd/releases/tag/v16.4.1)** +- *2022.07.11*, **[v16.4.0](//github.com/coderaiser/cloudcmd/releases/tag/v16.4.0)** +- *2022.07.02*, **[v16.3.1](//github.com/coderaiser/cloudcmd/releases/tag/v16.3.1)** +- *2022.07.01*, **[v16.3.0](//github.com/coderaiser/cloudcmd/releases/tag/v16.3.0)** +- *2022.06.17*, **[v16.2.0](//github.com/coderaiser/cloudcmd/releases/tag/v16.2.0)** +- *2022.05.12*, **[v16.1.1](//github.com/coderaiser/cloudcmd/releases/tag/v16.1.1)** +- *2022.04.23*, **[v16.1.0](//github.com/coderaiser/cloudcmd/releases/tag/v16.1.0)** +- *2022.04.22*, **[v16.0.1](//github.com/coderaiser/cloudcmd/releases/tag/v16.0.1)** +- *2022.02.19*, **[v16.0.0](//github.com/coderaiser/cloudcmd/releases/tag/v16.0.0)** +- *2022.01.20*, **[v15.9.15](//github.com/coderaiser/cloudcmd/releases/tag/v15.9.15)** +- *2022.01.13*, **[v15.9.14](//github.com/coderaiser/cloudcmd/releases/tag/v15.9.14)** +- *2021.12.23*, **[v15.9.13](//github.com/coderaiser/cloudcmd/releases/tag/v15.9.13)** +- *2021.12.16*, **[v15.9.12](//github.com/coderaiser/cloudcmd/releases/tag/v15.9.12)** +- *2021.12.09*, **[v15.9.11](//github.com/coderaiser/cloudcmd/releases/tag/v15.9.11)** +- *2021.12.04*, **[v15.9.10](//github.com/coderaiser/cloudcmd/releases/tag/v15.9.10)** +- *2021.11.22*, **[v15.9.9](//github.com/coderaiser/cloudcmd/releases/tag/v15.9.9)** +- *2021.02.03*, **[v15.6.0](//github.com/coderaiser/cloudcmd/releases/tag/v15.6.0)** +- *2021.02.02*, **[v15.5.2](//github.com/coderaiser/cloudcmd/releases/tag/v15.5.2)** +- *2021.01.31*, **[v15.5.1](//github.com/coderaiser/cloudcmd/releases/tag/v15.5.1)** +- *2021.01.30*, **[v15.5.0](//github.com/coderaiser/cloudcmd/releases/tag/v15.5.0)** +- *2021.01.26*, **[v15.4.4](//github.com/coderaiser/cloudcmd/releases/tag/v15.4.4)** +- *2021.01.25*, **[v15.4.3](//github.com/coderaiser/cloudcmd/releases/tag/v15.4.3)** +- *2021.01.21*, **[v15.4.2](//github.com/coderaiser/cloudcmd/releases/tag/v15.4.2)** +- *2021.01.20*, **[v15.4.1](//github.com/coderaiser/cloudcmd/releases/tag/v15.4.1)** +- *2021.01.19*, **[v15.4.0](//github.com/coderaiser/cloudcmd/releases/tag/v15.4.0)** +- *2021.01.19*, **[v15.3.4](//github.com/coderaiser/cloudcmd/releases/tag/v15.3.4)** +- *2021.01.17*, **[v15.3.1](//github.com/coderaiser/cloudcmd/releases/tag/v15.3.1)** +- *2021.01.17*, **[v15.3.0](//github.com/coderaiser/cloudcmd/releases/tag/v15.3.0)** +- *2021.01.16*, **[v15.2.0](//github.com/coderaiser/cloudcmd/releases/tag/v15.2.0)** +- *2021.01.07*, **[v15.1.0](//github.com/coderaiser/cloudcmd/releases/tag/v15.1.0)** +- *2021.01.05*, **[v15.0.4](//github.com/coderaiser/cloudcmd/releases/tag/v15.0.4)** +- *2020.01.05*, **[v15.0.3](//github.com/coderaiser/cloudcmd/releases/tag/v15.0.3)** +- *2020.12.31*, **[v15.0.2](//github.com/coderaiser/cloudcmd/releases/tag/v15.0.2)** +- *2020.12.30*, **[v15.0.1](//github.com/coderaiser/cloudcmd/releases/tag/v15.0.1)** +- *2020.12.28*, **[v15.0.0](//github.com/coderaiser/cloudcmd/releases/tag/v15.0.0)** +- *2020.08.21*, **[v14.9.3](//github.com/coderaiser/cloudcmd/releases/tag/v14.9.3)** +- *2020.08.19*, **[v14.9.2](//github.com/coderaiser/cloudcmd/releases/tag/v14.9.2)** +- *2020.08.16*, **[v14.9.1](//github.com/coderaiser/cloudcmd/releases/tag/v14.9.1)** +- *2020.08.14*, **[v14.9.0](//github.com/coderaiser/cloudcmd/releases/tag/v14.9.0)** +- *2020.08.14*, **[v14.8.0](//github.com/coderaiser/cloudcmd/releases/tag/v14.8.0)** +- *2020.08.11*, **[v14.7.2](//github.com/coderaiser/cloudcmd/releases/tag/v14.7.2)** +- *2020.08.11*, **[v14.7.1](//github.com/coderaiser/cloudcmd/releases/tag/v14.7.1)** +- *2020.08.10*, **[v14.7.0](//github.com/coderaiser/cloudcmd/releases/tag/v14.7.0)** +- *2020.05.20*, **[v14.6.0](//github.com/coderaiser/cloudcmd/releases/tag/v14.6.0)** +- *2020.05.06*, **[v14.5.1](//github.com/coderaiser/cloudcmd/releases/tag/v14.5.1)** +- *2020.05.04*, **[v14.5.0](//github.com/coderaiser/cloudcmd/releases/tag/v14.5.0)** +- *2020.04.27*, **[v14.4.0](//github.com/coderaiser/cloudcmd/releases/tag/v14.4.0)** +- *2020.04.13*, **[v14.3.10](//github.com/coderaiser/cloudcmd/releases/tag/v14.3.10)** +- *2020.04.10*, **[v14.3.9](//github.com/coderaiser/cloudcmd/releases/tag/v14.3.9)** +- *2020.04.04*, **[v14.3.8](//github.com/coderaiser/cloudcmd/releases/tag/v14.3.8)** +- *2020.04.03*, **[v14.3.7](//github.com/coderaiser/cloudcmd/releases/tag/v14.3.7)** +- *2020.03.31*, **[v14.3.6](//github.com/coderaiser/cloudcmd/releases/tag/v14.3.6)** +- *2020.03.25*, **[v14.3.5](//github.com/coderaiser/cloudcmd/releases/tag/v14.3.5)** +- *2020.03.03*, **[v14.3.4](//github.com/coderaiser/cloudcmd/releases/tag/v14.3.4)** +- *2020.02.23*, **[v14.3.3](//github.com/coderaiser/cloudcmd/releases/tag/v14.3.3)** +- *2020.02.21*, **[v14.3.2](//github.com/coderaiser/cloudcmd/releases/tag/v14.3.2)** +- *2020.02.21*, **[v14.3.1](//github.com/coderaiser/cloudcmd/releases/tag/v14.3.1)** +- *2020.01.29*, **[v14.3.0](//github.com/coderaiser/cloudcmd/releases/tag/v14.3.0)** +- *2019.12.21*, **[v14.2.1](//github.com/coderaiser/cloudcmd/releases/tag/v14.2.1)** +- *2019.11.15*, **[v14.2.0](//github.com/coderaiser/cloudcmd/releases/tag/v14.2.0)** +- *2019.10.16*, **[v14.1.2](//github.com/coderaiser/cloudcmd/releases/tag/v14.1.2)** +- *2019.10.09*, **[v14.1.1](//github.com/coderaiser/cloudcmd/releases/tag/v14.1.1)** +- *2019.10.02*, **[v14.1.0](//github.com/coderaiser/cloudcmd/releases/tag/v14.1.0)** +- *2019.09.25*, **[v14.0.2](//github.com/coderaiser/cloudcmd/releases/tag/v14.0.2)** +- *2019.09.25*, **[v14.0.1](//github.com/coderaiser/cloudcmd/releases/tag/v14.0.1)** +- *2019.09.22*, **[v14.0.0](//github.com/coderaiser/cloudcmd/releases/tag/v14.0.0)** +- *2019.09.21*, **[v13.4.2](//github.com/coderaiser/cloudcmd/releases/tag/v13.4.2)** +- *2019.09.20*, **[v13.4.1](//github.com/coderaiser/cloudcmd/releases/tag/v13.4.1)** +- *2019.09.03*, **[v13.4.0](//github.com/coderaiser/cloudcmd/releases/tag/v13.4.0)** +- *2019.08.28*, **[v13.3.0](//github.com/coderaiser/cloudcmd/releases/tag/v13.3.0)** +- *2019.08.22*, **[v13.2.1](//github.com/coderaiser/cloudcmd/releases/tag/v13.2.1)** +- *2019.08.20*, **[v13.2.0](//github.com/coderaiser/cloudcmd/releases/tag/v13.2.0)** +- *2019.08.16*, **[v13.1.0](//github.com/coderaiser/cloudcmd/releases/tag/v13.1.0)** +- *2019.08.14*, **[v13.0.1](//github.com/coderaiser/cloudcmd/releases/tag/v13.0.1)** +- *2019.08.14*, **[v13.0.0](//github.com/coderaiser/cloudcmd/releases/tag/v13.0.0)** +- *2019.08.02*, **[v12.6.3](//github.com/coderaiser/cloudcmd/releases/tag/v12.6.3)** +- *2019.06.06*, **[v12.6.2](//github.com/coderaiser/cloudcmd/releases/tag/v12.6.2)** +- *2019.06.04*, **[v12.6.1](//github.com/coderaiser/cloudcmd/releases/tag/v12.6.1)** +- *2019.05.31*, **[v12.6.0](//github.com/coderaiser/cloudcmd/releases/tag/v12.6.0)** +- *2019.05.28*, **[v12.5.0](//github.com/coderaiser/cloudcmd/releases/tag/v12.5.0)** +- *2019.05.27*, **[v12.4.0](//github.com/coderaiser/cloudcmd/releases/tag/v12.4.0)** +- *2019.05.24*, **[v12.3.2](//github.com/coderaiser/cloudcmd/releases/tag/v12.3.2)** +- *2019.05.24*, **[v12.3.1](//github.com/coderaiser/cloudcmd/releases/tag/v12.3.1)** +- *2019.05.24*, **[v12.3.0](//github.com/coderaiser/cloudcmd/releases/tag/v12.3.0)** +- *2019.05.13*, **[v12.2.0](//github.com/coderaiser/cloudcmd/releases/tag/v12.2.0)** +- *2019.04.15*, **[v12.1.0](//github.com/coderaiser/cloudcmd/releases/tag/v12.1.0)** +- *2019.04.04*, **[v12.0.2](//github.com/coderaiser/cloudcmd/releases/tag/v12.0.2)** +- *2019.04.04*, **[v12.0.1](//github.com/coderaiser/cloudcmd/releases/tag/v12.0.1)** +- *2019.04.01*, **[v12.0.0](//github.com/coderaiser/cloudcmd/releases/tag/v12.0.0)** +- *2019.03.27*, **[v11.8.6](//github.com/coderaiser/cloudcmd/releases/tag/v11.8.6)** +- *2019.02.20*, **[v11.8.5](//github.com/coderaiser/cloudcmd/releases/tag/v11.8.5)** +- *2019.02.15*, **[v11.8.4](//github.com/coderaiser/cloudcmd/releases/tag/v11.8.4)** +- *2018.12.04*, **[v11.8.3](//github.com/coderaiser/cloudcmd/releases/tag/v11.8.3)** +- *2018.11.22*, **[v11.8.2](//github.com/coderaiser/cloudcmd/releases/tag/v11.8.2)** +- *2018.11.14*, **[v11.8.1](//github.com/coderaiser/cloudcmd/releases/tag/v11.8.1)** +- *2018.11.09*, **[v11.8.0](//github.com/coderaiser/cloudcmd/releases/tag/v11.8.0)** +- *2018.11.01*, **[v11.7.1](//github.com/coderaiser/cloudcmd/releases/tag/v11.7.1)** +- *2018.10.25*, **[v11.7.0](//github.com/coderaiser/cloudcmd/releases/tag/v11.7.0)** +- *2018.10.23*, **[v11.6.0](//github.com/coderaiser/cloudcmd/releases/tag/v11.6.0)** +- *2018.10.23*, **[v11.5.4](//github.com/coderaiser/cloudcmd/releases/tag/v11.5.4)** +- *2018.10.19*, **[v11.5.3](//github.com/coderaiser/cloudcmd/releases/tag/v11.5.3)** +- *2018.10.19*, **[v11.5.2](//github.com/coderaiser/cloudcmd/releases/tag/v11.5.2)** +- *2018.10.17*, **[v11.5.1](//github.com/coderaiser/cloudcmd/releases/tag/v11.5.1)** +- *2018.10.16*, **[v11.5.0](//github.com/coderaiser/cloudcmd/releases/tag/v11.5.0)** +- *2018.10.16*, **[v11.4.1](//github.com/coderaiser/cloudcmd/releases/tag/v11.4.1)** +- *2018.10.12*, **[v11.4.0](//github.com/coderaiser/cloudcmd/releases/tag/v11.4.0)** +- *2018.10.12*, **[v11.3.1](//github.com/coderaiser/cloudcmd/releases/tag/v11.3.1)** +- *2018.10.11*, **[v11.3.0](//github.com/coderaiser/cloudcmd/releases/tag/v11.3.0)** +- *2018.10.04*, **[v11.2.3](//github.com/coderaiser/cloudcmd/releases/tag/v11.2.3)** +- *2018.09.28*, **[v11.2.2](//github.com/coderaiser/cloudcmd/releases/tag/v11.2.2)** +- *2018.09.28*, **[v11.2.1](//github.com/coderaiser/cloudcmd/releases/tag/v11.2.1)** +- *2018.09.28*, **[v11.2.0](//github.com/coderaiser/cloudcmd/releases/tag/v11.2.0)** +- *2018.09.27*, **[v11.1.0](//github.com/coderaiser/cloudcmd/releases/tag/v11.1.0)** +- *2018.09.26*, **[v11.0.0](//github.com/coderaiser/cloudcmd/releases/tag/v11.0.0)** +- *2018.09.21*, **[v10.8.2](//github.com/coderaiser/cloudcmd/releases/tag/v10.8.2)** +- *2018.09.20*, **[v10.8.1](//github.com/coderaiser/cloudcmd/releases/tag/v10.8.1)** +- *2018.09.19*, **[v10.8.0](//github.com/coderaiser/cloudcmd/releases/tag/v10.8.0)** +- *2018.09.14*, **[v10.7.0](//github.com/coderaiser/cloudcmd/releases/tag/v10.7.0)** +- *2018.09.10*, **[v10.6.0](//github.com/coderaiser/cloudcmd/releases/tag/v10.6.0)** +- *2018.09.08*, **[v10.5.3](//github.com/coderaiser/cloudcmd/releases/tag/v10.5.3)** +- *2018.08.25*, **[v10.5.2](//github.com/coderaiser/cloudcmd/releases/tag/v10.5.2)** +- *2018.08.25*, **[v10.5.1](//github.com/coderaiser/cloudcmd/releases/tag/v10.5.1)** +- *2018.08.23*, **[v10.5.0](//github.com/coderaiser/cloudcmd/releases/tag/v10.5.0)** +- *2018.07.18*, **[v10.4.1](//github.com/coderaiser/cloudcmd/releases/tag/v10.4.1)** +- *2018.07.17*, **[v10.4.0](//github.com/coderaiser/cloudcmd/releases/tag/v10.4.0)** +- *2018.07.02*, **[v10.3.2](//github.com/coderaiser/cloudcmd/releases/tag/v10.3.2)** +- *2018.06.25*, **[v10.3.1](//github.com/coderaiser/cloudcmd/releases/tag/v10.3.1)** +- *2018.06.22*, **[v10.3.0](//github.com/coderaiser/cloudcmd/releases/tag/v10.3.0)** +- *2018.06.21*, **[v10.2.3](//github.com/coderaiser/cloudcmd/releases/tag/v10.2.3)** +- *2018.06.15*, **[v10.2.2](//github.com/coderaiser/cloudcmd/releases/tag/v10.2.2)** +- *2018.06.13*, **[v10.2.1](//github.com/coderaiser/cloudcmd/releases/tag/v10.2.1)** +- *2018.06.11*, **[v10.2.0](//github.com/coderaiser/cloudcmd/releases/tag/v10.2.0)** +- *2018.06.09*, **[v10.1.2](//github.com/coderaiser/cloudcmd/releases/tag/v10.1.2)** +- *2018.06.08*, **[v10.1.1](//github.com/coderaiser/cloudcmd/releases/tag/v10.1.1)** +- *2018.06.07*, **[v10.1.0](//github.com/coderaiser/cloudcmd/releases/tag/v10.1.0)** +- *2018.06.04*, **[v10.0.3](//github.com/coderaiser/cloudcmd/releases/tag/v10.0.3)** +- *2018.05.29*, **[v10.0.2](//github.com/coderaiser/cloudcmd/releases/tag/v10.0.2)** +- *2018.05.29*, **[v10.0.1](//github.com/coderaiser/cloudcmd/releases/tag/v10.0.1)** +- *2018.05.25*, **[v10.0.0](//github.com/coderaiser/cloudcmd/releases/tag/v10.0.0)** +- *2018.05.24*, **[v9.6.0](//github.com/coderaiser/cloudcmd/releases/tag/v9.6.0)** +- *2018.05.15*, **[v9.5.0](//github.com/coderaiser/cloudcmd/releases/tag/v9.5.0)** +- *2018.05.08*, **[v9.4.0](//github.com/coderaiser/cloudcmd/releases/tag/v9.4.0)** +- *2018.05.01*, **[v9.3.2](//github.com/coderaiser/cloudcmd/releases/tag/v9.3.2)** +- *2018.04.30*, **[v9.3.1](//github.com/coderaiser/cloudcmd/releases/tag/v9.3.1)** +- *2018.04.27*, **[v9.3.0](//github.com/coderaiser/cloudcmd/releases/tag/v9.3.0)** +- *2018.04.25*, **[v9.2.0](//github.com/coderaiser/cloudcmd/releases/tag/v9.2.0)** +- *2018.04.23*, **[v9.1.6](//github.com/coderaiser/cloudcmd/releases/tag/v9.1.6)** +- *2018.04.19*, **[v9.1.5](//github.com/coderaiser/cloudcmd/releases/tag/v9.1.5)** +- *2018.04.17*, **[v9.1.4](//github.com/coderaiser/cloudcmd/releases/tag/v9.1.4)** +- *2018.04.16*, **[v9.1.3](//github.com/coderaiser/cloudcmd/releases/tag/v9.1.3)** +- *2018.04.12*, **[v9.1.2](//github.com/coderaiser/cloudcmd/releases/tag/v9.1.2)** +- *2018.04.10*, **[v9.1.1](//github.com/coderaiser/cloudcmd/releases/tag/v9.1.1)** +- *2018.04.02*, **[v9.1.0](//github.com/coderaiser/cloudcmd/releases/tag/v9.1.0)** +- *2018.03.30*, **[v9.0.0](//github.com/coderaiser/cloudcmd/releases/tag/v9.0.0)** +- *2018.03.24*, **[v8.5.2](//github.com/coderaiser/cloudcmd/releases/tag/v8.5.2)** +- *2018.03.24*, **[v8.5.1](//github.com/coderaiser/cloudcmd/releases/tag/v8.5.1)** +- *2018.03.20*, **[v8.5.0](//github.com/coderaiser/cloudcmd/releases/tag/v8.5.0)** +- *2018.03.16*, **[v8.4.1](//github.com/coderaiser/cloudcmd/releases/tag/v8.4.1)** +- *2018.03.14*, **[v8.4.0](//github.com/coderaiser/cloudcmd/releases/tag/v8.4.0)** +- *2018.03.02*, **[v8.3.0](//github.com/coderaiser/cloudcmd/releases/tag/v8.3.0)** +- *2018.02.19*, **[v8.2.2](//github.com/coderaiser/cloudcmd/releases/tag/v8.2.2)** +- *2018.01.23*, **[v8.2.1](//github.com/coderaiser/cloudcmd/releases/tag/v8.2.1)** +- *2018.01.16*, **[v8.2.0](//github.com/coderaiser/cloudcmd/releases/tag/v8.2.0)** +- *2017.12.08*, **[v8.1.3](//github.com/coderaiser/cloudcmd/releases/tag/v8.1.3)** +- *2017.10.23*, **[v8.1.2](//github.com/coderaiser/cloudcmd/releases/tag/v8.1.2)** +- *2017.10.19*, **[v8.1.1](//github.com/coderaiser/cloudcmd/releases/tag/v8.1.1)** +- *2017.10.19*, **[v8.1.0](//github.com/coderaiser/cloudcmd/releases/tag/v8.1.0)** +- *2017.10.13*, **[v8.0.5](//github.com/coderaiser/cloudcmd/releases/tag/v8.0.5)** +- *2017.10.10*, **[v8.0.4](//github.com/coderaiser/cloudcmd/releases/tag/v8.0.4)** +- *2017.10.06*, **[v8.0.3](//github.com/coderaiser/cloudcmd/releases/tag/v8.0.3)** +- *2017.10.06*, **[v8.0.2](//github.com/coderaiser/cloudcmd/releases/tag/v8.0.2)** +- *2017.10.02*, **[v8.0.1](//github.com/coderaiser/cloudcmd/releases/tag/v8.0.1)** +- *2017.10.02*, **[v8.0.0](//github.com/coderaiser/cloudcmd/releases/tag/v8.0.0)** +- *2017.09.29*, **[v7.9.0](//github.com/coderaiser/cloudcmd/releases/tag/v7.9.0)** +- *2017.09.25*, **[v7.8.0](//github.com/coderaiser/cloudcmd/releases/tag/v7.8.0)** +- *2017.09.22*, **[v7.7.3](//github.com/coderaiser/cloudcmd/releases/tag/v7.7.3)** +- *2017.09.22*, **[v7.7.2](//github.com/coderaiser/cloudcmd/releases/tag/v7.7.2)** +- *2017.09.18*, **[v7.7.1](//github.com/coderaiser/cloudcmd/releases/tag/v7.7.1)** +- *2017.09.12*, **[v7.7.0](//github.com/coderaiser/cloudcmd/releases/tag/v7.7.0)** +- *2017.09.11*, **[v7.6.0](//github.com/coderaiser/cloudcmd/releases/tag/v7.6.0)** +- *2017.09.08*, **[v7.5.2](//github.com/coderaiser/cloudcmd/releases/tag/v7.5.2)** +- *2017.09.08*, **[v7.5.1](//github.com/coderaiser/cloudcmd/releases/tag/v7.5.1)** +- *2017.09.08*, **[v7.5.0](//github.com/coderaiser/cloudcmd/releases/tag/v7.5.0)** +- *2017.09.04*, **[v7.4.0](//github.com/coderaiser/cloudcmd/releases/tag/v7.4.0)** +- *2017.08.29*, **[v7.3.2](//github.com/coderaiser/cloudcmd/releases/tag/v7.3.2)** +- *2017.08.14*, **[v7.3.1](//github.com/coderaiser/cloudcmd/releases/tag/v7.3.1)** +- *2017.08.14*, **[v7.3.0](//github.com/coderaiser/cloudcmd/releases/tag/v7.3.0)** +- *2017.08.11*, **[v7.2.2](//github.com/coderaiser/cloudcmd/releases/tag/v7.2.2)** +- *2017.07.31*, **[v7.2.1](//github.com/coderaiser/cloudcmd/releases/tag/v7.2.1)** +- *2017.07.28*, **[v7.2.0](//github.com/coderaiser/cloudcmd/releases/tag/v7.2.0)** +- *2017.07.27*, **[v7.1.1](//github.com/coderaiser/cloudcmd/releases/tag/v7.1.1)** +- *2017.07.27*, **[v7.1.0](//github.com/coderaiser/cloudcmd/releases/tag/v7.1.0)** +- *2017.07.14*, **[v7.0.2](//github.com/coderaiser/cloudcmd/releases/tag/v7.0.2)** +- *2017.07.12*, **[v7.0.1](//github.com/coderaiser/cloudcmd/releases/tag/v7.0.1)** +- *2017.07.12*, **[v7.0.0](//github.com/coderaiser/cloudcmd/releases/tag/v7.0.0)** +- *2017.07.14*, **[v6.15.5](//github.com/coderaiser/cloudcmd/releases/tag/v6.15.5)** +- *2017.07.10*, **[v6.15.4](//github.com/coderaiser/cloudcmd/releases/tag/v6.15.4)** +- *2017.06.26*, **[v6.15.3](//github.com/coderaiser/cloudcmd/releases/tag/v6.15.3)** +- *2017.06.22*, **[v6.15.2](//github.com/coderaiser/cloudcmd/releases/tag/v6.15.2)** +- *2017.06.14*, **[v6.15.1](//github.com/coderaiser/cloudcmd/releases/tag/v6.15.1)** +- *2017.06.06*, **[v6.15.0](//github.com/coderaiser/cloudcmd/releases/tag/v6.15.0)** +- *2017.05.25*, **[v6.14.4](//github.com/coderaiser/cloudcmd/releases/tag/v6.14.4)** +- *2017.05.22*, **[v6.14.3](//github.com/coderaiser/cloudcmd/releases/tag/v6.14.3)** +- *2017.05.18*, **[v6.14.2](//github.com/coderaiser/cloudcmd/releases/tag/v6.14.2)** +- *2017.05.18*, **[v6.14.1](//github.com/coderaiser/cloudcmd/releases/tag/v6.14.1)** - *2017.05.17*, **[v6.14.0](//github.com/coderaiser/cloudcmd/releases/tag/v6.14.0)** - *2017.05.15*, **[v6.13.0](//github.com/coderaiser/cloudcmd/releases/tag/v6.13.0)** - *2017.05.12*, **[v6.12.0](//github.com/coderaiser/cloudcmd/releases/tag/v6.12.0)** @@ -786,12 +1754,11 @@ Version history - *2012.07.11*, **[v0.1.1](//github.com/cloudcmd/archive/raw/master/cloudcmd-v0.1.1.zip)** - *2012.07.09*, **[v0.1.0](//github.com/cloudcmd/archive/raw/master/cloudcmd-v0.1.0.zip)** -Special Thanks ---------------- -- [Olena Zalitok](https://zalitok.github.io/ "Olena Zalitok") for **logo** and **favicon**. -- [TarZak](https://github.com/tarzak "TarZak") - - Russian and Ukrainian translations; - - config template and style; - - change order of directories and files; - - add ability do not hide path and header when files are scrolling; +## Special Thanks +- [Olena Zalitok](https://www.linkedin.com/in/ozalitok-ux-ui/ "Olena Zalitok") for **logo** and **favicon**. +- [TarZak](https://github.com/tarzak "TarZak") + - Russian and Ukrainian translations; + - config template and style; + - change order of directories and files; + - add ability to keep path and header when files are scrolling; diff --git a/LICENSE b/LICENSE index c7ef080f..a0d7436b 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ (The MIT License) -Copyright (c) 2012-2017 Coderaiser +Copyright (c) 2012-2025 Coderaiser Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/README.md b/README.md index 7fa28a77..dfe8d8c6 100644 --- a/README.md +++ b/README.md @@ -1,41 +1,33 @@ -# Cloud Commander v6.14.0 [![License][LicenseIMGURL]][LicenseURL] [![NPM version][NPMIMGURL]][NPMURL] [![Dependency Status][DependencyStatusIMGURL]][DependencyStatusURL] [![Build Status][BuildStatusIMGURL]][BuildStatusURL] [![Package Quality][PackageQualityIMGURL]][PackageQualityURL] [![Codacy][CodacyIMG]][CodacyURL] [![Gitter][GitterIMGURL]][GitterURL] [![OpenCollective](https://opencollective.com/cloudcmd/backers/badge.svg)](#backers) [![OpenCollective](https://opencollective.com/cloudcmd/sponsors/badge.svg)](#sponsors) +# Cloud Commander v19.19.1 [![Build Status][BuildStatusIMGURL]][BuildStatusURL] [![Codacy][CodacyIMG]][CodacyURL] [![Gitter][GitterIMGURL]][GitterURL] [![Deploy on InstaPods][DeployInstaPodsIMG]][DeployInstaPodsURL] -### [Main][MainURL] [Blog][BlogURL] Live([Heroku][HerokuURL]) +### [Main][MainURL] [Blog][BlogURL] [Support][SupportURL] [Demo][DemoURL] -[NPM_INFO_IMG]: https://nodei.co/npm/cloudcmd.png -[MainURL]: http://cloudcmd.io "Main" -[BlogURL]: http://blog.cloudcmd.io "Blog" -[HerokuURL]: http://cloudcmd.herokuapp.com/ "Heroku" -[NPMURL]: https://npmjs.org/package/cloudcmd "npm" -[NPMIMGURL]: https://img.shields.io/npm/v/cloudcmd.svg?style=flat -[LicenseURL]: https://tldrlegal.com/license/mit-license "MIT License" -[LicenseIMGURL]: https://img.shields.io/badge/license-MIT-317BF9.svg?style=flat -[DependencyStatusURL]: https://gemnasium.com/coderaiser/cloudcmd "Dependency Status" -[DependencyStatusIMGURL]: https://img.shields.io/gemnasium/coderaiser/cloudcmd.svg?style=flat -[BuildStatusURL]: https://travis-ci.org/coderaiser/cloudcmd "Build Status" -[BuildStatusIMGURL]: https://img.shields.io/travis/coderaiser/cloudcmd.svg?style=flat +[MainURL]: https://cloudcmd.io "Main" +[BlogURL]: https://blog.cloudcmd.io "Blog" +[SupportURL]: https://patreon.com/coderaiser "Patreon" +[DemoURL]: https://cloudcmd-zdp6.onrender.com +[NPM_INFO_IMG]: https://nodei.co/npm/cloudcmd.png +[BuildStatusURL]: https://github.com/coderaiser/cloudcmd/actions/workflows/nodejs.yml "Build Status" +[BuildStatusIMGURL]: https://github.com/coderaiser/cloudcmd/actions/workflows/nodejs.yml/badge.svg +[CodacyURL]: https://www.codacy.com/app/coderaiser/cloudcmd +[CodacyIMG]: https://api.codacy.com/project/badge/Grade/ddda78be780549ce8754f8d47a8c0e36 +[GitterURL]: https://gitter.im/cloudcmd/hello +[GitterIMGURL]: https://img.shields.io/gitter/room/coderaiser/cloudcmd.js.svg +[DeployURL]: https://heroku.com/deploy?template=https://github.com/coderaiser/cloudcmd "Deploy" +[DeployIMG]: https://www.herokucdn.com/deploy/button.png +[DeployInstaPodsIMG]: https://img.shields.io/badge/deploy%20on-InstaPods-blue +[DeployInstaPodsURL]: https://app.instapods.com/dashboard/pods/create?app=cloudcmd&ref=cloudcmd -[PackageQualityURL]: http://packagequality.com/#?package=cloudcmd "Package Quality" -[PackageQualityIMGURL]: http://packagequality.com/shield/cloudcmd.svg +**Cloud Commander** a file manager for the web with console and editor. -[CodacyURL]: https://www.codacy.com/app/coderaiser/cloudcmd -[CodacyIMG]: https://api.codacy.com/project/badge/Grade/ddda78be780549ce8754f8d47a8c0e36 - -[GitterURL]: https://gitter.im/cloudcmd -[GitterIMGURL]: https://img.shields.io/gitter/room/coderaiser/cloudcmd.js.svg - -[DeployURL]: https://heroku.com/deploy?template=https://github.com/coderaiser/cloudcmd "Deploy" -[DeployIMG]: https://www.herokucdn.com/deploy/button.png - -**Cloud Commander** is an orthodox web file manager with console and editor. - -![Cloud Commander](http://cloudcmd.io/img/logo/cloudcmd.png "Cloud Commander") +![Cloud Commander](https://cloudcmd.io/img/logo/cloudcmd.png "Cloud Commander") ## Install ``` npm i cloudcmd -g ``` + ## Start For starting just type in console: @@ -48,7 +40,13 @@ cloudcmd Open url `http://localhost:8000` in browser. +### View + +You will see something similar to this. +![View](https://cloudcmd.io/img/screen/view.png "View") + ## Deploy + `Cloud Commander` could be easily deployed to [Heroku][DeployURL]. [![Deploy][DeployIMG]][DeployURL] @@ -72,54 +70,72 @@ npm i cloudcmd express socket.io -S And create `index.js`: ```js -const http = require('http'); -const cloudcmd = require('cloudcmd'); -const io = require('socket.io'); -const app = require('express')(); +import http from 'node:http'; +import {cloudcmd} from 'cloudcmd'; +import {Server} from 'socket.io'; +import express from 'express'; + +const app = express(); const port = 1337; -const prefix = '/cloudcmd'; +const prefix = '/'; const server = http.createServer(app); -const socket = io.listen(server, { - path: `${prefix}/socket.io` +const socket = new Server(server, { + path: `${prefix}socket.io`, }); const config = { - prefix /* base URL or function which returns base URL (optional) */ + name: 'cloudcmd :)', }; -const plugins = [ - __dirname + '/plugin.js' -]; - const filePicker = { data: { FilePicker: { key: 'key', - } - } + }, + }, }; // override option from json/modules.json -const modules = {filePicker}; +const modules = { + filePicker, +}; -app.use(cloudcmd({ - socket, /* used by Config, Edit (optional) and Console (required) */ - config, /* config data (optional) */ - plugins, /* optional */ - modules, /* optional */ +const { + createConfigManager, + configPath, +} = cloudcmd; + +const configManager = createConfigManager({ + configPath, +}); + +app.use(prefix, cloudcmd({ + socket, // used by Config, Edit (optional) and Console (required) + config, // config data (optional) + modules, // optional + configManager, // optional })); server.listen(port); ``` -Docker ---------------- +## Docker + +The docker images are provided for multiple architectures and types. The following list shows all existing images: + +| Architecture | Type | +|----------------|--------------| +| amd64 | linux | +| arm64 (arm/v8) | linux | +| amd64 | 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: ```sh -docker run -v ~:/root -v /:/mnt/fs -t -p 8000:8000 coderaiser/cloudcmd +docker run -it --rm -v ~:/root -v /:/mnt/fs -w=/root -p 8000:8000 coderaiser/cloudcmd ``` Config would be read from home directory, hosts root file system would be mount to `/mnt/fs`, @@ -145,84 +161,19 @@ When you create this file run: docker-compose up ``` -Get involved ---------------- +## Documentation + +More documentation you can find on https://cloudcmd.io/. + +## Get involved There is a lot ways to be involved in `Cloud Commander` development: -- if you find a bug or got idea to share [create issue](https://github.com/coderaiser/cloudcmd/issues/new "Create issue"); +- support project on patreon: https://patreon.com/coderaiser; +- if you find a bug or got idea to share [create an issue](https://github.com/coderaiser/cloudcmd/issues/new "Create issue"); - if you fixed a bug, typo or implemented new feature [create pull request](https://github.com/coderaiser/cloudcmd/compare "Create pull request"); - if you know languages you can help with [site translations](https://github.com/coderaiser/cloudcmd/wiki "Cloud Commander community wiki"); -## Backers -Support us with a monthly donation and help us continue our activities. [[Become a backer](https://opencollective.com/cloudcmd#backer)] - -[![](https://opencollective.com/cloudcmd/backer/0/avatar.svg)](https://opencollective.com/cloudcmd/backer/0/website) -[![](https://opencollective.com/cloudcmd/backer/1/avatar.svg)](https://opencollective.com/cloudcmd/backer/1/website) -[![](https://opencollective.com/cloudcmd/backer/2/avatar.svg)](https://opencollective.com/cloudcmd/backer/2/website) -[![](https://opencollective.com/cloudcmd/backer/3/avatar.svg)](https://opencollective.com/cloudcmd/backer/3/website) -[![](https://opencollective.com/cloudcmd/backer/4/avatar.svg)](https://opencollective.com/cloudcmd/backer/4/website) -[![](https://opencollective.com/cloudcmd/backer/5/avatar.svg)](https://opencollective.com/cloudcmd/backer/5/website) -[![](https://opencollective.com/cloudcmd/backer/6/avatar.svg)](https://opencollective.com/cloudcmd/backer/6/website) -[![](https://opencollective.com/cloudcmd/backer/7/avatar.svg)](https://opencollective.com/cloudcmd/backer/7/website) -[![](https://opencollective.com/cloudcmd/backer/8/avatar.svg)](https://opencollective.com/cloudcmd/backer/8/website) -[![](https://opencollective.com/cloudcmd/backer/9/avatar.svg)](https://opencollective.com/cloudcmd/backer/9/website) -[![](https://opencollective.com/cloudcmd/backer/10/avatar.svg)](https://opencollective.com/cloudcmd/backer/10/website) -[![](https://opencollective.com/cloudcmd/backer/11/avatar.svg)](https://opencollective.com/cloudcmd/backer/11/website) -[![](https://opencollective.com/cloudcmd/backer/12/avatar.svg)](https://opencollective.com/cloudcmd/backer/12/website) -[![](https://opencollective.com/cloudcmd/backer/13/avatar.svg)](https://opencollective.com/cloudcmd/backer/13/website) -[![](https://opencollective.com/cloudcmd/backer/14/avatar.svg)](https://opencollective.com/cloudcmd/backer/14/website) -[![](https://opencollective.com/cloudcmd/backer/15/avatar.svg)](https://opencollective.com/cloudcmd/backer/15/website) -[![](https://opencollective.com/cloudcmd/backer/16/avatar.svg)](https://opencollective.com/cloudcmd/backer/16/website) -[![](https://opencollective.com/cloudcmd/backer/17/avatar.svg)](https://opencollective.com/cloudcmd/backer/17/website) -[![](https://opencollective.com/cloudcmd/backer/18/avatar.svg)](https://opencollective.com/cloudcmd/backer/18/website) -[![](https://opencollective.com/cloudcmd/backer/19/avatar.svg)](https://opencollective.com/cloudcmd/backer/19/website) -[![](https://opencollective.com/cloudcmd/backer/20/avatar.svg)](https://opencollective.com/cloudcmd/backer/20/website) -[![](https://opencollective.com/cloudcmd/backer/21/avatar.svg)](https://opencollective.com/cloudcmd/backer/21/website) -[![](https://opencollective.com/cloudcmd/backer/22/avatar.svg)](https://opencollective.com/cloudcmd/backer/22/website) -[![](https://opencollective.com/cloudcmd/backer/23/avatar.svg)](https://opencollective.com/cloudcmd/backer/23/website) -[![](https://opencollective.com/cloudcmd/backer/24/avatar.svg)](https://opencollective.com/cloudcmd/backer/24/website) -[![](https://opencollective.com/cloudcmd/backer/25/avatar.svg)](https://opencollective.com/cloudcmd/backer/25/website) -[![](https://opencollective.com/cloudcmd/backer/26/avatar.svg)](https://opencollective.com/cloudcmd/backer/26/website) -[![](https://opencollective.com/cloudcmd/backer/27/avatar.svg)](https://opencollective.com/cloudcmd/backer/27/website) -[![](https://opencollective.com/cloudcmd/backer/28/avatar.svg)](https://opencollective.com/cloudcmd/backer/28/website) -[![](https://opencollective.com/cloudcmd/backer/29/avatar.svg)](https://opencollective.com/cloudcmd/backer/29/website) - -## Sponsors -Become a sponsor and get your logo on our README on Github with a link to your site. [[Become a sponsor](https://opencollective.com/cloudcmd#sponsor)] - -[![](https://opencollective.com/cloudcmd/sponsor/0/avatar.svg)](https://opencollective.com/cloudcmd/sponsor/0/website) -[![](https://opencollective.com/cloudcmd/sponsor/1/avatar.svg)](https://opencollective.com/cloudcmd/sponsor/1/website) -[![](https://opencollective.com/cloudcmd/sponsor/2/avatar.svg)](https://opencollective.com/cloudcmd/sponsor/2/website) -[![](https://opencollective.com/cloudcmd/sponsor/3/avatar.svg)](https://opencollective.com/cloudcmd/sponsor/3/website) -[![](https://opencollective.com/cloudcmd/sponsor/4/avatar.svg)](https://opencollective.com/cloudcmd/sponsor/4/website) -[![](https://opencollective.com/cloudcmd/sponsor/5/avatar.svg)](https://opencollective.com/cloudcmd/sponsor/5/website) -[![](https://opencollective.com/cloudcmd/sponsor/6/avatar.svg)](https://opencollective.com/cloudcmd/sponsor/6/website) -[![](https://opencollective.com/cloudcmd/sponsor/7/avatar.svg)](https://opencollective.com/cloudcmd/sponsor/7/website) -[![](https://opencollective.com/cloudcmd/sponsor/8/avatar.svg)](https://opencollective.com/cloudcmd/sponsor/8/website) -[![](https://opencollective.com/cloudcmd/sponsor/9/avatar.svg)](https://opencollective.com/cloudcmd/sponsor/9/website) -[![](https://opencollective.com/cloudcmd/sponsor/10/avatar.svg)](https://opencollective.com/cloudcmd/sponsor/10/website) -[![](https://opencollective.com/cloudcmd/sponsor/11/avatar.svg)](https://opencollective.com/cloudcmd/sponsor/11/website) -[![](https://opencollective.com/cloudcmd/sponsor/12/avatar.svg)](https://opencollective.com/cloudcmd/sponsor/12/website) -[![](https://opencollective.com/cloudcmd/sponsor/13/avatar.svg)](https://opencollective.com/cloudcmd/sponsor/13/website) -[![](https://opencollective.com/cloudcmd/sponsor/14/avatar.svg)](https://opencollective.com/cloudcmd/sponsor/14/website) -[![](https://opencollective.com/cloudcmd/sponsor/15/avatar.svg)](https://opencollective.com/cloudcmd/sponsor/15/website) -[![](https://opencollective.com/cloudcmd/sponsor/16/avatar.svg)](https://opencollective.com/cloudcmd/sponsor/16/website) -[![](https://opencollective.com/cloudcmd/sponsor/17/avatar.svg)](https://opencollective.com/cloudcmd/sponsor/17/website) -[![](https://opencollective.com/cloudcmd/sponsor/18/avatar.svg)](https://opencollective.com/cloudcmd/sponsor/18/website) -[![](https://opencollective.com/cloudcmd/sponsor/19/avatar.svg)](https://opencollective.com/cloudcmd/sponsor/19/website) -[![](https://opencollective.com/cloudcmd/sponsor/20/avatar.svg)](https://opencollective.com/cloudcmd/sponsor/20/website) -[![](https://opencollective.com/cloudcmd/sponsor/21/avatar.svg)](https://opencollective.com/cloudcmd/sponsor/21/website) -[![](https://opencollective.com/cloudcmd/sponsor/22/avatar.svg)](https://opencollective.com/cloudcmd/sponsor/22/website) -[![](https://opencollective.com/cloudcmd/sponsor/23/avatar.svg)](https://opencollective.com/cloudcmd/sponsor/23/website) -[![](https://opencollective.com/cloudcmd/sponsor/24/avatar.svg)](https://opencollective.com/cloudcmd/sponsor/24/website) -[![](https://opencollective.com/cloudcmd/sponsor/25/avatar.svg)](https://opencollective.com/cloudcmd/sponsor/25/website) -[![](https://opencollective.com/cloudcmd/sponsor/26/avatar.svg)](https://opencollective.com/cloudcmd/sponsor/26/website) -[![](https://opencollective.com/cloudcmd/sponsor/27/avatar.svg)](https://opencollective.com/cloudcmd/sponsor/27/website) -[![](https://opencollective.com/cloudcmd/sponsor/28/avatar.svg)](https://opencollective.com/cloudcmd/sponsor/28/website) -[![](https://opencollective.com/cloudcmd/sponsor/29/avatar.svg)](https://opencollective.com/cloudcmd/sponsor/29/website) - ## License MIT - diff --git a/app.json b/app.json index f996a438..3dbe05a0 100644 --- a/app.json +++ b/app.json @@ -11,6 +11,7 @@ "folder", "orthodox" ], + "stack": "heroku-18", "env": { "NPM_CONFIG_PRODUCTION": { "description": "Keep false to install devDependencies and build frontend", @@ -22,6 +23,31 @@ "value": "edward", "required": false }, + "CLOUDCMD_CONTACT": { + "description": "enable contact", + "value": "true", + "required": false + }, + "CLOUDCMD_CONFIG_DIALOG": { + "description": "show config dialog", + "value": "false", + "required": false + }, + "CLOUDCMD_CONFIG_AUTH": { + "description": "disable auth change in config dialog", + "value": "false", + "required": false + }, + "CLOUDCMD_CONSOLE": { + "description": "enable console", + "value": "true", + "required": false + }, + "CLOUDCMD_SYNC_CONSOLE_PATH": { + "description": "sync console path", + "value": "false", + "required": false + }, "CLOUDCMD_TERMINAL": { "description": "enable terminal", "value": "true", @@ -32,8 +58,103 @@ "value": "gritty", "required": false }, - "CLOUDCMD_CONFIG_DIALOG": { - "description": "show config dialog", + "CLOUDCMD_TERMINAL_COMMAND": { + "description": "set command to run in terminal (shell by default)", + "value": "", + "required": false + }, + "CLOUDCMD_ONE_FILE_PANEL": { + "description": "show one file panel", + "value": "false", + "required": false + }, + "CLOUDCMD_KEYS_PANEL": { + "description": "show keys panel", + "value": "true", + "required": false + }, + "CLOUDCMD_NAME": { + "description": "set tab name in web browser", + "value": "", + "required": false + }, + "CLOUDCMD_AUTH": { + "description": "enable authorization", + "value": "false", + "required": false + }, + "CLOUDCMD_USERNAME": { + "description": "set username", + "value": "root", + "required": false + }, + "CLOUDCMD_PASSWORD": { + "description": "set password", + "value": "toor", + "required": false + }, + "CLOUDCMD_ROOT": { + "description": "set root dir", + "value": "", + "required": false + }, + "CLOUDCMD_VIM": { + "description": "enable vim hot keys", + "value": "false", + "required": false + }, + "CLOUDCMD_COLUMNS": { + "description": "set visible columns", + "value": "name-size-date-owner-mode", + "required": false + }, + "CLOUDCMD_OPEN": { + "description": "open web browser when server started", + "value": "false", + "required": false + }, + "CLOUDCMD_CONFIRM_COPY": { + "description": "confirm copy", + "value": "true", + "required": false + }, + "CLOUDCMD_CONFIRM_MOVE": { + "description": "confirm move", + "value": "true", + "required": false + }, + "CLOUDCMD_SHOW_FILE_NAME": { + "description": "show file name in view and edit", + "value": "false", + "required": false + }, + "CLOUDCMD_EXPORT": { + "description": "enable export of config through a server", + "value": "false", + "required": false + }, + "CLOUDCMD_EXPORT_TOKEN": { + "description": "authorization token used by export server", + "value": "root", + "required": false + }, + "CLOUDCMD_IMPORT": { + "description": "enable import of config", + "value": "false", + "required": false + }, + "CLOUDCMD_IMPORT_TOKEN": { + "description": "authorization token used to connect to export server", + "value": "root", + "required": false + }, + "CLOUDCMD_IMPORT_URL": { + "description": "url of an import server", + "value": "http://localhost:8000", + "required": false + }, + "CLOUDCMD_IMPORT_LISTEN": { + "description": "enable listen on config updates from import server", "value": "false", "required": false } diff --git a/bin/cloudcmd.js b/bin/cloudcmd.js index f8946a15..6ca6716c 100755 --- a/bin/cloudcmd.js +++ b/bin/cloudcmd.js @@ -1,24 +1,50 @@ #!/usr/bin/env node -'use strict'; +import process from 'node:process'; +import {promisify} from 'node:util'; +import {tryToCatch} from 'try-to-catch'; +import parse from 'yargs-parser'; +import exit from '../server/exit.js'; +import {createConfig, configPath} from '../server/config.js'; +import * as env from '../server/env.js'; +import prefixer from '../server/prefixer.js'; +import * as validate from '../server/validate.js'; +import Info from '../package.json' with { + type: 'json', +}; -const Info = require('../package'); -const DIR_SERVER = '../server/'; +process.on('unhandledRejection', exit); -const exit = require(DIR_SERVER + 'exit'); -const config = require(DIR_SERVER + 'config'); -const env = require(DIR_SERVER + 'env'); +const isUndefined = (a) => typeof a === 'undefined'; const choose = (a, b) => { - if (!a && typeof a !== 'boolean') + if (isUndefined(a)) return b; return a; }; -const argv = process.argv; -const args = require('minimist')(argv.slice(2), { +const config = createConfig({ + configPath, +}); + +const maybeRoot = (a) => { + if (a === '.') + return process.cwd(); + + return a; +}; + +const yargsOptions = { + configuration: { + 'strip-aliased': true, + 'strip-dashed': true, + }, + coerce: { + root: maybeRoot, + }, string: [ + 'name', 'port', 'password', 'username', @@ -27,7 +53,16 @@ const args = require('minimist')(argv.slice(2), { 'packer', 'root', 'prefix', + 'prefix-socket', 'terminal-path', + 'terminal-command', + 'columns', + 'menu', + 'theme', + 'import-url', + 'import-token', + 'export-token', + 'dropbox-token', ], boolean: [ 'auth', @@ -36,50 +71,91 @@ const args = require('minimist')(argv.slice(2), { 'server', 'online', 'open', - 'minify', - 'progress', 'config-dialog', + 'config-auth', + 'config-port', 'console', + 'sync-console-path', + 'contact', 'terminal', - 'one-panel-mode', - 'html-dialogs' + 'terminal-auto-restart', + 'one-file-panel', + 'confirm-copy', + 'confirm-move', + 'show-config', + 'show-dot-files', + 'show-file-name', + 'vim', + 'keys-panel', + 'color', + 'export', + 'import', + 'import-listen', + 'log', + 'zip', + 'dropbox', ], default: { - server : true, - auth : config('auth'), - port : config('port'), - minify : config('minify'), - online : config('online'), - open : config('open'), - editor : choose(env('editor'), config('editor')), - packer : config('packer') || 'tar', - zip : config('zip'), - username : config('username'), - root : config('root'), - prefix : config('prefix'), - progress : config('progress'), - console : config('console'), - terminal : choose(env.bool('terminal'), config('terminal')), + 'server': true, + 'name': choose(env.parse('name'), config('name')), + 'auth': choose(env.bool('auth'), config('auth')), + 'port': config('port'), + 'online': config('online'), + 'open': choose(env.bool('open'), config('open')), + 'editor': env.parse('editor') || config('editor'), + 'menu': env.parse('menu') || config('menu'), + 'packer': config('packer') || 'tar', + 'zip': config('zip'), + 'username': env.parse('username') || config('username'), + 'root': choose(env.parse('root'), config('root')), + 'prefix': choose(env.parse('prefix'), config('prefix')), + 'console': choose(env.bool('console'), config('console')), + 'contact': choose(env.bool('contact'), config('contact')), + 'terminal': choose(env.bool('terminal'), config('terminal')), + 'columns': env.parse('columns') || config('columns') || '', + 'theme': env.parse('theme') || config('theme') || '', + 'vim': choose(env.bool('vim'), config('vim')), + 'log': choose(env.bool('log'), config('log')), - 'terminal-path': env('terminal_path') || config('terminalPath'), + 'import-url': env.parse('import_url') || config('importUrl'), + 'import-listen': choose(env.bool('import_listen'), config('importListen')), + 'import': choose(env.bool('import'), config('import')), + 'export': choose(env.bool('export'), config('export')), + + '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')), + 'sync-console-path': choose(env.bool('sync_console_path'), config('syncConsolePath')), 'config-dialog': choose(env.bool('config_dialog'), config('configDialog')), - 'one-panel-mode': config('onePanelMode'), - 'html-dialogs': config('htmlDialogs') + 'config-auth': choose(env.bool('config_auth'), config('configAuth')), + 'config-port': choose(env.bool('config_port'), config('configPort')), + 'terminal-path': env.parse('terminal_path') || config('terminalPath'), + 'terminal-command': env.parse('terminal_command') || config('terminalCommand'), + 'terminal-auto-restart': choose(env.bool('terminal_auto_restart'), config('terminalAutoRestart')), + 'one-file-panel': choose(env.bool('one_file_panel'), config('oneFilePanel')), + 'confirm-copy': choose(env.bool('confirm_copy'), config('confirmCopy')), + 'confirm-move': choose(env.bool('confirm_move'), config('confirmMove')), + 'keys-panel': env.bool('keys_panel') || config('keysPanel'), + 'import-token': env.parse('import_token') || config('importToken'), + 'export-token': env.parse('export_token') || config('exportToken'), + + 'dropbox': config('dropbox'), + 'dropbox-token': config('dropboxToken') || '', }, alias: { - v: 'version', - h: 'help', - p: 'password', - o: 'online', - u: 'username', - s: 'save', - a: 'auth', - c: 'config' + version: 'v', + help: 'h', + password: 'p', + online: 'o', + username: 'u', + save: 's', + auth: 'a', + config: 'c', }, - unknown: (cmd) => { - exit('\'%s\' is not a cloudcmd option. See \'cloudcmd --help\'.', cmd); - } -}); +}; + +const {argv} = process; +const args = parse(argv.slice(2), yargsOptions); if (args.version) version(); @@ -88,60 +164,112 @@ else if (args.help) else main(); -function main() { - if (args.repl) - repl(); +async function main() { + const {validateArgs} = await import('@putout/cli-validate-args'); - checkUpdate(); + const error = await validateArgs(args, [ + ...yargsOptions.boolean, + ...yargsOptions.string, + ]); + + if (error) + return exit(error); + + if (args.repl) + await repl(); + + validate.columns(args.columns); + validate.theme(args.theme); port(args.port); + config('name', args.name); config('auth', args.auth); config('online', args.online); config('open', args.open); - config('minify', args.minify); config('username', args.username); - config('progress', args.progress); config('console', args.console); + config('syncConsolePath', args.syncConsolePath); + config('showDotFiles', args.showDotFiles); + config('showFileName', args.showFileName); + config('contact', args.contact); config('terminal', args.terminal); - config('terminalPath', args['terminal-path']); + config('terminalPath', args.terminalPath); + config('terminalCommand', args.terminalCommand); + config('terminalAutoRestart', args.terminalAutoRestart); config('editor', args.editor); - config('prefix', args.prefix); - config('root', args.root); - config('htmlDialogs', args['html-dialogs']); - config('onePanelMode', args['one-panel-mode']); - config('configDialog', args['config-dialog']); + config('menu', args.menu); + config('prefix', prefixer(args.prefix)); + config('prefixSocket', prefixer(args.prefixSocket)); + config('root', args.root || '/'); + config('vim', args.vim); + config('theme', args.theme); + config('columns', args.columns); + config('log', args.log); + config('confirmCopy', args.confirmCopy); + config('confirmMove', args.confirmMove); + config('oneFilePanel', args.oneFilePanel); + config('configDialog', args.configDialog); + config('configAuth', args.configAuth); + config('configPort', args.configPort); + config('keysPanel', args.keysPanel); + config('export', args.export); + config('exportToken', args.exportToken); + config('import', args.import); + config('importToken', args.importToken); + config('importListen', args.importListen); + config('importUrl', args.importUrl); - readConfig(args.config); + config('dropbox', args.dropbox); + config('dropboxToken', args.dropboxToken); + + await readConfig(args.config); const options = { - root: args.root || '/', /* --no-root */ - editor: args.editor, - packer: args.packer, - prefix: args.prefix + root: config('root'), + editor: config('editor'), + packer: config('packer'), + prefix: config('prefix'), + prefixSocket: config('prefixSocket'), + columns: config('columns'), + theme: config('theme'), + menu: config('menu'), }; - if (args.password) - config('password', getPassword(args.password)); + const password = env.parse('password') || args.password; - validateRoot(options.root); + if (password) + config('password', await getPassword(password)); - if (!args.save) - return start(options); + validateRoot(options.root, config); - config.save(() => { - start(options); - }); + if (args.showConfig) + await showConfig(); + + const {distributeImport} = await import('../server/distribute/import.js'); + const importConfig = promisify(distributeImport); + + await start(options, config); + + if (args.save) + config.write(); + + await tryToCatch(checkUpdate); + await importConfig(config); } -function validateRoot(root) { - const validate = require(DIR_SERVER + 'validate'); - validate.root(root, console.log); +function validateRoot(root, config) { + validate.root(root, config); + + if (root === '/') + return; + + if (config('log')) + console.log(`root: ${root}`); } -function getPassword(password) { - const criton = require('criton'); - +async function getPassword(password) { + const {default: criton} = await import('criton'); return criton(password, config('algo')); } @@ -149,93 +277,86 @@ function version() { console.log('v' + Info.version); } -function start(config) { - const SERVER = DIR_SERVER + 'server'; +async function start(options, config) { + if (!args.server) + return; - if (args.server) - require(SERVER)(config); + const {default: server} = await import('../server/server.js'); + server(options, config); } function port(arg) { const number = parseInt(arg, 10); if (!isNaN(number)) - config('port', number); - else - exit('cloudcmd --port: should be a number'); + return config('port', number); + + exit('cloudcmd --port: should be a number'); } -function readConfig(name) { +async function showConfig() { + const {showConfig} = await import('../server/show-config.js'); + const data = showConfig(config('*')); + + console.log(data); +} + +async function readConfig(name) { if (!name) return; - const fs = require('fs'); - const tryCatch = require('try-catch'); - const jju = require('jju'); + const {default: forEachKey} = await import('for-each-key'); - const readjsonSync = (name) => jju.parse(fs.readFileSync(name, 'utf8'), { - mode: 'json' + const data = await import(name, { + with: { + type: 'json', + }, }); - let data; - - const error = tryCatch(() => { - data = readjsonSync(name); - }); - - if (error) - return exit(error.message); - - Object.keys(data).forEach((item) => { - config(item, data[item]); - }); + forEachKey(config, data); } -function help() { - const bin = require('../json/help'); +async function help() { + const {default: bin} = await import('../json/help.json', { + with: { + type: 'json', + }, + }); + + const {default: forEachKey} = await import('for-each-key'); + const {default: currify} = await import('currify'); + const usage = 'Usage: cloudcmd [options]'; const url = Info.homepage; + const log = currify((a, b, c) => console.log(a, b, c)); console.log(usage); console.log('Options:'); - - Object.keys(bin).forEach((name) => { - console.log(' %s %s', name, bin[name]); - }); - + forEachKey(log(' %s %s'), bin); console.log('\nGeneral help using Cloud Commander: <%s>', url); } -function repl() { +async function repl() { console.log('REPL mode enabled (telnet localhost 1337)'); - require(DIR_SERVER + 'repl'); + await import('../server/repl.js'); } -function checkUpdate() { - const load = require('package-json'); - const noop = () => {}; +async function checkUpdate() { + const {default: load} = await import('package-json'); + const {version} = await load(Info.name, 'latest'); - load(Info.name, 'latest') - .then(showUpdateInfo) - .catch(noop); + await showUpdateInfo(version); } -function showUpdateInfo(data) { - const version = data.version; +async function showUpdateInfo(version) { + if (version === Info.version) + return; - if (version !== Info.version) { - const chalk = require('chalk'); - const rendy = require('rendy'); - - const latest = rendy('update available: {{ latest }}', { - latest: chalk.green.bold('v' + version), - }); - - const current = chalk.dim(rendy('(current: v{{ current }})', { - current: Info.version - })); - - console.log('%s %s', latest, current); - } + const {default: chalk} = await import('chalk'); + + const latestVersion = chalk.green.bold(`v${version}`); + const latest = `update available: ${latestVersion}`; + const current = chalk.dim(`(current: v${Info.version})`); + + console.log('%s %s', latest, current); } - diff --git a/bin/cloudcmd.spec.js b/bin/cloudcmd.spec.js new file mode 100644 index 00000000..d09541b9 --- /dev/null +++ b/bin/cloudcmd.spec.js @@ -0,0 +1,26 @@ +import {spawnSync} from 'node:child_process'; +import {test} from 'supertape'; +import info from '../package.json' with { + type: 'json', +}; + +const cliPath = new URL('cloudcmd.js', import.meta.url).pathname; + +test('cloudcmd: bin: cli: -h', (t) => { + const {stdout} = spawnSync(cliPath, ['-h'], { + encoding: 'utf8', + }); + + t.match(stdout, `Options`); + t.end(); +}); + +test('cloudcmd: bin: cli: -v', (t) => { + const {version} = info; + const {stdout} = spawnSync(cliPath, ['-v'], { + encoding: 'utf8', + }); + + t.match(stdout, `v${version}`); + t.end(); +}); diff --git a/bin/legacy.js b/bin/legacy.js deleted file mode 100755 index c30802c3..00000000 --- a/bin/legacy.js +++ /dev/null @@ -1,29 +0,0 @@ -#!/usr/bin/env node - -'use strict'; - -const fs = require('fs'); -const path = require('path'); - -const dir = path.join(__dirname, '../server'); -const dir_ = path.join(__dirname, '../legacy/server'); - -const setDir = (name) => { - return path.join(dir_, name); -}; - -fs.readdirSync(dir) - .map(fillFile) - .map(writeFile); - -function fillFile(name) { - return { - name: setDir(name), - data: `module.exports = require(\'../../server_/${name}\');` - }; -} - -function writeFile({name, data}) { - return fs.writeFileSync(name, data); -} - diff --git a/bin/release.js b/bin/release.js index 8bc32836..86e1d714 100755 --- a/bin/release.js +++ b/bin/release.js @@ -1,70 +1,72 @@ #!/usr/bin/env node -'use strict'; +import {promisify} from 'node:util'; +import process from 'node:process'; +import {tryToCatch} from 'try-to-catch'; +import minor from 'minor'; +import _place from 'place'; +import {rendy} from 'rendy'; +import shortdate from 'shortdate'; +import Info from '../package.json' with { + type: 'json', +}; -const DIR = '../'; -const Info = require(DIR + 'package'); +const place = promisify(_place); -const minor = require('minor'); -const place = require('place'); -const rendy = require('rendy'); -const shortdate = require('shortdate'); +await main(); -const ERROR = Error('ERROR: version is missing. release --patch|--minor|--major'); - -main((error) => { +async function main() { + const history = '## Version history\n\n'; + const link = '//github.com/coderaiser/cloudcmd/releases/tag/'; + + const template = '- ' + + '*{{ date }}*, ' + + '**[v{{ version }}]' + + '(' + + link + + 'v{{ version }})**\n'; + + const {version} = Info; + + const [error, versionNew] = await tryToCatch(cl); + if (error) - console.error(error.message); -}); - -function main(callback) { - const history = 'Version history\n---------------\n'; - const link = '//github.com/coderaiser/cloudcmd/releases/tag/'; - const template = '- *{{ date }}*, ' + - '**[v{{ version }}]' + - '(' + link + 'v{{ version }})**\n'; + return console.error(error); - const version = Info.version; + await replaceVersion('README.md', version, versionNew); + await replaceVersion('HELP.md', version, versionNew); - cl((error, versionNew) => { - if (error) { - callback(error); - } else { - replaceVersion('README.md', version, versionNew, callback); - replaceVersion('HELP.md', version, versionNew, function() { - const historyNew = history + rendy(template, { - date : shortdate(), - version : versionNew - }); - - replaceVersion('HELP.md', history, historyNew, callback); - }); - } - }); + const historyNew = history + + rendy(template, { + date: shortdate(), + version: versionNew, + }); + + await replaceVersion('HELP.md', history, historyNew); } -function replaceVersion(name, version, versionNew, callback) { - place(name, version, versionNew, (error) => { - let msg; - - if (!error) - msg = 'done: ' + name; - - callback(error, msg); - }); +async function replaceVersion(name, version, versionNew) { + const [error] = await tryToCatch(place, name, version, versionNew); + + if (error) + return console.error(error); + + console.log(`done: ${name}`); } -function cl(callback) { - const argv = process.argv; +async function cl() { + const {argv} = process; const length = argv.length - 1; const last = process.argv[length]; const regExp = /^--(major|minor|patch)$/; const [, match] = last.match(regExp) || []; - if (!regExp.test(last)) - return callback(ERROR); + console.log(last); - callback(null, getVersionNew(last, match)); + if (!regExp.test(last)) + throw Error('ERROR: version is missing. release --patch|--minor|--major'); + + return getVersionNew(last, match); } function getVersionNew(last, match) { @@ -73,4 +75,3 @@ function getVersionNew(last, match) { return last.substr(3); } - diff --git a/bower.json b/bower.json deleted file mode 100644 index bb29284d..00000000 --- a/bower.json +++ /dev/null @@ -1,40 +0,0 @@ -{ - "name": "cloudcmd", - "homepage": "https://github.com/coderaiser/cloudcmd", - "authors": [ - "coderaiser " - ], - "description": "orthodox web file manager with console and editor", - "main": "bin/cloudcmd.js", - "keywords": [ - "console", - "editor", - "file", - "file manager", - "folder", - "orthodox", - "view", - "copy", - "rename", - "move", - "delete", - "file operation" - ], - "license": "MIT", - "private": true, - "ignore": [ - "node_modules", - "modules", - "test" - ], - "dependencies": { - "domtokenlist-shim": "~1.1.0", - "findit": "1.1.7", - "menu": "~1.0.2", - "olark": "^1.0.0", - "jquery": "3.2.1", - "fancybox": "^2.1.6", - "philip": "1.3.6", - "smalltalk": "2.3.1" - } -} diff --git a/client/client.js b/client/client.js index 81caed42..a0e3cb07 100644 --- a/client/client.js +++ b/client/client.js @@ -1,51 +1,59 @@ -'use strict'; - -const itype = require('itype/legacy'); -const rendy = require('rendy'); -const exec = require('execon'); -const Images = require('./dom/images'); -const join = require('join-io/www/join'); - -const { +import process from 'node:process'; +import Emitify from 'emitify'; +import inherits from 'inherits'; +import {rendy} from 'rendy'; +import load from 'load.js'; +import {tryToCatch} from 'try-to-catch'; +import {addSlashToEnd} from 'format-io'; +import pascalCase from 'just-pascal-case'; +import currify from 'currify'; +import { apiURL, formatMsg, buildFromJSON, -} = require('../common/cloudfunc'); +} from '#common/cloudfunc'; +import * as Images from '#dom/images'; +import {unregisterSW} from './sw/register.js'; +import {getJsonFromFileTable} from './get-json-from-file-table.js'; +import {Key} from './key/index.js'; +import {loadModule} from './load-module.js'; -/* global Util, DOM */ +const noJS = (a) => a.replace(/.js$/, ''); -module.exports = new CloudCmdProto(Util, DOM); +const isDev = process.env.NODE_ENV === 'development'; -function CloudCmdProto(Util, DOM) { - let Key; - let Debug; - let Listeners; - - const log = (str) => { - if (!Debug) - return; - - console.log(str); - }; +inherits(CloudCmdProto, Emitify); + +export const createCloudCmd = ({DOM, Listeners}) => { + return new CloudCmdProto({ + DOM, + Listeners, + }); +}; + +load.addErrorListener((e, src) => { + const msg = `file ${src} could not be loaded`; + Images.show.error(msg); +}); + +function CloudCmdProto({DOM, Listeners}) { + Emitify.call(this); const CloudCmd = this; const Info = DOM.CurrentInfo; - const Storage = DOM.Storage; - const Files = DOM.Files; - this.log = log; - this.PREFIX = ''; - this.PREFIX_URL = ''; - this.DIRCLIENT = '/dist/'; - this.DIRCLIENT_MODULES = this.DIRCLIENT + 'modules/'; + const {Storage, Files} = DOM; - this.MIN_ONE_PANEL_WIDTH = 1155; - this.HOST = location.origin || - location.protocol + '//' + location.host; - - const TITLE = 'Cloud Commander'; - this.TITLE = TITLE; + this.log = () => { + if (!isDev) + return; + }; + this.prefix = ''; + this.prefixSocket = ''; + this.prefixURL = ''; + this.MIN_ONE_PANEL_WIDTH = DOM.getCSSVar('min-one-panel-width'); + this.HOST = location.origin || location.protocol + '//' + location.host; this.sort = { left: 'name', right: 'name', @@ -56,43 +64,24 @@ function CloudCmdProto(Util, DOM) { right: 'asc', }; - log.enable = () => { - Debug = true; - }; - - log.disable = () => { - Debug = false; - }; - - const kebabToCamelCase = Util.kebabToCamelCase; - - /** - * Функция привязываеться ко всем ссылкам и - * загружает содержимое каталогов - * - * @param params - { - * paramLink - ссылка - * needRefresh - необходимость обязательной загрузки данных с сервера - * panel - * } - * @param callback - */ - this.loadDir = (params, callback) => { - var imgPosition; - var panelChanged; - var p = params; + this.changeDir = async (path, overrides = {}) => { + const { + isRefresh, + panel, + history = true, + noCurrent, + currentName, + } = overrides; - const refresh = p.isRefresh; - const panel = p.panel; - const history = p.history; - const noCurrent = p.noCurrent; - const currentName = p.currentName; + const refresh = isRefresh; + let panelChanged; - if (!noCurrent) - if (panel && panel !== Info.panel) { - DOM.changePanel(); - panelChanged = true; - } + if (!noCurrent && panel && panel !== Info.panel) { + DOM.changePanel(); + panelChanged = true; + } + + let imgPosition; if (panelChanged || refresh || !history) imgPosition = 'top'; @@ -100,137 +89,50 @@ function CloudCmdProto(Util, DOM) { Images.show.load(imgPosition, panel); /* загружаем содержимое каталога */ - ajaxLoad(p.path, { + await ajaxLoad(addSlashToEnd(path), { refresh, history, noCurrent, currentName, - }, panel, callback); + showDotFiles: CloudCmd.config('showDotFiles'), + }, panel); }; - /** - * function load modules - * @params = {name, path, func, dobefore, arg} - */ - function loadModule(params) { - var name, path, func, doBefore, - funcName, isContain; - - if (params) { - name = params.name, - path = params.path, - func = params.func, - funcName = params.funcName, - doBefore = params.dobefore; - - if (path && !name) - name = kebabToCamelCase(path); - - isContain = /\.js/.test(path); - - if (!isContain) - path += '.js'; - - if (!CloudCmd[name]) { - CloudCmd[name] = (...args) => { - const prefix = CloudCmd.PREFIX; - const pathFull = prefix + CloudCmd.DIRCLIENT_MODULES + path; - - exec(doBefore); - - return DOM.load.js(pathFull, func || - function(error) { - var Proto = CloudCmd[name]; - - if (!error && itype.function(Proto)) - CloudCmd[name] = applyConstructor(Proto, args); - }); - }; - - CloudCmd[name][funcName] = CloudCmd[name]; - } - } - } - - /* - * apply arguemnts to constructor - * - * @param constructor - * @param args - */ - function applyConstructor(constructor, args) { - var F = function () { - return constructor.apply(this, args); - }; - - F.prototype = constructor.prototype; - return new F(); - } - /** * Конструктор CloudClient, который * выполняет весь функционал по * инициализации */ - this.init = (prefix, config) => { - const func = () => { - exec.series([ - initModules, - baseInit, - loadPlugins, - () => { - CloudCmd.route(location.hash); - } - ]); - }; - - const funcBefore = (callback) => { - const src = prefix + '/join:' + [ - CloudCmd.DIRCLIENT_MODULES + 'polyfill.js', - '/modules/domtokenlist-shim/dist/domtokenlist.min.js', - ].join(':'); - - DOM.loadJquery(() => { - DOM.load.js(src, callback); - }); - }; - - CloudCmd.PREFIX = prefix; - CloudCmd.PREFIX_URL = prefix + apiURL; + this.init = async (prefix, config) => { + CloudCmd.prefix = prefix; + CloudCmd.prefixURL = `${prefix}${apiURL}`; + CloudCmd.prefixSocket = config.prefixSocket; + CloudCmd.DIR_DIST = `${prefix}/dist`; + CloudCmd.DIR_MODULES = `${this.DIR_DIST}/modules`; CloudCmd.config = (key) => config[key]; + CloudCmd.config.if = currify((key, fn, a) => config[key] && fn(a)); CloudCmd._config = (key, value) => { /* * should be called from config.js only * after successful update on server */ + if (key === 'password') + return; + config[key] = value; }; - if (config.onePanelMode) + if (config.oneFilePanel) CloudCmd.MIN_ONE_PANEL_WIDTH = Infinity; - exec.if(document.body.scrollIntoViewIfNeeded, func, funcBefore); - }; - - function loadPlugins(callback) { - const prefix = CloudCmd.PREFIX; - const plugins = prefix + '/plugins.js'; + if (!document.body.scrollIntoViewIfNeeded) + await load.js(`${CloudCmd.DIR_MODULES}/polyfill.js`); - DOM.load.js(plugins, callback); - } - - this.join = (urls) => { - const prefix = CloudCmd.PREFIX; + await initModules(); + await baseInit(); - if (!Array.isArray(urls)) - throw Error('urls should be array!'); - - const noPrefixUrls = urls.map((url) => { - return url.replace(prefix, ''); - }); - - return prefix + join(noPrefixUrls); + CloudCmd.route(location.hash); }; this.route = (path) => { @@ -240,14 +142,15 @@ function CloudCmdProto(Util, DOM) { return; const [kebabModule] = query; - const module = kebabToCamelCase(kebabModule.slice(1)); + const module = noJS(pascalCase(kebabModule.slice(1))); - const file = query[1]; + const [, file] = query; const current = DOM.getCurrentByName(file); if (file && !current) { const msg = formatMsg('set current file', file, 'error'); CloudCmd.log(msg); + return; } @@ -255,124 +158,122 @@ function CloudCmdProto(Util, DOM) { CloudCmd.execFromModule(module, 'show'); }; - this.logOut = () => { - const url = CloudCmd.PREFIX + '/logout'; + this.logOut = async () => { + const url = CloudCmd.prefix + '/logout'; const error = () => document.location.reload(); + const {prefix} = CloudCmd; - DOM.load.ajax({url, error}); + await DOM.Storage.clear(); + unregisterSW(prefix); + DOM.load.ajax({ + url, + error, + }); }; - function initModules(callback) { - exec.if(CloudCmd.Key, () => { - Key = new CloudCmd.Key(); - CloudCmd.Key = Key; - Key.bind(); - }, (func) => { - /* привязываем клавиши к функциям */ - const path = 'key.js'; - - loadModule({ - path, - func - }); - }); + const initModules = async () => { + CloudCmd.Key = Key; + CloudCmd.Key.bind(); - Files.get('modules', (error, modules) => { - const showLoad = Images.show.load; - - const doBefore = { - 'edit': showLoad, - 'menu': showLoad, - }; - - const load = (name, path, dobefore) => { - const isTmpl = path === 'template'; - const funcName = isTmpl ? 'get' : 'show'; - - loadModule({ - name, - path, - dobefore, - funcName, - }); - }; - - if (!modules) - modules = []; - - modules.local.forEach((module) => { - load(null, module, doBefore[module]); + const [, modules] = await tryToCatch(Files.get, 'modules'); + const showLoad = Images.show.load; + + const doBefore = { + edit: showLoad, + menu: showLoad, + }; + + const load = (name, path, dobefore) => { + loadModule({ + name, + path, + dobefore, }); - - callback(); - }); + }; + + if (!modules) + return; + + for (const module of modules.local) { + load(null, module, doBefore[module]); + } + }; + + async function saveCurrentName(currentName) { + await Storage.set('current-name', currentName); } - function baseInit(callback) { + async function baseInit() { const files = DOM.getFiles(); + CloudCmd.on('current-file', DOM.updateCurrentInfo); + CloudCmd.on('current-name', saveCurrentName); + + const name = await Storage.get('current-name'); + const currentFile = name && DOM.getCurrentByName(name) || files[0]; + /* выделяем строку с первым файлом */ if (files) - DOM.setCurrentFile(files[0], { + DOM.setCurrentFile(currentFile, { // when hash is present // it should be handled with this.route // overwre otherwise - history: !location.hash + history: !location.hash, }); const dirPath = DOM.getCurrentDirPath(); - Listeners = CloudCmd.Listeners; + Listeners.init(); - Listeners.setOnPanel('left'); - Listeners.setOnPanel('right'); + const panels = getPanels(); + panels.forEach(Listeners.setOnPanel); Listeners.initKeysPanel(); - Storage.get(dirPath, (error, data) => { - if (!data) { - data = getJSONfromFileTable(); - Storage.set(dirPath, data); - } - }); + if (!CloudCmd.config('dirStorage')) + return; - callback(); + const data = await Storage.get(dirPath); + + if (!data) + await Storage.setJson(dirPath, getJsonFromFileTable()); } - this.execFromModule = (moduleName, funcName, ...args) => { - const obj = CloudCmd[moduleName]; - const isObj = itype.object(obj); + function getPanels() { + const panels = ['left']; - exec.if(isObj, () => { - const obj = CloudCmd[moduleName]; - const func = obj[funcName]; - - func(...args); - }, obj); + if (CloudCmd.config('oneFilePanel')) + return panels; + + return [ + ...panels, + 'right', + ]; + } + + this.execFromModule = async (moduleName, funcName, ...args) => { + await CloudCmd[moduleName](); + + const func = CloudCmd[moduleName][funcName]; + func(...args); }; - this.refresh = (options = {}, callback) => { - if (!callback && typeof options === 'function') { - callback = options; - options = {}; - } - - const panel = options.panel || Info.panel; + this.refresh = async (options = {}) => { + const {panel = Info.panel, currentName} = options; + const path = DOM.getCurrentDirPath(panel); const isRefresh = true; const history = false; - const noCurrent = options ? options.noCurrent : false; - const currentName = options.currentName; + const noCurrent = options?.noCurrent; - CloudCmd.loadDir({ - path, + await CloudCmd.changeDir(path, { isRefresh, history, panel, noCurrent, currentName, - }, callback); + }); }; /** @@ -382,177 +283,146 @@ function CloudCmdProto(Util, DOM) { * @param options * { refresh, history } - необходимость обновить данные о каталоге * @param panel - * @param callback * */ - function ajaxLoad(path, options, panel, callback) { - const create = (error, json) => { - const RESTful = DOM.RESTful; - const name = options.currentName || Info.name; - const obj = Util.json.parse(json); - const isRefresh = options.refresh; - const noCurrent = options.noCurrent; - - if (!isRefresh && json) - return createFileTable(obj, panel, options, callback); - - const position = DOM.getPanelPosition(panel); - const sort = CloudCmd.sort[position]; - const order = CloudCmd.order[position]; - - const query = rendy('?sort={{ sort }}&order={{ order }}', { - sort, - order, - }); - - RESTful.read(path + query, 'json', (error, obj) => { - if (error) - return; - - Storage.set(path, obj); - - options.sort = sort; - options.order = order; - - createFileTable(obj, panel, options, () => { - if (isRefresh && !noCurrent) - DOM.setCurrentByName(name); - - exec(callback); - }); - }); - }; + async function ajaxLoad(path, options = {}, panel) { + const {RESTful} = DOM; - if (!options) - options = {}; + CloudCmd.log(`reading dir: "${path}";`); - CloudCmd.log('reading dir: "' + path + '";'); + const dirStorage = CloudCmd.config('dirStorage'); + const json = dirStorage && await Storage.getJson(path); + + const name = options.currentName || Info.name; + const {noCurrent, refresh} = options; + + if (!refresh && json) + return await createFileTable(json, panel, options); + + const position = DOM.getPanelPosition(panel); + const sort = CloudCmd.sort[position]; + const order = CloudCmd.order[position]; + + const query = rendy('?sort={{ sort }}&order={{ order }}', { + sort, + order, + }); + + const [, newObj] = await RESTful.read(path + query, 'json'); + + if (!newObj) + // that's OK, error handled by RESTful + return; + + options.sort = sort; + options.order = order; + + await createFileTable(newObj, panel, options); + + if (refresh && !noCurrent) + DOM.setCurrentByName(name); if (!CloudCmd.config('dirStorage')) - return create(); + return; - Storage.get(path, create); + Storage.setJson(path, newObj); } /** * Функция строит файловую таблицу - * @param json - данные о файлах + * @param data - данные о файлах * @param panelParam - * @param history - * @param callback + * @param options - history, noCurrent, showDotFiles */ - function createFileTable(json, panelParam, options, callback) { - var history = options.history, - noCurrent = options.noCurrent, - names = ['file', 'path', 'link', 'pathLink']; + async function createFileTable(data, panelParam, options) { + const { + history, + noCurrent, + showDotFiles, + } = options; - Files.get(names, function(error, templFile, templPath, templLink, templPathLink) { - var childNodes, i, - Dialog = DOM.Dialog, - current, - panel = panelParam || DOM.getPanel(), - - dir = Info.dir, - name = Info.name; - - if (error) - return Dialog.alert(TITLE, error.responseText); - - childNodes = panel.childNodes; - i = childNodes.length; - - while (i--) - panel.removeChild(panel.lastChild); - - panel.innerHTML = buildFromJSON({ - sort : options.sort, - order : options.order, - data : json, - id : panel.id, - prefix : CloudCmd.PREFIX, - template : { - file : templFile, - path : templPath, - pathLink : templPathLink, - link : templLink - } - }); - - Listeners.setOnPanel(panel); - - if (!noCurrent) { - if (name === '..' && dir !== '/') - current = DOM.getCurrentByName(dir); - - if (!current) - current = DOM.getFiles(panel)[0]; - - DOM.setCurrentFile(current, { - history: history - }); - } - - exec(callback); - }); - } - - /** - * Функция генерирует JSON из html-таблицы файлов и - * используеться при первом заходе в корень - */ - function getJSONfromFileTable() { - var name, size, owner, mode, ret, - path = DOM.getCurrentDirPath(), - infoFiles = Info.files || [], - - fileTable = { - path : path, - files : [] + const names = [ + 'file', + 'path', + 'link', + 'pathLink', + ]; + + const [error, [ + file, + path, + link, + pathLink, + ]] = await tryToCatch(Files.get, names); + + if (error) + return DOM.Dialog.alert(error.responseText); + + const panel = panelParam || DOM.getPanel(); + const {prefix} = CloudCmd; + + const {dir, name} = Info; + + const {childNodes} = panel; + let i = childNodes.length; + + while (i--) + panel.removeChild(panel.lastChild); + + panel.innerHTML = buildFromJSON({ + sort: options.sort, + order: options.order, + data, + id: panel.id, + prefix, + showDotFiles, + template: { + file, + path, + pathLink, + link, }, - - files = fileTable.files; - - [].forEach.call(infoFiles, function(current) { - name = DOM.getCurrentName(current); - size = DOM.getCurrentSize(current); - owner = DOM.getCurrentOwner(current); - mode = DOM.getCurrentMode(current); - - if (name !== '..') - files.push({ - name : name, - size : size, - mode : mode, - owner : owner - }); }); - ret = Util.json.stringify(fileTable); + Listeners.setOnPanel(panel); - return ret; - } - - this.goToParentDir = () => { - let path = Info.dirPath; - const dir = Info.dir; - const parentPath = Info.parentDirPath; - - if (path === Info.parentDirPath) - return; - - path = parentPath; - - CloudCmd.loadDir({path}, () => { - const panel = Info.panel; - let current = DOM.getCurrentByName(dir); + if (!noCurrent) { + let current; + + if (name === '..' && dir !== '/') + current = DOM.getCurrentByName(dir); if (!current) - current = DOM.getFiles(panel)[0]; + [current] = DOM.getFiles(panel); DOM.setCurrentFile(current, { - history + history, }); + + CloudCmd.emit('active-dir', Info.dirPath); + } + } + + this.goToParentDir = async () => { + const { + dir, + dirPath, + parentDirPath, + panel, + } = Info; + + if (dirPath === parentDirPath) + return; + + const path = parentDirPath; + + await CloudCmd.changeDir(path); + + const current = DOM.getCurrentByName(dir); + const [first] = DOM.getFiles(panel); + + DOM.setCurrentFile(current || first, { + history, }); }; } - diff --git a/client/cloudcmd.js b/client/cloudcmd.js index db23f2ad..f2416fd4 100644 --- a/client/cloudcmd.js +++ b/client/cloudcmd.js @@ -1,44 +1,74 @@ -'use strict'; +import '../css/main.css'; +import process from 'node:process'; +import wraptile from 'wraptile'; +import load from 'load.js'; +import * as Util from '#common/util'; +import * as CloudFunc from '#common/cloudfunc'; +import DOM from '#dom'; +import {registerSW, listenSW} from './sw/register.js'; +import {initSortPanel, sortPanel} from './sort.js'; +import {createCloudCmd} from './client.js'; +import * as Listeners from './listeners/index.js'; -// prevent additional loading of exec by spero, remedy, ishtar, salam, omnes -window.exec = require('execon'); +const isDev = process.env.NODE_ENV === 'development'; -// prevent additional loading of emitify -window.Emitify = require('emitify/legacy'); +export default init; -window.CloudCmd = (config) => { - window.Promise = window.Promise || require('es6-promise'); - window.Util = require('../common/util'); - window.CloudFunc = require('../common/cloudfunc'); - - const DOM = require('./dom'); - - window.DOM = DOM; - window.CloudCmd = require('./client'); - - const Dialog = require('./dom/dialog'); - - const prefix = getPrefix(config.prefix); - const {htmlDialogs} = config; - - DOM.Dialog = Dialog(prefix, { - htmlDialogs +globalThis.CloudCmd = init; + +async function init(config) { + globalThis.CloudCmd = createCloudCmd({ + DOM, + Listeners, }); + globalThis.DOM = DOM; + globalThis.Util = Util; + globalThis.CloudFunc = CloudFunc; - require('./listeners'); - require('./key'); - require('./sort'); + await register(config); - window.CloudCmd.init(prefix, 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@5.5'); + }, 100); +} function getPrefix(prefix) { if (!prefix) return ''; - + if (!prefix.indexOf('/')) return prefix; - 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)); +} diff --git a/client/dom/buffer.js b/client/dom/buffer.js index 9badc537..c6d20ccd 100644 --- a/client/dom/buffer.js +++ b/client/dom/buffer.js @@ -1,133 +1,124 @@ -'use strict'; +/* global CloudCmd*/ +import * as Storage from '#dom/storage'; +import tryToPromiseAll from '../../common/try-to-promise-all.js'; -/* global CloudCmd */ +const CLASS = 'cut-file'; +const COPY = 'copy'; +const CUT = 'cut'; -const jonny = require('jonny'); -const exec = require('execon'); - -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 TITLE = 'Buffer'; - - 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(TITLE, msg); - } - - function getNames() { - const files = DOM.getActiveFiles(); - const names = DOM.getFilenames(files); - - return names; - } - - function addCutClass() { - const files = DOM.getActiveFiles(); - - files.forEach((element) => { - element.classList.add(CLASS); - }); - } - - function rmCutClass() { - const files = DOM.getByClassAll(CLASS); - - [...files].forEach((element) => { - element.classList.remove(CLASS); - }); - } - - function callIfEnabled(callback) { - const is = CloudCmd.config('buffer'); - - if (is) - return callback(); - - showMessage('Buffer disabled in config!'); - } - - function copy() { - const names = getNames(); - const from = Info.dirPath; - - clear(); - - if (!names.length) - return; - - Storage.remove(CUT) - .set(COPY, { - from : from, - names: names - }); - } - - function cut() { - const names = getNames(); - const from = Info.dirPath; - - clear(); - - if (!names.length) - return; - - addCutClass(); - - Storage - .set(CUT, { - from : from, - names: names - }); - } - - function clear() { - Storage.remove(COPY) - .remove(CUT); - - rmCutClass(); - } - - function paste() { - const copy = Storage.get.bind(Storage, COPY); - const cut = Storage.get.bind(Storage, CUT); - - exec.parallel([copy, cut], function(error, cp, ct) { - const opStr = cp ? 'copy' : 'move'; - const opData = cp || ct; - const Operation = CloudCmd.Operation; - const msg = 'Path is same!'; - const path = Info.dirPath; - - if (!error && !cp && !ct) - error = 'Buffer is empty!'; - - if (error) - return showMessage(error); - - const data = jonny.parse(opData); - data.to = path; - - if (data.from === path) - return showMessage(msg); - - Operation.show(opStr, data); - clear(); - }); - } - - return Buffer; +function showMessage(msg) { + globalThis.DOM.Dialog.alert(msg); } + +function getNames() { + const {DOM} = globalThis; + const files = DOM.getActiveFiles(); + + return DOM.getFilenames(files); +} + +function addCutClass() { + const {DOM} = globalThis; + const files = DOM.getActiveFiles(); + + for (const element of files) { + element.classList.add(CLASS); + } +} + +function rmCutClass() { + const {DOM} = globalThis; + const files = DOM.getByClassAll(CLASS); + + for (const element of files) { + element.classList.remove(CLASS); + } +} + +const checkEnabled = (fn) => () => { + const is = CloudCmd.config('buffer'); + + if (is) + return fn(); + + showMessage('Buffer disabled in config!'); +}; + +async function readBuffer() { + const [e, cp, ct] = await tryToPromiseAll([ + Storage.getJson(COPY), + Storage.getJson(CUT), + ]); + + return [ + e, + cp, + ct, + ]; +} + +export const copy = checkEnabled(async () => { + const Info = globalThis.DOM.CurrentInfo; + const names = getNames(); + const from = Info.dirPath; + + await clear(); + + if (!names.length) + return; + + await Storage.remove(CUT); + await Storage.setJson(COPY, { + from, + names, + }); +}); + +export const cut = checkEnabled(async () => { + const Info = globalThis.DOM.CurrentInfo; + const names = getNames(); + const from = Info.dirPath; + + await clear(); + + if (!names.length) + return; + + addCutClass(); + + await Storage.setJson(CUT, { + from, + names, + }); +}); + +export const clear = checkEnabled(async () => { + await Storage.remove(COPY); + await Storage.remove(CUT); + + rmCutClass(); +}); + +export const paste = checkEnabled(async () => { + const Info = globalThis.DOM.CurrentInfo; + const [error, cp, ct] = await readBuffer(); + + if (error || !cp && !ct) + return showMessage(error || 'Buffer is empty!'); + + const opStr = cp ? 'copy' : 'move'; + const data = cp || ct; + const {Operation} = CloudCmd; + const msg = 'Path is same!'; + const to = Info.dirPath; + + if (data.from === to) + return showMessage(msg); + + Operation.show(opStr, { + ...data, + to, + }); + + await clear(); +}); diff --git a/client/dom/cmd.js b/client/dom/cmd.js new file mode 100644 index 00000000..d228b315 --- /dev/null +++ b/client/dom/cmd.js @@ -0,0 +1,83 @@ +/* global DOM */ +const SELECTED_FILE = 'selected-file'; +const Cmd = { + getSelectedFiles, + isSelected, + unselectFile, + selectFile, + selectAllFiles, + toggleSelectedFile, + toggleAllSelectedFiles, +}; + +/** + * selected file check + * + * @param currentFile + */ +export function isSelected(currentFile) { + if (!currentFile) + return false; + + return DOM.isContainClass(currentFile, SELECTED_FILE); +} + +/** + * select current file + * @param currentFile + */ +export function selectFile(currentFile) { + const current = currentFile || DOM.getCurrentFile(); + + current.classList.add(SELECTED_FILE); + + return Cmd; +} + +export function unselectFile(currentFile) { + const current = currentFile || DOM.getCurrentFile(); + + current.classList.remove(SELECTED_FILE); + + return Cmd; +} + +export function toggleSelectedFile(currentFile) { + const current = currentFile || DOM.getCurrentFile(); + const name = DOM.getCurrentName(current); + + if (name === '..') + return Cmd; + + current.classList.toggle(SELECTED_FILE); + + return Cmd; +} + +export function toggleAllSelectedFiles() { + DOM + .getAllFiles() + .map(DOM.toggleSelectedFile); + + return Cmd; +} + +export function selectAllFiles() { + DOM + .getAllFiles() + .map(DOM.selectFile); + + return Cmd; +} + +/** + * unified way to get selected files + * + * @currentFile + */ +export function getSelectedFiles() { + const panel = DOM.getPanel(); + const selected = DOM.getByClassAll(SELECTED_FILE, panel); + + return Array.from(selected); +} diff --git a/client/dom/current-file.js b/client/dom/current-file.js new file mode 100644 index 00000000..b8113054 --- /dev/null +++ b/client/dom/current-file.js @@ -0,0 +1,311 @@ +/* global DOM */ +/* global CloudCmd */ +import createElement from '@cloudcmd/create-element'; +import {getTitle, FS} from '#common/cloudfunc'; +import {encode, decode} from '#common/entity'; + +let Title; + +const CURRENT_FILE = 'current-file'; +const encodeNBSP = (a) => a?.replace('\xa0', ' '); +const decodeNBSP = (a) => a?.replace(' ', '\xa0'); + +export const _CURRENT_FILE = CURRENT_FILE; + +/** + * set name from current (or param) file + * + * @param name + * @param current + */ +export const setCurrentName = (name, current) => { + const Info = DOM.CurrentInfo; + const {link} = Info; + const {prefix} = CloudCmd; + const dir = prefix + FS + Info.dirPath; + const encoded = encode(name); + + link.title = encoded; + link.href = dir + encoded; + link.innerHTML = encoded; + + current.setAttribute('data-name', createNameAttribute(name)); + CloudCmd.emit('current-file', current); + + return link; +}; + +/** + * get name from current (or param) file + * + * @param currentFile + */ +export const getCurrentName = (currentFile) => { + const current = currentFile || DOM.getCurrentFile(); + + if (!current) + return ''; + + return parseNameAttribute(current.getAttribute('data-name')); +}; + +/** + * Generate a `data-name` attribute for the given filename + * @param name The string name to encode + */ +const createNameAttribute = (name) => { + const encoded = btoa(encodeURI(name)); + return `js-file-${encoded}`; +}; + +/** + * Parse a `data-name` attribute string back into the original filename + * @param attribute The string we wish to decode + */ +const parseNameAttribute = (attribute) => { + attribute = attribute.replace('js-file-', ''); + return decodeNBSP(decodeURI(atob(attribute))); +}; + +export const _parseNameAttribute = parseNameAttribute; + +const parseHrefAttribute = (prefix, attribute) => { + attribute = attribute.replace(RegExp('^' + prefix + FS), ''); + return decode(decodeNBSP(attribute)); +}; + +export const _parseHrefAttribute = parseHrefAttribute; + +/** + * get current directory path + */ +export const getCurrentDirPath = (panel = DOM.getPanel()) => { + const path = DOM.getByDataName('js-path', panel); + return path.textContent; +}; + +/** + * get link from current (or param) file + * + * @param currentFile - current file by default + */ +export const getCurrentPath = (currentFile) => { + const current = currentFile || DOM.getCurrentFile(); + const [element] = DOM.getByTag('a', current); + const {prefix} = CloudCmd; + + return parseHrefAttribute(prefix, element.getAttribute('href')); +}; + +/** + * get current directory name + */ +export const getCurrentDirName = () => { + const href = DOM + .getCurrentDirPath() + .replace(/\/$/, ''); + + const substr = href.substr(href, href.lastIndexOf('/')); + + return href.replace(`${substr}/`, '') || '/'; +}; + +/** + * get current directory path + */ +export const getParentDirPath = (panel) => { + const path = DOM.getCurrentDirPath(panel); + const dirName = DOM.getCurrentDirName() + '/'; + const index = path.lastIndexOf(dirName); + + if (path === '/') + return path; + + return path.slice(0, index); +}; + +/** + * get not current directory path + */ +export const getNotCurrentDirPath = () => { + const panel = DOM.getPanel({ + active: false, + }); + + return DOM.getCurrentDirPath(panel); +}; + +/** + * unified way to get current file + * + * @currentFile + */ +export const getCurrentFile = () => { + return DOM.getByClass(CURRENT_FILE); +}; + +/** + * get current file by name + */ +export const getCurrentByName = (name, panel = DOM.CurrentInfo.panel) => { + const dataName = 'js-file-' + btoa(encodeURI(encodeNBSP(name))); + return DOM.getByDataName(dataName, panel); +}; + +/** + * private function that unset currentFile + * + * @currentFile + */ +function unsetCurrentFile(currentFile) { + const is = DOM.isCurrentFile(currentFile); + + if (!is) + return; + + currentFile.classList.remove(CURRENT_FILE); +} + +/** + * unified way to set current file + */ +export const setCurrentFile = (currentFile, options) => { + const o = options; + const currentFileWas = DOM.getCurrentFile(); + + if (!currentFile) + return DOM; + + let pathWas = ''; + + if (currentFileWas) { + pathWas = DOM.getCurrentDirPath(); + unsetCurrentFile(currentFileWas); + } + + currentFile.classList.add(CURRENT_FILE); + + const path = DOM.getCurrentDirPath(); + const name = CloudCmd.config('name'); + + if (path !== pathWas) { + DOM.setTitle(getTitle({ + name, + path, + })); + + /* history could be present + * but it should be false + * to prevent default behavior + */ + if (!o || o.history) { + const historyPath = path === '/' ? path : FS + path; + DOM.setHistory(historyPath, null, historyPath); + } + } + + /* scrolling to current file */ + const CENTER = true; + + DOM.scrollIntoViewIfNeeded(currentFile, CENTER); + + CloudCmd.emit('current-file', currentFile); + CloudCmd.emit('current-path', path); + CloudCmd.emit('current-name', DOM.getCurrentName(currentFile)); + + return DOM; +}; + +export const setCurrentByName = (name) => { + const current = DOM.getCurrentByName(name); + return DOM.setCurrentFile(current); +}; + +/* + * set current file by position + * + * @param layer - element + * @param - position {x, y} + */ +export const getCurrentByPosition = ({x, y}) => { + const element = document.elementFromPoint(x, y); + + const getEl = (el) => { + const {tagName} = el; + const isChild = /A|SPAN|LI/.test(tagName); + + if (!isChild) + return null; + + if (tagName === 'A') + return el.parentElement.parentElement; + + if (tagName === 'SPAN') + return el.parentElement; + + return el; + }; + + const el = getEl(element); + + if (el && el.tagName !== 'LI') + return null; + + return el; +}; + +/** + * current file check + * + * @param currentFile + */ +export const isCurrentFile = (currentFile) => { + if (!currentFile) + return false; + + return DOM.isContainClass(currentFile, CURRENT_FILE); +}; + +/** + * set title or create title element + * + * @param name + */ +export const setTitle = (name) => { + if (!Title) + Title = DOM.getByTag('title')[0] || createElement('title', { + innerHTML: name, + parent: document.head, + }); + + Title.textContent = name; + + return DOM; +}; + +/** + * check is current file is a directory + * + * @param currentFile + */ +export const isCurrentIsDir = (currentFile) => { + const current = currentFile || DOM.getCurrentFile(); + const path = DOM.getCurrentPath(current); + const fileType = DOM.getCurrentType(current); + + const isZip = path.endsWith('.zip'); + const isDir = /^directory(-link)?/.test(fileType); + + return isDir || isZip; +}; + +export const getCurrentType = (currentFile) => { + const current = currentFile || DOM.getCurrentFile(); + const el = DOM.getByDataName('js-type', current); + + const type = el.className + .split(' ') + .pop(); + + return type; +}; diff --git a/client/dom/current-file.spec.js b/client/dom/current-file.spec.js new file mode 100644 index 00000000..85b18a29 --- /dev/null +++ b/client/dom/current-file.spec.js @@ -0,0 +1,308 @@ +import {test, stub} from 'supertape'; +import {create} from 'auto-globals'; +import wraptile from 'wraptile'; +import * as currentFile from './current-file.js'; + +const id = (a) => a; + +const returns = wraptile(id); +const {_CURRENT_FILE} = currentFile; + +test('current-file: setCurrentName: setAttribute', (t) => { + const {DOM, CloudCmd} = globalThis; + + globalThis.DOM = getDOM(); + globalThis.CloudCmd = getCloudCmd(); + + const current = create(); + const {setAttribute} = current; + + currentFile.setCurrentName('hello', current); + + globalThis.DOM = DOM; + globalThis.CloudCmd = CloudCmd; + + t.calledWith(setAttribute, [ + 'data-name', + 'js-file-aGVsbG8=', + ], 'should call setAttribute'); + t.end(); +}); + +test('current-file: setCurrentName: setAttribute: cyrillic', (t) => { + const {DOM, CloudCmd} = globalThis; + + globalThis.DOM = getDOM(); + globalThis.CloudCmd = getCloudCmd(); + + const current = create(); + const {setAttribute} = current; + + currentFile.setCurrentName('ай', current); + + globalThis.DOM = DOM; + globalThis.CloudCmd = CloudCmd; + + t.calledWith(setAttribute, [ + 'data-name', + 'js-file-JUQwJUIwJUQwJUI5', + ], 'should call setAttribute'); + t.end(); +}); + +test('current-file: getCurrentName', (t) => { + const current = create(); + current.getAttribute.returns('js-file-Ymlu'); + + const result = currentFile.getCurrentName(current); + + t.equal(result, 'bin'); + t.end(); +}); + +test('current-file: emit', (t) => { + const {DOM, CloudCmd} = globalThis; + + const emit = stub(); + + globalThis.DOM = getDOM(); + globalThis.CloudCmd = getCloudCmd({ + emit, + }); + + const current = create(); + + currentFile.setCurrentName('hello', current); + + globalThis.DOM = DOM; + globalThis.CloudCmd = CloudCmd; + + t.calledWith(emit, ['current-file', current], 'should call emit'); + t.end(); +}); + +test('current-file: setCurrentName: return', (t) => { + const {DOM, CloudCmd} = globalThis; + + const link = {}; + + globalThis.DOM = getDOM({ + link, + }); + + globalThis.CloudCmd = getCloudCmd(); + + const current = create(); + const result = currentFile.setCurrentName('hello', current); + + globalThis.DOM = DOM; + globalThis.CloudCmd = CloudCmd; + + t.equal(result, link, 'should return link'); + t.end(); +}); + +test('current-file: getParentDirPath: result', (t) => { + const {DOM} = globalThis; + + const getCurrentDirPath = returns('/D/Films/+++favorite films/'); + const getCurrentDirName = returns('+++favorite films'); + + globalThis.DOM = getDOM({ + getCurrentDirPath, + getCurrentDirName, + }); + + const result = currentFile.getParentDirPath(); + const expected = '/D/Films/'; + + globalThis.DOM = DOM; + + t.equal(result, expected, 'should return parent dir path'); + t.end(); +}); + +test('current-file: isCurrentFile: no', (t) => { + const {DOM, CloudCmd} = globalThis; + + globalThis.DOM = getDOM(); + globalThis.CloudCmd = getCloudCmd(); + + const result = currentFile.isCurrentFile(); + + globalThis.DOM = DOM; + globalThis.CloudCmd = CloudCmd; + + t.notOk(result); + t.end(); +}); + +test('current-file: isCurrentFile', (t) => { + const {DOM, CloudCmd} = globalThis; + + const isContainClass = stub(); + + globalThis.DOM = getDOM({ + isContainClass, + }); + + globalThis.CloudCmd = getCloudCmd(); + + const current = {}; + currentFile.isCurrentFile(current); + + globalThis.DOM = DOM; + globalThis.CloudCmd = CloudCmd; + + t.calledWith(isContainClass, [current, _CURRENT_FILE], 'should call isContainClass'); + t.end(); +}); + +test('current-file: getCurrentType', (t) => { + const {DOM, CloudCmd} = globalThis; + + globalThis.DOM = getDOM(); + globalThis.CloudCmd = getCloudCmd(); + + const {getByDataName} = globalThis.DOM; + + getByDataName.returns({ + className: 'mini-icon directory', + }); + + const current = create(); + + currentFile.getCurrentType(current); + + globalThis.DOM = DOM; + globalThis.CloudCmd = CloudCmd; + + t.calledWith(getByDataName, ['js-type', current]); + t.end(); +}); + +test('current-file: isCurrentIsDir: getCurrentType', (t) => { + const {DOM, CloudCmd} = globalThis; + + globalThis.DOM = getDOM(); + globalThis.CloudCmd = getCloudCmd(); + + const {getCurrentType} = globalThis.DOM; + + const current = create(); + + currentFile.isCurrentIsDir(current); + + globalThis.DOM = DOM; + globalThis.CloudCmd = CloudCmd; + + t.calledWith(getCurrentType, [current]); + t.end(); +}); + +test('current-file: isCurrentIsDir: directory', (t) => { + const {DOM, CloudCmd} = globalThis; + + globalThis.DOM = getDOM({ + getCurrentType: stub().returns('directory'), + }); + + globalThis.CloudCmd = getCloudCmd(); + + const current = create(); + + const result = currentFile.isCurrentIsDir(current); + + globalThis.DOM = DOM; + globalThis.CloudCmd = CloudCmd; + + t.ok(result); + t.end(); +}); + +test('current-file: isCurrentIsDir: directory-link', (t) => { + const {DOM, CloudCmd} = globalThis; + + globalThis.DOM = getDOM({ + getCurrentType: stub().returns('directory-link'), + }); + + globalThis.CloudCmd = getCloudCmd(); + + const current = create(); + + const result = currentFile.isCurrentIsDir(current); + + globalThis.DOM = DOM; + globalThis.CloudCmd = CloudCmd; + + t.ok(result); + t.end(); +}); + +test('current-file: isCurrentIsDir: file', (t) => { + const {DOM, CloudCmd} = globalThis; + + globalThis.DOM = getDOM({ + getCurrentType: stub().returns('file'), + }); + + globalThis.CloudCmd = getCloudCmd(); + + const current = create(); + + const result = currentFile.isCurrentIsDir(current); + + globalThis.DOM = DOM; + globalThis.CloudCmd = CloudCmd; + + t.notOk(result); + t.end(); +}); + +const getCloudCmd = ({emit} = {}) => ({ + prefix: '', + emit: emit || stub(), +}); + +test('current-file: parseNameAttribute', (t) => { + const result = currentFile._parseNameAttribute('js-file-aGVsbG8mbmJzcDt3b3JsZA=='); + const expected = 'hello\xa0world'; + + t.equal(result, expected); + t.end(); +}); + +test('current-file: parseHrefAttribute', (t) => { + const prefix = '/api/v1'; + const result = currentFile._parseHrefAttribute(prefix, '/api/v1/fs/hello world'); + const expected = '/hello\xa0world'; + + t.equal(result, expected); + t.end(); +}); + +function getDOM(overrides = {}) { + const { + link = {}, + getCurrentDirPath = stub(), + getCurrentDirName = stub(), + getByDataName = stub(), + isContainClass = stub(), + getCurrentType = stub(), + getCurrentPath = stub().returns(''), + } = overrides; + + return { + getCurrentDirPath, + getCurrentDirName, + getCurrentPath, + getByDataName, + isContainClass, + getCurrentType, + CurrentInfo: { + link, + dirPath: '/', + }, + }; +} diff --git a/client/dom/dialog.js b/client/dom/dialog.js index b879f9c4..b1791d92 100644 --- a/client/dom/dialog.js +++ b/client/dom/dialog.js @@ -1,56 +1,18 @@ -/* global DOM */ -/* global smalltalk */ +import {tryToCatch} from 'try-to-catch'; +import * as smalltalk from 'smalltalk'; -'use strict'; +const title = 'Cloud Commander'; -module.exports = Dialog; +export const alert = (...a) => smalltalk.alert(title, ...a, { + cancel: false, +}); -function Dialog(prefix, config) { - if (!(this instanceof Dialog)) - return new Dialog(prefix, config); - - load(config.htmlDialogs); - - function getJsName(htmlDialogs) { - const is = window.Promise; - const js = '.min.js'; - const jsName = is ? js : '.poly' + js; - - if (!htmlDialogs) - return '.native' + jsName; - - return jsName; - } - - function load(htmlDialogs) { - const noop = () => {}; - const name = 'smalltalk'; - const dir = '/modules/' + name + '/dist/'; - const jsName = getJsName(htmlDialogs); - - const names = [jsName, '.min.css'].map((ext) => { - return prefix + dir + name + ext; - }); - - DOM.load.parallel(names, noop); - } - - const alert = (title, message) => { - return smalltalk.alert(title, message); - }; - - this.alert = alert; - - this.prompt = (title, message, value, options) => { - return smalltalk.prompt(title, message, value, options); - }; - - this.confirm = (title, message, options) => { - return smalltalk.confirm(title, message, options); - }; - - this.alert.noFiles = (title) => { - return alert(title, 'No files selected!'); - }; -} +export const prompt = (...a) => tryToCatch(smalltalk.prompt, title, ...a); +export const confirm = (...a) => tryToCatch(smalltalk.confirm, title, ...a); +export const progress = (...a) => smalltalk.progress(title, ...a); +alert.noFiles = () => { + return smalltalk.alert(title, 'No files selected!', { + cancel: false, + }); +}; diff --git a/client/dom/directory.js b/client/dom/directory.js index dbfe929f..efbca119 100644 --- a/client/dom/directory.js +++ b/client/dom/directory.js @@ -1,90 +1,64 @@ -/* global CloudCmd */ -/* global DOM */ +/* global DOM, CloudCmd */ +import philip from 'philip'; +import * as Dialog from '#dom/dialog'; +import {FS} from '#common/cloudfunc'; +import * as Images from '#dom/images'; -'use strict'; - -const Images = require('./images'); -const {FS} = require('../../common/cloudfunc'); - -module.exports = (items) => { - const Info = DOM.CurrentInfo; - const load = DOM.load; - const Dialog = DOM.Dialog; - +export const uploadDirectory = (items) => { if (items.length) Images.show('top'); - const entries = [...items].map((item) => { - return item.webkitGetAsEntry(); + const entries = Array + .from(items) + .map((item) => item.webkitGetAsEntry()); + + const dirPath = DOM.getCurrentDirPath(); + const path = dirPath.replace(/\/$/, ''); + + const progress = Dialog.progress('Uploading...'); + + progress.catch(() => { + Dialog.alert('Upload aborted'); + uploader.abort(); }); - const addDir = (name) => { - return `/modules/${name}/lib/${name}.js`; - }; - - const array = [ - 'findit', - 'philip' - ]; - - const url = CloudCmd.join(array.map(addDir)); - - load.js(url, () => { - const path = Info.dirPath - .replace(/\/$/, ''); + const uploader = philip(entries, (type, name, data, i, n, callback) => { + const {prefixURL} = CloudCmd; + const full = prefixURL + FS + path + name; - const uploader = window.philip(entries, (type, name, data, i, n, callback) => { - const prefixURL = CloudCmd.PREFIX_URL; - const full = prefixURL + FS + path + name; + let upload; + switch(type) { + case 'file': + upload = uploadFile(full, data); + break; + + case 'directory': + upload = uploadDir(full); + break; + } + + upload.on('end', callback); + + upload.on('progress', (count) => { + const current = percent(i, n); + const next = percent(i + 1, n); + const max = next - current; + const value = current + percent(count, 100, max); - let upload; - switch(type) { - case 'file': - upload = uploadFile(full, data); - break; - - case 'directory': - upload = uploadDir(full); - break; - } - - upload.on('end', callback); - - upload.on('progress', (count) => { - const current = percent(i, n); - const next = percent(i + 1, n); - const max = next - current; - const value = current + percent(count, 100, max); - - setProgress(value); - }); + progress.setProgress(value); }); - - uploader.on('error', (error) => { - Dialog.alert(error); - uploader.abort(); - }); - - uploader.on('progress', setProgress); - uploader.on('end', CloudCmd.refresh); }); + + uploader.on('error', (error) => { + Dialog.alert(error); + uploader.abort(); + }); + + uploader.on('end', CloudCmd.refresh); }; -function percent(i, n, per = 100) { - return Math.round(i * per / n); -} +const percent = (i, n, per = 100) => Math.round(i * per / n); -function setProgress(count) { - DOM.Images - .setProgress(count) - .show('top'); -} - -function uploadFile(url, data) { - return DOM.load.put(url, data); -} - -function uploadDir(url) { - return DOM.load.put(url + '?dir'); -} +const uploadFile = (url, data) => DOM.load.put(url, data); +const uploadDir = (url) => DOM.load.put(`${url}?dir`); diff --git a/client/dom/dom-tree.js b/client/dom/dom-tree.js index 0c468116..fad5ad40 100644 --- a/client/dom/dom-tree.js +++ b/client/dom/dom-tree.js @@ -1,6 +1,15 @@ -'use strict'; +import currify from 'currify'; -const DOM = module.exports; +const DOM = { + show, + hide, + getByClass, + getByClassAll, + getByDataName, + getById, + getByTag, + isContainClass, +}; /** * check class of element @@ -8,71 +17,76 @@ const DOM = module.exports; * @param element * @param className */ -module.exports.isContainClass = (element, className) => { +export function isContainClass(element, className) { if (!element) throw Error('element could not be empty!'); if (!className) throw Error('className could not be empty!'); - const classList = element.classList; - const ret = classList.contains(className); + if (Array.isArray(className)) + return className.some(currify( + isContainClass, + element, + )); - return ret; -}; + const {classList} = element; + + return classList.contains(className); +} /** * Function search element by tag * @param tag - className * @param element - element */ -module.exports.getByTag = (tag, element = document) => { +export function getByTag(tag, element = document) { return element.getElementsByTagName(tag); -}; +} /** * Function search element by id - * @param Id - id + * @param id + * @param element */ -module.exports.getById = (id, element = document) => { - return element.querySelector('#' + id); -}; +export function getById(id, element = document) { + return element.querySelector(`#${id}`); +} /** * Function search first element by class name * @param className - className * @param element - element */ -module.exports.getByClass = (className, element = document) => { +export function getByClass(className, element = document) { return DOM.getByClassAll(className, element)[0]; -}; +} -module.exports.getByDataName = (attribute, element = document) => { - const selector = '[' + 'data-name="' + attribute + '"]'; +export function getByDataName(attribute, element = document) { + const selector = '[' + 'data-name="' + attribute + '"]'; return element.querySelector(selector); -}; +} /** * Function search element by class name - * @param pClass - className - * @param element - element + * @param className + * @param element */ -module.exports.getByClassAll = (className, element) => { +export function getByClassAll(className, element) { return (element || document).getElementsByClassName(className); -}; +} /** * add class=hidden to element * * @param element */ -module.exports.hide = (element) => { +export function hide(element) { element.classList.add('hidden'); return DOM; -}; +} -module.exports.show = (element) => { +export function show(element) { element.classList.remove('hidden'); return DOM; -}; - +} diff --git a/client/dom/dom-tree.spec.js b/client/dom/dom-tree.spec.js new file mode 100644 index 00000000..53b376c7 --- /dev/null +++ b/client/dom/dom-tree.spec.js @@ -0,0 +1,152 @@ +import {test, stub} from 'supertape'; +import {create} from 'auto-globals'; +import {tryCatch} from 'try-catch'; +import { + isContainClass, + getByTag, + getById, + getByClass, + getByDataName, + getByClassAll, + hide, + show, +} from './dom-tree.js'; + +test('dom: isContainClass: no element', (t) => { + const [e] = tryCatch(isContainClass); + + t.equal(e.message, 'element could not be empty!', 'should throw when no element'); + t.end(); +}); + +test('dom: isContainClass: no className', (t) => { + const [e] = tryCatch(isContainClass, {}); + + t.equal(e.message, 'className could not be empty!', 'should throw when no element'); + t.end(); +}); + +test('dom: isContainClass: contains', (t) => { + const el = create(); + const {contains} = el.classList; + + const className = 'hello'; + isContainClass(el, className); + + t.calledWith(contains, [className], 'should call contains'); + t.end(); +}); + +test('dom: isContainClass: contains: array', (t) => { + const el = create(); + const {contains} = el.classList; + + const className = 'hello'; + isContainClass(el, ['world', className, 'hello']); + + t.calledWith(contains, [className], 'should call contains'); + t.end(); +}); + +test('dom: getByTag', (t) => { + const getElementsByTagName = stub(); + const element = { + getElementsByTagName, + }; + + getByTag('div', element); + + t.calledWith(getElementsByTagName, ['div'], 'should call getElementsByTagName'); + t.end(); +}); + +test('dom: getById', (t) => { + const querySelector = stub(); + const element = { + querySelector, + }; + + getById('my-id', element); + + t.calledWith(querySelector, ['#my-id'], 'should call querySelector with id selector'); + t.end(); +}); + +test('dom: getByClassAll', (t) => { + const getElementsByClassName = stub(); + const element = { + getElementsByClassName, + }; + + getByClassAll('my-class', element); + + t.calledWith(getElementsByClassName, ['my-class'], 'should call getElementsByClassName'); + t.end(); +}); + +test('dom: getByClass: calls getByClassAll', (t) => { + const element = { + getElementsByClassName: stub().returns(['first']), + }; + + const result = getByClass('my-class', element); + + t.equal(result, 'first', 'should return first element from class list'); + t.end(); +}); + +test('dom: getByDataName', (t) => { + const querySelector = stub(); + const element = { + querySelector, + }; + + getByDataName('hello', element); + + t.calledWith(querySelector, ['[data-name="hello"]'], 'should call querySelector with data-name selector'); + t.end(); +}); + +test('dom: hide', (t) => { + const add = stub(); + const element = { + classList: { + add, + }, + }; + + hide(element); + + t.calledWith(add, ['hidden'], 'should add hidden class'); + t.end(); +}); + +test('dom: show', (t) => { + const remove = stub(); + const element = { + classList: { + remove, + }, + }; + + show(element); + + t.calledWith(remove, ['hidden'], 'should remove hidden class'); + t.end(); +}); + +test('dom: getByClassAll: without element uses document', (t) => { + const getElementsByClassName = stub(); + const prevDocument = globalThis.document; + + globalThis.document = { + getElementsByClassName, + }; + + getByClassAll('my-class'); + + globalThis.document = prevDocument; + + t.calledWith(getElementsByClassName, ['my-class'], 'should fallback to document when no element'); + t.end(); +}); diff --git a/client/dom/events.js b/client/dom/events.js deleted file mode 100644 index c0977849..00000000 --- a/client/dom/events.js +++ /dev/null @@ -1,309 +0,0 @@ -'use strict'; - -const itype = require('itype/legacy'); - -module.exports = new EventsProto(); - -function EventsProto() { - const Events = this; - - function parseArgs(eventName, element, listener, callback) { - let isFunc; - - const EVENT_NAME = 1; - const ELEMENT = 0; - const type = itype(eventName); - - switch(type) { - default: - if (!/element$/.test(type)) - throw Error('unknown eventName: ' + type); - - parseArgs( - arguments[EVENT_NAME], - arguments[ELEMENT], - listener, - callback - ); - break; - - case 'string': - isFunc = itype.function(element); - - if (isFunc) { - listener = element; - element = null; - } - - if (!element) - element = window; - - callback(element, [ - eventName, - listener, - false - ]); - break; - - case 'array': - eventName.forEach((eventName) => { - parseArgs( - eventName, - element, - listener, - callback - ); - }); - break; - - case 'object': - Object.keys(eventName).forEach((name) => { - 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, function(element, args) { - element.addEventListener.apply(element, args); - }); - - return Events; - }; - - /** - * safe add event listener - * - * @param type - * @param listener - * @param element {document by default} - */ - this.addOnce = (type, element, listener) => { - var 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.apply(element, args); - }); - - return Events; - }; - - /** - * safe add event keydown listener - * - * @param listener - */ - this.addKey = function(...argsArr) { - const name = 'keydown'; - const args = [name].concat(argsArr); - - return this.add(...args); - }; - - /** - * safe remove event click listener - * - * @param listener - */ - this.rmKey = function(...argsArr) { - const name = 'keydown'; - const args = [name].concat(argsArr); - - return this.remove(...args); - }; - - /** - * safe add event click listener - * - * @param listener - */ - this.addClick = function(...argsArr) { - const name = 'click'; - const args = [name].concat(argsArr); - - return this.add(...args); - }; - - /** - * safe remove event click listener - * - * @param listener - */ - this.rmClick = function(...argsArr) { - const name = 'click'; - const args = [name].concat(argsArr); - - return this.remove(...args); - }; - - this.addContextMenu = function(...argsArr) { - const name = 'contextmenu'; - const args = [name].concat(argsArr); - - return this.add(...args); - }; - - /** - * safe add event click listener - * - * @param listener - */ - this.addError = function(...argsArr) { - const name = 'error'; - const args = [name].concat(argsArr); - - return this.add(...args); - }; - - /** - * safe add load click listener - * - * @param listener - */ - this.addLoad = function(...argsArr) { - const name = 'load'; - const args = [name].concat(argsArr); - - return this.add(...args); - }; - - /** - * crossbrowser create event - * - * @param eventName - * @param keyCode - not necessarily - */ - this.create = function(eventName, keyCode) { - const event = document.createEvent('Event'); - - event.initEvent(eventName, true, true); - - if (keyCode) - event.keyCode = keyCode; - - event.isDefaultPrevented = function() { - return this.defaultPrevented; - }; - - return event; - }; - - /** - * create keydown event - * - * @param keyCode - */ - this.createKey = function(keyCode) { - return this.create('keydown', keyCode); - }; - - /** - * create click event - */ - this.createClick = function() { - return this.create('click'); - }; - - /** - * create click event - */ - this.createDblClick = function() { - return this.create('dblclick'); - }; - - /** - * dispatch event - * - * @param event - */ - this.dispatch = (event, element) => { - let customEvent; - const isStr = itype.string(event); - - if (isStr) - customEvent = Events.create(event); - else - customEvent = event; - - return (element || window).dispatchEvent(customEvent); - }; - - /** - * dispatch keydown event - * - * @param keyCode - * @param element - */ - this.dispatchKey = function(keyCode, element) { - const event = this.createKey(keyCode); - return this.dispatch(event, element); - }; - - /** - * dispatch click event - * - * @param element - */ - this.dispatchClick = function(element) { - const event = this.createClick(); - return this.dispatch(event, element); - }; - - /** - * dispatch dblclick event - * - * @param element - */ - this.dispatchDblClick = function(element) { - const event = this.createDblClick(); - - return this.dispatch(event, element); - }; - - function checkType(type) { - if (!type) - throw Error('type could not be empty!'); - } -} - diff --git a/client/dom/events/event-store.js b/client/dom/events/event-store.js new file mode 100644 index 00000000..1cbfe7a4 --- /dev/null +++ b/client/dom/events/event-store.js @@ -0,0 +1,15 @@ +let list = []; + +export const add = (el, name, fn) => { + list.push([ + el, + name, + fn, + ]); +}; + +export const clear = () => { + list = []; +}; + +export const get = () => list; diff --git a/client/dom/events/event-store.spec.js b/client/dom/events/event-store.spec.js new file mode 100644 index 00000000..6a623939 --- /dev/null +++ b/client/dom/events/event-store.spec.js @@ -0,0 +1,37 @@ +import {test} from 'supertape'; +import * as eventStore from './event-store.js'; + +test('event-store: get', (t) => { + const el = {}; + const name = 'click'; + const fn = () => {}; + + eventStore.add(el, name, fn); + const result = eventStore.get(); + + const expected = [ + [ + el, + name, + fn, + ], + ]; + + t.deepEqual(result, expected); + t.end(); +}); + +test('event-store: clear', (t) => { + const el = {}; + const name = 'click'; + const fn = () => {}; + + eventStore.add(el, name, fn); + eventStore.clear(); + + const result = eventStore.get(); + const expected = []; + + t.deepEqual(result, expected); + t.end(); +}); diff --git a/client/dom/events/index.js b/client/dom/events/index.js new file mode 100644 index 00000000..c49d2333 --- /dev/null +++ b/client/dom/events/index.js @@ -0,0 +1,203 @@ +import itype from 'itype'; +import * as EventStore from './event-store.js'; + +/** + * safe add event listener + * + * @param type + * @param element - document by default + * @param listener + */ +export const add = (type, element, listener) => { + checkType(type); + + parseArgs(type, element, listener, (element, args) => { + const [name, fn, options] = args; + + element.addEventListener(name, fn, options); + EventStore.add(element, name, fn); + }); + + return Events; +}; + +/** + * safe add event listener + * + * @param type + * @param listener + * @param element - document by default + */ +export const addOnce = (type, element, listener) => { + const once = (event) => { + Events.remove(type, element, once); + listener(event); + }; + + if (!listener) { + listener = element; + element = null; + } + + add(type, element, once); + + return Events; +}; + +/** + * safe remove event listener + * + * @param type + * @param listener + * @param element - document by default + */ +export const remove = (type, element, listener) => { + checkType(type); + + parseArgs(type, element, listener, (element, args) => { + element.removeEventListener(...args); + }); + + return Events; +}; + +/** + * remove all added event listeners + */ +export const removeAll = () => { + const events = EventStore.get(); + + for (const [el, name, fn] of events) + el.removeEventListener(name, fn); + + EventStore.clear(); +}; + +/** + * safe add event keydown listener + * + * @param args + */ +export const addKey = function(...args) { + return add('keydown', ...args); +}; + +/** + * safe remove event click listener + * + * @param args + */ +export const rmKey = function(...args) { + return Events.remove('keydown', ...args); +}; + +/** + * safe add event click listener + */ +export const addClick = function(...args) { + return Events.add('click', ...args); +}; + +/** + * safe remove event click listener + */ +export const rmClick = function(...args) { + return remove('click', ...args); +}; + +export const addContextMenu = function(...args) { + return add('contextmenu', ...args); +}; + +/** + * safe add load listener + */ +export const addLoad = function(...args) { + return add('load', ...args); +}; + +function checkType(type) { + if (!type) + throw Error('type could not be empty!'); +} + +const getEventOptions = (eventName) => { + if (eventName !== 'touchstart') + return false; + + return { + passive: true, + }; +}; + +function parseArgs(eventName, element, listener, callback) { + let isFunc; + const args = [ + eventName, + element, + listener, + callback, + ]; + + const EVENT_NAME = 1; + const ELEMENT = 0; + const type = itype(eventName); + + switch(type) { + default: + if (!type.endsWith('element')) + throw Error(`unknown eventName: ${type}`); + + parseArgs(args[EVENT_NAME], args[ELEMENT], listener, callback); + break; + + case 'string': + isFunc = itype.function(element); + + if (isFunc) { + listener = element; + element = null; + } + + if (!element) + element = window; + + callback(element, [ + eventName, + listener, + getEventOptions(eventName), + ]); + break; + + case 'array': + + for (const name of eventName) { + parseArgs(name, element, listener, callback); + } + + break; + + case 'object': + + for (const name of Object.keys(eventName)) { + const eventListener = eventName[name]; + + parseArgs(name, element, eventListener, callback); + } + + break; + } +} + +const Events = { + add, + addClick, + addContextMenu, + addKey, + addLoad, + addOnce, + remove, + removeAll, + rmClick, + rmKey, +}; diff --git a/client/dom/files.js b/client/dom/files.js index 44e9f7e1..395ac0fa 100644 --- a/client/dom/files.js +++ b/client/dom/files.js @@ -1,105 +1,82 @@ /* global CloudCmd */ - -'use strict'; - -const itype = require('itype/legacy'); -const currify = require('currify/legacy'); -const exec = require('execon'); - -const Storage = require('./storage'); -const load = require('./load'); -const RESTful = require('./rest'); +import itype from 'itype'; +import {promisify} from 'es6-promisify'; +import * as load from '#dom/load'; +import * as RESTful from '#dom/rest'; const Promises = {}; const FILES_JSON = 'config|modules'; const FILES_HTML = 'file|path|link|pathLink|media'; const FILES_HTML_ROOT = 'view/media-tmpl|config-tmpl|upload'; const DIR_HTML = '/tmpl/'; -const DIR_HTML_FS = DIR_HTML + 'fs/'; +const DIR_HTML_FS = `${DIR_HTML}fs/`; const DIR_JSON = '/json/'; const timeout = getTimeoutOnce(2000); -const get = currify(getFile); -const unaryMap = (array, fn) => array.map((a) => fn(a)); +export const get = getFile; -module.exports.get = get; - -function getFile(name, callback) { +function getFile(name) { const type = itype(name); - let array; + check(name); - check(name, callback); + if (type === 'string') + return getModule(name); - switch(type) { - case 'string': - getModule(name, callback); - break; - - case 'array': - array = unaryMap(name, get); - - exec.parallel(array, callback); - break; - } + if (type === 'array') + return Promise.all(name.map(getFile)); } -function check(name, callback) { +function check(name) { if (!name) throw Error('name could not be empty!'); - - if (typeof callback !== 'function') - throw Error('callback should be a function'); } -function getModule(name, callback) { - let path; - - const regExpHTML = new RegExp(FILES_HTML + '|' + FILES_HTML_ROOT); - const regExpJSON = new RegExp(FILES_JSON); +function getModule(name) { + const regExpHTML = RegExp(FILES_HTML + '|' + FILES_HTML_ROOT); + const regExpJSON = RegExp(FILES_JSON); const isHTML = regExpHTML.test(name); const isJSON = regExpJSON.test(name); - if (!isHTML && !isJSON) { - showError(name); - } else if (name === 'config') { - getConfig(callback); - } else { - path = getPath(name, isHTML, isJSON); - - getSystemFile(path, callback); - } + if (!isHTML && !isJSON) + return showError(name); + if (name === 'config') + return getConfig(); + + const path = getPath(name, isHTML, isJSON); + + return getSystemFile(path); } function getPath(name, isHTML, isJSON) { let path; - const regExp = new RegExp(FILES_HTML_ROOT); + const regExp = RegExp(FILES_HTML_ROOT); const isRoot = regExp.test(name); if (isHTML) { if (isRoot) path = DIR_HTML + name.replace('-tmpl', ''); else - path = DIR_HTML_FS + name; + path = DIR_HTML_FS + name; path += '.hbs'; } else if (isJSON) { - path = DIR_JSON + name + '.json'; + path = DIR_JSON + name + '.json'; } return path; } function showError(name) { - const str = 'Wrong file name: ' + name; - const error = new Error(str); + const str = `Wrong file name: ${name}`; + const error = Error(str); - throw(error); + throw error; } -function getSystemFile(file, callback) { - const prefix = CloudCmd.PREFIX; +const getSystemFile = promisify((file, callback) => { + const {prefix} = CloudCmd; if (!Promises[file]) Promises[file] = new Promise((success, error) => { @@ -108,7 +85,7 @@ function getSystemFile(file, callback) { load.ajax({ url, success, - error + error, }); }); @@ -118,37 +95,29 @@ function getSystemFile(file, callback) { Promises[file] = null; callback(error); }); -} +}); -function getConfig(callback) { +const getConfig = async () => { let is; if (!Promises.config) - Promises.config = new Promise((resolve, reject) => { + Promises.config = () => { is = true; - RESTful.Config.read((error, data) => { - if (error) - return reject(error); - - resolve(data); - }); - }); + return RESTful.Config.read(); + }; - Promises.config.then(function(data) { + const [, data] = await Promises.config(); + + if (data) is = false; - Storage.setAllowed(data.localStorage); - - callback(null, data); - - timeout(() => { - if (!is) - Promises.config = null; - }); - }, function() { + + timeout(() => { if (!is) Promises.config = null; }); -} + + return data; +}; function getTimeoutOnce(time) { let is; @@ -165,4 +134,3 @@ function getTimeoutOnce(time) { }, time); }; } - diff --git a/client/dom/images.js b/client/dom/images.js index 67d4eec4..75663e72 100644 --- a/client/dom/images.js +++ b/client/dom/images.js @@ -1,22 +1,13 @@ -/* global CloudCmd */ - -'use strict'; - -const DOM = require('./'); - -const Images = module.exports; +/* global DOM */ +import createElement from '@cloudcmd/create-element'; const LOADING = 'loading'; const HIDDEN = 'hidden'; const ERROR = 'error'; -const LoadingImage = LOADING + getLoadingType(); +const getLoadingType = () => isSVG() ? '-svg' : '-gif'; -function getLoadingType() { - return isSVG() ? '-svg' : '-gif'; -} - -module.exports.get = getElement; +export const get = getElement; /** * check SVG SMIL animation support @@ -35,54 +26,60 @@ function isSVG() { return /SVGAnimate/.test(name); } - function getElement() { - return DOM.load({ - name : 'span', - id : 'js-status-image', - className : 'icon', - attribute : 'data-progress', - notAppend : true + return createElement('span', { + id: 'js-status-image', + className: 'icon', + dataName: 'progress', + notAppend: true, }); } /* Функция создаёт картинку загрузки */ -module.exports.loading = () => { +export const loading = () => { const element = getElement(); - const classList = element.classList; + const {classList} = element; + const loadingImage = LOADING + getLoadingType(); - classList.add(LOADING, LoadingImage); + classList.add(LOADING, loadingImage); classList.remove(ERROR, HIDDEN); return element; }; /* Функция создаёт картинку ошибки загрузки */ -module.exports.error = () => { +export const error = () => { const element = getElement(); - const classList = element.classList; + const {classList} = element; + const loadingImage = LOADING + getLoadingType(); classList.add(ERROR); - classList.remove(HIDDEN, LOADING, LoadingImage); + classList.remove(HIDDEN, LOADING, loadingImage); return element; }; -module.exports.show = show; -module.exports.show.load = show; -module.exports.show.error = error; +show.load = show; +show.error = (text) => { + const image = Images.error(); + + DOM.show(image); + image.title = text; + + return image; +}; /** * Function shows loading spinner * position = {top: true}; */ -function show(position, panel) { +export function show(position, panel) { const image = Images.loading(); const parent = image.parentElement; const refreshButton = DOM.getRefreshButton(panel); let current; - + if (position === 'top') { current = refreshButton.parentElement; } else { @@ -94,7 +91,7 @@ function show(position, panel) { current = refreshButton.parentElement; } - if (!parent || (parent && parent !== current)) + if (!parent || parent && parent !== current) current.appendChild(image); DOM.show(image); @@ -102,36 +99,25 @@ function show(position, panel) { return image; } -function error(text) { - const image = Images.error(); - - DOM.show(image); - image.title = text; - - CloudCmd.log(text); - - return image; -} - /** * hide load image */ -module.exports.hide = () => { +export function hide() { const element = Images.get(); DOM.hide(element); return Images; -}; +} -module.exports.setProgress = (value, title) => { +export const setProgress = (value, title) => { const DATA = 'data-progress'; const element = Images.get(); - + if (!element) return Images; - element.setAttribute(DATA, value + '%'); + element.setAttribute(DATA, `${value}%`); if (title) element.title = title; @@ -139,7 +125,7 @@ module.exports.setProgress = (value, title) => { return Images; }; -module.exports.clearProgress = () => { +export const clearProgress = () => { const DATA = 'data-progress'; const element = Images.get(); @@ -152,3 +138,12 @@ module.exports.clearProgress = () => { return Images; }; +const Images = { + clearProgress, + setProgress, + show, + hide, + get, + error, + loading, +}; diff --git a/client/dom/index.js b/client/dom/index.js index cd69be81..a82b6f72 100644 --- a/client/dom/index.js +++ b/client/dom/index.js @@ -1,1220 +1,811 @@ /* global CloudCmd */ +import * as load from '#dom/load'; +import * as Files from '#dom/files'; +import * as Dialog from '#dom/dialog'; +import * as Events from '#dom/events'; +import {getExt} from '#common/util'; +import * as Storage from '#dom/storage'; +import * as RESTful from '#dom/rest'; +import * as Images from '#dom/images'; +import renameCurrent from './operations/rename-current.js'; +import * as CurrentFile from './current-file.js'; +import * as DOMTree from './dom-tree.js'; +import * as Cmd from './cmd.js'; +import * as IO from './io/index.js'; +import {uploadDirectory} from './directory.js'; +import * as Buffer from './buffer.js'; +import {loadRemote as _loadRemote} from './load-remote.js'; +import {selectByPattern} from './select-by-pattern.js'; -'use strict'; +const {assign} = Object; -const itype = require('itype/legacy'); -const exec = require('execon'); -const jonny = require('jonny'); -const Util = require('../../common/util'); +const DOM = { + getCurrentDirName, + getNotCurrentDirPath, + getParentDirPath, + loadRemote, + loadSocket, + promptNewDir, + promptNewFile, + unselectFiles, + getActiveFiles, + getCurrentDate, + getCurrentSize, + loadCurrentSize, + loadCurrentHash, + setCurrentSize, + getCurrentMode, + getCurrentOwner, + getCurrentData, + getRefreshButton, + getAllFiles, + expandSelection, + shrinkSelection, + setHistory, + getCurrentLink, + getFilenames, + checkStorageHash, + saveDataToStorage, + getFM, + getPanelPosition, + getCSSVar, + getPanel, + getFiles, + showPanel, + hidePanel, + remove, + deleteCurrent, + deleteSelected, + renameCurrent, + scrollIntoViewIfNeeded, + scrollByPages, + changePanel, + getPackerExt, + goToDirectory, + duplicatePanel, + swapPanels, + updateCurrentInfo, +}; -const { - getTitle, - FS, - Entity, -} = require('../../common/cloudfunc'); +assign(DOM, { + ...DOMTree, + ...CurrentFile, + ...Cmd, +}); -const DOMTree = require('./dom-tree'); - -const DOM = Object.assign({}, DOMTree, new CmdProto()); - -module.exports = DOM; - -const Images = require('./images'); -const load = require('./load'); -const Files = require('./files'); -const RESTful = require('./rest'); -const Storage = require('./storage'); +export const CurrentInfo = {}; DOM.Images = Images; DOM.load = load; DOM.Files = Files; DOM.RESTful = RESTful; +DOM.IO = IO; DOM.Storage = Storage; +DOM.Dialog = Dialog; +DOM.CurrentInfo = CurrentInfo; -DOM.uploadDirectory = require('./directory'); -DOM.Buffer = require('./buffer'); -DOM.Events = require('./events'); +export default DOM; -const loadRemote = require('./load-remote'); -const selectByPattern = require('./select-by-pattern'); +DOM.uploadDirectory = uploadDirectory; +DOM.Buffer = Buffer; +DOM.Events = Events; +const isString = (a) => typeof a === 'string'; -function CmdProto() { - let Title; - let CurrentInfo = {}; +const TabPanel = { + 'js-left': null, + 'js-right': null, +}; + +export function loadRemote(name, options, callback) { + _loadRemote(name, options, callback); + return DOM; +} + +export function loadSocket(callback) { + DOM.loadRemote('socket', { + name: 'io', + }, callback); - const Cmd = this; - const CURRENT_FILE = 'current-file'; - const SELECTED_FILE = 'selected-file'; - const TITLE = 'Cloud Commander'; - const TabPanel = { - 'js-left' : null, - 'js-right' : null - }; + return DOM; +} + +/** + * create new folder + * + */ +export async function promptNewDir() { + await promptNew('directory'); +} + +/** + * create new file + * + * @typeName + * @type + */ +export async function promptNewFile() { + await promptNew('file'); +} + +async function promptNew(typeName) { + const {Dialog} = DOM; + const dir = DOM.getCurrentDirPath(); + const msg = `New ${typeName}` || 'File'; - this.loadRemote = (name, options, callback) => { - loadRemote(name, options, callback); - return DOM; - }; - /** - * load jquery from google cdn or local copy - * @param callback - */ - this.loadJquery = function(callback) { - DOM.loadRemote('jquery', { - name : '$' - }, callback); - - return DOM; - }; - - this.loadSocket = function(callback) { - DOM.loadRemote('socket', { - name : 'io' - }, callback); - - return DOM; - }; - - /** function loads css and js of Menu - * @param callback - */ - this.loadMenu = function(callback) { - return DOM.loadRemote('menu', callback); - }; - - /** - * create new folder - * - */ - this.promptNewDir = function() { - promptNew('directory', '?dir'); - }; - - /** - * create new file - * - * @typeName - * @type - */ - this.promptNewFile = () => { - promptNew('file'); - }; - - function promptNew(typeName, type) { - const {Dialog} = DOM; - const dir = Cmd.getCurrentDirPath(); - const msg = 'New ' + typeName || 'File'; - const getName = () => { - const name = Cmd.getCurrentName(); - - if (name === '..') - return ''; - - return name; - }; - - const name = getName(); - const cancel = false; - - Dialog.prompt(TITLE, msg, name, {cancel}).then((name) => { - if (!name) - return; - - const path = (type) => { - const result = dir + name; - - if (!type) - return result; - - return result + type; - }; - - RESTful.write(path(type), (error) => { - if (error) - return; - - const currentName = name; - - CloudCmd.refresh({ - currentName - }); - }); - }); - } - - /** - * get current direcotory name - */ - this.getCurrentDirName = () => { - const href = DOM.getCurrentDirPath() - .replace(/\/$/, ''); - - const substr = href.substr(href, href.lastIndexOf('/')); - const ret = href.replace(substr + '/', '') || '/'; - - return ret; - }; - - /** - * get current direcotory path - */ - this.getCurrentDirPath = (panel = DOM.getPanel()) => { - const path = DOM.getByDataName('js-path', panel); - const ret = path && path.textContent; - - return ret; - }; - - /** - * get current direcotory path - */ - this.getParentDirPath = (panel) => { - const path = DOM.getCurrentDirPath(panel); - const dirName = DOM.getCurrentDirName() + '/'; - - if (path !== '/') - return path.replace(RegExp(dirName + '$'), ''); - - return path; - }; - - /** - * get not current direcotory path - */ - this.getNotCurrentDirPath = () => { - const panel = DOM.getPanel({active: false}); - const path = DOM.getCurrentDirPath(panel); - - return path; - }; - - /** - * unified way to get current file - * - * @currentFile - */ - this.getCurrentFile = () => { - return DOM.getByClass(CURRENT_FILE); - }; - - /** - * get current file by name - */ - this.getCurrentByName = (name, panel = CurrentInfo.panel) => { - const dataName = 'js-file-' + name; - const element = DOM.getByDataName(dataName, panel); - - return element; - }; - - /** - * unified way to get current file - * - * @currentFile - */ - this.getSelectedFiles = () => { - const panel = DOM.getPanel(); - const selected = DOM.getByClassAll(SELECTED_FILE, panel); - - return [...selected]; - }; - - /* - * unselect all files - */ - this.unselectFiles = (files) => { - files = files || DOM.getSelectedFiles(); - - [...files].forEach(DOM.toggleSelectedFile); - }; - - /** - * get all selected files or current when none selected - * - * @currentFile - */ - this.getActiveFiles = () => { - const current = DOM.getCurrentFile(); - const files = DOM.getSelectedFiles(); - const name = DOM.getCurrentName(current); - - if (!files.length && name !== '..') - return [current]; - - return files; - }; - - /** - * get size - * @currentFile - */ - this.getCurrentSize = (currentFile) => { - const current = currentFile || Cmd.getCurrentFile(); - /* если это папка - возвращаем слово dir вместо размера*/ - const size = DOM.getByDataName('js-size', current) - .textContent - .replace(/^<|>$/g, ''); - - return size; - }; - - /** - * get size - * @currentFile - */ - this.loadCurrentSize = (callback, currentFile) => { - const current = currentFile || DOM.getCurrentFile(); - const query = '?size'; - const link = DOM.getCurrentPath(current); - - Images.show.load(); + const getName = () => { + const name = DOM.getCurrentName(); if (name === '..') - return; - - RESTful.read(link + query, (error, size) => { - if (error) - return; - - DOM.setCurrentSize(size, current); - exec(callback, current); - Images.hide(); - }); - }; - - /** - * load hash - * @callback - * @currentFile - */ - this.loadCurrentHash = (callback, currentFile) => { - const current = currentFile || DOM.getCurrentFile(); - const query = '?hash'; - const link = DOM.getCurrentPath(current); - - RESTful.read(link + query, callback); - }; - - /** - * load current modification time of file - * @callback - * @currentFile - */ - this.loadCurrentTime = (callback, currentFile) => { - const current = currentFile || DOM.getCurrentFile(); - const query = '?time'; - const link = DOM.getCurrentPath(current); - - RESTful.read(link + query, callback); - }; - - /** - * set size - * @currentFile - */ - this.setCurrentSize = (size, currentFile) => { - const current = currentFile || DOM.getCurrentFile(); - const sizeElement = DOM.getByDataName('js-size', current); - - sizeElement.textContent = size; - }; - - /** - * @currentFile - */ - this.getCurrentMode = (currentFile) => { - const current = currentFile || DOM.getCurrentFile(); - const mode = DOM.getByDataName('js-mode', current); - - return mode.textContent; - }; - - /** - * @currentFile - */ - this.getCurrentOwner = (currentFile) => { - const current = currentFile || DOM.getCurrentFile(); - const owner = DOM.getByDataName('js-owner', current); - - return owner.textContent; - }; - - /** - * unified way to get current file content - * - * @param callback - * @param currentFile - */ - this.getCurrentData = (callback, currentFile) => { - let hash; - const Dialog = DOM.Dialog; - const Info = DOM.CurrentInfo; - const current = currentFile || DOM.getCurrentFile(); - const path = DOM.getCurrentPath(current); - const isDir = DOM.isCurrentIsDir(current); - - const func = (error, data) => { - const ONE_MEGABYTE = 1024 * 1024 * 1024; - - if (!error) { - if (itype.object(data)) - data = jonny.stringify(data); - - const length = data.length; - - if (hash && length < ONE_MEGABYTE) - DOM.saveDataToStorage(path, data, hash); - } - - callback(error, data); - }; - - if (Info.name === '..') { - Dialog.alert.noFiles(TITLE); - return callback(Error('No files selected!')); - } - - if (isDir) - return RESTful.read(path, func); - - DOM.checkStorageHash(path, (error, equal, hashNew) => { - if (error) - return callback(error); - - if (equal) - return DOM.getDataFromStorage(path, callback); - - hash = hashNew; - RESTful.read(path, func); - }); - }; - - /** - * unified way to save current file content - * - * @callback - function({data, name}) {} - * @currentFile - */ - this.saveCurrentData = (url, data, callback, query = '') => { - DOM.RESTful.write(url + query, data, (error) => { - !error && DOM.saveDataToStorage(url, data); - }); - }; - - /** - * unified way to get RefreshButton - */ - this.getRefreshButton = (panel) => { - const currentPanel = panel || DOM.getPanel(); - const refresh = DOM.getByDataName('js-refresh', currentPanel); - - return refresh; - }; - - this.setCurrentByName = (name) => { - const current = DOM.getCurrentByName(name); - return DOM.setCurrentFile(current); - }; - - /** - * private function thet unset currentfile - * - * @currentFile - */ - function unsetCurrentFile(currentFile) { - const is = DOM.isCurrentFile(currentFile); - - if (!is) - return; - - currentFile.classList.remove(CURRENT_FILE); - } - - /** - * unified way to set current file - */ - this.setCurrentFile = (currentFile, options) => { - const o = options; - const CENTER = true; - const currentFileWas = DOM.getCurrentFile(); - - if (!currentFile) - return DOM; - - let pathWas = ''; - - if (currentFileWas) { - pathWas = DOM.getCurrentDirPath(); - unsetCurrentFile(currentFileWas); - } - - currentFile.classList.add(CURRENT_FILE); - - let path = DOM.getCurrentDirPath(); - - if (path !== pathWas) { - DOM.setTitle(getTitle(path)); - - /* history could be present - * but it should be false - * to prevent default behavior - */ - if (!o || o.history !== false) { - if (path !== '/') - path = FS + path; - - DOM.setHistory(path, null, path); - } - } - - /* scrolling to current file */ - DOM.scrollIntoViewIfNeeded(currentFile, CENTER); - - Cmd.updateCurrentInfo(); - - return DOM; - }; - - /* - * set current file by position - * - * @param layer - element - * @param - position {x, y} - */ - this.getCurrentByPosition = ({x, y}) => { - const element = document.elementFromPoint(x, y); - - const getEl = (el) => { - const {tagName} = el; - const isChild = /A|SPAN|LI/.test(tagName); - - if (!isChild) - return null; - - if (tagName === 'A') - return el.parentElement.parentElement; - - if (tagName === 'SPAN') - return el.parentElement; - - return el; - }; - - const el = getEl(element); - - if (el && el.tagName !== 'LI') - return null; - - return el; - }; - - /** - * select current file - * @param currentFile - */ - this.selectFile = (currentFile) => { - const current = currentFile || DOM.getCurrentFile(); - - current.classList.add(SELECTED_FILE); - - return Cmd; - }; - - this.toggleSelectedFile = (currentFile) => { - const current = currentFile || DOM.getCurrentFile(); - const name = DOM.getCurrentName(current); - - if (name === '..') - return Cmd; - - current.classList.toggle(SELECTED_FILE); - - return Cmd; - }; - - this.toggleAllSelectedFiles = () => { - DOM.getAllFiles().map(DOM.toggleSelectedFile); - - return Cmd; - }; - - this.selectAllFiles = () => { - DOM.getAllFiles().map(DOM.selectFile); - - return Cmd; - }; - - this.getAllFiles = () => { - const panel = DOM.getPanel(); - const files = DOM.getFiles(panel); - const name = DOM.getCurrentName(files[0]); - - const from = (a) => a === '..' ? 1 : 0; - const i = from(name); - - return [...files].slice(i); - }; - - /** - * open dialog with expand selection - */ - this.expandSelection = () => { - const msg = 'expand'; - const files = CurrentInfo.files; - - selectByPattern(msg, files); - }; - - /** - * open dialog with shrink selection - */ - this.shrinkSelection = () => { - const msg = 'shrink'; - const files = CurrentInfo.files; - - selectByPattern(msg, files); - }; - - /** - * setting history wrapper - */ - this.setHistory = (data, title, url) => { - const ret = window.history; - - url = CloudCmd.PREFIX + url; - - if (ret) - history.pushState(data, title, url); - - return ret; - }; - - /** - * set title or create title element - * - * @param name - */ - - this.setTitle = (name) => { - if (!Title) - Title = DOM.getByTag('title')[0] || - DOM.load({ - name : 'title', - innerHTML : name, - parentElement : document.head - }); - - Title.textContent = name; - - return DOM; - }; - - /** - * current file check - * - * @param currentFile - */ - this.isCurrentFile = (currentFile) => { - if (!currentFile) - return false; - - return DOM.isContainClass(currentFile, CURRENT_FILE); - }; - - /** - * selected file check - * - * @param currentFile - */ - this.isSelected = (selected) => { - if (!selected) - return false; - - return DOM.isContainClass(selected, SELECTED_FILE); - }; - - /** - * check is current file is a directory - * - * @param currentFile - */ - this.isCurrentIsDir = (currentFile) => { - const current = currentFile || this.getCurrentFile(); - const fileType = DOM.getByDataName('js-type', current); - const ret = DOM.isContainClass(fileType, 'directory'); - - return ret; - }; - - /** - * get link from current (or param) file - * - * @param currentFile - current file by default - */ - this.getCurrentLink = (currentFile) => { - const current = currentFile || this.getCurrentFile(); - const link = DOM.getByTag('a', current); - - return link[0]; - }; - - /** - * get link from current (or param) file - * - * @param currentFile - current file by default - */ - this.getCurrentPath = (currentFile) => { - const current = currentFile || DOM.getCurrentFile(); - const element = DOM.getByTag('a', current)[0]; - const prefix = CloudCmd.PREFIX; - const path = element.getAttribute('href') - .replace(RegExp('^' + prefix + FS), ''); - - return path; - }; - - /** - * get name from current (or param) file - * - * @param currentFile - */ - this.getCurrentName = (currentFile) => { - const current = currentFile || DOM.getCurrentFile(); - - if (!current) return ''; - - const link = DOM.getCurrentLink(current); - - if (!link) - return ''; - - const name = link.title; return name; }; - this.getFilenames = (files) => { - if (!files) - throw Error('AllFiles could not be empty'); - - const first = files[0] || DOM.getCurrentFile(); - const name = DOM.getCurrentName(first); - - const allFiles = [...files]; - - if (name === '..') - allFiles.shift(); - - const names = allFiles.map((current) => { - return DOM.getCurrentName(current); - }); - - return names; - }; + const name = getName(); + const [cancel, currentName] = await Dialog.prompt(msg, name); - /** - * set name from current (or param) file - * - * @param name - * @param current - */ - this.setCurrentName = (name, current) => { - const Info = CurrentInfo; - const link = Info.link; - const PREFIX = CloudCmd.PREFIX; - const dir = PREFIX + FS + Info.dirPath; - - link.title = name; - link.innerHTML = Entity.encode(name); - link.href = dir + name; - - current.setAttribute('data-name', 'js-file-' + name); - - return link; - }; + if (cancel) + return; - /** - * check storage hash - */ - this.checkStorageHash = (name, callback) => { - const parallel = exec.parallel; - const loadHash = DOM.loadCurrentHash; - const nameHash = name + '-hash'; - const getStoreHash = exec.with(Storage.get, nameHash); - - if (typeof name !== 'string') - throw Error('name should be a string!'); - - if (typeof callback !== 'function') - throw Error('callback should be a function!'); - - parallel([loadHash, getStoreHash], (error, loadHash, storeHash) => { - let equal; - const isContain = /error/.test(loadHash); - - if (isContain) - error = loadHash; - else if (loadHash === storeHash) - equal = true; - - callback(error, equal, loadHash); - }); - }; + const path = `${dir}${currentName}`; - /** - * save data to storage - * - * @param name - * @param data - * @param hash - * @param callback - */ - this.saveDataToStorage = function(name, data, hash, callback) { - const allowed = CloudCmd.config('localStorage'); - const isDir = DOM.isCurrentIsDir(); - const nameHash = name + '-hash'; - const nameData = name + '-data'; - - if (!allowed || isDir) - return exec(callback); - - exec.if(hash, () => { - Storage.set(nameHash, hash); - Storage.set(nameData, data); - - exec(callback, hash); - }, (callback) => { - DOM.loadCurrentHash((error, loadHash) => { - hash = loadHash; - callback(); - }); - }); - }; + if (typeName === 'directory') + await RESTful.createDirectory(path); + else + await RESTful.write(path); - /** - * save data to storage - * - * @param name - * @param data - * @param callback - */ - this.getDataFromStorage = (name, callback) => { - const nameHash = name + '-hash'; - const nameData = name + '-data'; - const allowed = CloudCmd.config('localStorage'); - const isDir = DOM.isCurrentIsDir(); - - if (!allowed || isDir) - return exec(callback); - - exec.parallel([ - exec.with(Storage.get, nameData), - exec.with(Storage.get, nameHash), - ], callback); - }; - - this.getFM = () => { - return DOM.getPanel().parentElement; - }; - - this.getPanelPosition = (panel) => { - panel = panel || DOM.getPanel(); - - return panel.dataset.name.replace('js-', ''); - }; - - /** function getting panel active, or passive - * @param options = {active: true} - */ - this.getPanel = (options) => { - var files, panel, isLeft, - dataName = 'js-', - current = DOM.getCurrentFile(); - - if (!current) { - panel = DOM.getByDataName('js-left'); - } else { - files = current.parentElement, - panel = files.parentElement, - isLeft = panel.getAttribute('data-name') === 'js-left'; - } - - /* if {active : false} getting passive panel */ - if (options && !options.active) { - dataName += isLeft ? 'right' : 'left'; - panel = DOM.getByDataName(dataName); - } - - /* if two panels showed - * then always work with passive - * panel - */ - if (window.innerWidth < CloudCmd.MIN_ONE_PANEL_WIDTH) - panel = DOM.getByDataName('js-left'); - - - if (!panel) - throw Error('can not find Active Panel!'); - - return panel; - }; - - this.getFiles = (element) => { - const files = DOM.getByDataName('js-files', element); - return files.children || []; - }; - - /** - * shows panel right or left (or active) - */ - this.showPanel = (active) => { - const panel = DOM.getPanel({active: active}); - - if (!panel) - return false; - - DOM.show(panel); - - return true; - }; - - /** - * hides panel right or left (or active) - */ - this.hidePanel = (active) => { - var ret = false, - panel = DOM.getPanel({active: active}); - - if (panel) - ret = DOM.hide(panel); - - return ret; - }; - - /** - * open window with URL - * @param url - */ - this.openWindow = (url) => { - var left = 140, - top = 187, - width = 1000, - height = 650, - - options = 'left=' + left + - ',top=' + top + - ',width=' + width + - ',height=' + height + - ',personalbar=0,toolbar=0' + - ',scrollbars=1,resizable=1', - - wnd = window.open(url, 'Cloud Commander Auth', options); - - if (!wnd) - DOM.Dialog.alert(TITLE, 'Please disable your popup blocker and try again.'); - - return wnd; - }; - - /** - * remove child of element - * @param pChild - * @param element - */ - this.remove = (child, element) => { - const parent = element || document.body; - - parent.removeChild(child); - - return DOM; - }; - - /** - * remove current file from file table - * @param current - * - */ - this.deleteCurrent = (current) => { - var next, prev, currentNew; - - if (!current) - Cmd.getCurrentFile(); - - var parent = current && current.parentElement; - var name = Cmd.getCurrentName(current); - - if (current && name !== '..') { - next = current.nextSibling, - prev = current.previousSibling; - - if (next) - currentNew = next; - else if (prev) - currentNew = prev; - - DOM.setCurrentFile(currentNew); - - parent.removeChild(current); - } - - return currentNew; - }; - - /** - * remove selected files from file table - * @Selected - */ - this.deleteSelected = (selected) => { - var i, n, current; - - if (!selected) - selected = DOM.getSelectedFiles(); - - if (selected) { - n = selected.length; - - for (i = 0; i < n; i++) { - current = selected[i]; - DOM.deleteCurrent(current); - } - } - - return selected; - }; - - /** - * rename current file - * - * @currentFile - */ - this.renameCurrent = (current) => { - const Dialog = DOM.Dialog; - - if (!Cmd.isCurrentFile(current)) - current = Cmd.getCurrentFile(); - - const from = Cmd.getCurrentName(current); - - if (from === '..') - return Dialog.alert.noFiles(TITLE); - - const cancel = false; - - Dialog.prompt(TITLE, 'Rename', from, {cancel}).then((to) => { - const isExist = !!DOM.getCurrentByName(to); - const dirPath = Cmd.getCurrentDirPath(); - - if (from === to) - return; - - const files = { - from : dirPath + from, - to : dirPath + to - }; - - RESTful.mv(files, (error) => { - if (error) - return; - - DOM.setCurrentName(to, current); - Cmd.updateCurrentInfo(); - Storage.remove(dirPath); - - if (isExist) - CloudCmd.refresh(); - }); - }); - }; - - /** - * unified way to scrollIntoViewIfNeeded - * (native suporte by webkit only) - * @param element - * @param pCenter - */ - this.scrollIntoViewIfNeeded = function(element, center) { - var ret = element && element.scrollIntoViewIfNeeded; - - /* for scroll as small as possible - * param should be false - */ - if (arguments.length === 1) - center = false; - - if (ret) - element.scrollIntoViewIfNeeded(center); - - return ret; - }; - - /* scroll on one page*/ - this.scrollByPages = (element, pPages) => { - var ret = element && element.scrollByPages && pPages; - - if (ret) - element.scrollByPages(pPages); - - return ret; - }; - - this.changePanel = () => { - let panel = DOM.getPanel(); - const panelPassive = DOM.getPanel({ - active: false - }); - - let name = DOM.getCurrentName(); - const filesPassive = DOM.getFiles(panelPassive); - - let dataName = panel.getAttribute('data-name'); - - TabPanel[dataName] = name; - - panel = panelPassive; - dataName = panel.getAttribute('data-name'); - - name = TabPanel[dataName]; - - let files; - let current; - - if (name) { - current = DOM.getCurrentByName(name, panel); - - if (current) - files = current.parentElement; - } - - if (!files || !files.parentElement) { - current = DOM.getCurrentByName(name, panel); - - if (!current) - current = filesPassive[0]; - } - - DOM.setCurrentFile(current, { - history: true - }); - - return DOM; - }; - - this.getPackerExt = (type) => { - if (type === 'zip') - return '.zip'; - - return '.tar.gz'; - }; - - this.goToDirectory = () => { - const msg = 'Go to directory:'; - const path = CurrentInfo.dirPath; - const Dialog = DOM.Dialog; - const cancel = false; - - Dialog.prompt(TITLE, msg, path, {cancel}).then((path) => { - CloudCmd.loadDir({ - path: path - }); - }); - }, - - this.duplicatePanel = () => { - const Info = CurrentInfo; - const isDir = Info.isDir; - const panel = Info.panelPassive; - const noCurrent = !Info.isOnePanel; - - const getPath = (isDir) => { - if (isDir) - return Info.path; - - return Info.dirPath; - }; - - const path = getPath(isDir); - - CloudCmd.loadDir({ - path, - panel, - noCurrent, - }); - }; - - this.swapPanels = () => { - const Info = CurrentInfo; - const {panel} = Info; - const {files} = Info; - const {element} = Info; - - const panelPassive = Info.panelPassive; - - const dirPath = DOM.getCurrentDirPath(); - const dirPathPassive = DOM.getNotCurrentDirPath(); - - let currentIndex = files.indexOf(element); - - CloudCmd.loadDir({ - path: dirPath, - panel: panelPassive, - noCurrent: true - }); - - CloudCmd.loadDir({ - path: dirPathPassive, - panel: panel - }, () => { - const files = Info.files; - const length = files.length - 1; - - if (currentIndex > length) - currentIndex = length; - - const el = files[currentIndex]; - - DOM.setCurrentFile(el); - }); - }; - - this.CurrentInfo = CurrentInfo, - - this.updateCurrentInfo = (currentFile) => { - const info = Cmd.CurrentInfo; - const current = currentFile || Cmd.getCurrentFile(); - const files = current.parentElement; - const panel = files.parentElement; - - const panelPassive = Cmd.getPanel({ - active: false - }); - - const filesPassive = DOM.getFiles(panelPassive); - const name = Cmd.getCurrentName(current); - - info.dir = Cmd.getCurrentDirName(); - info.dirPath = Cmd.getCurrentDirPath(); - info.parentDirPath = Cmd.getParentDirPath(); - info.element = current; - info.ext = Util.getExt(name); - info.files = [...files.children]; - info.filesPassive = [...filesPassive]; - info.first = files.firstChild; - info.getData = Cmd.getCurrentData; - info.last = files.lastChild; - info.link = Cmd.getCurrentLink(current); - info.mode = Cmd.getCurrentMode(current); - info.name = name; - info.path = Cmd.getCurrentPath(current); - info.panel = panel; - info.panelPassive = panelPassive; - info.size = Cmd.getCurrentSize(current); - info.isDir = Cmd.isCurrentIsDir(); - info.isSelected = Cmd.isSelected(current); - info.panelPosition = Cmd.getPanel().dataset.name.replace('js-', ''); - info.isOnePanel = - info.panel.getAttribute('data-name') === - info.panelPassive.getAttribute('data-name'); - }; + await CloudCmd.refresh({ + currentName, + }); } +/** + * get current directory name + */ +export function getCurrentDirName() { + const href = DOM + .getCurrentDirPath() + .replace(/\/$/, ''); + + const substr = href.substr(href, href.lastIndexOf('/')); + + return href.replace(`${substr}/`, '') || '/'; +} + +/** + * get current directory path + */ +export function getParentDirPath(panel) { + const path = DOM.getCurrentDirPath(panel); + const dirName = DOM.getCurrentDirName() + '/'; + const index = path.lastIndexOf(dirName); + + if (path !== '/') + return path.slice(0, index); + + return path; +} + +/** + * get not current directory path + */ +export function getNotCurrentDirPath() { + const panel = DOM.getPanel({ + active: false, + }); + + return DOM.getCurrentDirPath(panel); +} + +/* + * unselect all files + */ +export function unselectFiles(files) { + files = files || DOM.getSelectedFiles(); + + Array + .from(files) + .forEach(DOM.toggleSelectedFile); +} + +/** + * get all selected files or current when none selected + * + * @currentFile + */ +export function getActiveFiles() { + const current = DOM.getCurrentFile(); + const files = DOM.getSelectedFiles(); + const name = DOM.getCurrentName(current); + + if (!files.length && name !== '..') + return [current]; + + return files; +} + +export function getCurrentDate(currentFile) { + const current = currentFile || DOM.getCurrentFile(); + + return DOM.getByDataName('js-date', current).textContent; +} + +/** + * get size + * @currentFile + */ +export function getCurrentSize(currentFile) { + const current = currentFile || DOM.getCurrentFile(); + + /* если это папка - возвращаем слово dir вместо размера*/ + const size = DOM + .getByDataName('js-size', current) + .textContent + .replace(/^<|>$/g, ''); + + return size; +} + +/** + * get size + * @currentFile + */ +export async function loadCurrentSize(currentFile) { + const current = currentFile || DOM.getCurrentFile(); + const query = '?size'; + const link = DOM.getCurrentPath(current); + + Images.show.load(); + + if (name === '..') + return; + + const [, size] = await RESTful.read(link + query); + + DOM.setCurrentSize(size, current); + Images.hide(); + + return current; +} + +/** + * load hash + * @callback + * @currentFile + */ +export async function loadCurrentHash(currentFile) { + const current = currentFile || DOM.getCurrentFile(); + const query = '?hash'; + const link = DOM.getCurrentPath(current); + + const [, data] = await RESTful.read(link + query); + + return data; +} + +/** + * set size + * @currentFile + */ +export function setCurrentSize(size, currentFile) { + const current = currentFile || DOM.getCurrentFile(); + const sizeElement = DOM.getByDataName('js-size', current); + + sizeElement.textContent = size; +} + +/** + * @currentFile + */ +export function getCurrentMode(currentFile) { + const current = currentFile || DOM.getCurrentFile(); + const mode = DOM.getByDataName('js-mode', current); + + return mode.textContent; +} + +/** + * @currentFile + */ +export function getCurrentOwner(currentFile) { + const current = currentFile || DOM.getCurrentFile(); + const owner = DOM.getByDataName('js-owner', current); + + return owner.textContent; +} + +/** + * unified way to get current file content + * + * @param currentFile + */ +export async function getCurrentData(currentFile) { + const {Dialog} = DOM; + const Info = DOM.CurrentInfo; + const current = currentFile || DOM.getCurrentFile(); + const path = DOM.getCurrentPath(current); + const isDir = DOM.isCurrentIsDir(current); + + if (Info.name === '..') { + Dialog.alert.noFiles(); + return [ + Error('No Files'), + ]; + } + + if (isDir) + return await RESTful.read(path); + + const [hashNew, hash] = await DOM.checkStorageHash(path); + + if (!hashNew) + return [ + Error(`Can't get hash of a file`), + ]; + + if (hash === hashNew) + return [null, await Storage.get(`${path}-data`)]; + + const [e, data] = await RESTful.read(path); + + if (e) + return [ + e, + null, + ]; + + const ONE_MEGABYTE = 1024 ** 2 * 1024; + const {length} = data; + + if (hash && length < ONE_MEGABYTE) + await DOM.saveDataToStorage(path, data, hashNew); + + return [null, data]; +} + +/** + * unified way to get RefreshButton + */ +export function getRefreshButton(panel = DOM.getPanel()) { + return DOM.getByDataName('js-refresh', panel); +} + +export function getAllFiles() { + const panel = DOM.getPanel(); + const files = DOM.getFiles(panel); + const name = DOM.getCurrentName(files[0]); + + const from = (a) => a === '..' ? 1 : 0; + const i = from(name); + + return Array + .from(files) + .slice(i); +} + +/** + * open dialog with expand selection + */ +export async function expandSelection() { + const msg = 'expand'; + const {files} = CurrentInfo; + + await selectByPattern(msg, files); +} + +/** + * open dialog with shrink selection + */ +export async function shrinkSelection() { + const msg = 'shrink'; + const {files} = CurrentInfo; + + await selectByPattern(msg, files); +} + +/** + * setting history wrapper + */ +export function setHistory(data, title, url) { + const ret = globalThis.history; + const {prefix} = CloudCmd; + + url = prefix + url; + + if (ret) + history.pushState(data, title, url); + + return ret; +} + +/** + * get link from current (or param) file + * + * @param currentFile - current file by default + */ +export function getCurrentLink(currentFile) { + const current = currentFile || DOM.getCurrentFile(); + const link = DOM.getByTag('a', current); + + return link[0]; +} + +export function getFilenames(files) { + if (!files) + throw Error('AllFiles could not be empty'); + + const first = files[0] || DOM.getCurrentFile(); + const name = DOM.getCurrentName(first); + + const allFiles = Array.from(files); + + if (name === '..') + allFiles.shift(); + + return allFiles.map(DOM.getCurrentName); +} + +/** + * check storage hash + */ +export async function checkStorageHash(name) { + const nameHash = `${name}-hash`; + + if (!isString(name)) + throw Error('name should be a string!'); + + const [loadHash, storeHash] = await Promise.all([ + DOM.loadCurrentHash(), + Storage.get(nameHash), + ]); + + return [loadHash, storeHash]; +} + +/** + * save data to storage + * + * @param name + * @param data + * @param hash + */ +export async function saveDataToStorage(name, data, hash) { + const isDir = DOM.isCurrentIsDir(); + + if (isDir) + return; + + hash = hash || await DOM.loadCurrentHash(); + + const nameHash = `${name}-hash`; + const nameData = `${name}-data`; + + await Storage.set(nameHash, hash); + await Storage.set(nameData, data); + + return hash; +} + +export function getFM() { + const {parentElement} = DOM.getPanel(); + return parentElement; +} + +export function getPanelPosition(panel) { + panel = panel || DOM.getPanel(); + + return panel.dataset.name.replace('js-', ''); +} + +export function getCSSVar(name, {body = document.body} = {}) { + const bodyStyle = getComputedStyle(body); + return bodyStyle.getPropertyValue(`--${name}`); +} + +/** function getting panel active, or passive + * @param options = {active: true} + */ +export function getPanel(options) { + let files; + let panel; + let isLeft; + let dataName = 'js-'; + + const current = DOM.getCurrentFile(); + + if (!current) { + panel = DOM.getByDataName('js-left'); + } else { + files = current.parentElement; + panel = files.parentElement; + isLeft = panel.getAttribute('data-name') === 'js-left'; + } + + /* if {active : false} getting passive panel */ + if (options && !options.active) { + dataName += isLeft ? 'right' : 'left'; + panel = DOM.getByDataName(dataName); + } + + /* if two panels showed + * then always work with passive + * panel + */ + if (globalThis.innerWidth < CloudCmd.MIN_ONE_PANEL_WIDTH) + panel = DOM.getByDataName('js-left'); + + if (!panel) + throw Error('can not find Active Panel!'); + + return panel; +} + +export function getFiles(element) { + const files = DOM.getByDataName('js-files', element); + return files.children || []; +} + +/** + * shows panel right or left (or active) + */ +export function showPanel(active) { + const panel = DOM.getPanel({ + active, + }); + + if (!panel) + return false; + + DOM.show(panel); + + return true; +} + +/** + * hides panel right or left (or active) + */ +export function hidePanel(active) { + const panel = DOM.getPanel({ + active, + }); + + if (!panel) + return false; + + return DOM.hide(panel); +} + +/** + * remove child of element + * @param child + * @param element + */ +export function remove(child, element) { + const parent = element || document.body; + + parent.removeChild(child); + + return DOM; +} + +/** + * remove current file from file table + * @param current + * + */ +export function deleteCurrent(current) { + if (!current) + DOM.getCurrentFile(); + + const parent = current?.parentElement; + const name = DOM.getCurrentName(current); + + if (current && name !== '..') { + const next = current.nextSibling; + const prev = current.previousSibling; + + DOM.setCurrentFile(next || prev); + parent.removeChild(current); + } +} + +/** + * remove selected files from file table + * @Selected + */ +export function deleteSelected(selected) { + selected = selected || DOM.getSelectedFiles(); + + if (!selected) + return; + + selected.map(DOM.deleteCurrent); +} + +/** + * rename current file + * + * @currentFile + */ +export function scrollIntoViewIfNeeded(element, center = false) { + if (!element || !element.scrollIntoViewIfNeeded) + return; + + element.scrollIntoViewIfNeeded(center); +} + +/* scroll on one page */ +export function scrollByPages(element, pPages) { + const ret = element?.scrollByPages && pPages; + + if (ret) + element.scrollByPages(pPages); + + return ret; +} + +export function changePanel() { + const Info = CurrentInfo; + let panel = DOM.getPanel(); + + CloudCmd.emit('passive-dir', Info.dirPath); + + const panelPassive = DOM.getPanel({ + active: false, + }); + + let name = DOM.getCurrentName(); + const filesPassive = DOM.getFiles(panelPassive); + + let dataName = panel.getAttribute('data-name'); + + TabPanel[dataName] = name; + + panel = panelPassive; + dataName = panel.getAttribute('data-name'); + + name = TabPanel[dataName]; + + let files; + let current; + + if (name) { + current = DOM.getCurrentByName(name, panel); + + if (current) + files = current.parentElement; + } + + if (!files || !files.parentElement) { + current = DOM.getCurrentByName(name, panel); + + if (!current) + [current] = filesPassive; + } + + DOM.setCurrentFile(current, { + history: true, + }); + + CloudCmd.emit('active-dir', Info.dirPath); + + return DOM; +} + +export function getPackerExt(type) { + if (type === 'zip') + return '.zip'; + + return '.tar.gz'; +} + +export async function goToDirectory(overrides = {}) { + const {Dialog} = DOM; + const { + prompt = Dialog.prompt, + changeDir = CloudCmd.changeDir, + } = overrides; + + const msg = 'Go to directory:'; + const {dirPath} = CurrentInfo; + + const [cancel, path = dirPath] = await prompt(msg, dirPath); + + if (cancel) + return; + + await changeDir(path); +} + +export async function duplicatePanel() { + const Info = CurrentInfo; + const {isDir} = Info; + const panel = Info.panelPassive; + const noCurrent = !Info.isOnePanel; + + const getPath = (isDir) => { + if (isDir) + return Info.path; + + return Info.dirPath; + }; + + const path = getPath(isDir); + + await CloudCmd.changeDir(path, { + panel, + noCurrent, + }); +} + +export async function swapPanels() { + const Info = CurrentInfo; + const { + panel, + files, + element, + panelPassive, + } = Info; + + const path = DOM.getCurrentDirPath(); + const dirPathPassive = DOM.getNotCurrentDirPath(); + + let currentIndex = files.indexOf(element); + + await CloudCmd.changeDir(path, { + panel: panelPassive, + noCurrent: true, + }); + + await CloudCmd.changeDir(dirPathPassive, { + panel, + }); + + const length = Info.files.length - 1; + + if (currentIndex > length) + currentIndex = length; + + const el = Info.files[currentIndex]; + + DOM.setCurrentFile(el); +} + +export function updateCurrentInfo(currentFile) { + const info = DOM.CurrentInfo; + const current = currentFile || DOM.getCurrentFile(); + const files = current.parentElement; + + const panelPassive = DOM.getPanel({ + active: false, + }); + + const filesPassive = DOM.getFiles(panelPassive); + const name = DOM.getCurrentName(current); + + info.dir = DOM.getCurrentDirName(); + info.dirPath = DOM.getCurrentDirPath(); + info.parentDirPath = DOM.getParentDirPath(); + info.element = current; + info.ext = getExt(name); + info.files = Array.from(files.children); + info.filesPassive = Array.from(filesPassive); + info.first = files.firstChild; + info.getData = DOM.getCurrentData; + info.last = files.lastChild; + info.link = DOM.getCurrentLink(current); + info.mode = DOM.getCurrentMode(current); + info.name = name; + info.path = DOM.getCurrentPath(current); + info.panel = files.parentElement || DOM.getPanel(); + info.panelPassive = panelPassive; + info.size = DOM.getCurrentSize(current); + info.isDir = DOM.isCurrentIsDir(); + info.isSelected = DOM.isSelected(current); + info.panelPosition = DOM + .getPanel() + .dataset + .name + .replace('js-', ''); + info.isOnePanel = info.panel.getAttribute('data-name') === info.panelPassive.getAttribute('data-name'); +} diff --git a/client/dom/index.spec.js b/client/dom/index.spec.js new file mode 100644 index 00000000..268efe5f --- /dev/null +++ b/client/dom/index.spec.js @@ -0,0 +1,52 @@ +import {test, stub} from 'supertape'; +import {getCSSVar, goToDirectory} from '#dom'; + +globalThis.CloudCmd = {}; + +test('cloudcmd: client: dom: goToDirectory', async (t) => { + const path = ''; + const changeDir = stub(); + const prompt = stub().returns([null, path]); + + await goToDirectory({ + prompt, + changeDir, + }); + + t.calledWith(changeDir, [path]); + 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(); +}); diff --git a/client/dom/io/index.js b/client/dom/io/index.js new file mode 100644 index 00000000..192769e6 --- /dev/null +++ b/client/dom/io/index.js @@ -0,0 +1,166 @@ +import {FS} from '#common/cloudfunc'; +import {sendRequest as _sendRequest} from './send-request.js'; + +const {assign} = Object; + +const imgPosition = { + top: true, +}; + +export const remove = async (url, data, overrides = {}) => { + const { + sendRequest = _sendRequest, + } = overrides; + + const request = { + method: 'DELETE', + url: FS + url, + imgPosition: { + top: Boolean(data), + }, + }; + + if (data) + assign(request, { + data, + url: `${request.url}?files`, + }); + + return await sendRequest(request); +}; + +export const patch = async (url, data) => { + return await _sendRequest({ + method: 'PATCH', + url: FS + url, + data, + imgPosition, + }); +}; + +export const write = async (url, data) => { + return await _sendRequest({ + method: 'PUT', + url: FS + url, + data, + imgPosition, + }); +}; + +export const createDirectory = async (url, overrides = {}) => { + const { + sendRequest = _sendRequest, + } = overrides; + + return await sendRequest({ + method: 'PUT', + url: `${FS}${url}?dir`, + imgPosition, + }); +}; + +export const read = async (url, dataType = 'text') => { + const notLog = !url.includes('?'); + + return await _sendRequest({ + method: 'GET', + url: FS + url, + notLog, + dataType, + }); +}; + +export const copy = async (from, to, names) => { + return await _sendRequest({ + method: 'PUT', + url: '/copy', + data: { + from, + to, + names, + }, + imgPosition, + }); +}; + +export const pack = async (data) => { + return await _sendRequest({ + method: 'PUT', + url: '/pack', + data, + }); +}; + +export const extract = async (data) => { + return await _sendRequest({ + method: 'PUT', + url: '/extract', + data, + }); +}; + +export const move = async (from, to, names) => { + return await _sendRequest({ + method: 'PUT', + url: '/move', + data: { + from, + to, + names, + }, + imgPosition, + }); +}; + +export const rename = async (from, to) => { + return await _sendRequest({ + method: 'PUT', + url: '/rename', + data: { + from, + to, + }, + imgPosition, + }); +}; + +export const Config = { + read: async () => { + return await _sendRequest({ + method: 'GET', + url: '/config', + imgPosition, + notLog: true, + }); + }, + + write: async (data) => { + return await _sendRequest({ + method: 'PATCH', + url: '/config', + data, + imgPosition, + }); + }, +}; + +export const Markdown = { + read: async (url) => { + return await _sendRequest({ + method: 'GET', + url: `/markdown${url}`, + imgPosition, + notLog: true, + }); + }, + + render: async (data) => { + return await _sendRequest({ + method: 'PUT', + url: '/markdown', + data, + imgPosition, + notLog: true, + }); + }, +}; diff --git a/client/dom/io/index.spec.js b/client/dom/io/index.spec.js new file mode 100644 index 00000000..8e9e2d08 --- /dev/null +++ b/client/dom/io/index.spec.js @@ -0,0 +1,61 @@ +import {test, stub} from 'supertape'; +import * as io from './index.js'; + +test('client: dom: io', (t) => { + const sendRequest = stub(); + + io.createDirectory('/hello', { + sendRequest, + }); + + const expected = { + imgPosition: { + top: true, + }, + method: 'PUT', + url: '/fs/hello?dir', + }; + + t.calledWith(sendRequest, [expected]); + t.end(); +}); + +test('client: dom: io: remove: no files', async (t) => { + const sendRequest = stub(); + + await io.remove('/hello', null, { + sendRequest, + }); + + const expected = { + imgPosition: { + top: false, + }, + method: 'DELETE', + url: '/fs/hello', + }; + + t.calledWith(sendRequest, [expected]); + t.end(); +}); + +test('client: dom: io: remove: files', async (t) => { + const sendRequest = stub(); + const files = ['world']; + + await io.remove('/hello', files, { + sendRequest, + }); + + const expected = { + imgPosition: { + top: true, + }, + data: ['world'], + method: 'DELETE', + url: '/fs/hello?files', + }; + + t.calledWith(sendRequest, [expected]); + t.end(); +}); diff --git a/client/dom/io/send-request.js b/client/dom/io/send-request.js new file mode 100644 index 00000000..177d34b5 --- /dev/null +++ b/client/dom/io/send-request.js @@ -0,0 +1,48 @@ +/* global CloudCmd */ +import {promisify} from 'es6-promisify'; +import * as Images from '#dom/images'; +import * as load from '#dom/load'; + +export const sendRequest = promisify((params, callback) => { + const p = params; + const {prefixURL} = CloudCmd; + + p.url = prefixURL + p.url; + p.url = encodeURI(p.url); + + p.url = replaceHash(p.url); + + load.ajax({ + method: p.method, + url: p.url, + data: p.data, + dataType: p.dataType, + error: (jqXHR) => { + const response = jqXHR.responseText; + + const {statusText, status} = jqXHR; + + const text = status === 404 ? response : statusText; + + callback(Error(text)); + }, + success: (data) => { + Images.hide(); + + if (!p.notLog) + CloudCmd.log(data); + + callback(null, data); + }, + }); +}); + +export const _replaceHash = replaceHash; + +function replaceHash(url) { + /* + * if we send ajax request - + * no need in hash so we escape # + */ + return url.replace(/#/g, '%23'); +} diff --git a/client/dom/io/send-request.spec.js b/client/dom/io/send-request.spec.js new file mode 100644 index 00000000..f8a960d8 --- /dev/null +++ b/client/dom/io/send-request.spec.js @@ -0,0 +1,11 @@ +import {test} from 'supertape'; +import {_replaceHash} from './send-request.js'; + +test('cloudcmd: client: io: replaceHash', (t) => { + const url = '/hello/####world'; + const result = _replaceHash(url); + const expected = '/hello/%23%23%23%23world'; + + t.equal(result, expected); + t.end(); +}); diff --git a/client/dom/load-remote.js b/client/dom/load-remote.js index e5debcce..5be8e327 100644 --- a/client/dom/load-remote.js +++ b/client/dom/load-remote.js @@ -1,69 +1,58 @@ -'use strict'; - /* global CloudCmd */ +import {callbackify} from 'node:util'; +import {rendy} from 'rendy'; +import itype from 'itype'; +import * as load from 'load.js'; +import {tryToCatch} from 'try-to-catch'; +import {findObjByNameInArr} from '#common/util'; +import * as Files from '#dom/files'; -const exec = require('execon'); -const rendy = require('rendy'); -const itype = require('itype/legacy'); -const {findObjByNameInArr} = require('../../common/util'); - -const load = require('./load'); -const Files = require('./files'); - -module.exports = (name, options, callback = options) => { - const {PREFIX, config} = CloudCmd; +export const loadRemote = callbackify(async (name, options) => { + const {prefix, config} = CloudCmd; const o = options; if (o.name && window[o.name]) - return callback(); + return; - Files.get('modules', (error, modules) => { - const online = config('online') && navigator.onLine; - const module = findObjByNameInArr(modules.remote, name); + const modules = await Files.get('modules'); + + const online = config('online') && navigator.onLine; + const module = findObjByNameInArr(modules.remote, name); + + const isArray = itype.array(module.local); + const {version} = module; + + let remoteTmpls; + let local; + + if (isArray) { + remoteTmpls = module.remote; + ({local} = module); + } else { + remoteTmpls = [module.remote]; + local = [module.local]; + } + + const localURL = []; + + for (const url of local) { + localURL.push(prefix + url); + } + + const remoteURL = []; + + for (const tmpl of remoteTmpls) { + remoteURL.push(rendy(tmpl, { + version, + })); + } + + if (online) { + const [e] = await tryToCatch(load.parallel, remoteURL); - const isArray = itype.array(module.local); - const version = module.version; - - let remoteTmpls, local; - if (isArray) { - remoteTmpls = module.remote; - local = module.local; - } else { - remoteTmpls = [module.remote]; - local = [module.local]; - } - - const localURL = local.map((url) => { - return PREFIX + url; - }); - - const remoteURL = remoteTmpls.map((tmpl) => { - return rendy(tmpl, { - version: version - }); - }); - - const on = funcON(localURL, remoteURL, callback); - const off = funcOFF(localURL, callback); - - exec.if(online, on, off); - }); -}; - -function funcOFF(local, callback) { - return () => { - load.parallel(local, callback); - }; -} - -function funcON (local, remote,callback) { - return () => { - load.parallel(remote, (error) => { - if (error) - return funcOFF(); - - callback(); - }); - }; -} - + if (!e) + return; + } + + await load.parallel(localURL); +}); diff --git a/client/dom/load.js b/client/dom/load.js index bc09f3d8..8c7011c1 100644 --- a/client/dom/load.js +++ b/client/dom/load.js @@ -1,130 +1,8 @@ -'use strict'; - -const itype = require('itype/legacy'); -const jonny = require('jonny'); -const Emitify = require('emitify/legacy'); -const exec = require('execon'); -const Images = require('./images'); -const Events = require('./events'); - -const {getExt} = require('../../common/util'); - -module.exports = load; -module.exports.getIdBySrc = getIdBySrc; -module.exports.ext = ext; - -/** - * Функция создаёт элемент и загружает файл с src. - * - * @param params = { - * name, - название тэга - * src', - путь к файлу - * func, - обьект, содержаий одну из функций - * или сразу две onload и onerror - * {onload: function() {}, onerror: function();} - * style, - * id, - * element, - * async, - true by default - * inner: 'id{color:red, }, - * class, - * notAppend - false by default - * - */ -function load(params) { - const { - src, - id = getIdBySrc(params.src), - func, - name, - async, - inner, - style, - parent = document.body, - className, - attribute, - notAppend, - } = params; - - let element = document.getElementById(id); - - if (element) { - exec(func); - return element; - } - - element = document.createElement(name); - - const funcError = () => { - const msg = `file ${src} could not be loaded`; - const error = new Error(msg); - - parent.removeChild(element); - - Images.show.error(msg); - - const callback = func && func.onerror || func.onload || func; - - exec(callback, error); - }; - - const funcLoad = () => { - const callback = func && func.onload || func; - - Events.remove('error', element, funcError); - - exec(callback); - }; - - if (/^(script|link)$/.test(name)) - Events.addOnce('load', element, funcLoad) - .addError(element, funcError); - - if (id) - element.id = id; - - if (className) - element.className = className; - - if (src) { - if (name !== 'link') { - element.src = src; - } else { - element.href = src; - element.rel = 'stylesheet'; - } - } - - if (attribute) { - const type = itype(attribute); - - switch(type) { - case 'string': - element.setAttribute(attribute, ''); - break; - - case 'object': - Object.keys(attribute).forEach((name) => { - element.setAttribute(name, attribute[name]); - }); - break; - } - } - - if (style) - element.style.cssText = style; - - if (async && name === 'script' || async === undefined) - element.async = true; - - if (!notAppend) - parent.appendChild(element); - - if (inner) - element.innerHTML = inner; - - return element; -} +import itype from 'itype'; +import jonny from 'jonny'; +import Emitify from 'emitify'; +import exec from 'execon'; +import * as Images from '#dom/images'; /** * Function gets id by src @@ -132,17 +10,18 @@ function load(params) { * * Example: http://domain.com/1.js -> 1_js */ -function getIdBySrc(src) { +export function getIdBySrc(src) { const isStr = itype.string(src); if (!isStr) return; - if (~src.indexOf(':')) + if (src.includes(':')) src += '-join'; const num = src.lastIndexOf('/') + 1; const sub = src.substr(src, num); + const id = src .replace(sub, '') .replace(/\./g, '-'); @@ -155,34 +34,37 @@ function getIdBySrc(src) { * * @param params */ -module.exports.ajax = (params) => { +export const ajax = (params) => { const p = params; const isObject = itype.object(p.data); const isArray = itype.array(p.data); const isArrayBuf = itype(p.data) === 'arraybuffer'; const type = p.type || p.method || 'GET'; - const headers = p.headers || {}; + + const {headers = {}} = p; + const xhr = new XMLHttpRequest(); xhr.open(type, p.url, true); - Object.keys(headers).forEach((name) => { + for (const name of Object.keys(headers)) { const value = headers[name]; xhr.setRequestHeader(name, value); - }); + } if (p.responseType) xhr.responseType = p.responseType; let data; + if (!isArrayBuf && isObject || isArray) data = jonny.stringify(p.data); else - data = p.data; + ({data} = p); xhr.onreadystatechange = (event) => { const xhr = event.target; - const OK = 200; + const OK = 200; if (xhr.readyState !== xhr.DONE) return; @@ -190,43 +72,41 @@ module.exports.ajax = (params) => { Images.clearProgress(); const TYPE_JSON = 'application/json'; - const type = xhr.getResponseHeader('content-type'); + const type = xhr.getResponseHeader('content-type'); if (xhr.status !== OK) return exec(p.error, xhr); const notText = p.dataType !== 'text'; - const isContain = ~type.indexOf(TYPE_JSON); + const isContain = type.includes(TYPE_JSON); let data = xhr.response; + if (type && isContain && notText) data = jonny.parse(xhr.response) || xhr.response; - + exec(p.success, data, xhr.statusText, xhr); }; xhr.send(data); }; -module.exports.put = (url, body) => { +export const put = (url, body) => { const emitter = Emitify(); const xhr = new XMLHttpRequest(); - url = encodeURI(url) - .replace('#', '%23'); + url = encodeURI(url).replace(/#/g, '#'); xhr.open('put', url, true); xhr.upload.onprogress = (event) => { - var percent, count; + if (!event.lengthComputable) + return; - if (event.lengthComputable) { - percent = (event.loaded / event.total) * 100; - count = Math.round(percent); - - emitter.emit('progress', count); - } - + const percent = event.loaded / event.total * 100; + const count = Math.round(percent); + + emitter.emit('progress', count); }; xhr.onreadystatechange = () => { @@ -236,8 +116,10 @@ module.exports.put = (url, body) => { if (!over) return; - if (xhr.status === OK) + if (xhr.status === OK) { + emitter.emit('progress', 100); return emitter.emit('end'); + } const error = Error(xhr.responseText); emitter.emit('error', error); @@ -247,116 +129,3 @@ module.exports.put = (url, body) => { return emitter; }; - -function ext(src, func) { - switch (getExt(src)) { - case '.js': - return load.js(src, func); - - case '.css': - return load.css(src, func); - - default: - return load({ - src, - func, - }); - } -} - -/** - * create elements and load them to DOM-tree - * one-by-one - * - * @param params - * @param callback - */ -load.series = (params, callback) => { - if (!params) - return load; - - const funcs = params - .map((url) => ext.bind(null, url)) - .concat(callback); - - exec.series(funcs); - - return load; -}; - -/** - * improve callback of funcs so - * we pop number of function and - * if it's last we call pCallBack - * - * @param params - * @param callback - onload function - */ -load.parallel = (params, callback) => { - if (!params) - return load; - - const funcs = params.map((url) => { - return ext.bind(null, url); - }); - - exec.parallel(funcs, callback); - - return load; -}; - -/** - * Функция загружает js-файл - * - * @param src - * @param func - */ -load.js = (src, func) => { - const name = 'script'; - - return load({ - name, - src, - func, - }); -}, - -load.css = (src, func) => { - const name = 'link'; - const {head:parent} = document; - - return load({ - name, - src, - parent, - func - }); -}; - -/** - * Функция создаёт елемент style и записывает туда стили - * @param params - структура параметров, заполняеться таким - * образом: {src: ' ',func: '', id: '', element: '', inner: ''} - * все параметры опциональны - */ -load.style = (params) => { - const { - id, - src, - name = 'style', - func, - inner, - parent = document.head, - element, - } = params; - - return load({ - id, - src, - func, - name, - inner, - parent, - element, - }); -}; diff --git a/client/dom/operations/rename-current.js b/client/dom/operations/rename-current.js new file mode 100644 index 00000000..8b6536d3 --- /dev/null +++ b/client/dom/operations/rename-current.js @@ -0,0 +1,66 @@ +/* global CloudCmd */ +import capitalize from 'just-capitalize'; +import * as _Dialog from '#dom/dialog'; +import * as Storage from '#dom/storage'; +import * as RESTful from '#dom/rest'; +import * as _currentFile from '../current-file.js'; + +export default async (current, overrides = {}) => { + const { + refresh = CloudCmd.refresh, + Dialog = _Dialog, + currentFile = _currentFile, + } = overrides; + + const { + isCurrentFile, + getCurrentName, + getCurrentFile, + getCurrentByName, + getCurrentType, + getCurrentDirPath, + setCurrentName, + } = currentFile; + + if (!isCurrentFile(current)) + current = getCurrentFile(); + + const from = getCurrentName(current); + + if (from === '..') + return Dialog.alert.noFiles(); + + const [cancel, to] = await Dialog.prompt('Rename', from); + + if (cancel) + return; + + const nextFile = getCurrentByName(to); + + if (nextFile) { + const type = getCurrentType(nextFile); + const msg = `${capitalize(type)} "${to}" already exists. Proceed?`; + const [cancel] = await Dialog.confirm(msg); + + if (cancel) + return; + } + + if (from === to) + return; + + const dirPath = getCurrentDirPath(); + + const fromFull = `${dirPath}${from}`; + const toFull = `${dirPath}${to}`; + + const [e] = await RESTful.rename(fromFull, toFull); + + if (e) + return; + + setCurrentName(to, current); + + Storage.remove(dirPath); + refresh(); +}; diff --git a/client/dom/operations/rename-current.spec.js b/client/dom/operations/rename-current.spec.js new file mode 100644 index 00000000..a5ebb415 --- /dev/null +++ b/client/dom/operations/rename-current.spec.js @@ -0,0 +1,86 @@ +import {test, stub} from 'supertape'; +import renameCurrent from './rename-current.js'; + +test('cloudcmd: client: dom: renameCurrent: isCurrentFile', async (t) => { + const current = {}; + const isCurrentFile = stub(); + + const currentFile = stubCurrentFile({ + isCurrentFile, + }); + + await renameCurrent(current, { + Dialog: stubDialog(), + currentFile, + }); + + t.calledWith(isCurrentFile, [current], 'should call isCurrentFile'); + t.end(); +}); + +test('cloudcmd: client: dom: renameCurrent: file exist', async (t) => { + const current = {}; + const name = 'hello'; + + const prompt = stub().returns([null, name]); + const confirm = stub().returns([true]); + + const getCurrentByName = stub().returns(current); + const getCurrentType = stub().returns('directory'); + + const Dialog = stubDialog({ + confirm, + prompt, + }); + + const currentFile = stubCurrentFile({ + getCurrentByName, + getCurrentType, + }); + + await renameCurrent(null, { + Dialog, + currentFile, + }); + + const expected = 'Directory "hello" already exists. Proceed?'; + + t.calledWith(confirm, [expected], 'should call confirm'); + t.end(); +}); + +const stubDialog = (fns = {}) => { + const { + alert = stub().returns([]), + confirm = stub().returns([]), + prompt = stub().returns([]), + } = fns; + + return { + alert, + confirm, + prompt, + }; +}; + +const stubCurrentFile = (fns = {}) => { + const { + isCurrentFile = stub(), + getCurrentName = stub(), + getCurrentFile = stub(), + getCurrentByName = stub(), + getCurrentType = stub(), + getCurrentDirPath = stub(), + setCurrentName = stub(), + } = fns; + + return { + isCurrentFile, + getCurrentName, + getCurrentFile, + getCurrentByName, + getCurrentType, + getCurrentDirPath, + setCurrentName, + }; +}; diff --git a/client/dom/rest.js b/client/dom/rest.js index bb4d9e35..3cf2fb66 100644 --- a/client/dom/rest.js +++ b/client/dom/rest.js @@ -1,211 +1,40 @@ -'use strict'; +import {tryToCatch} from 'try-to-catch'; +import * as Dialog from '#dom/dialog'; +import * as Images from '#dom/images'; +import {encode} from '#common/entity'; +import * as IO from './io/index.js'; -/* global CloudCmd, DOM */ +const handleError = (promise) => async (...args) => { + const [e, data] = await tryToCatch(promise, ...args); + + if (!e) + return [e, data]; + + const encoded = encode(e.message); + + Images.show.error(encoded); + Dialog.alert(encoded); + + return [e, data]; +}; -const itype = require('itype/legacy'); +export const remove = handleError(IO.remove); +export const patch = handleError(IO.patch); +export const write = handleError(IO.write); +export const createDirectory = handleError(IO.createDirectory); +export const read = handleError(IO.read); +export const copy = handleError(IO.copy); +export const pack = handleError(IO.pack); +export const extract = handleError(IO.extract); +export const move = handleError(IO.move); +export const rename = handleError(IO.rename); -const {FS} = require('../../common/cloudfunc'); +export const Config = { + read: handleError(IO.Config.read), + write: handleError(IO.Config.write), +}; -module.exports = new RESTful(); - -const Images = require('./images'); -const load = require('./load'); - -function RESTful() { - this.delete = (url, data, callback) => { - const isFunc = itype.function(data); - - if (!callback && isFunc) { - callback = data; - data = null; - } - - sendRequest({ - method : 'DELETE', - url : FS + url, - data, - callback, - imgPosition : { top: !!data } - }); - }; - - this.patch = function(url, data, callback) { - var isFunc = itype.function(data); - - if (!callback && isFunc) { - callback = data; - data = null; - } - - sendRequest({ - method : 'PATCH', - url : FS + url, - data : data, - callback : callback, - imgPosition : { top: true } - }); - }; - - this.write = function(url, data, callback) { - var isFunc = itype.function(data); - - if (!callback && isFunc) { - callback = data; - data = null; - } - - sendRequest({ - method : 'PUT', - url : FS + url, - data : data, - callback : callback, - imgPosition : { top: true } - }); - }; - - this.read = function(url, dataType, callback) { - var isQuery = /\?/.test(url); - var isBeautify = /\?beautify$/.test(url); - var isMinify = /\?minify$/.test(url); - var notLog = !isQuery || isBeautify || isMinify; - var isFunc = itype.function(dataType); - - if (!callback && isFunc) { - callback = dataType; - dataType = 'text'; - } - - sendRequest({ - method: 'GET', - url: FS + url, - callback: callback, - notLog: notLog, - dataType: dataType - }); - }; - - this.cp = function(data, callback) { - sendRequest({ - method : 'PUT', - url : '/cp', - data : data, - callback : callback, - imgPosition : { top: true } - }); - }; - - this.pack = function(data, callback) { - sendRequest({ - method : 'PUT', - url : '/pack', - data : data, - callback : callback - }); - }; - - this.extract = function(data, callback) { - sendRequest({ - method : 'PUT', - url : '/extract', - data : data, - callback : callback - }); - }; - - this.mv = function(data, callback) { - sendRequest({ - method : 'PUT', - url : '/mv', - data : data, - callback : callback, - imgPosition : { top: true } - }); - }; - - this.Config = { - read: function(callback) { - sendRequest({ - method : 'GET', - url : '/config', - callback : callback, - imgPosition : { top: true }, - notLog : true - }); - }, - - write: function(data, callback) { - sendRequest({ - method : 'PATCH', - url : '/config', - data : data, - callback : callback, - imgPosition : { top: true } - }); - } - }; - - this.Markdown = { - read : function(url, callback) { - sendRequest({ - method : 'GET', - url : '/markdown' + url, - callback : callback, - imgPosition : { top: true }, - notLog : true - }); - }, - - render : function(data, callback) { - sendRequest({ - method : 'PUT', - url : '/markdown', - data : data, - callback : callback, - imgPosition : { top: true }, - notLog : true - }); - } - }; - - function sendRequest(params) { - var p = params, - prefixUrl = CloudCmd.PREFIX_URL; - - p.url = prefixUrl + p.url; - p.url = encodeURI(p.url); - - /* - * if we send ajax request - - * no need in hash so we escape # - */ - p.url = p.url.replace('#', '%23'); - - load.ajax({ - method : p.method, - url : p.url, - data : p.data, - dataType : p.dataType, - error : (jqXHR) => { - const response = jqXHR.responseText; - const statusText = jqXHR.statusText; - const status = jqXHR.status; - const text = status === 404 ? response : statusText; - - Images.show.error(text); - setTimeout(() => { - DOM.Dialog.alert(CloudCmd.TITLE, text); - }, 100); - - p.callback(Error(text)); - }, - success: (data) => { - Images.hide(); - - if (!p.notLog) - CloudCmd.log(data); - - p.callback(null, data); - } - }); - } -} +export const Markdown = { + read: handleError(IO.Markdown.read), + render: handleError(IO.Markdown.render), +}; diff --git a/client/dom/select-by-pattern.js b/client/dom/select-by-pattern.js index 870d722f..0bada6ef 100644 --- a/client/dom/select-by-pattern.js +++ b/client/dom/select-by-pattern.js @@ -1,52 +1,46 @@ -'use strict'; - -/* global DOM */ +import {alert, prompt} from '#dom/dialog'; +import {getRegExp} from '#common/util'; +import {getCurrentName} from './current-file.js'; +import { + isSelected, + toggleSelectedFile, +} from './cmd.js'; let SelectType = '*.*'; -const TITLE = 'Cloud Commander'; -const {getRegExp} = require('../../common/util'); - -module.exports = (msg, files) => { - const allMsg = `Specify file type for ${msg} selection`; - const cancel = false; - const {Dialog} = DOM; +export const selectByPattern = async (msg, files) => { + if (!files) + return; - Dialog.prompt(TITLE, allMsg, SelectType, {cancel}).then((type) => { - SelectType = type; + const allMsg = `Specify file type for ${msg} selection`; + const [cancel, type] = await prompt(allMsg, SelectType); + + if (cancel) + return; + + SelectType = type; + + const regExp = getRegExp(type); + let matches = 0; + + for (const current of files) { + const name = getCurrentName(current); - const regExp = getRegExp(type); + if (name === '..' || !regExp.test(name)) + continue; - if (!files) - return; + ++matches; - let matches = 0; + let selected = isSelected(current); + const shouldSel = msg === 'expand'; - files.forEach((current) => { - const name = DOM.getCurrentName(current); - - if (name === '..') - return; - - const isMatch = regExp.test(name); - - if (!isMatch) - return; - - ++matches; - - let isSelected = DOM.isSelected(current); - const shouldSel = msg === 'expand'; - - if (shouldSel) - isSelected = !isSelected; - - if (isSelected) - DOM.toggleSelectedFile(current); - }); + if (shouldSel) + selected = !selected; - if (!matches) - Dialog.alert('Select Files', 'No matches found!'); - }); + if (selected) + toggleSelectedFile(current); + } + + if (!matches) + alert('No matches found!'); }; - diff --git a/client/dom/storage.js b/client/dom/storage.js index 84e08b2d..d5cf231f 100644 --- a/client/dom/storage.js +++ b/client/dom/storage.js @@ -1,84 +1,26 @@ -'use strict'; +const {parse, stringify} = JSON; -const itype = require('itype/legacy'); -const jonny = require('jonny'); -const exec = require('execon'); - -/* приватный переключатель возможности работы с кэшем */ -let Allowed; - -/** - * allow Storage usage - */ -module.exports.setAllowed = (isAllowed) => { - Allowed = isAllowed; +export const set = (name, data) => { + localStorage.setItem(name, data); }; -/** remove element */ -module.exports.remove = (item, callback) => { - if (Allowed) - localStorage.removeItem(item); - - exec(callback, null, Allowed); - - return module.exports; +export const setJson = (name, data) => { + localStorage.setItem(name, stringify(data)); }; -module.exports.removeMatch = (string, callback) => { - const reg = RegExp('^' + string + '.*$'); - const test = (a) => reg.test(a); - const remove = (a) => localStorage.removeItem(a); - - Object.keys(localStorage) - .filter(test) - .forEach(remove); - - exec(callback); - - return module.exports; +export const get = (name) => { + return localStorage.getItem(name); }; -/** если доступен localStorage и - * в нём есть нужная нам директория - - * записываем данные в него - */ -module.exports.set = (name, data, callback) => { - let str, error; - - if (itype.object(data)) - str = jonny.stringify(data); - - if (Allowed && name) - error = exec.try(() => { - localStorage.setItem(name, str || data); - }); - - exec(callback, error); - - return module.exports; -}, - -/** Если доступен Storage принимаем из него данные*/ -module.exports.get = (name, callback) => { - let ret; - - if (Allowed) - ret = localStorage.getItem(name); - - exec(callback, null, ret); - - return module.exports; -}, - -/** функция чистит весь кэш для всех каталогов*/ -module.exports.clear = (callback) => { - const ret = Allowed; - - if (ret) - localStorage.clear(); - - exec(callback, null, ret); - - return module.exports; +export const getJson = (name) => { + const data = localStorage.getItem(name); + return parse(data); }; +export const clear = () => { + localStorage.clear(); +}; + +export const remove = (item) => { + localStorage.removeItem(item); +}; diff --git a/client/dom/storage.spec.js b/client/dom/storage.spec.js new file mode 100644 index 00000000..c538952d --- /dev/null +++ b/client/dom/storage.spec.js @@ -0,0 +1,105 @@ +import {test, stub} from 'supertape'; +import * as storage from '#dom/storage'; + +const {stringify} = JSON; + +test('cloudcmd: client: storage: set', async (t) => { + const {localStorage} = globalThis; + const setItem = stub(); + + globalThis.localStorage = { + setItem, + }; + + await storage.set('hello', 'world'); + globalThis.localStorage = localStorage; + + t.calledWith(setItem, ['hello', 'world'], 'should call setItem'); + t.end(); +}); + +test('cloudcmd: client: storage: get', async (t) => { + const {localStorage} = globalThis; + const getItem = stub().returns('world'); + + globalThis.localStorage = { + getItem, + }; + + const result = await storage.get('hello'); + + globalThis.localStorage = localStorage; + + t.equal(result, 'world'); + t.end(); +}); + +test('cloudcmd: client: storage: getJson', async (t) => { + const {localStorage} = globalThis; + const expected = { + hello: 'world', + }; + + const getItem = stub().returns(stringify(expected)); + + globalThis.localStorage = { + getItem, + }; + + const result = await storage.getJson('hello'); + + globalThis.localStorage = localStorage; + + t.deepEqual(result, expected); + t.end(); +}); + +test('cloudcmd: client: storage: setJson', async (t) => { + const {localStorage} = globalThis; + const data = { + hello: 'world', + }; + + const expected = stringify(data); + const setItem = stub(); + + globalThis.localStorage = { + setItem, + }; + + await storage.setJson('hello', data); + globalThis.localStorage = localStorage; + + t.calledWith(setItem, ['hello', expected]); + t.end(); +}); + +test('cloudcmd: client: storage: remove', async (t) => { + const {localStorage} = globalThis; + const removeItem = stub(); + + globalThis.localStorage = { + removeItem, + }; + + await storage.remove('hello'); + globalThis.localStorage = localStorage; + + t.calledWith(removeItem, ['hello'], 'should call removeItem'); + t.end(); +}); + +test('cloudcmd: client: storage: clear', async (t) => { + const {localStorage} = globalThis; + const clear = stub(); + + globalThis.localStorage = { + clear, + }; + + await storage.clear(); + globalThis.localStorage = localStorage; + + t.calledWithNoArgs(clear, 'should call clear'); + t.end(); +}); diff --git a/client/dom/upload-files.js b/client/dom/upload-files.js index 67d9eb01..1c37fe1b 100644 --- a/client/dom/upload-files.js +++ b/client/dom/upload-files.js @@ -1,27 +1,19 @@ -'use strict'; - /* global CloudCmd */ +import {eachSeries} from 'execon'; +import wraptile from 'wraptile'; +import * as load from '#dom/load'; +import {alert} from '#dom/dialog'; +import {FS} from '#common/cloudfunc'; +import * as Images from '#dom/images'; +import {getCurrentDirPath} from './current-file.js'; -const {eachSeries} = require('execon'); -const wraptile = require('wraptile/legacy'); - -const DOM = require('.'); -const load = require('./load'); -const Images = require('./images'); - -const {FS} = require('../../common/cloudfunc'); - -const onEnd = wraptile(_onEnd); const loadFile = wraptile(_loadFile); +const onEnd = wraptile(_onEnd); -const { - getCurrentDirPath: getPathWhenRootEmpty -} = DOM; - -module.exports = (dir, files) => { +export const uploadFiles = (dir, files) => { if (!files) { files = dir; - dir = getPathWhenRootEmpty(); + dir = getCurrentDirPath(); } const n = files.length; @@ -29,7 +21,7 @@ module.exports = (dir, files) => { if (!n) return; - const array = [...files]; + const array = Array.from(files); const {name} = files[0]; eachSeries(array, loadFile(dir, n), onEnd(name)); @@ -37,17 +29,17 @@ module.exports = (dir, files) => { function _onEnd(currentName) { CloudCmd.refresh({ - currentName + currentName, }); } function _loadFile(dir, n, file, callback) { let i = 0; - const name = file.name; + const {name} = file; const path = dir + name; - const {PREFIX_URL} = CloudCmd; - const api = PREFIX_URL + FS; + const {prefixURL} = CloudCmd; + const api = prefixURL + FS; const percent = (i, n, per = 100) => { return Math.round(i * per / n); @@ -57,7 +49,9 @@ function _loadFile(dir, n, file, callback) { ++i; - load.put(api + path, file) + load + .put(api + path, file) + .on('error', showError) .on('end', callback) .on('progress', (count) => { const max = step(n); @@ -68,3 +62,6 @@ function _loadFile(dir, n, file, callback) { }); } +function showError({message}) { + alert(message); +} diff --git a/client/get-json-from-file-table.js b/client/get-json-from-file-table.js new file mode 100644 index 00000000..ea90f366 --- /dev/null +++ b/client/get-json-from-file-table.js @@ -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, + }; +}; diff --git a/client/input.js b/client/input.js deleted file mode 100644 index b6de04ea..00000000 --- a/client/input.js +++ /dev/null @@ -1,78 +0,0 @@ -'use strict'; - -const currify = require('currify/legacy'); - -const isType = currify((type, object, name) => { - return typeof object[name] === type; -}); - -const isBool = isType('boolean'); - -module.exports.getElementByName = getElementByName; - -function getElementByName(selector, element) { - const str = `[data-name="js-${selector}"]`; - - return element - .querySelector(str); -} - -module.exports.getName = (element) => { - const name = element - .getAttribute('data-name') - .replace(/^js-/, ''); - - return name; -}; - -module.exports.convert = (config) => { - const result = Object.assign({}, config); - const array = Object.keys(result); - - array - .filter(isBool(result)) - .forEach((name) => { - const item = result[name]; - - result[name] = setState(item); - }); - - return result; -}; - -function setState(state) { - if (state) - return ' checked'; - - return ''; -} - -module.exports.getValue = (name, element) => { - const el = getElementByName(name, element); - const type = el.type; - - switch(type) { - case 'checkbox': - return el.checked; - case 'number': - return Number(el.value); - default: - return el.value; - } -}; - -module.exports.setValue = (name, value, element) => { - const el = getElementByName(name, element); - const type = el.type; - - switch(type) { - case 'checkbox': - el.checked = value; - break; - - default: - el.value = value; - break; - } -}; - diff --git a/client/key.js b/client/key.js deleted file mode 100644 index abfa8a0a..00000000 --- a/client/key.js +++ /dev/null @@ -1,573 +0,0 @@ -/* global CloudCmd, DOM */ - -'use strict'; - -const Info = DOM.CurrentInfo; - -const exec = require('execon'); - -const Events = require('./dom/events'); -const Buffer = require('./dom/buffer'); -const {escapeRegExp} = require('../common/util'); - -let Chars = []; -const KEY = { - BACKSPACE : 8, - TAB : 9, - ENTER : 13, - ESC : 27, - - SPACE : 32, - PAGE_UP : 33, - PAGE_DOWN : 34, - END : 35, - HOME : 36, - - LEFT : 37, - UP : 38, - RIGHT : 39, - DOWN : 40, - - INSERT : 45, - DELETE : 46, - - ZERO : 48, - - A : 65, - - C : 67, - D : 68, - - G : 71, - - M : 77, - - O : 79, - Q : 81, - R : 82, - S : 83, - T : 84, - U : 85, - - V : 86, - - X : 88, - - Z : 90, - - INSERT_MAC : 96, - - ASTERISK : 106, - PLUS : 107, - MINUS : 109, - - F1 : 112, - F2 : 113, - F3 : 114, - F4 : 115, - F5 : 116, - F6 : 117, - F7 : 118, - F8 : 119, - F9 : 120, - F10 : 121, - - EQUAL : 187, - HYPHEN : 189, - DOT : 190, - SLASH : 191, - TRA : 192, /* Typewritten Reverse Apostrophe (`) */ - BACKSLASH : 220, - - BRACKET_CLOSE: 221 -}; - -KeyProto.prototype = KEY; -CloudCmd.Key = KeyProto; - -function KeyProto() { - const Key = this; - - let Binded; - - this.isBind = () => { - return Binded; - }; - - this.setBind = () => { - Binded = true; - }; - - this.unsetBind = () => { - Binded = false; - }; - - this.bind = () => { - Events.addKey(listener); - Binded = true; - }; - - function getChar(event) { - /* - * event.keyIdentifier deprecated in chrome v51 - * but event.key is absent in chrome <= v51 - */ - - if (event.key) - return event.key; - - return fromCharCode(event.keyIdentifier); - } - - function listener(event) { - const keyCode = event.keyCode; - const alt = event.altKey; - const ctrl = event.ctrlKey; - const shift = event.shiftKey; - const meta = event.metaKey; - const isBetween = keyCode >= KEY.ZERO && keyCode <= KEY.Z; - const isNumpad = /Numpad/.test(event.code); - - let char = getChar(event); - let isSymbol = ~['.', '_', '-', '+', '='].indexOf(char); - - if (!isSymbol) { - isSymbol = getSymbol(shift, keyCode); - - if (isSymbol) - char = isSymbol; - } - - /* in case buttons can be processed */ - if (Key.isBind()) - if (!isNumpad && !alt && !ctrl && !meta && (isBetween || isSymbol)) - setCurrentByChar(char); - else { - Chars = []; - switchKey(event); - } - } - - function getSymbol(shift, keyCode) { - switch (keyCode) { - case KEY.DOT: - return '.'; - - case KEY.HYPHEN: - return shift ? '_' : '-'; - - case KEY.EQUAL: - return shift ? '+' : '='; - } - } - - function fromCharCode(keyIdentifier) { - const code = keyIdentifier.substring(2); - const hex = parseInt(code, 16); - const char = String.fromCharCode(hex); - - return char; - } - - function setCurrentByChar(char) { - let firstByName; - let skipCount = 0; - let setted = false; - let i = 0; - - const escapeChar = escapeRegExp(char); - const regExp = new RegExp('^' + escapeChar + '.*$', 'i'); - const {files} = Info; - const n = Chars.length; - - while(i < n && char === Chars[i]) { - i++; - } - - if (!i) - Chars = []; - - const skipN = skipCount = i; - Chars.push(char); - - const names = DOM.getFilenames(files); - const isTest = (a) => regExp.test(a); - const isRoot = (a) => a === '..'; - const not = (f) => (a) => !f(a); - const setCurrent = (name) => { - const byName = DOM.getCurrentByName(name); - - if (!skipCount) { - setted = true; - DOM.setCurrentFile(byName); - return true; - } else { - if (skipN === skipCount) - firstByName = byName; - - --skipCount; - } - }; - - names - .filter(isTest) - .filter(not(isRoot)) - .some(setCurrent); - - if (!setted) { - DOM.setCurrentFile(firstByName); - Chars = [char]; - } - } - - function switchKey(event) { - let i, isSelected, prev, next; - let current = Info.element; - let name = Info.name; - - const {Operation} = CloudCmd; - const panel = Info.panel; - const path = Info.path; - const isDir = Info.isDir; - - const keyCode = event.keyCode; - const alt = event.altKey; - const shift = event.shiftKey; - const ctrl = event.ctrlKey; - const meta = event.metaKey; - const ctrlMeta = ctrl || meta; - - if (current) { - prev = current.previousSibling; - next = current.nextSibling; - } - - switch (keyCode) { - case Key.TAB: - DOM.changePanel(); - event.preventDefault(); - break; - - case Key.INSERT: - DOM .toggleSelectedFile(current) - .setCurrentFile(next); - break; - - case Key.INSERT_MAC: - DOM .toggleSelectedFile(current) - .setCurrentFile(next); - break; - - case Key.DELETE: - if (shift) - Operation.show('delete:silent'); - else - Operation.show('delete'); - break; - - case Key.ASTERISK: - DOM.toggleAllSelectedFiles(current); - break; - - case Key.PLUS: - DOM.expandSelection(); - event.preventDefault(); - break; - - case Key.MINUS: - DOM.shrinkSelection(); - event.preventDefault(); - break; - - case Key.F1: - CloudCmd.Help.show(); - event.preventDefault(); - break; - - case Key.F2: - DOM.renameCurrent(current); - break; - - case Key.F3: - if (shift) - CloudCmd.Markdown.show(path); - else if (ctrlMeta) - CloudCmd.sortPanel('name'); - else - CloudCmd.View.show(); - - event.preventDefault(); - break; - - case Key.F4: - if (shift) - CloudCmd.EditFileVim.show(); - else - CloudCmd.EditFile.show(); - - event.preventDefault(); - break; - - case Key.F5: - if (ctrlMeta) - CloudCmd.sortPanel('date'); - else - Operation.show('copy'); - - event.preventDefault(); - break; - - case Key.F6: - if (ctrlMeta) - CloudCmd.sortPanel('size'); - else - Operation.show('move'); - - event.preventDefault(); - break; - - case Key.F7: - if (shift) - DOM.promptNewFile(); - else - DOM.promptNewDir(); - - event.preventDefault(); - break; - - case Key.F8: - Operation.show('delete'); - event.preventDefault(); - break; - - case Key.F9: - CloudCmd.Menu.show(); - event.preventDefault(); - break; - - case Key.F10: - CloudCmd.Config.show(); - event.preventDefault(); - break; - - case Key.TRA: - event.preventDefault(); - - if (shift) - return CloudCmd.Terminal.show(); - - CloudCmd.Konsole.show(); - break; - - case KEY.BRACKET_CLOSE: - CloudCmd.Konsole.show(); - event.preventDefault(); - break; - - case Key.SPACE: - if (!isDir || name === '..') - isSelected = true; - else - isSelected = DOM.isSelected(current); - - exec.if(isSelected, () => { - DOM.toggleSelectedFile(current); - }, (callback) => { - DOM.loadCurrentSize(callback, current); - }); - - event.preventDefault(); - break; - - case Key.U: - if (ctrlMeta) { - DOM.swapPanels(); - event.preventDefault(); - } - break; - - /* navigation on file table: * - * in case of pressing button 'up', * - * select previous row */ - case Key.UP: - if (shift) - DOM.toggleSelectedFile(current); - - DOM.setCurrentFile(prev); - event.preventDefault(); - break; - - /* in case of pressing button 'down', * - * select next row */ - case Key.DOWN: - if (shift) - DOM.toggleSelectedFile(current); - - DOM.setCurrentFile(next); - event.preventDefault(); - break; - - case Key.LEFT: - if (!alt) - return; - - event.preventDefault(); - - name = Info.panel.getAttribute('data-name'); - - if (name === 'js-right') - DOM.duplicatePanel(); - - break; - - case Key.RIGHT: - if (!alt) - return; - - event.preventDefault(); - - name = Info.panel.getAttribute('data-name'); - - if (name === 'js-left') - DOM.duplicatePanel(); - - break; - - /* in case of pressing button 'Home', * - * go to top element */ - case Key.HOME: - DOM.setCurrentFile(Info.first); - event.preventDefault(); - break; - - /* in case of pressing button 'End', select last element */ - case Key.END: - DOM.setCurrentFile(Info.last); - event.preventDefault(); - break; - - /* если нажали клавишу page down проматываем экран */ - case Key.PAGE_DOWN: - DOM.scrollByPages(panel, 1); - - for (i = 0; i < 30; i++) { - if (!current.nextSibling) - break; - - current = current.nextSibling; - } - - DOM.setCurrentFile(current); - event.preventDefault(); - break; - - /* если нажали клавишу page up проматываем экран */ - case Key.PAGE_UP: - DOM.scrollByPages(panel, -1); - - for (i = 0; i < 30; i++) { - if (!current.previousSibling) - break; - - current = current.previousSibling; - } - - DOM.setCurrentFile(current); - event.preventDefault(); - break; - - /* open directory */ - case Key.ENTER: - if (Info.isDir) - CloudCmd.loadDir({ - path: path === '/' ? '/' : path + '/' - }); - break; - - case Key.BACKSPACE: - CloudCmd.goToParentDir(); - event.preventDefault(); - break; - - case Key.BACKSLASH: - if (ctrlMeta) - CloudCmd.loadDir({ - path: '/' - }); - break; - - case Key.A: - if (ctrlMeta) { - DOM.selectAllFiles(); - event.preventDefault(); - } - - break; - - case Key.G: - if (alt) { - DOM.goToDirectory(); - event.preventDefault(); - } - - break; - - case Key.M: - if (ctrlMeta) { - CloudCmd.EditNames.show(); - event.preventDefault(); - } - - break; - - /** - * обновляем страницу, - * загружаем содержимое каталога - * при этом данные берём всегда с - * сервера, а не из кэша - * (обновляем кэш) - */ - case Key.R: - if (ctrlMeta) { - CloudCmd.log('reloading page...\n'); - CloudCmd.refresh(); - event.preventDefault(); - } - break; - - case Key.C: - if (ctrlMeta) - Buffer.copy(); - break; - - case Key.X: - if (ctrlMeta) - Buffer.cut(); - break; - - case Key.V: - if (ctrlMeta) - Buffer.paste(); - break; - - case Key.Z: - if (ctrlMeta) - Buffer.clear(); - break; - - /* чистим хранилище */ - case Key.D: - if (ctrlMeta) { - CloudCmd.log('clearing storage...'); - - DOM.Storage.clear(() => { - CloudCmd.log('storage cleared'); - }); - - event.preventDefault(); - } - break; - } - } -} - diff --git a/client/key/binder.js b/client/key/binder.js new file mode 100644 index 00000000..6aec97ea --- /dev/null +++ b/client/key/binder.js @@ -0,0 +1,15 @@ +export const createBinder = () => { + let binded = false; + + return { + isBind() { + return binded; + }, + setBind() { + binded = true; + }, + unsetBind() { + binded = false; + }, + }; +}; diff --git a/client/key/binder.spec.js b/client/key/binder.spec.js new file mode 100644 index 00000000..f9d54fdd --- /dev/null +++ b/client/key/binder.spec.js @@ -0,0 +1,28 @@ +import {test} from 'supertape'; +import {createBinder} from './binder.js'; + +test('client: key: binder: isBind: default', (t) => { + const binder = createBinder(); + + t.notOk(binder.isBind(), 'should not be bind by default'); + t.end(); +}); + +test('client: key: binder: setBind', (t) => { + const binder = createBinder(); + + binder.setBind(); + + t.ok(binder.isBind(), 'should be bind'); + t.end(); +}); + +test('client: key: binder: unsetBind', (t) => { + const binder = createBinder(); + + binder.setBind(); + binder.unsetBind(); + + t.notOk(binder.isBind(), 'should not be bind'); + t.end(); +}); diff --git a/client/key/index.js b/client/key/index.js new file mode 100644 index 00000000..283a7f11 --- /dev/null +++ b/client/key/index.js @@ -0,0 +1,544 @@ +/* global CloudCmd, DOM */ +import clipboard from '@cloudcmd/clipboard'; +import {fullstore} from 'fullstore'; +import * as Events from '#dom/events'; +import * as Buffer from '../dom/buffer.js'; +import * as KEY from './key.js'; +import _vim from './vim/index.js'; +import setCurrentByChar from './set-current-by-char.js'; +import {createBinder} from './binder.js'; + +const Chars = fullstore(); + +const toggleVim = (keyCode, overrides = {}) => { + const {_config, config} = overrides; + + if (!config('vim') && keyCode === KEY.ESC) + _config('vim', true); +}; + +const isUndefined = (a) => typeof a === 'undefined'; + +Chars([]); + +const {assign} = Object; +const binder = createBinder(); + +const bind = () => { + Events.addKey(listener, true); + binder.setBind(); +}; + +export const Key = assign(binder, KEY, { + bind, +}); + +export const _listener = listener; + +function getChar(event) { + /* + * event.keyIdentifier deprecated in chrome v51 + * but event.key is absent in chrome <= v51 + */ + const { + key, + shift, + keyCode, + keyIdentifier, + } = event; + + const char = key || fromCharCode(keyIdentifier); + const symbol = getSymbol(shift, keyCode); + + return [symbol, char]; +} + +async function listener(event, overrides = {}) { + const { + config = CloudCmd.config, + _config = CloudCmd._config, + switchKey = _switchKey, + vim = _vim, + } = overrides; + + const {keyCode} = event; + + // strange chrome bug calls listener twice + // in second time event misses a lot fields + if (isUndefined(event.altKey)) + return; + + const alt = event.altKey; + const ctrl = event.ctrlKey; + const meta = event.metaKey; + const isBetween = keyCode >= KEY.ZERO && keyCode <= KEY.Z; + const isNumpad = /Numpad/.test(event.code); + + const [symbol, char] = getChar(event); + + if (!binder.isBind()) + return; + + toggleVim(keyCode, { + config, + _config, + }); + + const isVim = config('vim'); + + if (!isVim && !isNumpad && !alt && !ctrl && !meta && (isBetween || symbol)) + return setCurrentByChar(char, Chars); + + Chars([]); + await switchKey(event); + + if (keyCode >= KEY.F1 && keyCode <= KEY.F10) + return; + + if (isVim) + vim(char, event); +} + +function getSymbol(shift, keyCode) { + switch(keyCode) { + case KEY.DOT: + return '.'; + + case KEY.HYPHEN: + return shift ? '_' : '-'; + + case KEY.EQUAL: + return shift ? '+' : '='; + } + + return ''; +} + +function fromCharCode(keyIdentifier) { + const code = keyIdentifier.substring(2); + const hex = parseInt(code, 16); + + return String.fromCharCode(hex); +} + +async function _switchKey(event) { + const Info = DOM.CurrentInfo; + let i; + let isSelected; + let prev; + let next; + let current = Info.element; + let dataName; + + const { + name, + panel, + path, + isDir, + } = Info; + + const { + Operation, + changeDir, + config, + } = CloudCmd; + + const {keyCode} = event; + + const alt = event.altKey; + const shift = event.shiftKey; + const ctrl = event.ctrlKey; + const meta = event.metaKey; + const ctrlMeta = ctrl || meta; + + if (current) { + prev = current.previousSibling; + next = current.nextSibling; + } + + switch(keyCode) { + case KEY.TAB: + DOM.changePanel(); + event.preventDefault(); + break; + + case KEY.INSERT: + DOM + .toggleSelectedFile(current) + .setCurrentFile(next); + break; + + case KEY.INSERT_MAC: + DOM + .toggleSelectedFile(current) + .setCurrentFile(next); + break; + + case KEY.DELETE: + if (shift) + Operation.show('delete:silent'); + else + Operation.show('delete'); + + break; + + case KEY.ASTERISK: + DOM.toggleAllSelectedFiles(current); + break; + + case KEY.PLUS: + DOM.expandSelection(); + event.preventDefault(); + break; + + case KEY.MINUS: + DOM.shrinkSelection(); + event.preventDefault(); + break; + + case KEY.F1: + CloudCmd.Help.show(); + event.preventDefault(); + break; + + case KEY.F2: + CloudCmd.UserMenu.show(); + break; + + case KEY.F3: + event.preventDefault(); + + if (Info.isDir) + await changeDir(path); + else if (shift) + CloudCmd.View.show(null, { + raw: true, + }); + else if (ctrlMeta) + CloudCmd.sortPanel('name'); + else + CloudCmd.View.show(); + + break; + + case KEY.F4: + if (config('vim')) + CloudCmd.EditFileVim.show(); + else + CloudCmd.EditFile.show(); + + event.preventDefault(); + break; + + case KEY.F5: + if (ctrlMeta) + CloudCmd.sortPanel('date'); + else if (alt) + Operation.show('pack'); + else + Operation.show('copy'); + + event.preventDefault(); + break; + + case KEY.F6: + if (ctrlMeta) + CloudCmd.sortPanel('size'); + else if (shift) + DOM.renameCurrent(current); + else + Operation.show('move'); + + event.preventDefault(); + break; + + case KEY.F7: + if (shift) + DOM.promptNewFile(); + else + DOM.promptNewDir(); + + event.preventDefault(); + break; + + case KEY.F8: + Operation.show('delete'); + event.preventDefault(); + break; + + case KEY.F9: + if (alt) + Operation.show('extract'); + else + CloudCmd.Menu.show(); + + event.preventDefault(); + break; + + case KEY.F10: + CloudCmd.Config.show(); + event.preventDefault(); + break; + + case KEY.TRA: + event.preventDefault(); + + if (shift) + return CloudCmd.Terminal.show(); + + CloudCmd.Konsole.show(); + break; + + case KEY.BRACKET_CLOSE: + CloudCmd.Konsole.show(); + event.preventDefault(); + break; + + case KEY.SPACE: + event.preventDefault(); + + if (!isDir || name === '..') + isSelected = true; + else + isSelected = DOM.isSelected(current); + + if (!isSelected) + await DOM.loadCurrentSize(current); + + DOM.toggleSelectedFile(current); + + break; + + case KEY.U: + if (ctrlMeta) { + DOM.swapPanels(); + event.preventDefault(); + } + + break; + + /* navigation on file table: * + * in case of pressing button 'up', * + * select previous row */ + case KEY.UP: + if (shift) + DOM.toggleSelectedFile(current); + + DOM.setCurrentFile(prev); + event.preventDefault(); + break; + + /* in case of pressing button 'down', * + * select next row */ + case KEY.DOWN: + if (shift) + DOM.toggleSelectedFile(current); + + DOM.setCurrentFile(next); + event.preventDefault(); + break; + + case KEY.LEFT: + if (!alt) + return; + + event.preventDefault(); + + dataName = Info.panel.getAttribute('data-name'); + + if (dataName === 'js-right') + DOM.duplicatePanel(); + + break; + + case KEY.RIGHT: + if (!alt) + return; + + event.preventDefault(); + + dataName = Info.panel.getAttribute('data-name'); + + if (dataName === 'js-left') + DOM.duplicatePanel(); + + break; + + /* in case of pressing button 'Home', * + * go to top element */ + case KEY.HOME: + DOM.setCurrentFile(Info.first); + event.preventDefault(); + break; + + /* in case of pressing button 'End', select last element */ + case KEY.END: + DOM.setCurrentFile(Info.last); + event.preventDefault(); + break; + + /* если нажали клавишу page down проматываем экран */ + case KEY.PAGE_DOWN: + DOM.scrollByPages(panel, 1); + + for (i = 0; i < 30; i++) { + if (!current.nextSibling) + break; + + current = current.nextSibling; + } + + DOM.setCurrentFile(current); + event.preventDefault(); + break; + + /* если нажали клавишу page up проматываем экран */ + case KEY.PAGE_UP: + DOM.scrollByPages(panel, -1); + + for (i = 0; i < 30; i++) { + if (!current.previousSibling) + break; + + current = current.previousSibling; + } + + DOM.setCurrentFile(current); + event.preventDefault(); + break; + + case KEY.ENTER: + if (Info.isDir) + await changeDir(path); + else + CloudCmd.View.show(); + + break; + + case KEY.BACKSPACE: + CloudCmd.goToParentDir(); + event.preventDefault(); + break; + + case KEY.BACKSLASH: + if (ctrlMeta) + await changeDir('/'); + + break; + + case KEY.A: + if (ctrlMeta) { + DOM.selectAllFiles(); + event.preventDefault(); + } + + break; + + case KEY.G: + if (alt) { + DOM.goToDirectory(); + event.preventDefault(); + } + + break; + + case KEY.L: + if (ctrlMeta && shift) { + CloudCmd.logOut(); + event.preventDefault(); + } + + break; + + case KEY.M: + if (ctrlMeta) { + if (config('vim')) + CloudCmd.EditNamesVim.show(); + else + CloudCmd.EditNames.show(); + + event.preventDefault(); + } + + break; + + case KEY.P: + if (!ctrlMeta) + return; + + event.preventDefault(); + clipboard + .writeText(Info.dirPath) + .catch(CloudCmd.log); + + break; + + /** + * обновляем страницу, + * загружаем содержимое каталога + * при этом данные берём всегда с + * сервера, а не из кэша + * (обновляем кэш) + */ + case KEY.R: + if (ctrlMeta) { + CloudCmd.log('reloading page...\n'); + CloudCmd.refresh(); + event.preventDefault(); + } + + break; + + case KEY.C: + if (ctrlMeta) + Buffer.copy(); + + break; + + case KEY.X: + if (ctrlMeta) + Buffer.cut(); + + break; + + case KEY.V: + if (ctrlMeta) + Buffer.paste(); + + break; + + case KEY.Z: + if (ctrlMeta) + Buffer.clear(); + + break; + + case KEY.COLON: + CloudCmd.CommandLine.show(); + event.preventDefault(); + break; + + /* чистим хранилище */ + case KEY.D: + if (ctrlMeta) { + CloudCmd.log('clearing storage...'); + await DOM.Storage.clear(); + CloudCmd.log('storage cleared'); + 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; + } +} diff --git a/client/key/index.spec.js b/client/key/index.spec.js new file mode 100644 index 00000000..bec92b31 --- /dev/null +++ b/client/key/index.spec.js @@ -0,0 +1,56 @@ +import autoGlobals from 'auto-globals'; +import supertape from 'supertape'; +import {ESC} from './key.js'; +import {Key, _listener} from './index.js'; +import {getDOM, getCloudCmd} from './vim/globals.fixture.js'; + +const test = autoGlobals(supertape); +const {stub} = supertape; + +globalThis.DOM = getDOM(); +globalThis.CloudCmd = getCloudCmd(); + +test('cloudcmd: client: key: enable vim', async (t) => { + const vim = stub(); + const config = stub().returns(true); + const _config = stub(); + + const event = { + keyCode: ESC, + key: 'Escape', + altKey: false, + }; + + Key.setBind(); + + await _listener(event, { + vim, + config, + _config, + switchKey: stub(), + }); + + t.calledWith(vim, ['Escape', event]); + t.end(); +}); + +test('cloudcmd: client: key: disable vim', async (t) => { + const _config = stub(); + const config = stub(); + + const event = { + keyCode: ESC, + key: 'Escape', + altKey: false, + }; + + Key.setBind(); + await _listener(event, { + config, + _config, + switchKey: stub(), + }); + + t.calledWith(_config, ['vim', true]); + t.end(); +}); diff --git a/client/key/key.js b/client/key/key.js new file mode 100644 index 00000000..6772e34c --- /dev/null +++ b/client/key/key.js @@ -0,0 +1,58 @@ +export const BACKSPACE = 8; +export const TAB = 9; +export const ENTER = 13; +export const CAPSLOCK = 20; +export const ESC = 27; +export const SPACE = 32; +export const PAGE_UP = 33; +export const PAGE_DOWN = 34; +export const END = 35; +export const HOME = 36; +export const LEFT = 37; +export const UP = 38; +export const RIGHT = 39; +export const DOWN = 40; +export const INSERT = 45; +export const DELETE = 46; +export const ZERO = 48; +export const SEMICOLON = 52; +export const A = 65; +export const C = 67; +export const D = 68; +export const G = 71; +export const J = 74; +export const K = 75; +export const L = 76; +export const M = 77; +export const O = 79; +export const P = 80; +export const Q = 81; +export const R = 82; +export const S = 83; +export const T = 84; +export const U = 85; +export const V = 86; +export const X = 88; +export const Z = 90; +export const INSERT_MAC = 96; +export const ASTERISK = 106; +export const PLUS = 107; +export const MINUS = 109; +export const F1 = 112; +export const F2 = 113; +export const F3 = 114; +export const F4 = 115; +export const F5 = 116; +export const F6 = 117; +export const F7 = 118; +export const F8 = 119; +export const F9 = 120; +export const F10 = 121; +export const COLON = 186; +export const EQUAL = 187; +export const HYPHEN = 189; +export const DOT = 190; +export const SLASH = 191; +export const TRA = 192; +export const BACKSLASH = 220; +export const BRACKET_CLOSE = 221; diff --git a/client/key/set-current-by-char.js b/client/key/set-current-by-char.js new file mode 100644 index 00000000..92764f11 --- /dev/null +++ b/client/key/set-current-by-char.js @@ -0,0 +1,57 @@ +/* global DOM */ +import {escapeRegExp} from '#common/util'; + +export default function setCurrentByChar(char, charStore) { + const Info = DOM.CurrentInfo; + let firstByName; + let skipCount = 0; + let set = false; + let i = 0; + + const escapeChar = escapeRegExp(char); + const regExp = new RegExp(`^${escapeChar}.*$`, 'i'); + const {files} = Info; + const chars = charStore(); + const n = chars.length; + + while (i < n && char === chars[i]) + i++; + + if (!i) + charStore([]); + + const skipN = skipCount = i; + + charStore(charStore().concat(char)); + + const names = DOM.getFilenames(files); + const isTest = (a) => regExp.test(a); + const isRoot = (a) => a === '..'; + const not = (f) => (a) => !f(a); + + const setCurrent = (name) => { + const byName = DOM.getCurrentByName(name); + + if (!skipCount) { + set = true; + DOM.setCurrentFile(byName); + + return true; + } + + if (skipN === skipCount) + firstByName = byName; + + --skipCount; + }; + + names + .filter(isTest) + .filter(not(isRoot)) + .some(setCurrent); + + if (!set) { + DOM.setCurrentFile(firstByName); + charStore([char]); + } +} diff --git a/client/key/vim/find.js b/client/key/vim/find.js new file mode 100644 index 00000000..e8db825a --- /dev/null +++ b/client/key/vim/find.js @@ -0,0 +1,47 @@ +import {fullstore} from 'fullstore'; +import limier from 'limier'; + +const searchStore = fullstore([]); +const searchIndex = fullstore(0); + +export const find = (value, names) => { + const result = limier(value, names); + + searchStore(result); + searchIndex(0); + + return result; +}; + +export const findNext = () => { + const names = searchStore(); + const index = next(searchIndex(), names.length); + + searchIndex(index); + return names[searchIndex()]; +}; + +export const findPrevious = () => { + const names = searchStore(); + const index = previous(searchIndex(), names.length); + + searchIndex(index); + return names[index]; +}; + +export const _next = next; +export const _previous = previous; + +function next(index, length) { + if (index === length - 1) + return 0; + + return ++index; +} + +function previous(index, length) { + if (!index) + return length - 1; + + return --index; +} diff --git a/client/key/vim/find.spec.js b/client/key/vim/find.spec.js new file mode 100644 index 00000000..191a3652 --- /dev/null +++ b/client/key/vim/find.spec.js @@ -0,0 +1,55 @@ +import test from 'supertape'; +import {getDOM} from './globals.fixture.js'; +import { + _next, + _previous, + find, + findNext, + findPrevious, +} from './find.js'; + +globalThis.DOM = getDOM(); + +test('cloudcmd: client: vim: _next', (t) => { + const result = _next(1, 2); + + t.notOk(result, 'should return 0'); + t.end(); +}); + +test('cloudcmd: client: vim: _next: increment', (t) => { + const result = _next(0, 2); + + t.equal(result, 1, 'should return 1'); + t.end(); +}); + +test('cloudcmd: client: vim: _previous', (t) => { + const result = _previous(0, 2); + + t.equal(result, 1, 'should return 1'); + t.end(); +}); + +test('cloudcmd: client: vim: _previous: decrement', (t) => { + const result = _previous(1, 2); + + t.equal(result, 0, 'should return 0'); + t.end(); +}); + +test('cloudcmd: client: vim: findNext: after find', (t) => { + find('a', ['alpha', 'beta', 'apple']); + const result = findNext(); + + t.equal(result, 'beta', 'should return next found name'); + t.end(); +}); + +test('cloudcmd: client: vim: findPrevious: after find', (t) => { + find('a', ['alpha', 'beta', 'apple']); + const result = findPrevious(); + + t.equal(result, 'apple', 'should return previous found name'); + t.end(); +}); diff --git a/client/key/vim/globals.fixture.js b/client/key/vim/globals.fixture.js new file mode 100644 index 00000000..c49894d7 --- /dev/null +++ b/client/key/vim/globals.fixture.js @@ -0,0 +1,46 @@ +const noop = () => {}; + +export const getDOM = () => { + const prompt = Promise.resolve.bind(Promise); + const CurrentInfo = { + element: {}, + files: [], + }; + + const Buffer = { + copy: noop, + paste: noop, + }; + + const Dialog = { + prompt, + }; + + return { + Buffer, + CurrentInfo, + Dialog, + selectFile: noop, + unselectFile: noop, + unselectFiles: noop, + setCurrentFile: noop, + getCurrentName: noop, + setCurrentByName: noop, + toggleSelectedFile: noop, + prompNewDirectory: noop, + promptNewFile: noop, + }; +}; + +export const getCloudCmd = () => { + const show = () => {}; + + return { + Operation: { + show, + }, + + config: noop, + _config: noop, + }; +}; diff --git a/client/key/vim/index.js b/client/key/vim/index.js new file mode 100644 index 00000000..981f6f19 --- /dev/null +++ b/client/key/vim/index.js @@ -0,0 +1,167 @@ +import vim from './vim.js'; +import * as finder from './find.js'; +import { + setCurrent, + selectFileNotParent, +} from './set-current.js'; + +export default (key, event, overrides = {}) => { + const defaults = { + ...globalThis.DOM, + ...globalThis.CloudCmd, + }; + + const deps = { + ...defaults, + ...overrides, + }; + + const operations = getOperations(event, deps); + + vim(key, operations, deps); +}; + +const getOperations = (event, deps) => { + const { + Info = globalThis.DOM.CurrentInfo, + CloudCmd = globalThis.CloudCmd, + Operation, + unselectFiles, + setCurrentFile, + setCurrentByName, + getCurrentName, + prompt = globalThis.DOM.Dialog.prompt, + preventDefault = event?.preventDefault?.bind(event), + stopImmediatePropagation = event?.preventDefault?.bind(event), + promptNewFile = globalThis.DOM.promptNewFile, + toggleSelectedFile, + Buffer = {}, + createFindNext = _createFindNext, + createFindPrevious = _createFindPrevious, + createMakeFile = _createMakeFile, + renameCurrent, + } = deps; + + return { + makeFile: createMakeFile({ + promptNewFile, + preventDefault, + stopImmediatePropagation, + }), + findNext: createFindNext({ + setCurrentByName, + }), + findPrevious: createFindPrevious({ + setCurrentByName, + }), + escape: unselectFiles, + rename: () => { + event.preventDefault(); + renameCurrent(); + }, + remove: () => { + Operation.show('delete'); + }, + operationCopy: () => { + event.preventDefault(); + Operation.show('copy'); + }, + operationMove: () => { + event.preventDefault(); + Operation.show('move'); + }, + + makeDirectory: () => { + event.stopImmediatePropagation(); + event.preventDefault(); + globalThis.DOM.promptNewDir(); + }, + + terminal: () => { + CloudCmd.Terminal.show(); + }, + + edit: () => { + CloudCmd.EditFileVim.show(); + }, + + copy: () => { + Buffer.copy(); + unselectFiles(); + }, + + select: () => { + const current = Info.element; + toggleSelectedFile(current); + }, + + paste: Buffer.paste, + + moveNext: ({count, isVisual, isDelete}) => { + setCurrent('next', { + count, + isVisual, + isDelete, + }, { + Info, + setCurrentFile, + unselectFiles, + Operation, + }); + }, + + movePrevious: ({count, isVisual, isDelete}) => { + setCurrent('previous', { + count, + isVisual, + isDelete, + }, { + Info, + setCurrentFile, + unselectFiles, + Operation, + }); + }, + + find: async () => { + preventDefault(); + const [, value] = await prompt('Find', ''); + + if (!value) + return; + + const names = Info.files.map(getCurrentName); + const [result] = finder.find(value, names); + + setCurrentByName(result); + }, + }; +}; + +export const selectFile = selectFileNotParent; + +const _createFindPrevious = (overrides = {}) => () => { + const {setCurrentByName} = overrides; + const name = finder.findPrevious(); + + setCurrentByName(name); +}; + +const _createFindNext = (overrides = {}) => () => { + const {setCurrentByName} = overrides; + const name = finder.findNext(); + + setCurrentByName(name); +}; + +const _createMakeFile = (overrides = {}) => () => { + const { + promptNewFile, + stopImmediatePropagation, + preventDefault, + } = overrides; + + stopImmediatePropagation(); + preventDefault(); + promptNewFile(); +}; diff --git a/client/key/vim/index.spec.js b/client/key/vim/index.spec.js new file mode 100644 index 00000000..231c6577 --- /dev/null +++ b/client/key/vim/index.spec.js @@ -0,0 +1,756 @@ +import {test, stub} from 'supertape'; +import {getDOM, getCloudCmd} from './globals.fixture.js'; +import vim, {selectFile as vimSelectFile} from './index.js'; +import * as finder from './find.js'; + +globalThis.DOM = getDOM(); +globalThis.CloudCmd = getCloudCmd(); + +const {assign} = Object; +const {DOM} = globalThis; +const {Buffer} = DOM; + +test('cloudcmd: client: key: set next file: no', (t) => { + const element = {}; + const setCurrentFile = stub(); + const unselectFiles = stub(); + + const Info = { + element, + }; + + vim('j', {}, { + Info, + setCurrentFile, + unselectFiles, + }); + + t.calledWith(setCurrentFile, [element], 'should set next file'); + t.end(); +}); + +test('cloudcmd: client: key: set next file current: j', async (t) => { + const nextSibling = 'hello'; + const element = { + nextSibling, + }; + + const setCurrentFile = stub(); + + const Info = { + element, + }; + + await vim('j', {}, { + Info, + setCurrentFile, + unselectFiles: stub(), + }); + + t.calledWith(setCurrentFile, [nextSibling], 'should set next file'); + t.end(); +}); + +test('cloudcmd: client: key: set next file current: mjj', (t) => { + const nextSibling = 'hello'; + const element = { + nextSibling, + }; + + const setCurrentFile = stub(); + + const Info = { + element, + }; + + const deps = { + Info, + setCurrentFile, + unselectFiles: stub(), + }; + + vim('m', {}, deps); + vim('j', {}, deps); + vim('j', {}, deps); + + t.calledWith(setCurrentFile, [nextSibling], 'should set next file'); + t.end(); +}); + +test('cloudcmd: client: key: set next file current: g', (t) => { + const nextSibling = 'hello'; + const element = { + nextSibling, + }; + + const setCurrentFile = stub(); + + const Info = { + element, + }; + + const deps = { + Info, + setCurrentFile, + unselectFiles: stub(), + }; + + vim('g', {}, deps); + vim('j', {}, deps); + + t.calledWith(setCurrentFile, [nextSibling], 'should ignore g'); + t.end(); +}); + +test('cloudcmd: client: key: set +2 file current', (t) => { + const last = {}; + const setCurrentFile = stub(); + const element = {}; + + const Info = { + element, + }; + + const deps = { + setCurrentFile, + Info, + unselectFiles: stub(), + }; + + const event = {}; + + vim('2', event, deps); + vim('j', event, deps); + + t.calledWith(setCurrentFile, [last], 'should set next file'); + t.end(); +}); + +test('cloudcmd: client: key: select +2 files from current before delete', (t) => { + const last = {}; + const nextSibling = { + nextSibling: last, + }; + + const element = { + nextSibling, + }; + + const setCurrentFile = stub(); + + const Info = { + element, + }; + + const Operation = { + show: stub(), + }; + + const selectFile = stub(); + const getCurrentName = stub().returns('x'); + + const event = {}; + + const deps = { + Info, + setCurrentFile, + selectFile, + getCurrentName, + Operation, + }; + + vim('d', event, deps); + vim('2', event, deps); + vim('j', event, deps); + + t.calledWith(setCurrentFile, [last], 'should set next file'); + t.end(); +}); + +test('cloudcmd: client: key: delete +2 files from current', (t) => { + const last = {}; + const nextSibling = { + nextSibling: last, + }; + + const element = { + nextSibling, + }; + + const setCurrentFile = stub(); + const show = stub(); + + const deps = { + Info: { + element, + }, + Operation: { + show, + }, + setCurrentFile, + selectFile: stub(), + getCurrentName: stub().returns('x'), + unselectFiles: stub(), + }; + + const event = {}; + + vim('d', event, deps); + vim('2', event, deps); + vim('j', event, deps); + + t.calledWith(show, ['delete'], 'should call delete'); + t.end(); +}); + +test('cloudcmd: client: key: set previous file current', (t) => { + const previousSibling = 'hello'; + const element = { + previousSibling, + }; + + const setCurrentFile = stub(); + const unselectFiles = stub(); + + const Info = { + element, + }; + + const deps = { + Info, + setCurrentFile, + unselectFiles, + }; + + vim('k', {}, deps); + + t.calledWith(setCurrentFile, [previousSibling], 'should set previous file'); + t.end(); +}); + +test('cloudcmd: client: key: copy: no', (t) => { + const copy = stub(); + + vim('y', {}, { + unselectFiles: stub(), + Buffer: { + copy, + }, + }); + + t.notCalled(copy, 'should not copy files'); + t.end(); +}); + +test('cloudcmd: client: key: copy', (t) => { + const copy = stub(); + const Info = { + element: {}, + }; + + const toggleSelectedFile = stub(); + const unselectFiles = stub(); + + const deps = { + Info, + unselectFiles, + toggleSelectedFile, + Buffer: { + copy, + }, + }; + + vim('v', {}, deps); + vim('y', {}, deps); + + t.calledWithNoArgs(copy, 'should copy files'); + t.end(); +}); + +test('cloudcmd: client: key: copy: unselectFiles', (t) => { + const unselectFiles = stub(); + const Info = { + element: {}, + }; + + const toggleSelectedFile = stub(); + + const deps = { + Info, + unselectFiles, + toggleSelectedFile, + Buffer: { + copy: stub(), + }, + }; + + vim('v', {}, deps); + vim('y', {}, deps); + + t.calledWithNoArgs(unselectFiles, 'should unselect files'); + t.end(); +}); + +test('cloudcmd: client: key: paste', (t) => { + const paste = stub(); + + Buffer.paste = paste; + + vim('p', {}, { + Buffer, + }); + + t.calledWithNoArgs(paste, 'should paste files'); + t.end(); +}); + +test('cloudcmd: client: key: selectFile: ..', (t) => { + const getCurrentName = stub().returns('..'); + const selectFile = stub(); + const current = {}; + + vimSelectFile(current, { + selectFile, + getCurrentName, + }); + + t.notCalled(selectFile, 'should not call selectFile'); + t.end(); +}); + +test('cloudcmd: client: key: selectFile', (t) => { + const selectFile = stub(); + const getCurrentName = stub().returns('x'); + const current = {}; + + vimSelectFile(current, { + selectFile, + getCurrentName, + }); + + t.calledWith(selectFile, [current], 'should call selectFile'); + t.end(); +}); + +test('cloudcmd: client: key: set last file current: shift + g', async (t) => { + const last = 'last'; + const nextSibling = { + nextSibling: last, + }; + + const element = { + nextSibling, + }; + + const setCurrentFile = stub(); + + await vim('G', {}, { + Info: { + element, + }, + setCurrentFile, + unselectFiles: stub(), + }); + + t.calledWith(setCurrentFile, [last], 'should set last file'); + t.end(); +}); + +test('cloudcmd: client: key: set last file current: $', (t) => { + const last = 'last'; + const nextSibling = { + nextSibling: last, + }; + + const element = { + nextSibling, + }; + + const setCurrentFile = stub(); + + vim('$', {}, { + Info: { + element, + }, + setCurrentFile, + unselectFiles: stub(), + }); + + t.calledWith(setCurrentFile, [last], 'should set last file'); + t.end(); +}); + +test('cloudcmd: client: key: set first file current: gg', (t) => { + const first = 'first'; + const previousSibling = { + previousSibling: first, + }; + + const element = { + previousSibling, + }; + + const Operation = { + show: stub(), + }; + + const unselectFiles = stub(); + const setCurrentFile = stub(); + + const deps = { + Operation, + unselectFiles, + setCurrentFile, + Info: { + element, + }, + }; + + vim('g', {}, deps); + vim('g', {}, deps); + + t.calledWith(setCurrentFile, [first], 'should set first file'); + t.end(); +}); + +test('cloudcmd: client: key: set first file current: ^', async (t) => { + const first = 'first'; + const previousSibling = { + previousSibling: first, + }; + + const element = { + previousSibling, + }; + + const Operation = { + show: stub(), + }; + + const unselectFiles = stub(); + const setCurrentFile = stub(); + + const deps = { + setCurrentFile, + Info: { + element, + }, + unselectFiles, + Operation, + }; + + await vim('^', {}, deps); + + t.calledWith(setCurrentFile, [first], 'should set first file'); + t.end(); +}); + +test('cloudcmd: client: key: visual', (t) => { + const element = {}; + const toggleSelectedFile = stub(); + + const Info = { + element, + }; + + vim('v', {}, { + Info, + toggleSelectedFile, + }); + + t.calledWith(toggleSelectedFile, [element], 'should toggle selection'); + t.end(); +}); + +test('cloudcmd: client: key: ESC', (t) => { + const element = {}; + const unselectFiles = stub(); + + const Info = { + element, + }; + + vim('Escape', null, { + Info, + unselectFiles, + }); + + t.calledWithNoArgs(unselectFiles, 'should toggle selection'); + t.end(); +}); + +test('cloudcmd: client: key: Enter', async (t) => { + const nextSibling = 'hello'; + const element = { + nextSibling, + }; + + const unselectFiles = stub(); + const setCurrentFile = stub(); + + const Info = { + element, + }; + + await vim('Enter', null, { + Info, + setCurrentFile, + unselectFiles, + }); + + await vim('j', null, { + Info, + setCurrentFile, + unselectFiles, + }); + + t.calledWith(setCurrentFile, [nextSibling], 'should set next file'); + t.end(); +}); + +test('cloudcmd: client: key: /', (t) => { + const preventDefault = stub(); + const element = {}; + + const Info = { + element, + files: [], + }; + + const getCurrentName = stub().returns(''); + + const event = { + preventDefault, + }; + + const prompt = stub().returns([]); + + vim('/', event, { + getCurrentName, + Info, + prompt, + }); + + t.calledWithNoArgs(preventDefault); + t.end(); +}); + +test('cloudcmd: client: find', (t) => { + assign(DOM.Dialog, { + prompt: stub().returns([]), + }); + + const setCurrentByName = stub(); + + assign(DOM, { + setCurrentByName, + }); + + const event = { + preventDefault: stub(), + }; + + vim('/', event); + + t.notCalled(setCurrentByName); + t.end(); +}); + +test('cloudcmd: client: key: n', (t) => { + const findNext = stub(); + const createFindNext = stub().returns(findNext); + + const event = {}; + + vim('n', event, { + createFindNext, + }); + + t.calledWithNoArgs(findNext, 'should call findNext'); + t.end(); +}); + +test('cloudcmd: client: key: N', (t) => { + const findPrevious = stub(); + const createFindPrevious = stub().returns(findPrevious); + const event = {}; + + vim('N', event, { + createFindPrevious, + }); + + t.calledWithNoArgs(findPrevious); + t.end(); +}); + +test('cloudcmd: client: key: make directory', async (t) => { + const {DOM} = globalThis; + + assign(DOM, { + promptNewDir: stub(), + }); + + const event = { + stopImmediatePropagation: stub(), + preventDefault: stub(), + }; + + await vim('m', event); + await vim('d', event); + + t.calledWithNoArgs(DOM.promptNewDir); + t.end(); +}); + +test('cloudcmd: client: key: make file', (t) => { + const promptNewFile = stub(); + + const event = { + stopImmediatePropagation: stub(), + preventDefault: stub(), + }; + + vim('m', event); + vim('f', event, { + promptNewFile, + }); + + t.calledWithNoArgs(promptNewFile); + t.end(); +}); + +test('cloudcmd: client: vim: terminal', (t) => { + const CloudCmd = { + Terminal: { + show: stub(), + }, + }; + + const event = {}; + + vim('t', event, { + CloudCmd, + }); + vim('t', event, { + CloudCmd, + }); + + t.calledWithNoArgs(CloudCmd.Terminal.show); + t.end(); +}); + +test('cloudcmd: client: vim: edit', async (t) => { + globalThis.DOM = getDOM(); + globalThis.CloudCmd = getCloudCmd(); + + const {CloudCmd} = globalThis; + + assign(CloudCmd, { + EditFileVim: { + show: stub(), + }, + }); + + const event = {}; + + await vim('e', event); + + t.calledWithNoArgs(CloudCmd.EditFileVim.show); + t.end(); +}); + +test('cloudcmd: client: vim: rename', async (t) => { + const DOM = getDOM(); + const renameCurrent = stub(); + + assign(DOM, { + renameCurrent, + }); + + const event = { + preventDefault: stub(), + }; + + await vim('rr', event, DOM); + + t.calledWithNoArgs(renameCurrent); + t.end(); +}); + +test('cloudcmd: client: key: cc: operationCopy', (t) => { + const show = stub(); + const preventDefault = stub(); + + const Operation = { + show, + }; + + const event = { + preventDefault, + }; + + vim('c', event, { + Operation, + }); + + vim('c', event, { + Operation, + }); + + t.calledWith(show, ['copy'], 'should show copy operation'); + t.end(); +}); + +test('cloudcmd: client: key: mm: operationMove', (t) => { + const show = stub(); + const preventDefault = stub(); + + const Operation = { + show, + }; + + const event = { + preventDefault, + }; + + vim('m', event, { + Operation, + }); + + vim('m', event, { + Operation, + }); + + t.calledWith(show, ['move'], 'should show move operation'); + t.end(); +}); + +test('cloudcmd: client: key: n: findNext: real', (t) => { + const setCurrentByName = stub(); + + finder.find('a', ['alpha', 'beta', 'apple']); + + const event = {}; + + vim('n', event, { + setCurrentByName, + }); + + t.calledWith(setCurrentByName, ['beta'], 'should set current by next found name'); + t.end(); +}); + +test('cloudcmd: client: key: N: findPrevious: real', (t) => { + const setCurrentByName = stub(); + + finder.find('a', ['alpha', 'beta', 'apple']); + + const event = {}; + + vim('N', event, { + setCurrentByName, + }); + + t.calledWith(setCurrentByName, ['apple'], 'should set current by previous found name'); + t.end(); +}); diff --git a/client/key/vim/set-current.js b/client/key/vim/set-current.js new file mode 100644 index 00000000..a2fc8646 --- /dev/null +++ b/client/key/vim/set-current.js @@ -0,0 +1,33 @@ +/* global DOM */ +export function selectFileNotParent(current, {getCurrentName, selectFile} = DOM) { + const name = getCurrentName(current); + + if (name === '..') + return; + + selectFile(current); +} + +export const setCurrent = (sibling, {count, isVisual, isDelete}, {Info, setCurrentFile, unselectFiles, Operation}) => { + let current = Info.element; + const select = isVisual ? selectFileNotParent : unselectFiles; + + select(current); + + const position = `${sibling}Sibling`; + + for (let i = 0; i < count; i++) { + const next = current[position]; + + if (!next) + break; + + current = next; + select(current); + } + + setCurrentFile(current); + + if (isDelete) + Operation.show('delete'); +}; diff --git a/client/key/vim/vim.js b/client/key/vim/vim.js new file mode 100644 index 00000000..95a27caf --- /dev/null +++ b/client/key/vim/vim.js @@ -0,0 +1,220 @@ +import {fullstore} from 'fullstore'; + +const store = fullstore(''); +const visual = fullstore(false); + +const stopVisual = () => { + visual(false); +}; + +const end = () => { + store(''); +}; + +const rmFirst = (a) => { + return a + .split('') + .slice(1) + .join(''); +}; + +const noop = () => {}; + +export default (key, operations = {}) => { + const prevStore = store(); + const isVisual = visual(); + const value = store(prevStore.concat(key)); + + const { + escape = noop, + moveNext = noop, + movePrevious = noop, + remove = noop, + copy = noop, + paste = noop, + select = noop, + find = noop, + findNext = noop, + findPrevious = noop, + makeFile = noop, + makeDirectory = noop, + terminal = noop, + edit = noop, + operationCopy = noop, + operationMove = noop, + rename = noop, + } = operations; + + if (key === 'Enter') + return end(); + + if (key === 'Escape') { + visual(false); + escape(); + + return end(); + } + + if (key === 'j' || key === 'w') { + const { + count, + isDelete, + isVisual, + } = handleDelete(prevStore); + + !isNaN(count) && moveNext({ + count, + isVisual, + isDelete, + }); + + return end(); + } + + if (key === 'k' || key === 'b') { + const { + count, + isDelete, + isVisual, + } = handleDelete(prevStore); + + !isNaN(count) && movePrevious({ + count, + isVisual, + isDelete, + }); + + return end(); + } + + if (value === 'gg' || key === '^') { + const {isDelete, isVisual} = handleDelete(prevStore); + + movePrevious({ + count: Infinity, + isVisual, + isDelete, + }); + + return end(); + } + + if (value === 'md') { + makeDirectory(); + return end(); + } + + if (value === 'tt') { + terminal(); + return end(); + } + + if (value === 'e') { + edit(); + return end(); + } + + if (value === 'cc') { + operationCopy(); + return end(); + } + + if (value === 'mm') { + operationMove(); + return end(); + } + + if (value === 'mf') { + makeFile(); + return end(); + } + + if (value === 'rr') { + rename(); + return end(); + } + + if (key === 'd' && (visual() || prevStore === 'd')) { + stopVisual(); + remove(); + + return end(); + } + + if (key === 'G' || key === '$') { + moveNext({ + count: Infinity, + isVisual, + }); + + return end(); + } + + if (key === 'y') { + if (!visual()) + return end(); + + stopVisual(); + copy(); + + return end(); + } + + if (/^p$/i.test(key)) { + paste(); + return end(); + } + + if (/^v$/i.test(key)) { + visual(!visual()); + select(); + + return end(); + } + + if (key === '/') { + find(); + return end(); + } + + if (key === 'n') { + findNext(); + return end(); + } + + if (key === 'N') { + findPrevious(); + return end(); + } + + if (key === ' ') + return end(); +}; + +function handleDelete(prevStore) { + const isDelete = prevStore[0] === 'd'; + + if (isDelete) { + visual(true); + prevStore = rmFirst(prevStore); + } + + const count = getNumber(prevStore); + const isVisual = visual(); + + return { + count, + isDelete, + isVisual, + }; +} + +function getNumber(value) { + if (!value) + return 1; + + if (value === 'g') + return 1; + + return parseInt(value); +} diff --git a/client/key/vim/vim.spec.js b/client/key/vim/vim.spec.js new file mode 100644 index 00000000..02fd52d4 --- /dev/null +++ b/client/key/vim/vim.spec.js @@ -0,0 +1,100 @@ +import {test, stub} from 'supertape'; +import vim from './vim.js'; + +test('vim: no operations', (t) => { + const result = vim('hello', {}); + + t.notOk(result); + 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) => { + const movePrevious = stub(); + + vim('^', { + movePrevious, + }); + + const expected = { + count: Infinity, + isVisual: false, + isDelete: false, + }; + + t.calledWith(movePrevious, [expected], 'should call movePrevious'); + t.end(); +}); + +test('vim: cc', (t) => { + const operationCopy = stub(); + + vim('cc', { + operationCopy, + }); + + t.calledWithNoArgs(operationCopy); + t.end(); +}); + +test('vim: mm', (t) => { + const operationMove = stub(); + + vim('mm', { + operationMove, + }); + + t.calledWithNoArgs(operationMove); + t.end(); +}); + +test('vim: w', (t) => { + const moveNext = stub(); + + vim('w', { + moveNext, + }); + + const expected = { + count: 1, + isVisual: false, + isDelete: false, + }; + + t.calledWith(moveNext, [expected], 'should call moveNext'); + t.end(); +}); + +test('vim: b', (t) => { + const movePrevious = stub(); + + vim('b', { + movePrevious, + }); + + const expected = { + count: 1, + isVisual: false, + isDelete: false, + }; + + t.calledWith(movePrevious, [expected], 'should call movePrevious'); + t.end(); +}); diff --git a/client/listeners/get-index.js b/client/listeners/get-index.js index d7870608..45ce85e8 100644 --- a/client/listeners/get-index.js +++ b/client/listeners/get-index.js @@ -1,11 +1,10 @@ -'use strict'; +import currify from 'currify'; -module.exports = (array, item) => { +export const getIndex = currify((array, item) => { const index = array.indexOf(item); if (!~index) return 0; return index; -}; - +}); diff --git a/test/client/listeners/get-index.js b/client/listeners/get-index.spec.js similarity index 65% rename from test/client/listeners/get-index.js rename to client/listeners/get-index.spec.js index 16dd6999..0380cdc1 100644 --- a/test/client/listeners/get-index.js +++ b/client/listeners/get-index.spec.js @@ -1,9 +1,5 @@ -'use strict'; - -const test = require('tape'); - -const dir = '../../../client/listeners'; -const getIndex = require(`${dir}/get-index`); +import test from 'supertape'; +import {getIndex} from './get-index.js'; test('cloudcmd: client: listeners: getIndex: not found', (t) => { const array = ['hello']; @@ -13,9 +9,11 @@ test('cloudcmd: client: listeners: getIndex: not found', (t) => { }); test('cloudcmd: client: listeners: getIndex: found', (t) => { - const array = ['hello', 'world']; + const array = [ + 'hello', + 'world', + ]; t.equal(getIndex(array, 'world'), 1, 'should return index'); t.end(); }); - diff --git a/client/listeners/get-range.js b/client/listeners/get-range.js index ef1ea0f8..839c2287 100644 --- a/client/listeners/get-range.js +++ b/client/listeners/get-range.js @@ -1,6 +1,4 @@ -'use strict'; - -module.exports = (indexFrom, indexTo, files) => { +export const getRange = (indexFrom, indexTo, files) => { if (indexFrom < indexTo) return files.slice(indexFrom, indexTo + 1); @@ -9,4 +7,3 @@ module.exports = (indexFrom, indexTo, files) => { return [files[indexFrom]]; }; - diff --git a/client/listeners/get-range.spec.js b/client/listeners/get-range.spec.js new file mode 100644 index 00000000..77c950f4 --- /dev/null +++ b/client/listeners/get-range.spec.js @@ -0,0 +1,52 @@ +import test from 'supertape'; +import {getRange} from './get-range.js'; + +test('cloudcmd: client: listeners: getRange: direct', (t) => { + const expected = [ + 'hello', + 'world', + ]; + + const files = [ + ...expected, + 'how', + 'come', + ]; + + const result = getRange(0, 1, files); + + t.deepEqual(result, expected, 'should return range'); + t.end(); +}); + +test('cloudcmd: client: listeners: getRange: reverse', (t) => { + const expected = [ + 'hello', + 'world', + ]; + + const files = [ + ...expected, + 'how', + 'come', + ]; + + const result = getRange(1, 0, files); + + t.deepEqual(result, expected, 'should return range'); + t.end(); +}); + +test('cloudcmd: client: listeners: getRange: one', (t) => { + const expected = ['hello']; + const files = [ + ...expected, + 'how', + 'come', + ]; + + const result = getRange(0, 0, files); + + t.deepEqual(result, expected, 'should return range'); + t.end(); +}); diff --git a/client/listeners/index.js b/client/listeners/index.js index aa1cc9ea..babc1e0d 100644 --- a/client/listeners/index.js +++ b/client/listeners/index.js @@ -1,35 +1,30 @@ /* global DOM, CloudCmd */ +import exec from 'execon'; +import itype from 'itype'; +import currify from 'currify'; +import {tryToCatch} from 'try-to-catch'; +import clipboard from '@cloudcmd/clipboard'; +import * as Events from '#dom/events'; +import {uploadFiles} from '#dom/upload-files'; +import {FS} from '#common/cloudfunc'; +import {getRange} from './get-range.js'; +import {getIndex} from './get-index.js'; -'use strict'; +const NBSP_REG = RegExp(String.fromCharCode(160), 'g'); +const SPACE = ' '; -const exec = require('execon'); -const itype = require('itype/legacy'); -const currify = require('currify/legacy'); -const getRange = require('./get-range'); - -const getIndex = currify(require('./get-index')); - -const uploadFiles = require('../dom/upload-files'); - -const { - FS, - apiURL -} = require('../../common/cloudfunc'); - -module.exports.init = () => { +export async function init() { contextMenu(); dragndrop(); unload(); pop(); resize(); - config(); header(); -}; - -CloudCmd.Listeners = module.exports; + await config(); +} const unselect = (event) => { - const isMac = /Mac/.test(window.navigator.platform); + const isMac = /Mac/.test(globalThis.navigator.platform); const { shiftKey, metaKey, @@ -43,31 +38,25 @@ const unselect = (event) => { }; const execAll = currify((funcs, event) => { - funcs.forEach((fn) => { + for (const fn of funcs) fn(event); - }); }); - -const Info = DOM.CurrentInfo; -const Storage = DOM.Storage; -const Events = DOM.Events; const EventsFiles = { mousedown: exec.with(execIfNotUL, setCurrentFileByEvent), - click: execAll([onClick, unselect]), + click: execAll([onClick, exec.with(execIfNotMobile, unselect)]), dragstart: exec.with(execIfNotUL, onDragStart), dblclick: exec.with(execIfNotUL, onDblClick), - touchstart: exec.with(execIfNotUL, onTouch) + touchstart: exec.with(execIfNotUL, onTouch), }; let EXT; function header() { const fm = DOM.getFM(); - const isDataset = (el) => el.dataset; - var isPanel = (el) => { + const isPanel = (el) => { return /^js-(left|right)$/.test(el.dataset.name); }; @@ -78,8 +67,7 @@ function header() { if (parent.dataset.name !== 'js-fm-header') return; - const name = (el.dataset.name || '') - .replace('js-', ''); + const name = (el.dataset.name || '').replace('js-', ''); if (!/^(name|size|date)$/.test(name)) return; @@ -100,44 +88,48 @@ function getPath(el, path = []) { return getPath(el.parentElement, path.concat(el)); } -function config() { - DOM.Files.get('config', (e, config) => { - const type = config && config.packer; - EXT = DOM.getPackerExt(type); - }); +async function config() { + const [, config] = await tryToCatch(DOM.Files.get, 'config'); + const type = config?.packer; + + EXT = DOM.getPackerExt(type); } -module.exports.initKeysPanel = () => { +export const initKeysPanel = () => { const keysElement = DOM.getById('js-keyspanel'); if (!keysElement) return; - Events.addClick(keysElement, ({target}) => { - const id = target.id; + Events.addClick(keysElement, (event) => { + const {target} = event; + const {id} = target; + const operation = (name) => { - const Operation = CloudCmd.Operation; - const fn = Operation.show.bind(null, name); + const {Operation} = CloudCmd; - return fn; + return Operation.show.bind(null, name); }; const clickFuncs = { - 'f1' : CloudCmd.Help.show, - 'f2' : DOM.renameCurrent, - 'f3' : CloudCmd.View.show, - 'f4' : CloudCmd.EditFile.show, - 'f5' : operation('copy'), - 'f6' : operation('move'), - 'f7' : DOM.promptNewDir, - 'f8' : operation('delete'), - 'f9' : CloudCmd.Menu.show, - 'f10' : CloudCmd.Config.show, - '~' : CloudCmd.Konsole.show, - 'shift~' : CloudCmd.Terminal.show, - 'contact' : CloudCmd.Contact.show, + 'f1': CloudCmd.Help.show, + 'f2': CloudCmd.UserMenu.show, + 'f3': CloudCmd.View.show, + 'f4': CloudCmd.EditFile.show, + 'f5': operation('copy'), + 'f6': operation('move'), + 'f7': DOM.promptNewDir, + 'f8': operation('delete'), + 'f9': () => { + event.stopPropagation(); + CloudCmd.Menu.show(); + }, + 'f10': CloudCmd.Config.show, + '~': CloudCmd.Konsole.show, + 'shift~': CloudCmd.Terminal.show, + 'contact': CloudCmd.Contact.show, }; - + exec(clickFuncs[id]); }); }; @@ -146,10 +138,10 @@ const getPanel = (side) => { if (!itype.string(side)) return side; - return DOM.getByDataName('js-' + side); + return DOM.getByDataName(`js-${side}`); }; -module.exports.setOnPanel = (side) => { +export const setOnPanel = (side) => { const panel = getPanel(side); const filesElement = DOM.getByDataName('js-files', panel); @@ -165,61 +157,71 @@ function getPathListener(panel) { } function isNoCurrent(panel) { + const Info = DOM.CurrentInfo; const infoPanel = Info.panel; - const namePanel = panel.getAttribute('data-name'); - const nameInfoPanel = infoPanel.getAttribute('data-name'); - - if (namePanel !== nameInfoPanel) + + if (!infoPanel) return true; - return false; + const namePanel = panel.getAttribute('data-name'); + const nameInfoPanel = infoPanel.getAttribute('data-name'); + + return namePanel !== nameInfoPanel; } -function onPathElementClick(panel, event) { - let link, href, url, noCurrent; +function decodePath(path) { + const url = CloudCmd.HOST; + const {prefix} = CloudCmd; + const prefixReg = RegExp('^' + prefix + FS); + + return decodeURI(path) + .replace(url, '') + .replace(prefixReg, '') // browser doesn't replace % -> %25% do it for him + .replace('%%', '%25%') + .replace(NBSP_REG, SPACE) || '/'; +} + +async function onPathElementClick(panel, event) { + const Info = DOM.CurrentInfo; + event.preventDefault(); - const prefix = CloudCmd.PREFIX; const element = event.target; const attr = element.getAttribute('data-name'); + const noCurrent = isNoCurrent(panel); - switch (attr) { - case 'js-clear-storage': - Storage.clear(); - break; + if (attr === 'js-copy-path') + return copyPath(element); - case 'js-refresh': - noCurrent = isNoCurrent(panel); - - CloudCmd.refresh({ + if (attr === 'js-refresh') + return CloudCmd.refresh({ panel, - noCurrent + noCurrent, }); - - event.preventDefault(); - break; - case 'js-path-link': - url = CloudCmd.HOST; - href = element.href; - link = href.replace(url, ''); - /** - * browser doesn't replace % -> %25% - * do it for him - */ - link = link.replace('%%', '%25%'); - link = decodeURI(link); - link = link.replace(RegExp('^' + prefix + FS), '') || '/'; - - noCurrent = isNoCurrent(panel); - - CloudCmd.loadDir({ - path : link, - isRefresh : false, - panel : noCurrent ? panel : Info.panel - }); - - event.preventDefault(); - } + if (attr !== 'js-path-link') + return; + + const {href} = element; + const path = decodePath(href); + + await CloudCmd.changeDir(path, { + isRefresh: false, + panel: noCurrent ? panel : Info.panel, + }); +} + +function copyPath(el) { + clipboard + .writeText(el.parentElement.title) + .then(CloudCmd.log) + .catch(CloudCmd.log); +} + +function execIfNotMobile(callback, event) { + const isMobile = DOM.getCSSVar('is-mobile'); + + if (!isMobile) + callback(event); } function execIfNotUL(callback, event) { @@ -231,30 +233,27 @@ function execIfNotUL(callback, event) { } function onClick(event) { - const ctrl = event.ctrlKey; - - if (!ctrl) - event.preventDefault(); - + event.preventDefault(); changePanel(event.target); } function toggleSelect(key, files) { - const isMac = /Mac/.test(window.navigator.platform); + const isMac = /Mac/.test(globalThis.navigator.platform); if (!key) throw Error('key should not be undefined!'); const [file] = files; - if (isMac && key.meta || key.ctrl) + if (isMac && key.meta) return DOM.toggleSelectedFile(file); if (key.shift) - return files.forEach(DOM.selectFile); + return files.map(DOM.selectFile); } function changePanel(element) { + const Info = DOM.CurrentInfo; const {panel} = Info; const files = DOM.getByDataName('js-files', panel); const ul = getULElement(element); @@ -263,21 +262,20 @@ function changePanel(element) { DOM.changePanel(); } -function onDblClick(event) { +async function onDblClick(event) { + event.preventDefault(); + const current = getLIElement(event.target); const isDir = DOM.isCurrentIsDir(current); const path = DOM.getCurrentPath(current); - if (isDir) { - CloudCmd.loadDir({ - path: path === '/' ? '/' : path + '/' - }); - - event.preventDefault(); - } + if (!isDir) + return CloudCmd.View.show(); + + await CloudCmd.changeDir(path); } -function onTouch(event) { +async function onTouch(event) { const current = getLIElement(event.target); const isDir = DOM.isCurrentIsDir(current); @@ -289,20 +287,18 @@ function onTouch(event) { if (!isCurrent) return; - CloudCmd.loadDir({ - path: DOM.getCurrentPath(current) - }); - - event.preventDefault(); + await CloudCmd.changeDir(DOM.getCurrentPath(current)); } - /* +/* * download file from browser to desktop * in Chrome (HTML5) */ function onDragStart(event) { + const Info = DOM.CurrentInfo; + const {prefixURL} = CloudCmd; const element = getLIElement(event.target); - const isDir = Info.isDir; + const {isDir} = Info; let link = DOM.getCurrentLink(element); let name = DOM.getCurrentName(element); @@ -311,13 +307,15 @@ function onDragStart(event) { name += EXT; link = document.createElement('a'); link.textContent = name; - link.href = apiURL + '/pack' + Info.path + EXT; + link.href = prefixURL + '/pack' + Info.path + EXT; } - event.dataTransfer.setData('DownloadURL', - 'application/octet-stream' + ':' + - name + ':' + - link); + event.dataTransfer.setData( + 'DownloadURL', + 'application/octet-stream' + ':' + name + + ':' + + link, + ); } function getLIElement(element) { @@ -338,13 +336,14 @@ function getULElement(element) { } function setCurrentFileByEvent(event) { + const Info = DOM.CurrentInfo; const BUTTON_LEFT = 0; const key = { alt: event.altKey, ctrl: event.ctrlKey, meta: event.metaKey, - shift: event.shiftKey + shift: event.shiftKey, }; const element = getLIElement(event.target); @@ -381,7 +380,7 @@ function contextMenu() { Events.addOnce('contextmenu', fm, (event) => { CloudCmd.Menu.show({ x: event.clientX, - y: event.clientY + y: event.clientY, }); }); @@ -392,21 +391,17 @@ function contextMenu() { function dragndrop() { const panels = DOM.getByClassAll('panel'); - const select = () => { - [...panels].forEach((panel) => { - panel.classList.add('selected-panel'); - }); + const select = ({target}) => { + target.classList.add('selected-panel'); }; - const unselect = () => { - [...panels].forEach((panel) => { - panel.classList.remove('selected-panel'); - }); + const unselect = ({target}) => { + target.classList.remove('selected-panel'); }; const onDrop = (event) => { - const files = event.dataTransfer.files; - const items = event.dataTransfer.items; + const {files, items} = event.dataTransfer; + const {length: filesCount} = files; event.preventDefault(); @@ -415,22 +410,28 @@ function dragndrop() { return uploadFiles(files); const isFile = (item) => item.kind === 'file'; - const dirFiles = [...items].filter(isFile); + + const dirFiles = Array + .from(items) + .filter(isFile); if (dirFiles.length) return DOM.uploadDirectory(dirFiles); - return CloudCmd.Operation.show('copy'); + const {Operation} = CloudCmd; + const operation = event.shiftKey ? 'move' : 'copy'; + + return Operation.show(operation); }; /** - * In Mac OS Chrome dropEffect = 'none' + * In macOS Chrome dropEffect = 'none' * so drop do not firing up when try * to upload file from download bar */ const onDragOver = (event) => { - const dataTransfer = event.dataTransfer; - const effectAllowed = dataTransfer.effectAllowed; + const {dataTransfer} = event; + const {effectAllowed} = dataTransfer; if (/move|linkMove/.test(effectAllowed)) dataTransfer.dropEffect = 'move'; @@ -440,19 +441,18 @@ function dragndrop() { event.preventDefault(); }; - Events.add('dragenter', select); - Events.add(['dragleave', 'drop'], unselect); - - [...panels].forEach((panel) => { - Events.add('dragover', panel, onDragOver) - .add('drop', panel, onDrop); - }); + for (const panel of panels) + Events + .add('dragover', panel, onDragOver) + .add('drop', panel, onDrop) + .add('dragenter', select) + .add(['dragleave', 'drop'], unselect); } function unload() { - DOM.Events.add(['unload', 'beforeunload'], (event) => { - const Key = CloudCmd.Key; - const isBind = Key && Key.isBind(); + Events.add(['unload', 'beforeunload'], (event) => { + const {Key} = CloudCmd; + const isBind = Key?.isBind(); if (isBind) return; @@ -463,15 +463,15 @@ function unload() { } function pop() { - Events.add('popstate', (event) => { - const path = event.state.replace(FS, ''); + Events.add('popstate', async ({state}) => { + const path = (state || '').replace(FS, ''); if (!path) return CloudCmd.route(location.hash); const history = false; - CloudCmd.loadDir({ - path, + + await CloudCmd.changeDir(path, { history, }); }); @@ -479,7 +479,8 @@ function pop() { function 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) return; @@ -499,4 +500,3 @@ function resize() { DOM.changePanel(); }); } - diff --git a/client/load-module.js b/client/load-module.js new file mode 100644 index 00000000..7fc2c328 --- /dev/null +++ b/client/load-module.js @@ -0,0 +1,56 @@ +/* global CloudCmd */ +import exec from 'execon'; +import {tryToCatch} from 'try-to-catch'; +import {js as loadJS} from 'load.js'; +import pascalCase from 'just-pascal-case'; + +const noJS = (a) => a.replace(/.js$/, ''); + +/** + * function load modules + * @params = {name, path, func, dobefore, arg} + */ +export const loadModule = (params) => { + if (!params) + return; + + const {path} = params; + + const name = path && noJS(pascalCase(path)); + const doBefore = params.dobefore; + + if (CloudCmd[name]) + return; + + CloudCmd[name] = async () => { + exec(doBefore); + + const {DIR_MODULES} = CloudCmd; + const pathFull = `${DIR_MODULES}/${path}.js`; + + await loadJS(pathFull); + const newModule = async (f) => f && f(); + const module = CloudCmd[name]; + + Object.assign(newModule, module); + + CloudCmd[name] = newModule; + CloudCmd.log('init', name); + + await module.init(); + + return newModule; + }; + + CloudCmd[name].show = async (...args) => { + CloudCmd.log('show', name, args); + const m = CloudCmd[name]; + + const [e, a] = await tryToCatch(m); + + if (e) + return; + + return await a.show(...args); + }; +}; diff --git a/client/modules/cloud.js b/client/modules/cloud.js index f4879b5a..cfe0d708 100644 --- a/client/modules/cloud.js +++ b/client/modules/cloud.js @@ -1,66 +1,64 @@ /* global CloudCmd, filepicker */ +import exec from 'execon'; +import currify from 'currify'; +import load from 'load.js'; +import {ajax} from '#dom/load'; +import * as Files from '#dom/files'; +import * as Images from '#dom/images'; -'use strict'; +const {log} = CloudCmd; -CloudCmd.Cloud = CloudProto; +const upload = currify(_upload); -const exec = require('execon'); +const Name = 'Cloud'; -const load = require('../dom/load'); -const Files = require('../dom/files'); -const Images = require('../dom/images'); -const Util = require('../../common/util'); +CloudCmd[Name] = { + init, + uploadFile, + saveFile, +}; -function CloudProto(callback) { - exec.series([ - loadFiles, - callback, - ]); +export async function init() { + const [modules] = await loadFiles(); + const {key} = modules.data.FilePicker; - return module.exports; + filepicker.setKey(key); + Images.hide(); } -module.exports.uploadFile = (filename, data) => { - const {log} = CloudCmd; +export function uploadFile(filename, data) { const mimetype = ''; filepicker.store(data, { mimetype, filename, }, (fpFile) => { - log(fpFile); filepicker.exportFile(fpFile, log, log); }); -}; - -module.exports.saveFile = (callback) => { - filepicker.pick((fpFile) => { - CloudCmd.log(fpFile); - const {url} = fpFile; - const responseType = 'arraybuffer'; - const success = exec.with(callback, fpFile.filename); - - load.ajax({ - url, - responseType, - success, - }); - }); -}; - -function loadFiles(callback) { - Util.time('filepicker load'); - - load.js('//api.filepicker.io/v1/filepicker.js', () => { - Files.get('modules', (error, modules) => { - const {key} = modules.data.FilePicker; - - filepicker.setKey(key); - - Images.hide(); - Util.timeEnd('filepicker loaded'); - exec(callback); - }); - }); } +export function saveFile(callback) { + filepicker.pick(upload(callback)); +} + +function _upload(callback, file) { + const {url, filename} = file; + + const responseType = 'arraybuffer'; + const success = exec.with(callback, filename); + + ajax({ + url, + responseType, + success, + }); +} + +function loadFiles() { + const js = '//api.filepicker.io/v2/filepicker.js'; + + return Promise.all([ + Files.get('modules'), + load.js(js), + ]); +} diff --git a/client/modules/command-line.js b/client/modules/command-line.js new file mode 100644 index 00000000..7a1c3993 --- /dev/null +++ b/client/modules/command-line.js @@ -0,0 +1,31 @@ +/* global CloudCmd */ +import * as Dialog from '#dom/dialog'; + +export function init() {} +CloudCmd.CommandLine = { + init, + show, + hide, +}; + +export async function show() { + const [, cmd] = await Dialog.prompt('Command Line', ''); + const TERMINAL = '^(t|terminal)'; + + if (RegExp(`${TERMINAL}$`).test(cmd)) + return await CloudCmd.Terminal.show(); + + if (RegExp(TERMINAL).test(cmd)) { + const command = cmd.replace(RegExp(`${TERMINAL} `), ''); + const exitCode = await CloudCmd.TerminalRun.show({ + command: `bash -c '${command}'`, + }); + + if (exitCode === -1) + await Dialog.alert(`☝️ Looks like Terminal is disabled, start Cloud Coammnder with '--terminal' flag.`); + + return; + } +} + +export function hide() {} diff --git a/client/modules/config.js b/client/modules/config.js deleted file mode 100644 index 47214f5d..00000000 --- a/client/modules/config.js +++ /dev/null @@ -1,295 +0,0 @@ -'use strict'; - -/* global CloudCmd, DOM, io */ - -const rendy = require('rendy'); -const exec = require('execon'); -const currify = require('currify/legacy'); -const input = require('../input'); - -const Images = require('../dom/images'); -const Events = require('../dom/events'); -const Files = require('../dom/files'); - -const {Dialog} = DOM; - -const TITLE = 'Config'; -const alert = currify(Dialog.alert, TITLE); - -const Config = module.exports; - -const showLoad = () => { - Images.show.load('top'); -}; - -CloudCmd.Config = ConfigProto; - -let Loading = true; - -function ConfigProto() { - if (!CloudCmd.config('configDialog')) - return; - - Loading = true; - - showLoad(); - exec.series([ - CloudCmd.View, - (callback) => { - Loading = false; - exec(callback); - DOM.loadSocket(initSocket); - }, - show - ]); - - return module.exports; -} - -const config = CloudCmd.config; - -const {Key} = CloudCmd; - -let Element; -let Template; - -function getHost() { - const {host, origin, protocol} = location; - const href = origin || `${protocol}//${host}`; - - return href; -} - -function initSocket(error) { - const href = getHost(); - const prefix = CloudCmd.PREFIX; - const FIVE_SECONDS = 5000; - - const socket = io.connect(href + prefix + '/config', { - 'max reconnection attempts' : Math.pow(2, 32), - 'reconnection limit' : FIVE_SECONDS, - path: prefix + '/socket.io' - }); - - const save = (data) => { - onSave(data); - socket.send(data); - }; - - if (error) - return; - - authCheck(socket); - - socket.on('connect', () => { - Config.save = save; - }); - - socket.on('config', (config) => { - DOM.Storage.setAllowed(config.localStorage); - }); - - socket.on('message', onSave); - socket.on('log', CloudCmd.log); - - socket.on('disconnect', () => { - Config.save = saveHttp; - }); - - socket.on('err', alert); -} - -function authCheck(socket) { - if (!config('auth')) - return; - - socket.emit('auth', config('username'), config('password')); - - socket.on('reject', () => { - alert('Wrong credentials!'); - }); -} - -Config.save = saveHttp; - -module.exports.show = show; - -function show() { - const prefix = CloudCmd.PREFIX; - const funcs = [ - exec.with(Files.get, 'config-tmpl'), - exec.with(DOM.load.parallel, [ - prefix + '/css/config.css' - ]) - ]; - - if (Loading) - return; - - showLoad(); - exec.parallel(funcs, fillTemplate); -} - -function fillTemplate(error, template) { - if (!Template) - Template = template; - - Files.get('config', (error, config) => { - if (error) - return alert('Could not load config!'); - - const obj = input.convert(config); - - obj[obj.editor + '-selected'] = 'selected'; - delete obj.editor; - - obj[obj.packer + '-selected'] = 'selected'; - delete obj.packer; - - const inner = rendy(Template, obj); - - Element = DOM.load({ - name : 'div', - className : 'config', - inner, - attribute : { - 'data-name': 'js-config' - } - }); - - const inputs = document.querySelectorAll('input, select', Element); - const inputFirst = inputs[0]; - - let afterShow; - if (inputFirst) { - onAuthChange(inputFirst.checked); - - afterShow = () => { - inputFirst.focus(); - }; - } - - [...inputs].forEach((input) => { - Events.addKey(input, onKey) - .add('change', input, ({target}) => { - onChange(target); - }); - }); - - const autoSize = true; - CloudCmd.View.show(Element, { - autoSize, - afterShow, - }); - }); -} - -module.exports.hide = () => { - CloudCmd.View.hide(); -}; - -function onChange(el) { - const obj = {}; - const name = input.getName(el); - const data = input.getValue(name, Element); - const type = el.type; - - if (type === 'checkbox') - if (/^(diff|buffer|dirStorage)$/.test(name)) - onLSChange(name, data); - else if (name === 'localStorage') - onLocalStorageChange(); - else if (name === 'auth') - onAuthChange(data); - - obj[name] = data; - - Config.save(obj); -} - -function onSave(obj) { - Object.keys(obj).forEach((name) => { - const data = obj[name]; - - CloudCmd._config(name, data); - input.setValue(name, data, Element); - }); - - DOM.Storage.setAllowed(obj.localStorage); -} - -function saveHttp(obj) { - const {RESTful} = DOM; - - RESTful.Config.write(obj, (error) => { - if (error) - return; - - onSave(obj); - }); -} - -function onLocalStorageChange() { - const names = ['diff', 'buffer', 'dirStorage', 'localStorage']; - const elements = names.map((name) => { - return input.getElementByName(name, Element); - }); - const el = {}; - const msg = 'Diff, Buffer and Directory Storage do not work without localStorage'; - - let isChecked; - - elements.forEach((element) => { - const name = input.getName(element); - - el[name] = element; - - if (element.checked) - isChecked = true; - }); - - if (!isChecked || el.localStorage.checked) - return; - - alert(msg); - - elements.forEach((element) => { - if (!element.checked) - return; - - element.checked = false; - onChange(element); - }); -} - -function onLSChange(name, data) { - const elLocalStorage = input.getElementByName('localStorage', Element); - const msg = `${name} depends on localStorage`; - - if (!data || elLocalStorage.checked) - return; - - Dialog.alert(TITLE, msg); - elLocalStorage.checked = true; -} - -function onAuthChange(checked) { - const elUsername = input.getElementByName('username', Element); - const elPassword = input.getElementByName('password', Element); - - elUsername.disabled = - elPassword.disabled = !checked; -} - -function onKey({keyCode, target}) { - switch (keyCode) { - case Key.ESC: - Config.hide(); - break; - - case Key.ENTER: - onChange(target); - break; - } -} - diff --git a/client/modules/config/index.js b/client/modules/config/index.js new file mode 100644 index 00000000..dfa4c105 --- /dev/null +++ b/client/modules/config/index.js @@ -0,0 +1,247 @@ +import '../../../css/config.css'; +import {rendy} from 'rendy'; +import currify from 'currify'; +import wraptile from 'wraptile'; +import squad from 'squad'; +import {promisify} from 'es6-promisify'; +import {tryToCatch} from 'try-to-catch'; +import load from 'load.js'; +import createElement from '@cloudcmd/create-element'; +import * as Events from '#dom/events'; +import * as Files from '#dom/files'; +import {getTitle} from '#common/cloudfunc'; +import * as Images from '#dom/images'; +import * as input from './input.js'; + +const {CloudCmd, DOM} = globalThis; + +const {Dialog, setTitle} = DOM; + +const Name = 'Config'; + +const loadSocket = promisify(DOM.loadSocket); + +const showLoad = () => { + Images.show.load('top'); +}; + +const addKey = currify((fn, input) => { + Events.addKey(input, fn); + return input; +}); + +const addChange = currify((fn, input) => { + Events.add('change', input, fn); + return input; +}); + +const Config = {}; + +let Template; + +const loadCSS = load.css; + +export async function init() { + if (!CloudCmd.config('configDialog')) + return; + + showLoad(); + + const {DIR_DIST} = CloudCmd; + + [Template] = await Promise.all([ + Files.get('config-tmpl'), + loadSocket(), + loadCSS(`${DIR_DIST}/config.css`), + CloudCmd.View(), + ]); + + initSocket(); +} + +const {config, Key} = CloudCmd; + +let Element; + +function getHost() { + const { + host, + origin, + protocol, + } = location; + + return origin || `${protocol}//${host}`; +} + +function initSocket() { + const href = getHost(); + const {prefixSocket, prefix} = CloudCmd; + + const ONE_MINUTE = 60 * 1000; + + const socket = globalThis.io.connect(href + prefixSocket + '/config', { + reconnectionAttempts: Infinity, + reconnectionDelay: ONE_MINUTE, + path: `${prefix}/socket.io`, + }); + + const save = (data) => { + onSave(data); + socket.send(data); + }; + + authCheck(socket); + + socket.on('connect', () => { + Config.save = save; + }); + + socket.on('message', onSave); + socket.on('log', CloudCmd.log); + + socket.on('disconnect', () => { + Config.save = saveHttp; + }); + + socket.on('err', Dialog.alert); +} + +function authCheck(socket) { + socket.emit('auth', config('username'), config('password')); + socket.on('reject', wraptile(Dialog.alert, 'Wrong credentials!')); +} + +Config.save = saveHttp; + +export async function show() { + if (!CloudCmd.config('configDialog')) + return; + + await fillTemplate(); +} + +async function fillTemplate() { + const [error, config] = await tryToCatch(Files.get, 'config'); + + if (error) + return Dialog.alert('Could not load config!'); + + const { + editor, + menu, + packer, + columns, + theme, + configAuth, + configPort, + ...obj + } = input.convert(config); + + obj[`${menu}-selected`] = 'selected'; + obj[`${editor}-selected`] = 'selected'; + obj[`${packer}-selected`] = 'selected'; + obj[`${columns}-selected`] = 'selected'; + obj[`${theme}-selected`] = 'selected'; + obj.configAuth = configAuth ? '' : 'hidden'; + obj.configPort = configPort ? '' : 'hidden'; + + const innerHTML = rendy(Template, obj); + + Element = createElement('form', { + className: 'config', + innerHTML, + }); + + const inputs = document.querySelectorAll('input, select', Element); + const [inputFirst] = inputs; + + let afterShow; + + if (inputFirst) { + onAuthChange(inputFirst.checked); + afterShow = inputFirst.focus.bind(inputFirst); + } + + const getTarget = ({target}) => target; + const handleChange = squad(onChange, getTarget); + + Array + .from(inputs) + .map(addKey(onKey)) + .map(addChange(handleChange)); + + const autoSize = true; + + CloudCmd.View.show(Element, { + autoSize, + afterShow, + }); +} + +export function hide() { + CloudCmd.View.hide(); +} + +async function onChange(el) { + const obj = {}; + const name = input.getName(el); + const data = input.getValue(name, Element); + + if (name === 'name') + onNameChange(data); + else if (name === 'auth') + onAuthChange(data); + + obj[name] = data; + + await Config.save(obj); +} + +function onSave(obj) { + for (const name of Object.keys(obj)) { + const data = obj[name]; + + CloudCmd._config(name, data); + input.setValue(name, data, Element); + } +} + +async function saveHttp(obj) { + const {RESTful} = DOM; + const [e] = await RESTful.Config.write(obj); + + if (e) + return; + + onSave(obj); +} + +function onAuthChange(checked) { + const elUsername = input.getElementByName('username', Element); + const elPassword = input.getElementByName('password', Element); + + elUsername.disabled = !checked; + elPassword.disabled = !checked; +} + +function onNameChange(name) { + setTitle(getTitle({ + name, + })); +} + +async function onKey({keyCode, target}) { + switch(keyCode) { + case Key.ESC: + return hide(); + + case Key.ENTER: + return await onChange(target); + } +} + +CloudCmd[Name] = { + init, + show, + hide, +}; diff --git a/client/modules/config/input.js b/client/modules/config/input.js new file mode 100644 index 00000000..34a4be69 --- /dev/null +++ b/client/modules/config/input.js @@ -0,0 +1,78 @@ +import {encode} from '#common/entity'; + +const isBool = (a) => typeof a === 'boolean'; +const isString = (a) => typeof a === 'string'; + +const {keys} = Object; + +export function getElementByName(selector, element) { + const str = `[data-name="js-${selector}"]`; + + return element.querySelector(str); +} + +export const getName = (element) => { + const name = element + .getAttribute('data-name') + .replace(/^js-/, ''); + + return name; +}; + +export const convert = (config) => { + const result = config; + + for (const name of keys(config)) { + const item = config[name]; + + if (isBool(item)) { + result[name] = setState(item); + continue; + } + + if (isString(item)) { + result[name] = encode(item); + continue; + } + } + + return result; +}; + +function setState(state) { + if (state) + return ' checked'; + + return ''; +} + +export const getValue = (name, element) => { + const el = getElementByName(name, element); + const {type} = el; + + switch(type) { + case 'checkbox': + return el.checked; + + case 'number': + return Number(el.value); + + default: + return el.value; + } +}; + +export const setValue = (name, value, element) => { + const el = getElementByName(name, element); + const {type} = el; + + switch(type) { + case 'checkbox': + el.checked = value; + break; + + default: + el.value = value; + break; + } +}; diff --git a/client/modules/config/input.spec.js b/client/modules/config/input.spec.js new file mode 100644 index 00000000..9d0866cd --- /dev/null +++ b/client/modules/config/input.spec.js @@ -0,0 +1,140 @@ +import {test, stub} from 'supertape'; +import { + convert, + getName, + getValue, + setValue, +} from './input.js'; + +test('cloudcmd: client: config: input: convert', (t) => { + const result = convert({ + name: 'hello ', + }); + + const expected = { + name: 'hello <world>', + }; + + t.deepEqual(result, expected); + t.end(); +}); + +test('cloudcmd: client: config: input: convert: bool', (t) => { + const result = convert({ + auth: true, + }); + + const expected = { + auth: ' checked', + }; + + t.deepEqual(result, expected); + t.end(); +}); + +test('cloudcmd: client: config: input: convert: bool false', (t) => { + const result = convert({ + auth: false, + }); + + const expected = { + auth: '', + }; + + t.deepEqual(result, expected); + t.end(); +}); + +test('cloudcmd: client: config: input: getName', (t) => { + const getAttribute = stub().returns('js-hello'); + const element = { + getAttribute, + }; + + const result = getName(element); + + t.equal(result, 'hello', 'should strip js- prefix'); + t.end(); +}); + +test('cloudcmd: client: config: input: getValue: checkbox', (t) => { + const querySelector = stub().returns({ + type: 'checkbox', + checked: true, + }); + + const element = { + querySelector, + }; + + const result = getValue('auth', element); + + t.ok(result, 'should return checked value'); + t.end(); +}); + +test('cloudcmd: client: config: input: getValue: number', (t) => { + const querySelector = stub().returns({ + type: 'number', + value: '42', + }); + + const element = { + querySelector, + }; + + const result = getValue('port', element); + + t.equal(result, 42, 'should return number'); + t.end(); +}); + +test('cloudcmd: client: config: input: getValue: default', (t) => { + const querySelector = stub().returns({ + type: 'text', + value: 'hello', + }); + + const element = { + querySelector, + }; + + const result = getValue('name', element); + + t.equal(result, 'hello', 'should return value as is'); + t.end(); +}); + +test('cloudcmd: client: config: input: setValue: checkbox', (t) => { + const el = { + type: 'checkbox', + checked: false, + }; + + const querySelector = stub().returns(el); + const element = { + querySelector, + }; + + setValue('auth', true, element); + + t.ok(el.checked, 'should set checked'); + t.end(); +}); + +test('cloudcmd: client: config: input: setValue: default', (t) => { + const el = { + type: 'text', + value: 'old', + }; + + const querySelector = stub().returns(el); + const element = { + querySelector, + }; + + setValue('name', 'new', element); + + t.equal(el.value, 'new', 'should set value'); + t.end(); +}); diff --git a/client/modules/contact.js b/client/modules/contact.js index 4e7bb89d..48c7bd19 100644 --- a/client/modules/contact.js +++ b/client/modules/contact.js @@ -1,66 +1,34 @@ /* global CloudCmd */ /* global DOM */ -/* global olark */ +import olark from '@cloudcmd/olark'; +import * as Images from '#dom/images'; -'use strict'; +CloudCmd.Contact = { + init, + show, + hide, +}; -CloudCmd.Contact = ContactProto; +const {Events} = DOM; +const {Key} = CloudCmd; -const exec = require('execon'); -const Images = require('../dom/images'); - -function ContactProto(callback) { - init(callback); - - return exports; -} - -const Events = DOM.Events; -const Key = CloudCmd.Key; - -module.exports.show = show; -module.exports.hide = hide; - -let Inited = false; - -function init(callback) { - if (Inited) - return; - - load(() => { - Inited = true; - - olark.identify('6216-545-10-4223'); - olark('api.box.onExpand', show); - olark('api.box.onShow', show); - olark('api.box.onShrink', hide); - - exec(callback); - }); - +export function init() { Events.addKey(onKey); + + olark.identify('6216-545-10-4223'); + olark('api.box.onExpand', show); + olark('api.box.onShow', show); + olark('api.box.onShrink', hide); } -function load(callback) { - const {PREFIX} = CloudCmd; - const path = `${PREFIX}/modules/olark/olark.min.js`; - - Images.show.load('top'); - - DOM.load.js(path, callback); -} - -function show() { +export function show() { Key.unsetBind(); Images.hide(); - if (Inited) - return olark('api.box.expand'); - - init(show); + olark('api.box.expand'); } -function hide() { +export function hide() { Key.setBind(); olark('api.box.hide'); } @@ -69,4 +37,3 @@ function onKey({keyCode}) { if (keyCode === Key.ESC) hide(); } - diff --git a/client/modules/edit-file-vim.js b/client/modules/edit-file-vim.js index 6b598d57..16d557ae 100644 --- a/client/modules/edit-file-vim.js +++ b/client/modules/edit-file-vim.js @@ -1,210 +1,46 @@ -'use strict'; +import * as Events from '#dom/events'; -/* global CloudCmd, DOM, MenuIO */ +const {CloudCmd} = globalThis; -const Format = require('format-io'); -const currify = require('currify/legacy'); -const squad = require('squad'); -const store = require('../../common/store'); -const Key = CloudCmd.Key; - -const Events = require('../dom/events'); - -const call = currify((fn, callback) => { - fn(); - callback(); -}); - -CloudCmd.EditFileVim = function EditFileVimProto(callback) { - const Info = DOM.CurrentInfo; - const Dialog = DOM.Dialog; - const EditFileVim = this; - const config = CloudCmd.config; - - let Menu; - - const exec = require('execon'); - const TITLE = 'Edit'; - const Images = DOM.Images; - - let MSG_CHANGED; - const ConfigView = { - bindKeys: false, - beforeClose: () => { - Events.rmKey(listener); - exec.ifExist(Menu, 'hide'); - isChanged(); - } - }; - - function init(callback) { - const editor = store(); - - const getMainEditor = () => CloudCmd.Edit.getEditor(); - const getEditor = squad(editor, getMainEditor); - const auth = squad(authCheck, editor); - const listeners = squad(setListeners, editor); - - exec.series([ - CloudCmd.Edit, - call(getEditor), - call(auth), - call(listeners), - EditFileVim.show, - ], callback); - } - - function getName() { - const {name, isDir} = Info; - - if (isDir) - return `${name}.json`; - - return name; - } - - this.show = () => { - Images.show.load(); - - Info.getData((error, data) => { - const path = Info.path; - const name = getName(); - - if (error) - return Images.hide(); - - setMsgChanged(name); - - Events.addKey(listener); - - CloudCmd.Edit - .show(ConfigView) - .getEditor() - .setValueFirst(path, data) - .setModeForPath(name) - .enableKey() - .setOptions({ - keyMap: 'vim' - }); - }); - }; - - this.hide = () => { - CloudCmd.Edit.hide(); - }; - - function setListeners(editor) { - const element = CloudCmd.Edit.getElement(); - - Events.addOnce('contextmenu', element, setMenu); - - editor.on('save', (value) => { - DOM.setCurrentSize(Format.size(value)); - }); - } - - function authCheck(spawn) { - if (!config('auth')) - return; - - spawn.emit('auth', config('username'), config('password')); - spawn.on('reject', () => { - Dialog.alert(TITLE, 'Wrong credentials!'); - }); - } - - function setMenu(event) { - const position = { - x: event.clientX, - y: event.clientY - }; - - event.preventDefault(); - - !Menu && DOM.loadRemote('menu', (error) => { - let noFocus; - const editor = CloudCmd.Edit.getEditor(); - const options = { - beforeShow: (params) => { - params.x -= 18; - params.y -= 27; - }, - - afterClick: () => { - !noFocus && editor.focus(); - } - }; - - const menuData = { - 'Save Ctrl+S' : () => { - editor.save(); - }, - 'Go To Line Ctrl+G' : () => { - noFocus = true; - editor.goToLine(); - }, - 'Cut Ctrl+X' : () => { - editor.cutToClipboard(); - }, - 'Copy Ctrl+C' : () => { - editor.copyToClipboard(); - }, - 'Paste Ctrl+V' : () => { - editor.pasteFromClipboard(); - }, - 'Delete Del' : () => { - editor.remove('right'); - }, - 'Select All Ctrl+A' : () => { - editor.selectAll(); - }, - 'Beautify Ctrl+B' : () => { - editor.beautify(); - }, - 'Minify Ctrl+M' : () => { - editor.minify(); - }, - 'Close Esc' : () => { - EditFileVim.hide(); - } - }; - - if (error) - return Dialog.alert(TITLE, error); - - if (Menu || !MenuIO) - return; - - const element = CloudCmd.Edit.getElement(); - - Menu = new MenuIO(element, options, menuData); - Menu.show(position.x, position.y); - }); - } - - function setMsgChanged(name) { - MSG_CHANGED = 'Do you want to save changes to ' + name + '?'; - } - - function isChanged() { - const editor = CloudCmd.Edit.getEditor(); - const is = editor.isChanged(); - - if (!is) - return; - - const cancel = false; - Dialog.confirm(TITLE, MSG_CHANGED, {cancel}) - .then(() => { - editor.save(); - }); - } - - function listener({keyCode, shiftKey}) { - if (shiftKey && keyCode === Key.ESC) - EditFileVim.hide(); - } - - init(callback); +CloudCmd.EditFileVim = { + init, + show, + hide, }; +const {Key} = CloudCmd; + +const ConfigView = { + bindKeys: false, + beforeClose: () => { + Events.rmKey(listener); + CloudCmd.EditFile.isChanged(); + }, +}; + +export async function init() { + await CloudCmd.EditFile(); +} + +export async function show() { + Events.addKey(listener); + + const editFile = await CloudCmd.EditFile.show(ConfigView); + + editFile + .getEditor() + .setKeyMap('vim'); +} + +export function hide() { + CloudCmd.Edit.hide(); +} + +function listener(event) { + const {keyCode, shiftKey} = event; + + if (shiftKey && keyCode === Key.ESC) { + event.preventDefault(); + hide(); + } +} diff --git a/client/modules/edit-file.js b/client/modules/edit-file.js index 97b68f25..83a07e36 100644 --- a/client/modules/edit-file.js +++ b/client/modules/edit-file.js @@ -1,195 +1,193 @@ -'use strict'; +/* global CloudCmd, DOM*/ +import Format from 'format-io'; +import {fullstore} from 'fullstore'; +import exec from 'execon'; +import {supermenu} from 'supermenu'; -/* global CloudCmd, DOM, MenuIO */ - -const Format = require('format-io'); -const currify = require('currify/legacy'); -const squad = require('squad'); -const store = require('../../common/store'); - -const call = currify((fn, callback) => { - fn(); - callback(); -}); - -CloudCmd.EditFile = function EditFileProto(callback) { - const Info = DOM.CurrentInfo; - const Dialog = DOM.Dialog; - const EditFile = this; - const config = CloudCmd.config; - - let Menu; - - const exec = require('execon'); - const TITLE = 'Edit'; - const Images = DOM.Images; - - let MSG_CHANGED; - const ConfigView = { - beforeClose: () => { - exec.ifExist(Menu, 'hide'); - isChanged(); - } - }; - - function init(callback) { - const editor = store(); - - const getMainEditor = () => CloudCmd.Edit.getEditor(); - const getEditor = squad(editor, getMainEditor); - const auth = squad(authCheck, editor); - const listeners = squad(setListeners, editor); - - exec.series([ - CloudCmd.Edit, - call(getEditor), - call(auth), - call(listeners), - EditFile.show, - ], callback); - } - - function getName() { - const {name, isDir} = Info; - - if (isDir) - return `${name}.json`; - - return name; - } - - this.show = () => { - Images.show.load(); - - Info.getData((error, data) => { - const path = Info.path; - const name = getName(); - - if (error) - return Images.hide(); - - setMsgChanged(name); - - CloudCmd.Edit - .show(ConfigView) - .getEditor() - .setValueFirst(path, data) - .setModeForPath(name) - .enableKey(); - }); - }; - - this.hide = () => { - CloudCmd.Edit.hide(); - }; - - function setListeners(editor) { - const element = CloudCmd.Edit.getElement(); - - DOM.Events.addOnce('contextmenu', element, setMenu); - - editor.on('save', (value) => { - DOM.setCurrentSize(Format.size(value)); - }); - } - - function authCheck(spawn) { - if (!config('auth')) - return; - - spawn.emit('auth', config('username'), config('password')); - spawn.on('reject', () => { - Dialog.alert(TITLE, 'Wrong credentials!'); - }); - } - - function setMenu(event) { - const position = { - x: event.clientX, - y: event.clientY - }; - - event.preventDefault(); - - !Menu && DOM.loadRemote('menu', (error) => { - let noFocus; - const editor = CloudCmd.Edit.getEditor(); - const options = { - beforeShow: (params) => { - params.x -= 18; - params.y -= 27; - }, - - afterClick: () => { - !noFocus && editor.focus(); - } - }; - - const menuData = { - 'Save Ctrl+S' : () => { - editor.save(); - }, - 'Go To Line Ctrl+G' : () => { - noFocus = true; - editor.goToLine(); - }, - 'Cut Ctrl+X' : () => { - editor.cutToClipboard(); - }, - 'Copy Ctrl+C' : () => { - editor.copyToClipboard(); - }, - 'Paste Ctrl+V' : () => { - editor.pasteFromClipboard(); - }, - 'Delete Del' : () => { - editor.remove('right'); - }, - 'Select All Ctrl+A' : () => { - editor.selectAll(); - }, - 'Beautify Ctrl+B' : () => { - editor.beautify(); - }, - 'Minify Ctrl+M' : () => { - editor.minify(); - }, - 'Close Esc' : () => { - EditFile.hide(); - } - }; - - if (error) - return Dialog.alert(TITLE, error); - - if (Menu || !MenuIO) - return; - - const element = CloudCmd.Edit.getElement(); - - Menu = new MenuIO(element, options, menuData); - Menu.show(position.x, position.y); - }); - } - - function setMsgChanged(name) { - MSG_CHANGED = 'Do you want to save changes to ' + name + '?'; - } - - function isChanged() { - const editor = CloudCmd.Edit.getEditor(); - const is = editor.isChanged(); - - if (!is) - return; - - const cancel = false; - Dialog.confirm(TITLE, MSG_CHANGED, {cancel}) - .then(() => { - editor.save(); - }); - } - - init(callback); +CloudCmd.EditFile = { + init, + show, + hide, + isChanged, }; +const Info = DOM.CurrentInfo; + +const {Dialog, Images} = DOM; + +const {config} = CloudCmd; + +let Menu; +let MSG_CHANGED; + +const isLoading = fullstore(); + +const ConfigView = { + beforeClose: async () => { + exec.ifExist(Menu, 'hide'); + await isChanged(); + }, +}; + +export async function init() { + isLoading(true); + + await CloudCmd.Edit(); + + const editor = CloudCmd.Edit.getEditor(); + authCheck(editor); + setListeners(editor); + + isLoading(false); +} + +function getName() { + const {name, isDir} = Info; + + if (isDir) + return `${name}.json`; + + return name; +} + +export async function show(options) { + if (isLoading()) + return; + + const optionsEdit = { + ...ConfigView, + ...options, + }; + + if (CloudCmd.config('showFileName')) + optionsEdit.title = Info.name; + + Images.show.load(); + + CloudCmd.Edit + .getEditor() + .setOption('keyMap', 'default'); + + const [error, data] = await Info.getData(); + + if (error) { + Images.hide(); + return CloudCmd.Edit; + } + + const {path} = Info; + const name = getName(); + + setMsgChanged(name); + + CloudCmd.Edit + .getEditor() + .setValueFirst(path, data) + .setModeForPath(name) + .enableKey(); + + CloudCmd.Edit.show(optionsEdit); + + return CloudCmd.Edit; +} + +export function hide() { + CloudCmd.Edit.hide(); +} + +function setListeners(editor) { + const element = CloudCmd.Edit.getElement(); + + DOM.Events.addOnce('contextmenu', element, setMenu); + + editor.on('save', (value) => { + DOM.setCurrentSize(Format.size(value)); + }); +} + +function authCheck(spawn) { + spawn.emit('auth', config('username'), config('password')); + spawn.on('reject', () => { + Dialog.alert('Wrong credentials!'); + }); +} + +function setMenu(event) { + const position = { + x: event.clientX, + y: event.clientY, + }; + + event.preventDefault(); + + if (Menu) + return; + + const options = { + beforeShow: (params) => { + params.x -= 18; + params.y -= 27; + }, + + afterClick: () => { + CloudCmd.Edit + .getEditor() + .focus(); + }, + }; + + const element = CloudCmd.Edit.getElement(); + + Menu = supermenu(element, options, getMenuData()); + + Menu.addContextMenuListener(); + Menu.show(position.x, position.y); +} + +function getMenuData() { + const editor = CloudCmd.Edit.getEditor(); + + return { + 'Save Ctrl+S': () => { + editor.save(); + }, + 'Go To Line Ctrl+G': () => { + editor.goToLine(); + }, + 'Cut Ctrl+X': () => { + editor.cutToClipboard(); + }, + 'Copy Ctrl+C': () => { + editor.copyToClipboard(); + }, + 'Paste Ctrl+V': () => { + editor.pasteFromClipboard(); + }, + 'Delete Del': () => { + editor.remove('right'); + }, + 'Select All Ctrl+A': () => { + editor.selectAll(); + }, + 'Close Esc': hide, + }; +} + +function setMsgChanged(name) { + MSG_CHANGED = `Do you want to save changes to ${name}?`; +} + +export async function isChanged() { + const editor = CloudCmd.Edit.getEditor(); + const is = editor.isChanged(); + + if (!is) + return; + + const [cancel] = await Dialog.confirm(MSG_CHANGED); + + if (cancel) + return; + + editor.save(); +} diff --git a/client/modules/edit-names-vim.js b/client/modules/edit-names-vim.js new file mode 100644 index 00000000..8b3b2f89 --- /dev/null +++ b/client/modules/edit-names-vim.js @@ -0,0 +1,44 @@ +import * as Events from '#dom/events'; + +const {CloudCmd} = globalThis; + +CloudCmd.EditNamesVim = { + init, + show, + hide, +}; +const {Key} = CloudCmd; + +const ConfigView = { + bindKeys: false, + beforeClose: () => { + Events.rmKey(listener); + CloudCmd.EditNames.isChanged(); + }, +}; + +export async function init() { + await CloudCmd.EditNames(); +} + +export function show() { + Events.addKey(listener); + + CloudCmd.EditNames + .show(ConfigView) + .getEditor() + .setKeyMap('vim'); +} + +export function hide() { + CloudCmd.Edit.hide(); +} + +function listener(event) { + const {keyCode, shiftKey} = event; + + if (shiftKey && keyCode === Key.ESC) { + event.preventDefault(); + hide(); + } +} diff --git a/client/modules/edit-names.js b/client/modules/edit-names.js index d1d09664..7bc29054 100644 --- a/client/modules/edit-names.js +++ b/client/modules/edit-names.js @@ -1,223 +1,218 @@ -'use strict'; +import {tryToCatch} from 'try-to-catch'; +import exec from 'execon'; +import {supermenu} from 'supermenu'; +import {multiRename} from 'multi-rename'; -/* global CloudCmd, DOM */ +const {CloudCmd, DOM} = globalThis; -const currify = require('currify/legacy'); -const exec = require('execon'); - -const reject = Promise.reject.bind(Promise); - -CloudCmd.EditNames = function EditNamesProto(callback) { - const Info = DOM.CurrentInfo; - const Dialog = DOM.Dialog; - - const TITLE = 'Edit Names'; - const alert = currify(Dialog.alert, TITLE); - const refresh = currify(_refresh); - - const EditNames = this; - let Menu, MenuIO; - const ConfigView = { - beforeClose: () => { - exec.ifExist(Menu, 'hide'); - isChanged(); - DOM.Events.remove('keydown', keyListener); - } - }; - - function init(callback) { - let editor; - - exec.series([ - CloudCmd.Edit, - - (callback) => { - editor = CloudCmd.Edit.getEditor(); - callback(); - }, - - (callback) => { - setListeners(editor); - callback(); - }, - - (callback) => { - EditNames.show(); - callback(); - }, - ], callback); - } - - this.show = () => { - const names = getActiveNames().join('\n'); - - if (Info.name === '..' && names.length === 1) - return Dialog.alert.noFiles(TITLE); - - CloudCmd.Edit - .getEditor() - .setValueFirst('edit-names', names) - .setMode() - .disableKey(); - - DOM.Events.addKey(keyListener); - CloudCmd.Edit.show(ConfigView); - }; - - function keyListener(event) { - const ctrl = event.ctrlKey; - const meta = event.metaKey; - const ctrlMeta = ctrl || meta; - const Key = CloudCmd.Key; - - if (!ctrlMeta || event.keyCode !== Key.S) - return; - - EditNames.hide(); - } - - function getActiveNames() { - return DOM.getFilenames(DOM.getActiveFiles()); - } - - this.hide = () => { - CloudCmd.Edit.hide(); - }; - - function setListeners() { - const element = CloudCmd.Edit.getElement(); - - DOM.Events.addOnce('contextmenu', element, setMenu); - } - - function applyNames() { - const dir = Info.dirPath; - const from = getActiveNames(); - const nameIndex = from.indexOf(Info.name); - - const editor = CloudCmd.Edit.getEditor(); - const to = editor - .getValue() - .split('\n'); - - const root = CloudCmd.config('root'); - - Promise.resolve(root) - .then(rename(dir, from, to)) - .then(refresh(to, nameIndex)) - .catch(alert); - } - - function _refresh(to, nameIndex, res) { - if (res.status === 404) - return res.text().then(reject); - - const currentName = to[nameIndex]; - - CloudCmd.refresh({ - currentName - }); - } - - function getDir(root, dir) { - if (root === '/') - return dir; - - return root + dir; - } - - function rename(dir, from, to) { - return (root) => { - return fetch(CloudCmd.PREFIX + '/rename', { - method: 'put', - credentials: 'include', - body: JSON.stringify({ - from: from, - to: to, - dir: getDir(root, dir) - }) - }); - }; - } - - function setMenu(event) { - const position = { - x: event.clientX, - y: event.clientY - }; - - event.preventDefault(); - - !Menu && DOM.loadRemote('menu', (error) => { - MenuIO = window.MenuIO; - let noFocus; - const editor = CloudCmd.Edit.getEditor(); - const options = { - beforeShow: (params) => { - params.x -= 18; - params.y -= 27; - }, - - afterClick: () => { - !noFocus && editor.focus(); - } - }; - - const menuData = { - 'Save Ctrl+S' : () => { - editor.save(); - EditNames.hide(); - }, - 'Go To Line Ctrl+G' : () => { - noFocus = true; - editor.goToLine(); - }, - 'Cut Ctrl+X' : () => { - editor.cutToClipboard(); - }, - 'Copy Ctrl+C' : () => { - editor.copyToClipboard(); - }, - 'Paste Ctrl+V' : () => { - editor.pasteFromClipboard(); - }, - 'Delete Del' : () => { - editor.remove('right'); - }, - 'Select All Ctrl+A' : () => { - editor.selectAll(); - }, - 'Close Esc' : () => { - EditNames.hide(); - } - }; - - if (error) - return alert(error); - - if (Menu || !MenuIO) - return; - - const element = CloudCmd.Edit.getElement(); - - Menu = new MenuIO(element, options, menuData); - Menu.show(position.x, position.y); - }); - } - - function isChanged() { - const editor = CloudCmd.Edit.getEditor(); - const msg = 'Apply new names?'; - - if (!editor.isChanged()) - return; - - Dialog.confirm(TITLE, msg) - .then(EditNames.hide) - .then(applyNames) - .catch(EditNames.hide); - } - - init(callback); +CloudCmd.EditNames = { + init, + show, + hide, + isChanged, }; +const Info = DOM.CurrentInfo; +const {Dialog} = DOM; + +let Menu; + +const ConfigView = { + beforeClose: async () => { + exec.ifExist(Menu, 'hide'); + DOM.Events.remove('keydown', keyListener); + await isChanged(); + }, +}; + +export async function init() { + await CloudCmd.Edit(); + + setListeners(); +} + +export function show(options) { + const names = getActiveNames().join('\n'); + const config = { + ...ConfigView, + ...options, + }; + + if (Info.name === '..' && names.length === 1) + return Dialog.alert.noFiles(); + + DOM.Events.addKey(keyListener); + + CloudCmd.Edit + .getEditor() + .setValueFirst('edit-names', names) + .setMode() + .setOption('keyMap', 'default') + .disableKey(); + + CloudCmd.Edit.show(config); + + return CloudCmd.Edit; +} + +async function keyListener(event) { + const ctrl = event.ctrlKey; + const meta = event.metaKey; + const ctrlMeta = ctrl || meta; + const {Key} = CloudCmd; + + if (ctrlMeta && event.keyCode === Key.S) { + hide(); + return; + } + + if (ctrlMeta && event.keyCode === Key.P) { + const [, pattern] = await Dialog.prompt('Apply pattern:', '[n][e]'); + pattern && applyPattern(pattern); + } +} + +function applyPattern(pattern) { + const newNames = multiRename(pattern, getActiveNames()); + const editor = CloudCmd.Edit.getEditor(); + + editor.setValue(newNames.join('\n')); +} + +function getActiveNames() { + return DOM.getFilenames(DOM.getActiveFiles()); +} + +export function hide() { + CloudCmd.Edit.hide(); +} + +function setListeners() { + const element = CloudCmd.Edit.getElement(); + + DOM.Events.addOnce('contextmenu', element, setMenu); +} + +async function applyNames() { + const dir = Info.dirPath; + const from = getActiveNames(); + const nameIndex = from.indexOf(Info.name); + + const editor = CloudCmd.Edit.getEditor(); + const to = editor + .getValue() + .split('\n'); + + const root = CloudCmd.config('root'); + + const response = rename(dir, from, to, root); + const [error] = await tryToCatch(refresh, to, nameIndex, response); + + if (error) + alert(error); +} + +function refresh(to, nameIndex, res) { + if (res.status === 404) { + const error = res.text(); + throw error; + } + + const currentName = to[nameIndex]; + + CloudCmd.refresh({ + currentName, + }); +} + +function getDir(root, dir) { + if (root === '/') + return dir; + + return root + dir; +} + +function rename(path, from, to, root) { + const dir = getDir(root, path); + const {prefix} = CloudCmd; + + return fetch(`${prefix}/rename`, { + method: 'put', + credentials: 'include', + body: JSON.stringify({ + from, + to, + dir, + }), + }); +} + +function setMenu(event) { + const position = { + x: event.clientX, + y: event.clientY, + }; + + event.preventDefault(); + + if (Menu) + return; + + const editor = CloudCmd.Edit.getEditor(); + + const options = { + beforeShow: (params) => { + params.x -= 18; + params.y -= 27; + }, + + afterClick: () => { + editor.focus(); + }, + }; + + const menuData = { + 'Save Ctrl+S': async () => { + await applyNames(); + hide(); + }, + 'Go To Line Ctrl+G': () => { + editor.goToLine(); + }, + 'Cut Ctrl+X': () => { + editor.cutToClipboard(); + }, + 'Copy Ctrl+C': () => { + editor.copyToClipboard(); + }, + 'Paste Ctrl+V': () => { + editor.pasteFromClipboard(); + }, + 'Delete Del': () => { + editor.remove('right'); + }, + 'Select All Ctrl+A': () => { + editor.selectAll(); + }, + 'Close Esc': hide, + }; + + const element = CloudCmd.Edit.getElement(); + + Menu = supermenu(element, options, menuData); + + Menu.addContextMenuListener(); + Menu.show(position.x, position.y); +} + +export async function isChanged() { + const editor = CloudCmd.Edit.getEditor(); + const msg = 'Apply new names?'; + + if (!editor.isChanged()) + return; + + const [cancel] = await Dialog.confirm(msg); + + !cancel && await applyNames(); +} diff --git a/client/modules/edit.js b/client/modules/edit.js index d78252d9..593a11cb 100644 --- a/client/modules/edit.js +++ b/client/modules/edit.js @@ -1,139 +1,127 @@ /* global CloudCmd */ +import {montag} from 'montag'; +import {promisify} from 'es6-promisify'; +import {tryToCatch} from 'try-to-catch'; +import createElement from '@cloudcmd/create-element'; +import load from 'load.js'; +import {MAX_FILE_SIZE as maxSize} from '#common/cloudfunc'; +import {time, timeEnd} from '#common/util'; -'use strict'; - -const exec = require('execon'); -const currify = require('currify/legacy'); - -const load = require('../dom/load'); - -const {MAX_FILE_SIZE: maxSize} = require('../../common/cloudfunc'); -const {time, timeEnd} = require('../../common/util'); - -CloudCmd.Edit = EditProto; - -function EditProto(callback) { - const Name = 'Edit'; - const EditorName = CloudCmd.config('editor'); - const loadFiles = currify(_loadFiles); - - let Loading = true; - let Element; - let editor; - - const ConfigView = { - afterShow: () => { - editor - .moveCursorTo(0, 0) - .focus(); - } - }; - - const Edit = exec.bind(); - - function init(callback) { - const element = createElement(); - - exec.series([ - CloudCmd.View, - loadFiles(element) - ], callback); - } - - function createElement() { - const element = load({ - name: 'div', - style: - 'width : 100%;' + - 'height : 100%;' + - 'font-family: "Droid Sans Mono";' + - 'position : absolute;', - notAppend: true - }); - - Element = element; - - return element; - } - - function checkFn(name, fn) { - if (typeof fn !== 'function') - throw Error(name + ' should be a function!'); - } - - function initConfig(options = {}) { - const config = Object.assign({}, options, ConfigView); - - if (!options.afterShow) - return config; - - checkFn('options.afterShow', options.afterShow); - - const afterShow = {config}; - - config.afterShow = () => { - afterShow(); - options.afterShow(); - }; - - return config; - } - - Edit.show = (options) => { - if (Loading) - return; - - CloudCmd.View.show(Element, initConfig(options)); - - Edit.getEditor() - .setOptions({ - keyMap: 'default', - fontSize: 16, - }); - - return Edit; - }; - - Edit.getEditor = () => { - return editor; - }; - - Edit.getElement = () => { - return Element; - }; - - Edit.hide = () => { - CloudCmd.View.hide(); - return Edit; - }; - - function _loadFiles(element, callback) { - const socketPath = CloudCmd.PREFIX; - const prefix = socketPath + '/' + EditorName; - const url = prefix + '/' + EditorName + '.js'; - - time(Name + ' load'); - - load.js(url, () => { - const word = window[EditorName]; - const options = { - maxSize, - prefix, - socketPath, - }; - - word(element, options, (ed) => { - timeEnd(Name + ' load'); - editor = ed; - Loading = false; - - exec(callback); - }); - }); - } - - init(callback); - - return Edit; +export function getEditor() { + return editor; } +const isFn = (a) => typeof a === 'function'; +const loadJS = load.js; + +const Name = 'Edit'; + +CloudCmd[Name] = { + init, + show, + hide, + getEditor, + getElement, +}; + +const EditorName = CloudCmd.config('editor'); + +let Loading = true; +let Element; +let editor; + +const ConfigView = { + afterShow: () => { + editor + .moveCursorTo(0, 0) + .focus(); + }, +}; + +export async function init() { + const element = create(); + + await CloudCmd.View(); + await loadFiles(element); +} + +function create() { + const element = createElement('div', { + style: montag` + width: 100%; + height: 100%; + font-family: "Droid Sans Mono"; + `, + notAppend: true, + }); + + Element = element; + + return element; +} + +function checkFn(name, fn) { + if (!isFn(fn)) + throw Error(`${name} should be a function!`); +} + +function initConfig(options = {}) { + const config = { + ...options, + ...ConfigView, + }; + + if (!options.afterShow) + return config; + + checkFn('options.afterShow', options.afterShow); + + config.afterShow = () => { + ConfigView.afterShow(); + options.afterShow(); + }; + + return config; +} + +export function show(options) { + if (Loading) + return; + + CloudCmd.View.show(Element, initConfig(options)); + + getEditor().setOptions({ + fontSize: 16, + }); +} + +export function getElement() { + return Element; +} + +export function hide() { + CloudCmd.View.hide(); +} + +const loadFiles = async (element) => { + const prefix = `${CloudCmd.prefix}/${EditorName}`; + const socketPath = CloudCmd.prefix; + const prefixSocket = `${CloudCmd.prefixSocket}/${EditorName}`; + const url = `${prefix}/${EditorName}.js`; + + time(`${Name} load`); + + await loadJS(url); + + const word = promisify(window[EditorName]); + const [ed] = await tryToCatch(word, element, { + maxSize, + prefix, + prefixSocket, + socketPath, + }); + + timeEnd(`${Name} load`); + editor = ed; + Loading = false; +}; diff --git a/client/modules/help.js b/client/modules/help.js index 29de96fa..74657a90 100644 --- a/client/modules/help.js +++ b/client/modules/help.js @@ -1,34 +1,27 @@ -'use strict'; +import * as Images from '#dom/images'; -/* global CloudCmd */ +const {CloudCmd} = globalThis; -CloudCmd.Help = HelpProto; +CloudCmd.Help = { + init, + show, + hide, +}; -const Images = require('../dom/images'); - -function HelpProto() { +export function init() { Images.show.load('top'); - show(); - - return exports; } -module.exports.show = show; -module.exports.hide = hide; - -function show() { +export function show() { const positionLoad = 'top'; const relative = true; - CloudCmd - .Markdown - .show('/HELP.md', { - positionLoad, - relative, - }); + CloudCmd.Markdown.show('/HELP.md', { + positionLoad, + relative, + }); } -function hide() { +export function hide() { CloudCmd.View.hide(); } - diff --git a/client/modules/konsole.js b/client/modules/konsole.js index 8f9830b0..e9a465af 100644 --- a/client/modules/konsole.js +++ b/client/modules/konsole.js @@ -1,130 +1,143 @@ -'use strict'; - /* global CloudCmd */ /* global Util */ /* global DOM */ /* global Console */ +import exec from 'execon'; +import currify from 'currify'; +import {tryToCatch} from 'try-to-catch'; +import {js as loadJS} from 'load.js'; +import createElement from '@cloudcmd/create-element'; +import * as Images from '#dom/images'; -const exec = require('execon'); -const Images = require('../dom/images'); -const {Dialog} = DOM; +CloudCmd.Konsole = { + init, + show, + hide, +}; -CloudCmd.Konsole = ConsoleProto; +const {Dialog, CurrentInfo: Info} = DOM; -function ConsoleProto() { - const config = CloudCmd.config; - - const Name = 'Konsole'; - const TITLE = 'Console'; - - let Element; - let Loaded; - - const Konsole = this; - - function init() { - Images.show.load('top'); - - exec.series([ - CloudCmd.View, - load, - create, - Konsole.show, - ]); - - Element = DOM.load({ - name : 'div', - className : 'console' - }); - } - - this.hide = () => { - CloudCmd.View.hide(); - }; - - this.clear = () => { - Console.clear(); - }; - - function getPrefix() { - return CloudCmd.PREFIX + '/console'; - } - - function getEnv() { - return { - ACTIVE_DIR: DOM.getCurrentDirPath.bind(DOM), - PASSIVE_DIR: DOM.getNotCurrentDirPath.bind(DOM), - CURRENT_NAME: DOM.getCurrentName.bind(DOM), - CURRENT_PATH: () => { - return DOM.CurrentInfo.path; - } - }; - } - - function create(callback) { - const options = { - env: getEnv(), - prefix: getPrefix(), - socketPath: CloudCmd.PREFIX, - }; - - Console(Element, options, (spawn) => { - spawn.on('connect', exec.with(authCheck, spawn)); - exec(callback); - }); - - Console.addShortCuts({ - 'P': () => { - const command = Console.getPromptText(); - const path = DOM.getCurrentDirPath(); - - Console.setPromptText(command + path); - } - }); - } - - function authCheck(spawn) { - if (!config('auth')) - return; - - spawn.emit('auth', config('username'), config('password')); - - spawn.on('reject', () => { - Dialog.alert(TITLE, 'Wrong credentials!'); - }); - } - - this.show = (callback) => { - if (!Loaded) - return; - - CloudCmd.View.show(Element, { - afterShow: () => { - Console.focus(); - exec(callback); - } - }); - }; - - function load(callback) { - const prefix = getPrefix(); - const url = prefix + '/console.js'; - - DOM.load.js(url, (error) => { - if (error) - return Dialog.alert(TITLE, error.message); - - Loaded = true; - Util.timeEnd(Name + ' load'); - exec(callback); - }); - - Util.time(Name + ' load'); - } - - if (!CloudCmd.config('console')) +const rmLastSlash = (a) => a.replace(/\/$/, '') || '/'; + +let konsole; +const {config} = CloudCmd; + +const cd = currify((fn, dir) => fn(`cd ${rmLastSlash(dir)}`)); + +const Name = 'Konsole'; + +let Element; +let Loaded; + +export async function init() { + if (!config('console')) return; - init(); + Images.show.load('top'); + + await CloudCmd.View(); + await load(); + await create(); } +export function hide() { + CloudCmd.View.hide(); +} + +export const clear = () => { + konsole.clear(); +}; + +const getPrefix = () => CloudCmd.prefix + '/console'; + +function getPrefixSocket() { + return CloudCmd.prefixSocket + '/console'; +} + +const getEnv = () => ({ + ACTIVE_DIR: DOM.getCurrentDirPath.bind(DOM), + PASSIVE_DIR: DOM.getNotCurrentDirPath.bind(DOM), + CURRENT_NAME: DOM.getCurrentName.bind(DOM), + CURRENT_PATH: () => Info.path, +}); + +async function onPath(path) { + if (Info.dirPath === path) + return; + + await CloudCmd.changeDir(path); +} + +const getDirPath = () => { + if (config('syncConsolePath')) + return Info.dirPath; +}; + +const create = async () => { + const options = { + cwd: getDirPath(), + env: getEnv(), + prefix: getPrefix(), + prefixSocket: getPrefixSocket(), + socketPath: CloudCmd.prefix, + }; + + Element = createElement('div', { + className: 'console', + }); + + konsole = await Console(Element, options); + + konsole.on('connect', exec.with(authCheck, konsole)); + konsole.on('path', config.if('syncConsolePath', onPath)); + + CloudCmd.on('active-dir', config.if('syncConsolePath', cd(konsole.handler))); + + konsole.addShortCuts({ + P: () => { + const command = konsole.getPromptText(); + const path = DOM.getCurrentDirPath(); + + konsole.setPromptText(command + path); + }, + }); +}; + +function authCheck(konsole) { + konsole.emit('auth', config('username'), config('password')); + + konsole.on('reject', () => { + Dialog.alert('Wrong credentials!'); + }); +} + +export function show(callback) { + if (!Loaded) + return; + + if (!config('console')) + return; + + CloudCmd.View.show(Element, { + afterShow: () => { + konsole.focus(); + exec(callback); + }, + }); +} + +const load = async () => { + Util.time(`${Name} load`); + + const prefix = getPrefix(); + const url = `${prefix}/console.js`; + const [error] = await tryToCatch(loadJS, url); + + Loaded = true; + Util.timeEnd(`${Name} load`); + + if (error) + return Dialog.alert(error.message, { + cancel: false, + }); +}; diff --git a/client/modules/markdown.js b/client/modules/markdown.js index 7d23af50..c94c64e8 100644 --- a/client/modules/markdown.js +++ b/client/modules/markdown.js @@ -1,58 +1,47 @@ -'use strict'; +import createElement from '@cloudcmd/create-element'; +import * as Images from '#dom/images'; +import {Markdown} from '#dom/rest'; +import {alert} from '#dom/dialog'; -/*global CloudCmd */ +const {CloudCmd} = globalThis; -CloudCmd.Markdown = MarkdownProto; - -const exec = require('execon'); - -const Images = require('../dom/images'); -const load = require('../dom/load'); -const {Markdown} = require('../dom/rest'); - -function MarkdownProto(name, options) { - Images.show.load('top'); - - exec.series([ - CloudCmd.View, - exec.with(show, name, options), - ]); - - return module.exports; -} - -module.exports.show = show; - -module.exports.hide = () => { - CloudCmd.View.hide(); +CloudCmd.Markdown = { + init, + show, + hide, }; +export async function init() { + Images.show.load('top'); + await CloudCmd.View(); +} -function show(name, options = {}) { - const relativeQuery = '?relative'; - const { - positionLoad, - relative, - } = options; +export function hide() { + CloudCmd.View.hide(); +} + +export async function show(name, options = {}) { + const {positionLoad, relative} = options; Images.show.load(positionLoad); if (relative) - name += relativeQuery; + name += '?relative'; - Markdown.read(name, (error, inner) => { - const name = 'div'; - const className = 'help'; - - const div = load({ - name, - className, - inner, + const [error, innerHTML] = await Markdown.read(name); + Images.hide(); + + if (error) + return alert(error.message, { + cancel: false, }); - - Images.hide(); - - CloudCmd.View.show(div); + + const className = 'help'; + + const div = createElement('div', { + className, + innerHTML, }); + + CloudCmd.View.show(div); } - diff --git a/client/modules/menu.js b/client/modules/menu.js deleted file mode 100644 index cb87255f..00000000 --- a/client/modules/menu.js +++ /dev/null @@ -1,349 +0,0 @@ -/* global CloudCmd, DOM */ - -'use strict'; - -CloudCmd.Menu = MenuProto; - -const exec = require('execon'); -const currify = require('currify/legacy'); - -const {FS} = require('../../common/cloudfunc'); - -const load = require('../dom/load'); -const RESTful = require('../dom/rest'); - -const bind = (f, ...a) => (...b) => f(...a, ...b); - -function MenuProto(position) { - const config = CloudCmd.config; - const Buffer = DOM.Buffer; - const Info = DOM.CurrentInfo; - - let Loading = true; - const Key = CloudCmd.Key; - const Events = DOM.Events; - const Dialog = DOM.Dialog; - const Images = DOM.Images; - const Menu = this; - const TITLE = 'Menu'; - const alert = currify(Dialog.alert, TITLE); - const alertNoFiles = () => Dialog.alert.noFiles(TITLE); - - let MenuShowedName; - let MenuContext; - let MenuContextFile; - - this.ENABLED = false; - - function init() { - Loading = true; - Menu.show(); - - Events.addKey(listener); - } - - this.hide = () => { - MenuContext.hide(); - MenuContextFile.hide(); - }; - - this.show = (position = {}) => { - const { - x = 0, - y = 0, - } = position; - - const showFunc = () => { - show(x, y); - Images.hide(); - }; - - exec.if(window.MenuIO, showFunc, () => { - DOM.loadMenu((error) => { - if (error) - return alert(error); - - showFunc(); - }); - }); - }; - - function show(x, y) { - if (!x || !y) { - if (position) { - x = position.x; - y = position.y; - } else { - const pos = getCurrentPosition(); - - x = pos.x; - y = pos.y; - } - } - - if (!Loading) { - MenuContext.show(x, y); - MenuContextFile.show(x, y); - return; - } - - loadFileMenuData((isAuth, menuDataFile) => { - const NOT_FILE = true; - const fm = DOM.getFM(); - const menuData = getMenuData(isAuth); - const options = getOptions(NOT_FILE); - const optionsFile = getOptions(); - const MenuIO = window.MenuIO; - - MenuContext = new MenuIO(fm, options, menuData); - MenuContextFile = new MenuIO(fm, optionsFile, menuDataFile); - - const is = DOM.getCurrentByPosition({x, y}); - const menu = is ? MenuContextFile : MenuContext; - - menu.show(x, y); - - Loading = false; - position = null; - }); - } - - function getOptions(notFile) { - let name, func; - - if (notFile) { - name = 'context'; - func = Key.unsetBind; - } else { - name = 'contextFile'; - } - - const options = { - icon : true, - beforeClose : Key.setBind, - beforeShow : exec.with(beforeShow, func), - beforeClick, - name, - }; - - return options; - } - - function getMenuData(isAuth) { - const menu = { - 'Paste': Buffer.paste, - 'New': { - 'File': DOM.promptNewFile, - 'Directory': DOM.promptNewDir - }, - 'Upload': () => { - CloudCmd.Upload.show(); - }, - 'Upload From Cloud': uploadFromCloud, - '(Un)Select All': DOM.toggleAllSelectedFiles - }; - - if (isAuth) - menu['Log Out'] = CloudCmd.logOut; - - return menu; - } - - function loadFileMenuData(callback) { - const is = CloudCmd.config('auth'); - const show = (name) => { - CloudCmd[name].show(); - }; - - const menuBottom = getMenuData(is); - - const menuTop = { - 'View': bind(show, 'View'), - 'Edit': bind(show, 'EditFile'), - 'Rename': () => { - setTimeout(DOM.renameCurrent, 100); - }, - 'Delete': () => { - CloudCmd.Operation.show('delete'); - }, - 'Pack': () => { - CloudCmd.Operation.show('pack'); - }, - 'Extract': () => { - CloudCmd.Operation.show('extract'); - }, - 'Download': preDownload, - 'Upload To Cloud': bind(uploadTo, 'Cloud'), - 'Cut': () => { - isCurrent(Buffer.cut, alertNoFiles); - }, - 'Copy': () => { - isCurrent(Buffer.copy, alertNoFiles); - }, - }; - - const menu = Object.assign({}, menuTop, menuBottom); - - callback(is, menu); - } - - function isCurrent(yesFn, noFn) { - if (Info.name !== '..') - return yesFn(); - - noFn(); - } - - function isPath(x, y) { - const {panel} = Info; - const isEmptyRoot = !panel; - - if (isEmptyRoot) - return false; - - const el = document.elementFromPoint(x, y); - const elements = panel.querySelectorAll('[data-name="js-path"] *'); - const is = ~[].indexOf.call(elements, el); - - return is; - } - - function beforeShow(callback, params) { - const name = params.name; - let notShow = DOM.getCurrentByPosition({ - x: params.x, - y: params.y - }); - - if (params.name === 'contextFile') { - notShow = !notShow; - } - - if (!notShow) - MenuShowedName = name; - - exec(callback); - - if (!notShow) - notShow = isPath(params.x, params.y); - - return notShow; - } - - function beforeClick(name) { - return MenuShowedName !== name; - } - - function uploadTo(nameModule) { - Info.getData((error, data) => { - const name = Info.name; - const execFrom = CloudCmd.execFromModule; - - execFrom(nameModule, 'uploadFile', name, data); - }); - - CloudCmd.log('Uploading to ' + name + '...'); - } - - function uploadFromCloud() { - Images.show.load('top'); - - CloudCmd.execFromModule('Cloud', 'saveFile', (currentName, data) => { - const path = DOM.getCurrentDirPath() + currentName; - - RESTful.write(path, data, (error) => { - if (error) - return; - - CloudCmd.refresh({currentName}); - }); - }); - } - - function preDownload() { - download(config('packer')); - } - - function download(type) { - const TIME = 30 * 1000; - const prefixUr = CloudCmd.PREFIX_URL; - const PACK = '/pack'; - const date = Date.now(); - const files = DOM.getActiveFiles(); - - if (!files.length) - return alertNoFiles(); - - files.forEach((file) => { - const selected = DOM.isSelected(file); - const isDir = DOM.isCurrentIsDir(file); - /* - * if we send ajax request - - * no need in hash so we escape # - * and all other characters, like "%" - */ - const path = DOM.getCurrentPath(file) - .replace(/#/g, '%23'); - - CloudCmd.log('downloading file ' + path + '...'); - const encodedPath = encodeURI(path); - const id = load.getIdBySrc(path); - - let src; - - if (isDir) - src = prefixUr + PACK + encodedPath + DOM.getPackerExt(type); - else - src = prefixUr + FS + encodedPath + '?download'; - - const element = load({ - id : id + '-' + date, - name : 'iframe', - async : false, - className : 'hidden', - src, - }); - - setTimeout(() => { - document.body.removeChild(element); - }, TIME); - - if (selected) - DOM.toggleSelectedFile(file); - }); - } - - function getCurrentPosition() { - const current = Info.element; - const rect = current.getBoundingClientRect(); - - const position = { - x: rect.left + rect.width / 3, - y: rect.top - }; - - return position; - } - - function listener(event) { - const F9 = Key.F9; - const ESC = Key.ESC; - const key = event.keyCode; - const isBind = Key.isBind(); - - if (!isBind) - return; - - if (key === ESC) - return Menu.hide(); - - if (key === F9) { - const position = getCurrentPosition(); - MenuContext.show(position.x, position.y); - - event.preventDefault(); - } - } - - init(); -} diff --git a/client/modules/menu/cloudmenu.js b/client/modules/menu/cloudmenu.js new file mode 100644 index 00000000..8f7c1e68 --- /dev/null +++ b/client/modules/menu/cloudmenu.js @@ -0,0 +1,31 @@ +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 {prefix} = CloudCmd; + const {host, protocol} = globalThis.location; + const url = `${protocol}//${host}${prefix}/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); +} diff --git a/client/modules/menu/index.js b/client/modules/menu/index.js new file mode 100644 index 00000000..7235591e --- /dev/null +++ b/client/modules/menu/index.js @@ -0,0 +1,355 @@ +import exec from 'execon'; +import wrap from 'wraptile'; +import createElement from '@cloudcmd/create-element'; +import {getIdBySrc} from '#dom/load'; +import * as RESTful from '#dom/rest'; +import {FS} from '#common/cloudfunc'; + +const {CloudCmd, DOM} = globalThis; +const {config, Key} = CloudCmd; + +const { + Buffer, + Events, + Dialog, + Images, +} = DOM; + +const Info = DOM.CurrentInfo; +const alertNoFiles = Dialog.alert.noFiles; +const uploadTo = wrap(_uploadTo); + +let MenuShowedName; +let MenuContext; +let MenuContextFile; + +export const ENABLED = false; + +CloudCmd.Menu = { + init, + show, + hide, +}; + +export async function init() { + const {isAuth, menuDataFile} = getFileMenuData(); + + const fm = DOM.getFM(); + const menuData = getMenuData(isAuth); + + const options = getOptions({ + type: 'context', + }); + + const optionsFile = getOptions({ + type: 'file', + }); + + const {createCloudMenu} = await import('./cloudmenu.js'); + + const {name} = fm.dataset; + + MenuContext = await createCloudMenu(name, options, menuData); + MenuContextFile = await createCloudMenu(name, optionsFile, menuDataFile); + + MenuContext.addContextMenuListener(); + MenuContextFile.addContextMenuListener(); + + Events.addKey(listener); +} + +export function hide() { + MenuContext.hide(); + MenuContextFile.hide(); +} + +export function show(position) { + const {x, y} = getPosition(position); + + MenuContext.show(x, y); + MenuContextFile.show(x, y); + + Images.hide(); +} + +function getPosition(position) { + if (position) + return { + x: position.x, + y: position.y, + }; + + return getCurrentPosition(); +} + +function getMenuNameByEl(el) { + if (!el) + return 'context'; + + const name = DOM.getCurrentName(el); + + if (name === '..') + return 'context'; + + return 'contextFile'; +} + +function getOptions({type}) { + let name; + let func; + + if (type === 'context') { + name = 'context'; + func = Key.unsetBind; + } else if (type === 'file') { + name = 'contextFile'; + } + + const options = { + icon: true, + infiniteScroll: false, + beforeClose: Key.setBind, + beforeHide: Key.setBind, + beforeShow: exec.with(beforeShow, func), + beforeClick, + name, + }; + + return options; +} + +function getMenuData(isAuth) { + const menu = { + 'Paste': Buffer.paste, + 'New': { + File: DOM.promptNewFile, + Directory: DOM.promptNewDir, + }, + 'Upload': () => { + CloudCmd.Upload.show(); + }, + 'Upload From Cloud': uploadFromCloud, + 'Toggle File Selection': DOM.toggleSelectedFile, + '(Un)Select All': DOM.toggleAllSelectedFiles, + }; + + if (isAuth) + menu['Log Out'] = CloudCmd.logOut; + + return menu; +} + +function getFileMenuData() { + const isAuth = CloudCmd.config('auth'); + + const menuBottom = getMenuData(isAuth); + const menuTop = { + 'View': () => { + CloudCmd.View.show(); + }, + 'Edit': () => { + const name = config('vim') ? 'EditFileVim' : 'EditFile'; + CloudCmd[name].show(); + }, + 'Rename': () => { + setTimeout(DOM.renameCurrent, 100); + }, + 'Delete': () => { + CloudCmd.Operation.show('delete'); + }, + 'Pack': () => { + CloudCmd.Operation.show('pack'); + }, + 'Extract': () => { + CloudCmd.Operation.show('extract'); + }, + 'Download': preDownload, + 'Upload To Cloud': uploadTo('Cloud'), + 'Cut': () => { + isCurrent(Buffer.cut, alertNoFiles); + }, + 'Copy': () => { + isCurrent(Buffer.copy, alertNoFiles); + }, + }; + + const menuDataFile = { + ...menuTop, + ...menuBottom, + }; + + return { + isAuth, + menuDataFile, + }; +} + +function isCurrent(yesFn, noFn) { + if (Info.name !== '..') + return yesFn(); + + noFn(); +} + +function isPath(x, y) { + const {panel} = Info; + const isEmptyRoot = !panel; + + if (isEmptyRoot) + return false; + + const el = document.elementFromPoint(x, y); + const elements = panel.querySelectorAll('[data-name="js-path"] *'); + + return !~[].indexOf.call(elements, el); +} + +function beforeShow(callback, params) { + Key.unsetBind(); + + const { + name, + position = { + x: params.x, + y: params.y, + }, + } = params; + + const {x, y} = position; + + const el = DOM.getCurrentByPosition({ + x, + y, + }); + + const menuName = getMenuNameByEl(el); + + let isShow = menuName !== 'contextFile'; + + if (params.name === 'contextFile') + isShow = !isShow; + + if (isShow) + MenuShowedName = name; + + exec(callback); + + if (isShow) + isShow = isPath(x, y); + + return isShow; +} + +const beforeClick = (name) => MenuShowedName !== name; + +async function _uploadTo(nameModule) { + const [error, data] = await Info.getData(); + + if (error) + return; + + const {name} = Info; + + CloudCmd.execFromModule(nameModule, 'uploadFile', name, data); + CloudCmd.log(`Uploading to ${name}...`); +} + +function uploadFromCloud() { + Images.show.load('top'); + + CloudCmd.execFromModule('Cloud', 'saveFile', async (currentName, data) => { + const path = DOM.getCurrentDirPath() + currentName; + const [e] = await RESTful.write(path, data); + + if (e) + return; + + await CloudCmd.refresh({ + currentName, + }); + }); +} + +function preDownload() { + download(config('packer')); +} + +function download(type) { + const TIME = 30 * 1000; + const {prefixURL} = CloudCmd; + const PACK = '/pack'; + const date = Date.now(); + const files = DOM.getActiveFiles(); + + if (!files.length) + return alertNoFiles(); + + for (const file of files) { + const selected = DOM.isSelected(file); + const isDir = DOM.isCurrentIsDir(file); + const path = DOM.getCurrentPath(file); + + CloudCmd.log(`downloading file ${path}...`); + + /* + * if we send ajax request - + * no need in hash so we escape # + * and all other characters, like "%" + */ + const encodedPath = encodeURI(path).replace(/#/g, '#'); + const id = getIdBySrc(path); + + let src; + + if (isDir) + src = prefixURL + PACK + encodedPath + DOM.getPackerExt(type); + else + src = prefixURL + FS + encodedPath + '?download'; + + const element = createElement('iframe', { + id: id + '-' + date, + async: false, + className: 'hidden', + src, + }); + + const {body} = document; + const removeChild = body.removeChild.bind(body, element); + + setTimeout(removeChild, TIME); + + if (selected) + DOM.toggleSelectedFile(file); + } +} + +function getCurrentPosition() { + const current = Info.element; + const rect = current.getBoundingClientRect(); + + const position = { + x: Math.round(rect.left + rect.width / 3), + y: Math.round(rect.top), + }; + + return position; +} + +function listener(event) { + const {F9, ESC} = Key; + + const key = event.keyCode; + const isBind = Key.isBind(); + + if (key === ESC) { + Key.setBind(); + return hide(); + } + + if (isBind && key === F9) { + const position = getCurrentPosition(); + MenuContext.show(position.x, position.y); + + event.preventDefault(); + } +} diff --git a/client/modules/operation/format.js b/client/modules/operation/format.js new file mode 100644 index 00000000..c639799e --- /dev/null +++ b/client/modules/operation/format.js @@ -0,0 +1,6 @@ +export const format = (operation, from, to) => { + if (!to) + return `${operation} ${from}`; + + return `${operation} ${from} -> ${to}`; +}; diff --git a/client/modules/operation/get-next-current-name.js b/client/modules/operation/get-next-current-name.js new file mode 100644 index 00000000..63445888 --- /dev/null +++ b/client/modules/operation/get-next-current-name.js @@ -0,0 +1,16 @@ +import currify from 'currify'; + +const not = currify((array, value) => !array.includes(value)); +const notOneOf = currify((a, b) => a.filter(not(b))); + +export const getNextCurrentName = (currentName, names, removedNames) => { + const i = names.indexOf(currentName); + + const nextNames = notOneOf(names, removedNames); + const {length} = nextNames; + + if (nextNames[i]) + return nextNames[i]; + + return nextNames[length - 1]; +}; diff --git a/client/modules/operation/index.js b/client/modules/operation/index.js index 51813abe..f349f7d8 100644 --- a/client/modules/operation/index.js +++ b/client/modules/operation/index.js @@ -1,564 +1,516 @@ -/* global CloudCmd */ -/* global Util */ -/* global DOM */ -/* global spero */ -/* global remedy */ -/* global ishtar */ -/* global salam */ -/* global omnes */ +import currify from 'currify'; +import wraptile from 'wraptile'; +import {promisify} from 'es6-promisify'; +import exec from 'execon'; +import load from 'load.js'; +import {tryToCatch} from 'try-to-catch'; +import {encode} from '#common/entity'; +import {removeExtension} from './remove-extension.js'; +import {setListeners} from './set-listeners.js'; +import {getNextCurrentName} from './get-next-current-name.js'; -'use strict'; +const {DOM, CloudCmd} = globalThis; -CloudCmd.Operation = OperationProto; +const removeQuery = (a) => a.replace(/\?.*/, ''); -const currify = require('currify/legacy'); -const exec = require('execon'); +const Name = 'Operation'; -const RESTful = require('../../dom/rest'); -const removeExtension = require('./remove-extension'); +const {config} = CloudCmd; +const {Dialog, Images} = DOM; -function OperationProto(operation, data) { - const Name = 'Operation'; - const TITLE = CloudCmd.TITLE; - const {config} = CloudCmd; - const {Dialog, Images} = DOM; +const authCheck = wraptile(_authCheck); +const Operation = {}; + +let Loaded; + +let copyFn; +let moveFn; +let deleteFn; +let extractFn; +let packZipFn; +let packTarFn; + +const Info = DOM.CurrentInfo; +const showLoad = Images.show.load.bind(null, 'top'); + +const processFiles = currify(_processFiles); + +const noFilesCheck = () => { + const {length} = DOM.getActiveFiles(); + const is = Boolean(!length); - let Loaded; + if (is) + return Dialog.alert.noFiles(); - let { - cp: copyFn, - mv: moveFn, - pack: packFn, - delete: deleteFn, - extract: extractFn, - } = RESTful; + return is; +}; + +export const init = promisify((callback) => { + showLoad(); - const Info = DOM.CurrentInfo; - const showLoad = Images.show.load.bind(null, 'top'); - const Operation = this; - - function init() { - showLoad(); - - exec.series([ - DOM.loadSocket, - (callback) => { - if (config('progress')) - load((callback) => { - create(CloudCmd.PREFIX, callback); - }); - - callback(); - }, - () => { - Loaded = true; - Images.hide(); - Operation.show(operation, data); - } - ]); - } - - function authCheck(spawn, ok) { - if (!config('auth')) - return ok(); - - spawn.on('accept', ok); - spawn.on('reject', () => { - Dialog.alert(TITLE, 'Wrong credentials!'); - }); - - spawn.emit('auth', config('username'), config('password')); - } - - function _initSpero(prefix, fn) { - spero(prefix + '/spero', prefix, (copier) => { - fn(); + exec.series([ + DOM.loadSocket, + async (callback) => { + if (config('dropbox')) + return callback(); - copier.on('connect', () => { - authCheck(copier, () => { - copyFn = (data, callback) => { - setListeners(copier, callback); - copier.copy(data.from, data.to, data.names); - }; - }); - }); - - copier.on('disconnect', () => { - copyFn = RESTful.cp; - }); - }); - } - - function _initRemedy(prefix, fn) { - remedy(prefix + '/remedy', prefix, (remover) => { - fn(); - remover.on('connect', () => { - authCheck(remover, () => { - deleteFn = (from, files, callback) => { - setListeners(remover, callback); - from = from.replace(/\?.*/, ''); - remover.remove(from, files); - }; - }); - }); - - remover.on('disconnect', () => { - deleteFn = RESTful.remove; - }); - }); - } - - function _setPacker(prefix, name, pack, fn) { - pack(prefix + '/' + name, prefix, (packer) => { - fn(); - packer.on('connect', () => { - authCheck(packer, () => { - packFn = (data, callback) => { - setListeners(packer, {noContinue: true}, callback); - packer.pack(data.from, data.to, data.names); - }; - }); - }); - - packer.on('disconnect', () => { - packFn = RESTful.pack; - }); - }); - } - - function _initPacker(prefix, fn) { - if (config('packer') === 'zip') - return _setPacker(prefix, 'salam', salam, fn); - - _setPacker(prefix, 'ishtar', ishtar, fn); - } - - function _initExtractor(prefix, fn) { - omnes(prefix + '/omnes', prefix, (packer) => { - fn(); - packer.on('connect', () => { - authCheck(packer, () => { - extractFn = (data, callback) => { - setListeners(packer, {noContinue: true}, callback); - packer.extract(data.from, data.to); - }; - }); - }); - - packer.on('disconnect', () => { - extractFn = RESTful.extract; - }); - }); - } - - function create(prefix) { - const initSpero = currify(_initSpero); - const initRemedy = currify(_initRemedy); - const initPacker = currify(_initPacker); - const initExtractor = currify(_initExtractor); - - exec.parallel([ - initSpero(prefix), - initRemedy(prefix), - initPacker(prefix), - initExtractor(prefix) - ], exec.ret); - } - - function setListeners(emitter, options, callback) { - if (!callback) { - callback = options; - options = {}; - } - - let done; - let lastError; - - const listeners = { - progress: (value) => { - done = value === 100; - Images.setProgress(value); - }, - - end: () => { - Images - .hide() - .clearProgress(); - - Object.keys(listeners).forEach((name) => { - emitter.removeListener(name, listeners[name]); - }); - - if (lastError || done) - callback(lastError); - }, - - error: (error) => { - lastError = error; - - if (options.noContinue) { - listeners.end(error); - Dialog.alert(TITLE, error); - return; - } - - Dialog.confirm(TITLE, error + '\n Continue?') - .then(() => { - emitter.continue(); - }, () => { - emitter.abort(); - }); - } - }; - - const events = Object.keys(listeners); - - events.forEach((name) => { - emitter.on(name, listeners[name]); - }); - } - - this.hide = () => { - CloudCmd.View.hide(); - }; - - this.show = (operation, data) => { - if (Loaded) - switch(operation) { - case 'copy': - Operation.copy(data); - break; - - case 'move': - Operation.move(data); - break; - - case 'delete': - Operation.delete(); - break; - - case 'delete:silent': - Operation.deleteSilent(); - break; - - case 'pack': - Operation.pack(); - break; - - case 'extract': - Operation.extract(); - break; - } - }; - - this.copy = (data) => { - processFiles(data, copyFn, message('Copy')); - }; - - this.move = (data) => { - processFiles(data, moveFn, message('Rename/Move')); - }; - - this.delete = () => { - promptDelete(); - }; - - this.deleteSilent = () => { - deleteSilent(); - }; - - this.pack = () => { - const isZip = config('packer') === 'zip'; - twopack('pack', isZip ? 'zip' : 'tar'); - }; - - this.extract = () => { - twopack('extract'); - }; - - /** - * prompt and delete current file or selected files - * - * @currentFile - */ - function promptDelete() { - var type, isDir, msg, - name = '', - msgAsk = 'Do you really want to delete the ', - msgSel = 'selected ', - files = DOM.getSelectedFiles(), - names = DOM.getFilenames(files), - i, - n = names.length, - current = DOM.getCurrentFile(); - - if (n) { - for (i = 0; i < 5 && i < n; i++) - name += '\n' + names[i]; - - if (n >= 5) - name += '\n...'; - - msg = msgAsk + msgSel + n + ' files/directories?\n' + name ; - } else { - isDir = DOM.isCurrentIsDir(current); - - if (isDir) - type = 'directory'; - else - type = 'file'; - - type += ' '; - - name = DOM.getCurrentName(current); - msg = msgAsk + msgSel + type + name + '?'; - } - - if (name === '..') - return Dialog.alert.noFiles(TITLE); - - Dialog.confirm(TITLE, msg, {cancel: false}).then(() => { - deleteSilent(files); - }); - } - - /** - * delete current or selected files - * - * @files - */ - function deleteSilent(files) { - var n, names, - query = '?files', - path = Info.dirPath, - name = Info.name; - - if (name === '..') - return Dialog.alert.noFiles(TITLE); - - showLoad(); - - if (!files) - files = DOM.getSelectedFiles(); - - names = DOM.getFilenames(files), - n = names.length; - - if (!n) - names = [Info.name]; - - deleteFn(path + query, names, (error) => { - var Storage = DOM.Storage, - dirPath = Info.dirPath, - delCurrent = DOM.deleteCurrent, - delSelected = DOM.deleteSelected, - getByName = DOM.getCurrentByName; - - if (!error) { - if (n > 1) - delSelected(files); - else - delCurrent(getByName(name)); - - Storage.removeMatch(dirPath); - } - }); - } - - /* - * process files (copy or move) - * @param data - * @param operation - */ - function processFiles(data, operation, message) { - var name, selFiles, files, - panel, - shouldAsk, - sameName, - ok, - - from = '', - to = '', - - names = []; - - if (data) { - from = data.from; - to = data.to; - names = data.names; - panel = Info.panel; - } else { - from = Info.dirPath; - to = DOM.getNotCurrentDirPath(); - selFiles = DOM.getSelectedFiles(); - names = DOM.getFilenames(selFiles); - data = {}; - shouldAsk = true; - panel = Info.panelPassive; - } - - if (!names.length) - names.push(DOM.getCurrentName()); - - name = names[0]; - - sameName = !!DOM.getCurrentByName(name, panel); - - if (name === '..') - return Dialog.alert.noFiles(TITLE); - - if (shouldAsk) - return message(to, names).then(ask); - - ask(to); - - function ask(to) { - ok = from !== to && to; - - if (ok && !shouldAsk || !sameName) - return go(); - - const str = `"${ name }" already exist. Overwrite?`; - const cancel = false; - - Dialog.confirm(TITLE, str, {cancel}).then(go); - - function go() { - showLoad(); - - files = { - from : from, - to : to, - names : names - }; - - operation(files, (error) => { - !error && DOM.Storage.remove(from, () => { - const panel = Info.panel; - const panelPassive = Info.panelPassive; - const setCurrent = () => { - if (!name) - name = data.names[0]; - - DOM.setCurrentByName(name); - }; - - if (!Info.isOnePanel) - CloudCmd.refresh({ - panel: panelPassive, - noCurrent: true, - }); - - CloudCmd.refresh({panel}, setCurrent); - }); - }); - } - } - } - - function checkEmpty(name, operation) { - if (!operation) - throw Error(name + ' could not be empty!'); - } - - function twopack(operation, type) { - let op; - let fileFrom; - let currentName = Info.name; - - const Images = DOM.Images; - const path = Info.path; - const dirPath = Info.dirPath; - const activeFiles = DOM.getActiveFiles(); - const names = DOM.getFilenames(activeFiles); - - checkEmpty('operation', operation); - - if (!names.length) - return Dialog.alert.noFiles(TITLE); - - switch(operation) { - case 'extract': - op = extractFn; - - fileFrom = { - from: path, - to: dirPath - }; - - currentName = removeExtension(currentName); - - break; - - case 'pack': - op = packFn; - - if (names.length > 1) - currentName = Info.dir; - - currentName += DOM.getPackerExt(type); - - fileFrom = { - from: dirPath, - to: dirPath + currentName, - names, - }; - break; - } - - Images.show.load('top'); - - op(fileFrom, (error) => { - !error && CloudCmd.refresh({ - currentName - }); - }); - } - - function message(msg) { - return (to, names) => { - const n = names.length; - const name = names[0]; - - msg += ' '; - - if (names.length > 1) - msg += n + ' file(s)'; - else - msg += '"' + name + '"'; - - msg += ' to'; - - const cancel = false; - - return Dialog.prompt(TITLE, msg, to, {cancel}); - }; - } - - function load(callback) { - const prefix = CloudCmd.PREFIX; - const files = [ - '/spero/spero.js', - '/remedy/remedy.js', - '/ishtar/ishtar.js', - '/salam/salam.js', - '/omnes/omnes.js' - ].map((name) => { - return prefix + name; - }); - - DOM.load.parallel(files, (error) => { - if (error) - return Dialog.alert(TITLE, error.message); + const {prefix, prefixSocket} = CloudCmd; + await loadAll(); + await initOperations(prefix, prefixSocket, callback); + }, + (callback) => { Loaded = true; - Util.timeEnd(Name + ' load'); - exec(callback); - }); - - Util.time(Name + ' load'); - } + Images.hide(); + callback(); + }, + ], callback); +}); + +function _authCheck(spawn, ok) { + const accept = wraptile(ok); + const alertDialog = wraptile(Dialog.alert); - init(); + spawn.on('accept', accept(spawn)); + spawn.on('reject', alertDialog('Wrong credentials!')); + spawn.emit('auth', config('username'), config('password')); } +const onConnect = currify((fn, operator) => { + setOperations(operator); + fn(); +}); + +async function initOperations(prefix, socketPrefix, fn) { + socketPrefix = `${socketPrefix}/fileop`; + + const operator = await globalThis.fileop({ + prefix, + socketPrefix, + }); + + operator.on('connect', authCheck(operator, onConnect(fn))); +} + +function setOperations(operator) { + packTarFn = ({from, to, names}, callback) => { + const operation = 'Tar'; + const listen = setListeners({ + operation, + callback, + noContinue: true, + from, + to, + }); + + operator + .tar(from, to, names) + .then(listen); + }; + + packZipFn = ({from, to, names}, callback) => { + const operation = 'Zip'; + const listen = setListeners({ + operation, + callback, + noContinue: true, + from, + to, + }); + + operator + .zip(from, to, names) + .then(listen); + }; + + deleteFn = (from, files, callback) => { + from = removeQuery(from); + + const operation = 'Delete'; + const listen = setListeners({ + operation, + callback, + from, + }); + + operator + .remove(from, files) + .then(listen); + }; + + copyFn = ({from, to, names}, callback) => { + const operation = 'Copy'; + const listen = setListeners({ + operation, + callback, + from, + to, + names, + }); + + operator + .copy(from, to, names) + .then(listen); + }; + + moveFn = ({from, to, names}, callback) => { + const operation = 'Move'; + const listen = setListeners({ + operation, + callback, + from, + to, + }); + + operator + .move(from, to, names) + .then(listen); + }; + + extractFn = ({from, to}, callback) => { + const operation = 'Extract'; + const listen = setListeners({ + operation, + callback, + noContinue: true, + from, + to, + }); + + operator + .extract(from, to) + .then(listen); + }; +} + +function getPacker(type) { + if (type === 'zip') + return packZipFn; + + return packTarFn; +} + +export function hide() { + CloudCmd.View.hide(); +} + +export function show(operation, data) { + if (!Loaded) + return; + + if (operation === 'copy') + return Operation.copy(data); + + if (operation === 'move') + return Operation.move(data); + + if (operation === 'delete') + return Operation.delete(); + + if (operation === 'delete:silent') + return Operation.deleteSilent(); + + if (operation === 'pack') + return Operation.pack(); + + if (operation === 'extract') + return Operation.extract(); +} + +Operation.copy = processFiles({ + type: 'copy', +}); + +Operation.move = processFiles({ + type: 'move', +}); + +Operation.delete = promptDelete; + +Operation.deleteSilent = deleteSilent; + +Operation.pack = () => { + const isZip = config('packer') === 'zip'; + twopack('pack', isZip ? 'zip' : 'tar'); +}; + +Operation.extract = () => { + twopack('extract'); +}; + +/** + * prompt and delete current file or selected files + * + * @currentFile + */ +async function promptDelete() { + if (noFilesCheck()) + return; + + const msgAsk = 'Do you really want to delete the '; + const msgSel = 'selected '; + + const files = DOM.getActiveFiles(); + const names = DOM.getFilenames(files); + const n = names.length; + + let msg; + + if (n) { + let name = ''; + + for (let i = 0; i < 5 && i < n; i++) + name += '\n' + names[i]; + + if (n >= 5) + name += '\n...'; + + msg = msgAsk + msgSel + n + ' files/directories?\n' + encode(name); + } else { + const current = DOM.getCurrentFile(); + const isDir = DOM.isCurrentIsDir(current); + const getType = (isDir) => isDir ? 'directory' : 'file'; + + const type = getType(isDir) + ' '; + + const name = DOM.getCurrentName(current); + + msg = msgAsk + msgSel + type + name + '?'; + } + + const [cancel] = await Dialog.confirm(msg); + + if (cancel) + return; + + deleteSilent(files); +} + +/** + * delete current or selected files + * + * @files + */ +function deleteSilent(files = DOM.getActiveFiles()) { + const query = '?files'; + const path = Info.dirPath; + + if (noFilesCheck()) + return; + + showLoad(); + + const removedNames = DOM.getFilenames(files); + const names = DOM.CurrentInfo.files.map(DOM.getCurrentName); + const currentName = DOM.getCurrentName(); + const nextCurrentName = getNextCurrentName(currentName, names, removedNames); + + deleteFn(path + query, removedNames, async () => { + await CloudCmd.refresh(); + + const names = Info.files.map(DOM.getCurrentName); + const isCurrent = names.includes(currentName); + + const name = isCurrent ? currentName : nextCurrentName; + + DOM.setCurrentByName(name); + }); +} + +/* + * process files (copy or move) + * @param data + * @param operation + */ +async function _processFiles(options, data) { + let selFiles; + let files; + let panel; + let shouldAsk; + let ok; + + let from = ''; + let to = ''; + + let names = []; + + if (data) { + ({ + from, + to, + names, + } = data); + + ({panel} = Info); + } else { + from = Info.dirPath; + to = DOM.getNotCurrentDirPath(); + selFiles = DOM.getSelectedFiles(); + names = DOM.getFilenames(selFiles); + data = {}; + shouldAsk = true; + panel = Info.panelPassive; + } + + if (!names.length) + names.push(DOM.getCurrentName()); + + const [name] = names; + + const sameName = DOM.getCurrentByName(name, panel); + + if (!data && noFilesCheck()) + return; + + const {type} = options; + + const isCopy = type === 'copy'; + const option = isCopy ? 'confirmCopy' : 'confirmMove'; + const title = isCopy ? 'Copy' : 'Rename/Move'; + const operation = isCopy ? copyFn : moveFn; + + if (shouldAsk && config(option)) { + const [cancel, newTo] = await prompt(title, to, names.map(encode)); + + if (!cancel) + ask(newTo); + + return; + } + + ask(to); + + function ask(to) { + ok = from !== to && to; + + if (ok && !shouldAsk || !sameName) + return go(); + + const str = `"${name}" already exist. Overwrite?`; + const cancel = false; + + Dialog + .confirm(str, { + cancel, + }) + .then(go); + + function go() { + showLoad(); + + files = { + from, + to, + names, + }; + + operation(files, async () => { + await DOM.Storage.remove(from); + + const {panel, panelPassive} = Info; + + if (!Info.isOnePanel) + CloudCmd.refresh({ + panel: panelPassive, + noCurrent: true, + }); + + CloudCmd.refresh({ + panel, + }); + }); + } + } +} + +function checkEmpty(name, operation) { + if (!operation) + throw Error(`${name} could not be empty!`); +} + +function twopack(operation, type) { + let op; + let fileFrom; + let currentName = Info.name; + + const {path, dirPath} = Info; + + const activeFiles = DOM.getActiveFiles(); + const names = DOM.getFilenames(activeFiles); + + checkEmpty('operation', operation); + + if (!names.length) + return Dialog.alert.noFiles(); + + switch(operation) { + case 'extract': + op = extractFn; + + fileFrom = { + from: path, + to: dirPath, + }; + + currentName = removeExtension(currentName); + + break; + + case 'pack': + op = getPacker(type); + + if (names.length > 1) + currentName = Info.dir; + + currentName += DOM.getPackerExt(type); + + fileFrom = { + from: dirPath, + to: dirPath + currentName, + names, + }; + break; + } + + showLoad(); + + op(fileFrom, (error) => { + !error && CloudCmd.refresh({ + currentName, + }); + }); +} + +async function prompt(msg, to, names) { + const n = names.length; + const [name] = names; + + msg += ' '; + + if (names.length > 1) + msg += `${n} file(s)`; + else + msg += `"${name}"`; + + msg += ' to'; + + return await Dialog.prompt(msg, to); +} + +globalThis.CloudCmd[Name] = { + init, + hide, + show, +}; + +async function loadAll() { + const {prefix} = globalThis.CloudCmd; + const file = `${prefix}/fileop/fileop.js`; + + const [error] = await tryToCatch(load.js, file); + + if (error) + Dialog.alert(error.message); + + Loaded = true; +} diff --git a/client/modules/operation/remove-extension.js b/client/modules/operation/remove-extension.js index 52772c30..e6ce2c46 100644 --- a/client/modules/operation/remove-extension.js +++ b/client/modules/operation/remove-extension.js @@ -1,20 +1,17 @@ -'use strict'; +import {getExt} from '#common/util'; -const {getExt} = require('../../../common/util'); - -module.exports = (name) => { +export const removeExtension = (name) => { const ext = getExtension(name); return name.replace(ext, ''); }; function getExtension(name) { - if (/\.tar\.gz$/.test(name)) + if (name.endsWith('.tar.gz')) return '.tar.gz'; - if (/\.tar\.bz2$/.test(name)) + if (name.endsWith('.tar.bz2')) return '.tar.bz2'; return getExt(name); } - diff --git a/test/client/modules/operation/remove-extension.js b/client/modules/operation/remove-extension.spec.js similarity index 81% rename from test/client/modules/operation/remove-extension.js rename to client/modules/operation/remove-extension.spec.js index 6491f052..fa11e9e2 100644 --- a/test/client/modules/operation/remove-extension.js +++ b/client/modules/operation/remove-extension.spec.js @@ -1,9 +1,5 @@ -'use strict'; - -const test = require('tape'); -const dir = '../../../../client/modules/operation'; - -const removeExtension = require(`${dir}/remove-extension`); +import test from 'supertape'; +import {removeExtension} from './remove-extension.js'; test('cloudcmd: client: modules: operation: removeExtension: .tar.gz', (t) => { const name = 'hello'; @@ -16,7 +12,7 @@ test('cloudcmd: client: modules: operation: removeExtension: .tar.gz', (t) => { test('cloudcmd: client: modules: operation: removeExtension: .tar.bz2', (t) => { const name = 'hello'; const fullName = `${name}.tar.bz2`; - + t.equal(removeExtension(fullName), name, 'should remove .tar.bz2'); t.end(); }); @@ -24,8 +20,7 @@ test('cloudcmd: client: modules: operation: removeExtension: .tar.bz2', (t) => { test('cloudcmd: client: modules: operation: removeExtension: .bz2', (t) => { const name = 'hello'; const fullName = `${name}.bz2`; - + t.equal(removeExtension(fullName), name, 'should remove .bz2'); t.end(); }); - diff --git a/client/modules/operation/set-listeners.js b/client/modules/operation/set-listeners.js new file mode 100644 index 00000000..e54e7d14 --- /dev/null +++ b/client/modules/operation/set-listeners.js @@ -0,0 +1,75 @@ +/* global DOM */ +import forEachKey from 'for-each-key'; +import wraptile from 'wraptile'; +import {format} from './format.js'; + +const {Dialog, Images} = DOM; + +export const setListeners = (options) => (emitter) => { + const { + operation, + callback, + noContinue, + from, + to, + } = options; + + let done; + + const onAbort = wraptile(({emitter, operation}) => { + emitter.abort(); + + const msg = `${operation} aborted`; + + Dialog.alert(msg, { + cancel: false, + }); + }); + + const removeListener = emitter.removeListener.bind(emitter); + const on = emitter.on.bind(emitter); + + const message = format(operation, from, to); + const progress = Dialog.progress(message); + + progress.catch(onAbort({ + emitter, + operation, + })); + + const listeners = { + progress: (value) => { + done = value === 100; + progress.setProgress(value); + }, + + end: () => { + Images.hide(); + forEachKey(removeListener, listeners); + progress.remove(); + + callback(); + }, + + error: async (error) => { + if (noContinue) { + listeners.end(error); + Dialog.alert(error); + progress.remove(); + + return; + } + + const [cancel] = await Dialog.confirm(`${error} + Continue?`); + + if (!done && !cancel) + return emitter.continue(); + + emitter.abort(); + progress.remove(); + }, + }; + + forEachKey(on, listeners); +}; diff --git a/client/modules/polyfill.js b/client/modules/polyfill.js index ef50ea21..90b62689 100644 --- a/client/modules/polyfill.js +++ b/client/modules/polyfill.js @@ -1,188 +1,15 @@ -'use strict'; +import _scrollIntoViewIfNeeded from 'scroll-into-view-if-needed'; -/* global Util, DOM, $ */ +globalThis.DOM = globalThis.DOM || {}; -const itype = require('itype/legacy'); - -if (!window.XMLHttpRequest || !document.head) - DOM.load.ajax = $.ajax; - -/* setting head ie6 - ie8 */ -if (!document.head) - document.head = $('head')[0]; - -if (!Function.bind) - Function.prototype.bind = function (context) { - var aArgs = [].slice.call(arguments, 1), - fToBind = this, - NOP = function () {}, - fBound = function () { - var arr = [].slice.call(arguments), - args = aArgs.concat(arr); - - return fToBind.apply(context, args); - }; - - NOP.prototype = this.prototype; - fBound.prototype = new NOP(); - - return fBound; - }; - -if (!Array.isArray) - Array.isArray = itype.array.bind(); - -if (!document.addEventListener) - /** - * safe add event listener on ie - * @param pType - * @param pListener - */ - DOM.Events.add = (pType, element, listener) => { - return $(element || window).bind(itype, null, listener); - }; - -if (!document.removeEventListener) { - DOM.Events.remove = (pType, pElement, pListener) => { - if (!pElement) - pElement = window; - - $(pElement).unbind(pType, pListener); - }; -} - -if (!document.getElementsByClassName) { - DOM.getByClassAll = (className, el) => { - const selector = '.' + className; - - if (el) - return $(el).find(selector); - - return $.find(selector); - - }; -} - -/* function polyfill webkit standart function - * https://gist.github.com/2581101 - */ -DOM.scrollIntoViewIfNeeded = function(element, centerIfNeeded) { - var parent, - topWidth, - leftWidth, - parentComputedStyle, - parentBorderTopWidth, - parentBorderLeftWidth, - overTop, - overBottom, - overLeft, - overRight, - alignWithTop; +export const scrollIntoViewIfNeeded = (el, overrides = {}) => { + const { + scroll = _scrollIntoViewIfNeeded, + } = overrides; - if (window.getComputedStyle) { - if (arguments.length === 1) - centerIfNeeded = false; - - parent = element.parentNode; - parentComputedStyle = window.getComputedStyle(parent, null); - - topWidth = parentComputedStyle.getPropertyValue('border-top-width'); - leftWidth = parentComputedStyle.getPropertyValue('border-left-width'); - - parentBorderTopWidth = parseInt(topWidth, 10); - parentBorderLeftWidth = parseInt(leftWidth, 10); - - overTop = element.offsetTop - parent.offsetTop < parent.scrollTop, - overBottom = - (element.offsetTop - - parent.offsetTop + - element.clientHeight - - parentBorderTopWidth) > - (parent.scrollTop + parent.clientHeight), - - overLeft = element.offsetLeft - - parent.offsetLeft < parent.scrollLeft, - - overRight = - (element.offsetLeft - - parent.offsetLeft + - element.clientWidth - - parentBorderLeftWidth) > - (parent.scrollLeft + parent.clientWidth), - - alignWithTop = overTop && !overBottom; - - if ((overTop || overBottom) && centerIfNeeded) - parent.scrollTop = - element.offsetTop - - parent.offsetTop - - parent.clientHeight / 2 - - parentBorderTopWidth + - element.clientHeight / 2; - - if ((overLeft || overRight) && centerIfNeeded) - parent.scrollLeft = - element.offsetLeft - - parent.offsetLeft - - parent.clientWidth / 2 - - parentBorderLeftWidth + - element.clientWidth / 2; - - if ((overTop || overBottom || overLeft || overRight) && !centerIfNeeded) - element.scrollIntoView(alignWithTop); - } + return scroll(el, { + block: 'nearest', + }); }; -if (!window.JSON) { - window.JSON = {}; - - window.JSON.parse = $.parseJSON; - - /* https://gist.github.com/754454 */ - window.JSON.stringify = function(obj) { - var n, v, has, - ret = '', - value = '', - json = [], - isStr = itype.string(obj), - isObj = itype.object(obj), - isArray = itype.array(obj); - - if (!isObj || obj === null) { - // simple data type - if (isStr) - obj = '"' + obj + '"'; - - ret += obj; - } else { - // recurse array or object - for (n in obj) { - v = obj[n]; - has = obj.hasOwnProperty(n); - - if (has) { - isStr = itype.string(v); - isObj = itype.object(v); - - if (isStr) - v = '"' + v + '"'; - else if (v && isObj) - v = Util.json.stringify(v); - - if (!isArray) - value = '"' + n + '":'; - - json.push(value + v); - } - } - - if (isArray) - ret = '[' + json + ']'; - else - ret = '{' + json + '}'; - } - - return ret; - }; -} - +globalThis.DOM.scrollIntoViewIfNeeded = scrollIntoViewIfNeeded; diff --git a/client/modules/polyfill.spec.js b/client/modules/polyfill.spec.js new file mode 100644 index 00000000..740947eb --- /dev/null +++ b/client/modules/polyfill.spec.js @@ -0,0 +1,20 @@ +import {test, stub} from 'supertape'; +import {scrollIntoViewIfNeeded} from './polyfill.js'; + +test('cloudcmd: client: polyfill: scrollIntoViewIfNeeded', (t) => { + const scroll = stub(); + const el = {}; + + scrollIntoViewIfNeeded(el, { + scroll, + }); + + const args = [ + el, { + block: 'nearest', + }, + ]; + + t.calledWith(scroll, args, 'should call scrollIntoViewIfNeeded'); + t.end(); +}); diff --git a/client/modules/terminal-run.js b/client/modules/terminal-run.js new file mode 100644 index 00000000..029415ea --- /dev/null +++ b/client/modules/terminal-run.js @@ -0,0 +1,147 @@ +import '../../css/terminal.css'; +import {promisify} from 'es6-promisify'; +import {tryToCatch} from 'try-to-catch'; +import {fullstore} from 'fullstore'; +import exec from 'execon'; +import load from 'load.js'; +import DOM from '#dom'; +import * as Images from '#dom/images'; + +const {Dialog} = DOM; +const {CloudCmd} = globalThis; +const {Key, config} = CloudCmd; + +CloudCmd.TerminalRun = { + init, + show, + hide, +}; + +let Loaded; +let Terminal; +let Socket; + +const exitCodeStore = fullstore(); + +const loadAll = async () => { + const {prefix} = CloudCmd; + + const prefixGritty = getPrefix(); + const js = `${prefixGritty}/gritty.js`; + const css = `${prefix}/dist/terminal.css`; + + const [e] = await tryToCatch(load.parallel, [js, css]); + + if (e) { + const src = e.target.src.replace(globalThis.location.href, ''); + return Dialog.alert(`file ${src} could not be loaded`); + } + + Loaded = true; +}; + +export async function init() { + if (!config('terminal')) + return; + + Images.show.load('top'); + + await CloudCmd.View(); + await loadAll(); +} + +export async function show(options = {}) { + return await runTerminal(options); +} + +const runTerminal = promisify((options, fn) => { + if (!Loaded) + return fn(null, -1); + + if (!config('terminal')) + return; + + create(options); + + CloudCmd.View.show(Terminal.element, { + afterShow: () => { + Terminal.focus(); + }, + afterClose: (/* exec.series args */) => { + fn(null, exitCodeStore()); + }, + }); +}); + +export function hide() { + CloudCmd.View.hide(); +} + +const getPrefix = () => CloudCmd.prefix + '/gritty'; + +function getPrefixSocket() { + return CloudCmd.prefixSocket + '/gritty'; +} + +const getEnv = () => ({ + ACTIVE_DIR: DOM.getCurrentDirPath, + PASSIVE_DIR: DOM.getNotCurrentDirPath, + CURRENT_NAME: DOM.getCurrentName, + CURRENT_PATH: DOM.getCurrentPath, +}); + +function create(createOptions) { + const { + cwd = DOM.getCurrentDirPath(), + command, + autoClose, + closeMessage = 'Press any key to close Terminal...', + } = createOptions; + + const options = { + cwd, + env: getEnv(), + prefix: getPrefixSocket(), + socketPath: CloudCmd.prefix, + fontFamily: 'Droid Sans Mono', + command, + autoRestart: false, + }; + + let commandExit = false; + + const {socket, terminal} = globalThis.gritty(document.body, options); + + Socket = socket; + Terminal = terminal; + + Terminal.onKey(({domEvent}) => { + const {keyCode, shiftKey} = domEvent; + + if (commandExit) + hide(); + + if (shiftKey && keyCode === Key.ESC) + hide(); + }); + + Socket.on('exit', (code) => { + exitCodeStore(code); + + if (autoClose) + return hide(); + + terminal.write(`\n${closeMessage}`); + commandExit = true; + }); + + Socket.on('connect', exec.with(authCheck, socket)); +} + +function authCheck(spawn) { + spawn.emit('auth', config('username'), config('password')); + + spawn.on('reject', () => { + Dialog.alert('Wrong credentials!'); + }); +} diff --git a/client/modules/terminal.js b/client/modules/terminal.js index 17fc0a5b..186ee0b2 100644 --- a/client/modules/terminal.js +++ b/client/modules/terminal.js @@ -1,128 +1,113 @@ -'use strict'; +import '#css/terminal.css'; +import {tryToCatch} from 'try-to-catch'; +import exec from 'execon'; +import load from 'load.js'; +import * as Images from '#dom/images'; +import DOM from '#dom'; -/* global CloudCmd, gritty */ +const loadParallel = load.parallel; + +const {CloudCmd} = globalThis; -const exec = require('execon'); -const load = require('../dom/load'); -const DOM = require('../dom'); -const Images = require('../dom/images'); const {Dialog} = DOM; +const {Key, config} = globalThis.CloudCmd; -const TITLE = 'Terminal'; +CloudCmd.Terminal = { + init, + show, + hide, +}; -CloudCmd.Terminal = TerminalProto; - -const {Key} = CloudCmd; - -let Element; let Loaded; let Terminal; +let Socket; -const {config} = CloudCmd; +const loadAll = async () => { + const {prefix} = CloudCmd; + + const prefixGritty = getPrefix(); + const js = `${prefixGritty}/gritty.js`; + const css = `${prefix}/dist/terminal.css`; + + const [e] = await tryToCatch(loadParallel, [js, css]); + + if (e) { + const src = e.target.src.replace(globalThis.location.href, ''); + return Dialog.alert(`file ${src} could not be loaded`); + } + + Loaded = true; +}; -function TerminalProto() { +export async function init() { if (!config('terminal')) return; Images.show.load('top'); - exec.series([ - CloudCmd.View, - loadAll, - create, - show, - ]); - - Element = load({ - name: 'div', - className : 'terminal', - }); - - return module.exports; + await CloudCmd.View(); + await loadAll(); + create(); } -module.exports.show = show; - -module.exports.hide = hide; - -function hide () { +export function hide() { CloudCmd.View.hide(); } -function getPrefix() { - return CloudCmd.PREFIX + '/gritty'; +const getPrefix = () => CloudCmd.prefix + '/gritty'; + +function getPrefixSocket() { + return CloudCmd.prefixSocket + '/gritty'; } -function getEnv() { - return { - ACTIVE_DIR: DOM.getCurrentDirPath, - PASSIVE_DIR: DOM.getNotCurrentDirPath, - CURRENT_NAME: DOM.getCurrentName, - CURRENT_PATH: DOM.getCurrentPath - }; -} +const getEnv = () => ({ + ACTIVE_DIR: DOM.getCurrentDirPath, + PASSIVE_DIR: DOM.getNotCurrentDirPath, + CURRENT_NAME: DOM.getCurrentName, + CURRENT_PATH: DOM.getCurrentPath, +}); -function create(callback) { +function create() { const options = { env: getEnv(), - prefix: getPrefix(), - socketPath: CloudCmd.PREFIX, + prefix: getPrefixSocket(), + socketPath: CloudCmd.prefix, + fontFamily: 'Droid Sans Mono', }; - const {socket, terminal} = gritty(Element, options); - - terminal.focus(); + const {socket, terminal} = globalThis.gritty(document.body, options); + Socket = socket; Terminal = terminal; - terminal.on('key', (char, {keyCode, shiftKey}) => { - if (shiftKey && keyCode === Key.ESC) { + Terminal.onKey(({domEvent}) => { + const {keyCode, shiftKey} = domEvent; + + if (shiftKey && keyCode === Key.ESC) hide(); - } }); - socket.on('connect', exec.with(authCheck, socket)); - - exec(callback); + Socket.on('connect', exec.with(authCheck, socket)); } function authCheck(spawn) { - if (!config('auth')) - return; - spawn.emit('auth', config('username'), config('password')); spawn.on('reject', () => { - Dialog.alert(TITLE, 'Wrong credentials!'); + Dialog.alert('Wrong credentials!'); }); } -function show(callback) { +export function show() { if (!Loaded) return; - CloudCmd.View.show(Element, { - afterShow: () => { - if (Terminal) { - Terminal.fit(); // lines corrupt without - Terminal.focus(); - } - - exec(callback); - } - }); -} - -function loadAll(callback) { - const prefix = getPrefix(); - const url = prefix + '/gritty.js'; + if (!config('terminal')) + return; - DOM.load.js(url, (error) => { - if (error) - return Dialog.alert(TITLE, error.message); - - Loaded = true; - exec(callback); + CloudCmd.View.show(Terminal.element, { + afterShow: () => { + Terminal.focus(); + }, }); } - diff --git a/client/modules/upload.js b/client/modules/upload.js index 0337e47f..8433fbf5 100644 --- a/client/modules/upload.js +++ b/client/modules/upload.js @@ -1,60 +1,53 @@ /* global CloudCmd, DOM */ +import createElement from '@cloudcmd/create-element'; +import * as Files from '#dom/files'; +import {uploadFiles} from '#dom/upload-files'; +import * as Images from '#dom/images'; -'use strict'; +CloudCmd.Upload = { + init, + show, + hide, +}; -const exec = require('execon'); - -const load = require('../dom/load'); -const Files = require('../dom/files'); -const Images = require('../dom/images'); -const uploadFiles = require('../dom/upload-files'); - -CloudCmd.Upload = UploadProto; - -function UploadProto() { +export async function init() { Images.show.load('top'); - - exec.series([ - CloudCmd.View, - show - ]); - - return exports; + await CloudCmd.View(); } -module.exports.show = show; -module.exports.hide = hide; - -function show() { +export async function show() { Images.show.load('top'); - Files.get('upload', (error, data) => { - const autoSize = true; - - CloudCmd.View.show(data, { - autoSize, - afterShow, - }); + const innerHTML = await Files.get('upload'); + const autoSize = true; + + const el = createElement('div', { + innerHTML, + }); + + CloudCmd.View.show(el, { + autoSize, + afterShow, }); const fontFamily = [ '"Droid Sans Mono"', '"Ubuntu Mono"', '"Consolas"', - 'monospace' + 'monospace', ].join(', '); - load.style({ - id : 'upload-css', - inner : '[data-name=js-upload-file-button] {' + - `font-family: ${fontFamily};` + - 'font-size: 20px;' + - 'width: 97%' + - '}' + createElement('style', { + dataName: 'upload-css', + innerText: `[data-name=js-upload-file-button] { + font-family: ${fontFamily}; + font-size: 16px; + margin: 10px 0 10px 0; + }`, }); } -function hide() { +export function hide() { CloudCmd.View.hide(); } @@ -71,4 +64,3 @@ function afterShow() { uploadFiles(files); }); } - diff --git a/client/modules/user-menu/get-user-menu.js b/client/modules/user-menu/get-user-menu.js new file mode 100644 index 00000000..aa3a1076 --- /dev/null +++ b/client/modules/user-menu/get-user-menu.js @@ -0,0 +1,8 @@ +export const getUserMenu = (menuFn) => { + const module = {}; + const fn = Function('module', menuFn); + + fn(module); + + return module.exports; +}; diff --git a/client/modules/user-menu/get-user-menu.spec.js b/client/modules/user-menu/get-user-menu.spec.js new file mode 100644 index 00000000..606eb820 --- /dev/null +++ b/client/modules/user-menu/get-user-menu.spec.js @@ -0,0 +1,18 @@ +import test from 'supertape'; +import {getUserMenu} from './get-user-menu.js'; + +test('user-menu: getUserMenu', (t) => { + const menu = `module.exports = { + 'F2 - Rename file': ({DOM}) => { + const {element} = DOM.CurrentInfo; + DOM.renameCurrent(element); + } + }`; + + const result = getUserMenu(menu); + + const [key] = Object.keys(result); + + t.equal(key, 'F2 - Rename file'); + t.end(); +}); diff --git a/client/modules/user-menu/index.js b/client/modules/user-menu/index.js new file mode 100644 index 00000000..60d32d95 --- /dev/null +++ b/client/modules/user-menu/index.js @@ -0,0 +1,192 @@ +import '../../../css/user-menu.css'; +import currify from 'currify'; +import wraptile from 'wraptile'; +import {fullstore} from 'fullstore'; +import load from 'load.js'; +import createElement from '@cloudcmd/create-element'; +import {tryCatch} from 'try-catch'; +import {tryToCatch} from 'try-to-catch'; +import {codeFrameColumns} from '@babel/code-frame'; +import * as Dialog from '#dom/dialog'; +import * as Images from '#dom/images'; +import {getUserMenu} from './get-user-menu.js'; +import {navigate} from './navigate.js'; +import {parseError} from './parse-error.js'; +import {parseUserMenu} from './parse-user-menu.js'; +import {runSelected} from './run.js'; + +const loadCSS = load.css; +const sourceStore = fullstore(); + +const { + CloudCmd, + DOM, + CloudFunc, +} = globalThis; + +const Name = 'UserMenu'; + +CloudCmd[Name] = { + init, + show, + hide, +}; + +const {Key} = CloudCmd; + +export async function init() { + await Promise.all([ + loadCSS(`${CloudCmd.prefix}/dist/user-menu.css`), + CloudCmd.View(), + ]); +} + +const {CurrentInfo} = DOM; + +export async function show() { + Images.show.load('top'); + + const {dirPath} = CurrentInfo; + const res = await fetch(`${CloudCmd.prefix}/api/v1/user-menu?dir=${dirPath}`); + const source = await res.text(); + const [error, userMenu] = tryCatch(getUserMenu, source); + + Images.hide(); + + if (error) + return Dialog.alert(getCodeFrame({ + error, + source, + })); + + sourceStore(source); + + const { + names, + keys, + items, + settings, + } = parseUserMenu(userMenu); + + if (settings.run) + return runSelected(settings.select, items, runUserMenu); + + const button = createElement('button', { + className: 'cloudcmd-user-menu-button', + innerText: 'User Menu', + notAppend: true, + }); + + const select = createElement('select', { + className: 'cloudcmd-user-menu', + innerHTML: fillTemplate(names), + notAppend: true, + size: 10, + }); + + button.addEventListener('click', onButtonClick(userMenu, select)); + select.addEventListener('dblclick', onDblClick(userMenu)); + select.addEventListener('keydown', onKeyDown({ + keys, + userMenu, + })); + + const afterShow = () => select.focus(); + const autoSize = true; + + CloudCmd.View.show([button, select], { + autoSize, + afterShow, + }); +} + +function fillTemplate(options) { + const result = []; + + for (const option of options) + result.push(``); + + return result.join(''); +} + +export function hide() { + CloudCmd.View.hide(); +} + +const onDblClick = currify(async (items, e) => { + const {value} = e.target; + await runUserMenu(items[value]); +}); + +const onButtonClick = wraptile(async (items, {value}) => { + await runUserMenu(items[value]); +}); + +const onKeyDown = currify(async ({keys, userMenu}, e) => { + const {keyCode, target} = e; + + const keyName = e.key.toUpperCase(); + + e.preventDefault(); + e.stopPropagation(); + + let value; + + if (keyCode === Key.ESC) + return hide(); + + if (keyCode === Key.ENTER) + value = userMenu[target.value]; + else if (keys[keyName]) + value = keys[keyName]; + else + return navigate(target, e); + + await runUserMenu(value); +}); + +const runUserMenu = async (fn) => { + hide(); + + const [error] = await tryToCatch(fn, { + DOM, + CloudCmd, + CloudFunc, + tryToCatch, + }); + + if (!error) + return; + + const source = sourceStore(); + + return Dialog.alert(getCodeFrame({ + error, + source, + })); +}; + +function getCodeFrame({error, source}) { + const {code} = error; + + if (!code || code === 'frame') + return error.message; + + const [line, column] = parseError(error); + + const start = { + line, + column, + }; + + const location = { + start, + }; + + const frame = codeFrameColumns(source, location, { + message: error.message, + highlightCode: false, + }); + + return `
${frame}
`; +} diff --git a/client/modules/user-menu/navigate.js b/client/modules/user-menu/navigate.js new file mode 100644 index 00000000..0fa4d672 --- /dev/null +++ b/client/modules/user-menu/navigate.js @@ -0,0 +1,53 @@ +import {fullstore} from 'fullstore'; +import { + J, + K, + UP, + DOWN, +} from '../../key/key.js'; + +const store = fullstore(1); +const isDigit = (a) => /^\d+$/.test(a); + +export const navigate = (el, {key, keyCode}) => { + if (isDigit(key)) + store(Number(key)); + + if (keyCode === DOWN || keyCode === J) { + const count = store(); + store(1); + + return down(el, count); + } + + if (keyCode === UP || keyCode === K) { + const count = store(); + store(1); + + return up(el, count); + } +}; + +function down(el, count) { + const {length} = el; + + if (el.selectedIndex === length - 1) + el.selectedIndex = 0; + else + el.selectedIndex += count; + + if (el.selectedIndex < 0) + el.selectedIndex = length - 1; +} + +function up(el, count) { + const {length} = el; + + if (!el.selectedIndex) + el.selectedIndex = length - 1; + else + el.selectedIndex -= count; + + if (el.selectedIndex < 0) + el.selectedIndex = 0; +} diff --git a/client/modules/user-menu/navigate.spec.js b/client/modules/user-menu/navigate.spec.js new file mode 100644 index 00000000..6539c8e9 --- /dev/null +++ b/client/modules/user-menu/navigate.spec.js @@ -0,0 +1,163 @@ +import test from 'supertape'; +import {navigate} from './navigate.js'; +import { + UP, + DOWN, + J, + K, +} from '../../key/key.js'; + +test('cloudcmd: user-menu: navigate: DOWN', (t) => { + const el = { + length: 3, + selectedIndex: 0, + }; + + navigate(el, { + keyCode: DOWN, + }); + + t.equal(el.selectedIndex, 1); + t.end(); +}); + +test('cloudcmd: user-menu: navigate: J', (t) => { + const el = { + length: 3, + selectedIndex: 0, + }; + + navigate(el, { + keyCode: J, + }); + + t.equal(el.selectedIndex, 1); + t.end(); +}); + +test('cloudcmd: user-menu: navigate: DOWN: bottom', (t) => { + const el = { + length: 3, + selectedIndex: 2, + }; + + navigate(el, { + keyCode: DOWN, + }); + + t.equal(el.selectedIndex, 0); + t.end(); +}); + +test('cloudcmd: user-menu: navigate: K', (t) => { + const el = { + length: 3, + selectedIndex: 2, + }; + + navigate(el, { + keyCode: K, + }); + + t.equal(el.selectedIndex, 1); + t.end(); +}); + +test('cloudcmd: user-menu: navigate: UP', (t) => { + const el = { + length: 3, + selectedIndex: 2, + }; + + navigate(el, { + keyCode: UP, + }); + + t.equal(el.selectedIndex, 1); + t.end(); +}); + +test('cloudcmd: user-menu: navigate: UP: top', (t) => { + const el = { + length: 3, + selectedIndex: 0, + }; + + navigate(el, { + keyCode: UP, + }); + + t.equal(el.selectedIndex, 2); + t.end(); +}); + +test('cloudcmd: user-menu: navigate', (t) => { + const el = { + length: 3, + selectedIndex: 0, + }; + + navigate(el, { + keyCode: 0, + }); + + t.equal(el.selectedIndex, 0, 'should not change'); + t.end(); +}); + +test('cloudcmd: user-menu: navigate: DOWN: count', (t) => { + const el = { + length: 3, + selectedIndex: 0, + }; + + navigate(el, { + keyCode: 53, + key: '5', + }); + + navigate(el, { + keyCode: DOWN, + }); + + t.equal(el.selectedIndex, 5); + t.end(); +}); + +test('cloudcmd: user-menu: navigate: J: count: to big', (t) => { + const el = { + length: 3, + selectedIndex: -Infinity, + }; + + navigate(el, { + keyCode: 53, + key: '5', + }); + + navigate(el, { + keyCode: J, + }); + + t.equal(el.selectedIndex, 2); + t.end(); +}); + +test('cloudcmd: user-menu: navigate: K: count: to small', (t) => { + const el = { + length: 3, + selectedIndex: -Infinity, + }; + + navigate(el, { + keyCode: 53, + key: '5', + }); + + navigate(el, { + keyCode: K, + }); + + t.equal(el.selectedIndex, 0); + t.end(); +}); diff --git a/client/modules/user-menu/parse-error.js b/client/modules/user-menu/parse-error.js new file mode 100644 index 00000000..23d605e0 --- /dev/null +++ b/client/modules/user-menu/parse-error.js @@ -0,0 +1,21 @@ +const isNumber = (a) => typeof a === 'number'; + +export const parseError = (error) => { + const {lineNumber, columnNumber} = error; + + // thank you firefox + if (isNumber(lineNumber) && isNumber(columnNumber)) + return [lineNumber, columnNumber]; + + const before = error.stack.indexOf('>'); + const str = error.stack.slice(before + 1); + const after = str.indexOf(')'); + const newStr = str.slice(1, after); + + const [line, column] = newStr.split(':'); + + return [ + Number(line), + Number(column), + ]; +}; diff --git a/client/modules/user-menu/parse-error.spec.js b/client/modules/user-menu/parse-error.spec.js new file mode 100644 index 00000000..5ec8da45 --- /dev/null +++ b/client/modules/user-menu/parse-error.spec.js @@ -0,0 +1,33 @@ +import test from 'supertape'; +import {parseError} from './parse-error.js'; + +test('user-menu: parse-error', (t) => { + const result = parseError({ + lineNumber: 1, + columnNumber: 2, + }); + + const expected = [1, 2]; + + t.deepEqual(result, expected); + t.end(); +}); + +test('user-menu: parse-error: stack', (t) => { + const stack = ` + ReferenceError: s is not defined + at eval (eval at module.exports (get-user-menu.js:NaN), :1:2) + at module.exports (get-user-menu.js:6) + at tryCatch (VM12611 try-catch.js:7) + at AsyncFunction.show (index.js:67) + `; + + const result = parseError({ + stack, + }); + + const expected = [1, 2]; + + t.deepEqual(result, expected); + t.end(); +}); diff --git a/client/modules/user-menu/parse-user-menu.js b/client/modules/user-menu/parse-user-menu.js new file mode 100644 index 00000000..e4ad39e3 --- /dev/null +++ b/client/modules/user-menu/parse-user-menu.js @@ -0,0 +1,31 @@ +const {entries, assign} = Object; + +export const parseUserMenu = (userMenu) => { + const names = []; + const keys = {}; + const items = {}; + const settings = {}; + + for (const [str, fn] of entries(userMenu)) { + if (str === '__settings') { + assign(settings, userMenu[str]); + continue; + } + + if (str.startsWith('_')) + continue; + + names.push(str); + const [key, name] = str.split(' - '); + + keys[key] = fn; + items[name] = fn; + } + + return { + names, + keys, + items, + settings, + }; +}; diff --git a/client/modules/user-menu/parse-user-menu.spec.js b/client/modules/user-menu/parse-user-menu.spec.js new file mode 100644 index 00000000..fb763209 --- /dev/null +++ b/client/modules/user-menu/parse-user-menu.spec.js @@ -0,0 +1,35 @@ +import {test, stub} from 'supertape'; +import {parseUserMenu} from './parse-user-menu.js'; + +test('cloudcmd: user menu: parse', (t) => { + const fn = stub(); + const __settings = {}; + + const result = parseUserMenu({ + __settings, + 'F2 - Rename file': fn, + '_f': fn, + }); + + const names = [ + 'F2 - Rename file', + ]; + + const keys = { + F2: fn, + }; + + const items = { + 'Rename file': fn, + }; + + const expected = { + names, + keys, + items, + settings: __settings, + }; + + t.deepEqual(result, expected); + t.end(); +}); diff --git a/client/modules/user-menu/run.js b/client/modules/user-menu/run.js new file mode 100644 index 00000000..51e9fe02 --- /dev/null +++ b/client/modules/user-menu/run.js @@ -0,0 +1,5 @@ +export const runSelected = async (selectedItems, items, runUserMenu) => { + for (const selected of selectedItems) { + await runUserMenu(items[selected]); + } +}; diff --git a/client/modules/user-menu/run.spec.js b/client/modules/user-menu/run.spec.js new file mode 100644 index 00000000..86738712 --- /dev/null +++ b/client/modules/user-menu/run.spec.js @@ -0,0 +1,17 @@ +import {test, stub} from 'supertape'; +import {runSelected} from './run.js'; + +test('cloudcmd: client: user menu: run', async (t) => { + const runUserMenu = stub(); + const fn = stub(); + const selected = ['hello']; + + const items = { + hello: fn, + }; + + await runSelected(selected, items, runUserMenu); + + t.calledWith(runUserMenu, [fn]); + t.end(); +}); diff --git a/client/modules/view.js b/client/modules/view.js deleted file mode 100644 index c9a6145f..00000000 --- a/client/modules/view.js +++ /dev/null @@ -1,390 +0,0 @@ -'use strict'; - -/* global CloudCmd, DOM, $ */ - -const itype = require('itype/legacy'); -const rendy = require('rendy'); -const exec = require('execon'); - -const {time} = require('../../common/util'); -const {FS} = require('../../common/cloudfunc'); - -const Files = require('../dom/files'); -const Events = require('../dom/events'); -const load = require('../dom/load'); -const Images = require('../dom/images'); - -CloudCmd.View = ViewProto; - -module.exports = exec.bind(); - -module.exports.show = show; -module.exports.hide = hide; - -let Loading = false; - -const Name = 'View'; -const Info = DOM.CurrentInfo; -const Key = CloudCmd.Key; -const basename = (a) => a.split('/').pop(); - -let El, TemplateAudio, Overlay; - -const Config = { - beforeShow: (callback) => { - Images.hide(); - Key.unsetBind(); - showOverlay(); - exec(callback); - }, - beforeClose: (callback) => { - Events.rmKey(listener); - Key.setBind(); - exec(callback); - hideOverlay(); - }, - afterShow: (callback) => { - El.focus(); - exec(callback); - }, - afterClose : exec, - fitToView : true, - loop : false, - openEffect : 'none', - closeEffect : 'none', - autoSize : false, - height : '100%', - width : '100%', - minWidth : 0, - minHeight : 0, - padding : 0, - preload : 0, - keys : null, - mouseWheel : false, - arrows : false, - helpers : { - overlay : null, - title : null - } -}; - -function ViewProto(callback) { - const func = callback || exec.with(show, null); - - Loading = true; - - exec.series([ - DOM.loadJquery, - loadAll, - (callback) => { - Loading = false; - exec(callback); - } - ], func); - - Config.parent = Overlay = load({ - id : 'js-view', - name : 'div', - className : 'fancybox-overlay fancybox-overlay-fixed' - }); - - ['click', 'contextmenu'].forEach((name) => { - Events.add(name, Overlay, onOverLayClick); - }); - - return module.exports; -} - -function show(data, options) { - const prefixUrl = CloudCmd.PREFIX_URL + FS; - - if (Loading) - return; - - if (options && options.bindKeys !== false) - Events.addKey(listener); - - El = $('
'); - - if (data) { - const element = $(El).append(data); - $.fancybox(element, initConfig(Config, options)); - return; - } - - Images.show.load(); - - const path = prefixUrl + Info.path; - const type = getType(path); - - switch(type) { - default: - return Info.getData((error, data) => { - if (error) - return Images.hide(); - - const element = document.createTextNode(data); - /* add margin only for view text documents */ - El.css('margin', '2%'); - - $.fancybox(El.append(element), Config); - }); - - case 'image': - return showImage(path, prefixUrl); - - case 'media': - return getMediaElement(path, (element) => { - const media = DOM.getByDataName('js-media', element); - const onKey = exec.with(onMediaKey, media); - - $.fancybox.open(element, { - parent : Overlay, - beforeShow : () => { - Config.beforeShow(); - Events.addKey(onKey); - }, - beforeClose : () => { - Config.beforeClose(); - Events.rmKey(onKey); - }, - afterShow: () => { - element - .querySelector('audio, video') - .focus(); - }, - helpers: { - overlay : null, - title : null - } - }); - }); - } -} - -function initConfig(Config, options) { - const config = Object.assign({}, Config); - - if (!options) - return config; - - Object.keys(options).forEach((name) => { - const isConfig = !!config[name]; - const item = options[name]; - const isFunc = itype.function(item); - - if (!isFunc || !isConfig) { - config[name] = options[name]; - return; - } - - const func = config[name]; - config[name] = () => { - exec.series([func, item]); - }; - }); - - return config; -} - -function hide() { - $.fancybox.close(); -} - -function showImage(href, prefixUrl) { - const title = Info.name; - const excludeCurrent = (path) => { - return path !== Info.path; - }; - - const makeTitle = (path) => { - return { - href: prefixUrl + path, - title: basename(path), - }; - }; - - const first = { - href, - title, - }; - - const names = Info.files - .map(DOM.getCurrentPath) - .filter(isImage) - .filter(excludeCurrent) - .map(makeTitle); - - const config = Object.assign({}, Config, { - autoSize : true, - type : 'image', - prevEffect : 'none', - nextEffect : 'none', - arrows : true, - keys : true, - helpers : { - overlay : null, - title : {} - } - }); - - const allNames = [first].concat(names); - - $.fancybox.open(allNames, config); -} - -function isImage(name) { - const images = [ - 'jp(e|g|eg)', - 'gif', - 'png', - 'bmp', - 'webp', - 'svg', - 'ico' - ]; - - return images - .map((ext) => RegExp(`\\.${ext}$`, 'i')) - .some((reg) => reg.test(name)); -} - -function isMedia(name) { - return isAudio(name) || isVideo(name); -} - -function isAudio(name) { - return /\.(mp3|ogg|m4a)$/i.test(name); -} - -function isVideo(name) { - return /\.(mp4|avi)$/i.test(name); -} - -function getType(name) { - if (isImage(name)) - return 'image'; - - if (isMedia(name)) - return 'media'; -} - -function getMediaElement(src, callback) { - check(src, callback); - - Files.get('view/media-tmpl', (error, template) => { - const {name} = Info; - - if (error) - return alert(error); - - if (!TemplateAudio) - TemplateAudio = template; - - const is = isAudio(name); - const type = is ? 'audio' : 'video'; - - const rendered = rendy(TemplateAudio, { - src, - type, - name, - }); - - const [element] = $(rendered); - callback(element); - }); -} - -function check(src, callback) { - if (typeof src !== 'string') - throw Error('src should be a string!'); - - if (typeof callback !== 'function') - throw Error('callback should be a function'); -} - -function onMediaKey(media, event) { - const {keyCode} = event; - - if (keyCode === Key.SPACE) { - if (media.paused) - media.play(); - else - media.pause(); - } -} - -/** - * function loads css and js of FancyBox - * @callback - executes, when everything loaded - */ -function loadAll(callback) { - time(Name + ' load'); - - DOM.loadRemote('fancybox', () => { - const {PREFIX} = CloudCmd; - - load.css(PREFIX + '/css/view.css', callback); - - load.style({ - id : 'view-inlince-css', - inner : [ - '.fancybox-title-float-wrap .child {', - '-webkit-border-radius: 0;', - '-moz-border-radius: 0;', - 'border-radius: 0;', - '}' - ].join('') - }); - }); -} - -function onOverLayClick(event) { - const files = Info.files; - const filesPassive = Info.filesPassive; - const {target} = event; - const isOverlay = target === Overlay; - const position = { - x: event.clientX, - y: event.clientY - }; - - if (!isOverlay) - return; - - hideOverlay(); - - const element = DOM.getCurrentByPosition(position); - - if (!element) - return; - - const isFiles = ~files.indexOf(element); - const isFilesPassive = ~filesPassive.indexOf(element); - - if (!isFiles && !isFilesPassive) - return; - - const isCurrent = DOM.isCurrentFile(element); - - if (isCurrent) - return; - - DOM.setCurrentFile(element); - - hide(); -} - -function hideOverlay() { - Overlay.classList.remove('view-overlay'); -} - -function showOverlay() { - Overlay.classList.add('view-overlay'); -} - -function listener({keyCode}) { - if (keyCode === Key.ESC) - hide(); -} - diff --git a/client/modules/view/get-type.js b/client/modules/view/get-type.js new file mode 100644 index 00000000..a061399f --- /dev/null +++ b/client/modules/view/get-type.js @@ -0,0 +1,51 @@ +import currify from 'currify'; + +const testRegExp = currify((name, reg) => reg.test(name)); +const getRegExp = (ext) => RegExp(`\\.${ext}$`, 'i'); + +const isPDF = (a) => /\.pdf$/i.test(a); +const isHTML = (a) => a.endsWith('.html'); +const isMarkdown = (a) => /.\.md$/.test(a); + +export default (name) => { + if (isPDF(name)) + return 'pdf'; + + if (isImage(name)) + return 'image'; + + if (isMedia(name)) + return 'media'; + + if (isHTML(name)) + return 'html'; + + if (isMarkdown(name)) + return 'markdown'; +}; + +function isImage(name) { + const images = [ + 'jp(e|g|eg)', + 'gif', + 'png', + 'bmp', + 'webp', + 'svg', + 'ico', + ]; + + return images + .map(getRegExp) + .some(testRegExp(name)); +} + +function isMedia(name) { + return isAudio(name) || isVideo(name); +} + +const isAudio = (name) => /\.(mp3|ogg|m4a)$/i.test(name); + +function isVideo(name) { + return /\.(mp4|avi|webm)$/i.test(name); +} diff --git a/client/modules/view/index.js b/client/modules/view/index.js new file mode 100644 index 00000000..6626f1aa --- /dev/null +++ b/client/modules/view/index.js @@ -0,0 +1,372 @@ +import '#css/view.css'; +import {rendy} from 'rendy'; +import currify from 'currify'; +import wraptile from 'wraptile'; +import {tryToCatch} from 'try-to-catch'; +import load from 'load.js'; +import * as _modal from '@cloudcmd/modal'; +import _createElement from '@cloudcmd/create-element'; +import {time} from '#common/util'; +import * as Files from '#dom/files'; +import * as Events from '#dom/events'; +import {FS} from '#common/cloudfunc'; +import * as Images from '#dom/images'; +import {encode} from '#common/entity'; +import { + isImage, + isAudio, + getType, +} from './types.js'; + +const CloudCmd = globalThis.CloudCmd || {}; +const DOM = globalThis.DOM || {}; +const isString = (a) => typeof a === 'string'; +const {assign} = Object; +const {isArray} = Array; + +const lifo = currify((fn, el, cb, name) => fn(name, el, cb)); +const series = wraptile((...a) => { + for (const f of a) + f(); +}); + +const isFn = (a) => typeof a === 'function'; + +const noop = () => {}; +const addEvent = lifo(Events.add); + +const loadCSS = load.css; + +let Loading = false; + +const Name = 'View'; + +CloudCmd[Name] = { + init, + show, + hide, +}; + +const Info = DOM.CurrentInfo; +const {Key} = CloudCmd; + +const basename = (a) => a + .split('/') + .pop(); + +let El; +let TemplateAudio; +let Overlay; + +const Config = { + beforeShow: () => { + Images.hide(); + Key.unsetBind(); + }, + + beforeClose: () => { + Events.rmKey(listener); + Key.setBind(); + }, + + afterShow: () => { + El.focus(); + }, + + onOverlayClick, + afterClose: noop, + autoSize: false, + + helpers: { + title: {}, + }, +}; + +export const _Config = Config; + +export async function init() { + await loadAll(); + + const events = [ + 'click', + 'contextmenu', + ]; + + events.forEach(addEvent( + Overlay, + onOverlayClick, + )); +} + +export async function show(data, options = {}) { + const prefixURL = CloudCmd.prefixURL + FS; + + if (Loading) + return; + + if (!options || options.bindKeys !== false) + Events.addKey(listener); + + El = _createElement('div', { + className: 'view', + notAppend: true, + }); + + El.tabIndex = 0; + + if (data) { + if (isArray(data)) + El.append(...data); + else + El.append(data); + + _modal.open(El, initConfig(options)); + return; + } + + Images.show.load(); + + const path = prefixURL + Info.path; + const type = options.raw ? '' : await getType(path); + + switch(type) { + default: + return await viewFile(); + + case 'markdown': + return await CloudCmd.Markdown.show(Info.path); + + case 'html': + return viewHtml(path); + + case 'image': + return viewImage(Info.path, prefixURL); + + case 'media': + return await viewMedia(path); + + case 'pdf': + return viewPDF(path); + } +} + +export const _createIframe = createIframe; + +function createIframe(src, overrides = {}) { + const { + createElement = _createElement, + } = overrides; + + const element = createElement('iframe', { + src, + width: '100%', + height: '100%', + }); + + element.addEventListener('load', () => { + element.contentWindow.addEventListener('keydown', listener); + }); + + return element; +} + +export const _viewHtml = viewHtml; + +function viewHtml(src, overrides = {}) { + const {modal = _modal} = overrides; + modal.open(createIframe(src), Config); +} + +function viewPDF(src) { + const element = createIframe(src); + + const options = assign({}, Config); + + if (CloudCmd.config('showFileName')) + options.title = Info.name; + + _modal.open(element, options); +} + +async function viewMedia(path) { + const [e, element] = await getMediaElement(path); + + if (e) + return alert(e); + + const allConfig = { + ...Config, + ...{ + autoSize: true, + afterShow: () => { + element + .querySelector('audio, video') + .focus(); + }, + }, + }; + + _modal.open(element, allConfig); +} + +async function viewFile() { + const [error, data] = await Info.getData(); + + if (error) + return Images.hide(); + + const element = document.createTextNode(data); + const options = Config; + + if (CloudCmd.config('showFileName')) + options.title = Info.name; + + El.append(element); + _modal.open(El, options); +} + +const copy = (a) => assign({}, a); + +export const _initConfig = initConfig; + +function initConfig(options) { + const config = copy(Config); + + if (!options) + return config; + + const names = Object.keys(options); + + for (const name of names) { + const isConfig = Boolean(config[name]); + const item = options[name]; + + if (!isFn(item) || !isConfig) { + config[name] = options[name]; + continue; + } + + const fn = config[name]; + + config[name] = series(fn, item); + } + + return config; +} + +export function hide() { + _modal.close(); +} + +function viewImage(path, prefixURL) { + const isSupportedImage = (a) => isImage(a) || a === path; + const makeTitle = (path) => ({ + href: `${prefixURL}${path}`, + title: encode(basename(path)), + }); + + const names = Info.files + .map(DOM.getCurrentPath) + .filter(isSupportedImage); + + const titles = names.map(makeTitle); + + const index = names.indexOf(Info.path); + + const imageConfig = { + index, + autoSize: true, + arrows: true, + keys: true, + helpers: { + title: {}, + }, + }; + + const config = { + ...Config, + ...imageConfig, + }; + + _modal.open(titles, config); +} + +async function getMediaElement(src) { + check(src); + + const [error, template] = await tryToCatch(Files.get, 'view/media-tmpl'); + + if (error) + return [error]; + + const {name} = Info; + + if (!TemplateAudio) + TemplateAudio = template; + + const is = isAudio(name); + const type = is ? 'audio' : 'video'; + + const innerHTML = rendy(TemplateAudio, { + src, + type, + name, + }); + + const element = _createElement('div', { + innerHTML, + }); + + return [null, element]; +} + +function check(src) { + if (!isString(src)) + throw Error('src should be a string!'); +} + +async function loadAll() { + const {DIR_DIST} = CloudCmd; + + time(`${Name} load`); + + Loading = true; + await loadCSS(`${DIR_DIST}/view.css`); + Loading = false; +} + +function onOverlayClick(event) { + const position = { + x: event.clientX, + y: event.clientY, + }; + + setCurrentByPosition(position); +} + +function setCurrentByPosition(position) { + const element = DOM.getCurrentByPosition(position); + + if (!element) + return; + + const {files, filesPassive} = Info; + + const isFiles = files.includes(element); + const isFilesPassive = filesPassive.includes(element); + + if (!isFiles && !isFilesPassive) + return; + + const isCurrent = DOM.isCurrentFile(element); + + if (isCurrent) + return; + + DOM.setCurrentFile(element); +} + +function listener({keyCode}) { + if (keyCode === Key.ESC) + hide(); +} diff --git a/client/modules/view/index.spec.js b/client/modules/view/index.spec.js new file mode 100644 index 00000000..abfbe3f4 --- /dev/null +++ b/client/modules/view/index.spec.js @@ -0,0 +1,98 @@ +import autoGlobals from 'auto-globals'; +import {stub} from '@cloudcmd/stub'; +import {test as tape} from 'supertape'; +import { + _initConfig, + _viewHtml, + _Config, + _createIframe, +} from './index.js'; + +const test = autoGlobals(tape); + +test('cloudcmd: client: view: initConfig', (t) => { + let config; + let i = 0; + + const afterClose = () => ++i; + const options = { + afterClose, + }; + + config = _initConfig(options); + config.afterClose(); + + config = _initConfig(options); + config.afterClose(); + + t.equal(i, 2, 'should not change default config'); + t.end(); +}); + +test('cloudcmd: client: view: initConfig: no options', (t) => { + const config = _initConfig(); + const result = typeof config; + const expected = 'object'; + + t.equal(result, expected); + t.end(); +}); + +test('cloudcmd: client: view: html', (t) => { + const open = stub(); + const modal = { + open, + }; + + const src = '/hello.html'; + + _viewHtml(src, { + modal, + }); + + const [first] = open.args; + const [arg] = first; + + t.deepEqual(first, [arg, _Config]); + t.end(); +}); + +test('cloudcmd: client: view: createIframe', (t) => { + const addEventListener = stub(); + const el = { + addEventListener, + }; + + const createElement = stub().returns(el); + const src = '/hello.html'; + + _createIframe(src, { + createElement, + }); + + const expected = { + src, + height: '100%', + width: '100%', + }; + + t.calledWith(createElement, ['iframe', expected]); + t.end(); +}); + +test('cloudcmd: client: view: createIframe: returns', (t) => { + const addEventListener = stub(); + const el = { + addEventListener, + }; + + const createElement = stub().returns(el); + + const src = '/hello.html'; + const result = _createIframe(src, { + createElement, + }); + + t.equal(result, el); + t.end(); +}); diff --git a/client/modules/view/types.js b/client/modules/view/types.js new file mode 100644 index 00000000..320a4bc8 --- /dev/null +++ b/client/modules/view/types.js @@ -0,0 +1,74 @@ +import {extname} from 'node:path'; +import currify from 'currify'; + +export const isAudio = (name) => /\.(mp3|ogg|m4a|flac)$/i.test(name); + +const testRegExp = currify((name, reg) => reg.test(name)); +const getRegExp = (ext) => RegExp(`\\.${ext}$`, 'i'); + +const isPDF = (a) => /\.pdf$/i.test(a); +const isHTML = (a) => a.endsWith('.html'); +const isMarkdown = (a) => /.\.md$/.test(a); + +export const getType = async (path) => { + const ext = extname(path); + + if (!ext) + path = await detectType(path); + + if (isPDF(path)) + return 'pdf'; + + if (isImage(path)) + return 'image'; + + if (isMedia(path)) + return 'media'; + + if (isHTML(path)) + return 'html'; + + if (isMarkdown(path)) + return 'markdown'; +}; + +export function isImage(name) { + const images = [ + 'jp(e|g|eg)', + 'gif', + 'png', + 'bmp', + 'webp', + 'svg', + 'ico', + ]; + + return images + .map(getRegExp) + .some(testRegExp(name)); +} + +function isMedia(name) { + return isAudio(name) || isVideo(name); +} + +function isVideo(name) { + return /\.(mp4|avi|webm)$/i.test(name); +} + +export const _detectType = detectType; + +async function detectType(path) { + const {headers} = await fetch(path, { + method: 'HEAD', + }); + + for (const [name, value] of headers) { + if (name === 'content-type') + return `.${value + .split('/') + .pop()}`; + } + + return ''; +} diff --git a/client/modules/view/types.spec.js b/client/modules/view/types.spec.js new file mode 100644 index 00000000..f0542c18 --- /dev/null +++ b/client/modules/view/types.spec.js @@ -0,0 +1,51 @@ +import {test, stub} from 'supertape'; +import {isAudio, _detectType} from './types.js'; + +test('cloudcmd: client: view: types: isAudio', (t) => { + const result = isAudio('hello.mp3'); + + t.ok(result); + t.end(); +}); + +test('cloudcmd: client: view: types: isAudio: flac', (t) => { + const result = isAudio('hello.flac'); + + t.ok(result); + t.end(); +}); + +test('cloudcmd: client: view: types: isAudio: no', (t) => { + const result = isAudio('hello'); + + t.notOk(result); + t.end(); +}); + +test('cloudcmd: client: view: types: detectType', async (t) => { + const fetch = stub().returns({ + headers: [], + }); + + globalThis.fetch = fetch; + await _detectType('/hello'); + + const expected = ['/hello', { + method: 'HEAD', + }]; + + t.calledWith(fetch, expected); + t.end(); +}); + +test('cloudcmd: client: view: types: detectType: found', async (t) => { + globalThis.fetch = stub().returns({ + headers: [ + ['content-type', 'image/png'], + ], + }); + const result = await _detectType('/hello'); + + t.equal(result, '.png'); + t.end(); +}); diff --git a/client/sort.js b/client/sort.js index adf769c4..ed0971f3 100644 --- a/client/sort.js +++ b/client/sort.js @@ -1,35 +1,32 @@ -'use strict'; - /* global CloudCmd */ -const DOM = require('./dom'); +import {fullstore} from 'fullstore'; +import DOM from '#dom'; -const Info = DOM.CurrentInfo; -const sort = CloudCmd.sort; -const order = CloudCmd.order; -const position = DOM.getPanelPosition(); - -let sortPrevious = sort[position]; +const sortPrevious = fullstore(); const {getPanel} = DOM; -CloudCmd.sortPanel = (name, panel = getPanel()) => { - const position = panel - .dataset - .name - .replace('js-', ''); +export const initSortPanel = () => { + const {sort} = CloudCmd; + const position = DOM.getPanelPosition(); - if (name !== sortPrevious) { + 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'; - } else { - if (order[position] === 'asc') - order[position] = 'desc'; - else - order[position] = 'asc'; - } - sortPrevious = + sortPrevious(name); sort[position] = name; - const noCurrent = position !== Info.panelPosition; CloudCmd.refresh({ @@ -37,4 +34,3 @@ CloudCmd.sortPanel = (name, panel = getPanel()) => { noCurrent, }); }; - diff --git a/client/sw/register.js b/client/sw/register.js new file mode 100644 index 00000000..928d63c9 --- /dev/null +++ b/client/sw/register.js @@ -0,0 +1,30 @@ +import {tryToCatch} from 'try-to-catch'; + +export const listenSW = (sw, ...args) => { + sw?.addEventListener(...args); +}; + +export async function registerSW(prefix) { + if (!navigator.serviceWorker) + return; + + const isHTTPS = location.protocol === 'https:'; + const isLocalhost = location.hostname === 'localhost'; + + if (!isHTTPS && !isLocalhost) + return; + + const {serviceWorker} = navigator; + const register = serviceWorker.register.bind(serviceWorker); + const [e, sw] = await tryToCatch(register, `${prefix}/sw.js`); + + if (e) + return null; + + return sw; +} + +export async function unregisterSW(prefix) { + const reg = await registerSW(prefix); + reg?.unregister(prefix); +} diff --git a/client/sw/register.spec.js b/client/sw/register.spec.js new file mode 100644 index 00000000..52699f0b --- /dev/null +++ b/client/sw/register.spec.js @@ -0,0 +1,103 @@ +import autoGlobals from 'auto-globals'; +import tape from 'supertape'; +import {stub} from '@cloudcmd/stub'; +import {tryCatch} from 'try-catch'; +import { + listenSW, + registerSW, + unregisterSW, +} from './register.js'; + +const test = autoGlobals(tape); + +test('sw: listen', (t) => { + const addEventListener = stub(); + const sw = { + addEventListener, + }; + + listenSW(sw, 'hello', 'world'); + + t.calledWith(addEventListener, ['hello', 'world'], 'should call addEventListener'); + t.end(); +}); + +test('sw: lesten: no sw', (t) => { + const [e] = tryCatch(listenSW, null, 'hello', 'world'); + + t.notOk(e, 'should not throw'); + t.end(); +}); + +test('sw: register: registerSW: no serviceWorker', async (t, {navigator}) => { + delete navigator.serviceWorker; + + await registerSW(); + + t.pass('should not call register'); + t.end(); +}); + +test('sw: register: registerSW: no https', async (t, {location, navigator}) => { + const {register} = navigator.serviceWorker; + + location.protocol = 'http:'; + + await registerSW(); + + t.notCalled(register, 'should not call register'); + t.end(); +}); + +test('sw: register: registerSW: http', async (t, {location, navigator}) => { + Object.assign(location, { + protocol: 'http:', + hostname: 'cloudcmd.io', + }); + + const {register} = navigator.serviceWorker; + + await registerSW(); + + t.notCalled(register, 'should not call register'); + t.end(); +}); + +test('sw: register: registerSW: https self-signed', async (t, {location, navigator}) => { + Object.assign(location, { + protocol: 'https:', + hostname: 'self-signed.badssl.com', + }); + + const {register} = navigator.serviceWorker; + register.throws(Error('Cannot register service worker!')); + + const result = await registerSW(); + + t.notOk(result, 'should not throw'); + t.end(); +}); + +test('sw: register: registerSW', async (t, {location, navigator}) => { + location.hostname = 'localhost'; + + const {register} = navigator.serviceWorker; + await registerSW('/hello'); + + t.calledWith(register, ['/hello/sw.js'], 'should call register'); + t.end(); +}); + +test('sw: register: unregisterSW', async (t, {location, navigator}) => { + location.hostname = 'localhost'; + + const {serviceWorker} = navigator; + const {register} = serviceWorker; + + register.returns(serviceWorker); + + await unregisterSW('/hello'); + + t.calledWith(register, ['/hello/sw.js'], 'should call register'); + t.end(); +}); diff --git a/client/sw/sw.js b/client/sw/sw.js new file mode 100644 index 00000000..5b5643a3 --- /dev/null +++ b/client/sw/sw.js @@ -0,0 +1,98 @@ +import process from 'node:process'; +import codegen from 'codegen.macro'; +import {tryToCatch} from 'try-to-catch'; +import currify from 'currify'; + +const isDev = process.env.NODE_ENV === 'development'; + +const isGet = (a) => a.method === 'GET'; +const isBasic = (a) => a.type === 'basic'; + +const wait = currify((f, e) => e.waitUntil(f())); +const respondWith = currify((f, e) => { + const {request} = e; + const {url} = request; + const pathname = getPathName(url); + + if (url.endsWith('/') || /\^\/fs/.test(pathname)) + return; + + if (!isGet(request)) + return; + + if (!isBasic(request)) + return; + + if (pathname.startsWith('/api')) + return; + + if (/^socket.io/.test(pathname)) + return; + + e.respondWith(f(e)); +}); + +const getPathName = (url) => new URL(url).pathname; + +const date = codegen`module.exports = '"' + Date() + '"'`; +const NAME = `cloudcmd: ${date}`; + +const createRequest = (a) => new Request(a, { + credentials: 'same-origin', +}); + +const getRequest = (a, request) => { + if (a !== '/') + return request; + + return createRequest('/'); +}; + +globalThis.addEventListener('install', wait(onInstall)); +globalThis.addEventListener('fetch', respondWith(onFetch)); +globalThis.addEventListener('activate', wait(onActivate)); + +async function onActivate() { + console.info(`cloudcmd: sw: activate: ${NAME}`); + + await globalThis.clients.claim(); + const keys = await caches.keys(); + const deleteCache = caches.delete.bind(caches); + + await Promise.all(keys.map(deleteCache)); +} + +async function onInstall() { + console.info(`cloudcmd: sw: install: ${NAME}`); + + await globalThis.skipWaiting(); +} + +async function onFetch(event) { + const {request} = event; + const {url} = request; + const pathname = getPathName(url); + const newRequest = getRequest(pathname, event.request); + + const cache = await caches.open(NAME); + const response = await cache.match(request); + + if (!isDev && response) + return response; + + const [e, resp] = await tryToCatch(fetch, newRequest, { + credentials: 'same-origin', + }); + + if (e) + return new Response(e.message); + + await addToCache(request, resp.clone()); + + return resp; +} + +async function addToCache(request, response) { + const cache = await caches.open(NAME); + return cache.put(request, response); +} diff --git a/common/callbackify.js b/common/callbackify.js new file mode 100644 index 00000000..71160ac7 --- /dev/null +++ b/common/callbackify.js @@ -0,0 +1,9 @@ +const success = (f) => (data) => f(null, data); + +export default (promise) => (...a) => { + const fn = a.pop(); + + promise(...a) + .then(success(fn)) + .catch(fn); +}; diff --git a/common/callbackify.spec.js b/common/callbackify.spec.js new file mode 100644 index 00000000..d1586d5a --- /dev/null +++ b/common/callbackify.spec.js @@ -0,0 +1,26 @@ +import {promisify} from 'node:util'; +import {tryToCatch} from 'try-to-catch'; +import {test, stub} from 'supertape'; +import callbackify from './callbackify.js'; + +test('cloudcmd: common: callbackify: error', async (t) => { + const promise = stub().rejects(Error('hello')); + + const fn = callbackify(promise); + const newPromise = promisify(fn); + const [error] = await tryToCatch(newPromise); + + t.equal(error.message, 'hello'); + t.end(); +}); + +test('cloudcmd: common: callbackify', async (t) => { + const promise = stub().resolves('hi'); + + const fn = callbackify(promise); + const promiseAgain = promisify(fn); + const data = await promiseAgain(); + + t.equal(data, 'hi'); + t.end(); +}); diff --git a/common/cloudfunc.js b/common/cloudfunc.js index e4b9f994..7884d069 100644 --- a/common/cloudfunc.js +++ b/common/cloudfunc.js @@ -1,4 +1,299 @@ -'use strict'; +import {rendy} from 'rendy'; +import currify from 'currify'; +import {fullstore} from 'fullstore'; +import {encode} from '#common/entity'; -module.exports = require('../server/cloudfunc'); +const id = (a) => a; +const NAME = 'Cloud Commander'; +export const dateFormatter = fullstore(id); +export const getHeaderField = currify(_getHeaderField); +export const FS = '/fs'; + +const Path = fullstore(); + +Path('/'); + +const filterOutDotFiles = ({showDotFiles}) => ({name}) => { + if (showDotFiles) + return true; + + return !name.startsWith('.'); +}; + +export const apiURL = '/api/v1'; +export const MAX_FILE_SIZE = 500 * 1024; + +export const formatMsg = (msg, name, status) => { + status = status || 'ok'; + name = name || ''; + + if (name) + name = `("${name}")`; + + return `${msg}: ${status}${name}`; +}; + +/** + * Функция возвращает заголовок веб страницы + * @path + */ +export const getTitle = (options) => { + options = options || {}; + + const {path = Path(), name} = options; + + const array = [ + name || NAME, + path, + ]; + + return array + .filter(Boolean) + .join(' - '); +}; + +/** Функция получает адреса каждого каталога в пути + * возвращаеться массив каталогов + * @param url - адрес каталога + */ +export function getPathLink(url, prefix, template) { + if (!url) + throw Error('url could not be empty!'); + + if (!template) + throw Error('template could not be empty!'); + + const names = url + .split('/') + .slice(1, -1); + + const allNames = [ + '/', + ...names, + ]; + + const lines = []; + const n = allNames.length; + + let path = '/'; + + for (let i = 0; i < n; i++) { + const name = allNames[i]; + const isLast = i === n - 1; + + if (i) + path += `${name}/`; + + if (i && isLast) { + lines.push(`${name}/`); + continue; + } + + const slash = i ? '/' : ''; + + lines.push(rendy(template, { + path, + name, + slash, + prefix, + })); + } + + return lines.join(''); +} + +export function _getDataName(name) { + const encoded = btoa(encodeURI(name)); + return `data-name="js-file-${encoded}" `; +} + +/** + * Функция строит таблицу файлв из JSON-информации о файлах + * @param params - информация о файлах + * + */ +export const buildFromJSON = (params) => { + const { + prefix, + template, + sort = 'name', + order = 'asc', + showDotFiles, + } = params; + + const formatDate = dateFormatter(); + + const templateFile = template.file; + const templateLink = template.link; + const json = params.data; + + const path = encode(json.path); + const {files} = json; + + /* + * Строим путь каталога в котором мы находимся + * со всеми подкаталогами + */ + const htmlPath = getPathLink(path, prefix, template.pathLink); + + let fileTable = rendy(template.path, { + link: prefix + FS + path, + fullPath: path, + path: htmlPath, + }); + + const owner = 'owner'; + const mode = 'mode'; + + const getFieldName = getHeaderField(sort, order); + + const name = getFieldName('name'); + const size = getFieldName('size'); + const date = getFieldName('date'); + const time = getFieldName('time'); + + const header = rendy(templateFile, { + tag: 'div', + attribute: 'data-name="js-fm-header" ', + className: 'fm-header', + type: '', + name, + size, + date, + time, + owner, + mode, + }); + + /* сохраняем путь */ + Path(path); + + fileTable += `${header}
    `; + + /* Если мы не в корне */ + if (path !== '/') { + const dotDot = getDotDot(path); + const link = prefix + FS + dotDot; + + const linkResult = rendy(template.link, { + link, + title: '..', + name: '..', + }); + + const dataName = _getDataName('..'); + const attribute = `draggable="true" ${dataName}`; + + /* Сохраняем путь к каталогу верхнего уровня*/ + fileTable += rendy(template.file, { + tag: 'li', + attribute, + className: '', + type: 'directory', + name: linkResult, + size: '<dir>', + date: '--.--.----', + time: '--:--:--', + owner: '.', + mode: '--- --- ---', + }); + } + + fileTable += files + .filter(filterOutDotFiles({ + showDotFiles, + })) + .map(updateField) + .map((file) => { + const name = encode(file.name); + const link = prefix + FS + path + name; + + const { + type, + mode, + date, + time, + owner, + size, + } = file; + + const linkResult = rendy(templateLink, { + link, + title: name, + name, + attribute: getAttribute(file.type), + }); + + const dataName = _getDataName(file.name); + const attribute = `draggable="true" ${dataName}`; + + return rendy(templateFile, { + tag: 'li', + attribute, + className: '', + type, + name: linkResult, + size, + date: formatDate(date), + time, + owner, + mode, + }); + }) + .join(''); + + fileTable += '
'; + + return fileTable; +}; + +const updateField = (file) => ({ + ...file, + date: file.date || '--.--.----', + time: file.time || '--:--:--', + owner: file.owner || 'root', + size: getSize(file), +}); + +function getAttribute(type) { + if (type === 'directory') + return ''; + + return 'target="_blank" '; +} + +export const _getSize = getSize; + +function getSize({size, type}) { + if (type === 'directory') + return '<dir>'; + + if (/link/.test(type)) + return '<link>'; + + return size; +} + +function _getHeaderField(sort, order, name) { + const arrow = order === 'asc' ? '↑' : '↓'; + + if (sort !== name) + return name; + + if (sort === 'name' && order === 'asc') + return name; + + return `${name}${arrow}`; +} + +export function getDotDot(path) { + // убираем последний слеш и каталог в котором мы сейчас находимся + const lastSlash = path.substr(path, path.lastIndexOf('/')); + const dotDot = lastSlash.substr(lastSlash, lastSlash.lastIndexOf('/')); + + if (!dotDot) + return '/'; + + return dotDot; +} diff --git a/common/cloudfunc.spec.js b/common/cloudfunc.spec.js new file mode 100644 index 00000000..b679feeb --- /dev/null +++ b/common/cloudfunc.spec.js @@ -0,0 +1,364 @@ +import {readFileSync} from 'node:fs'; +import test from 'supertape'; +import {montag} from 'montag'; +import * as cheerio from 'cheerio'; +import {tryCatch} from 'try-catch'; +import { + _getSize, + getPathLink, + buildFromJSON, + _getDataName, + dateFormatter, + formatMsg, + getTitle, + getDotDot, + getHeaderField, +} from '#common/cloudfunc'; + +const templatePath = new URL('../tmpl/fs', import.meta.url).pathname; + +const template = { + pathLink: readFileSync(`${templatePath}/pathLink.hbs`, 'utf8'), + path: readFileSync(`${templatePath}/path.hbs`, 'utf8'), + file: readFileSync(`${templatePath}/file.hbs`, 'utf8'), + link: readFileSync(`${templatePath}/link.hbs`, 'utf8'), +}; + +test('cloudfunc: buildFromJSON: ..', (t) => { + const data = { + path: '/media/', + files: [{ + date: '30.08.2016', + mode: 'rwx rwx rwx', + name: 'floppy', + owner: 'root', + size: '7b', + type: 'directory-link', + }], + }; + + const html = buildFromJSON({ + prefix: '', + template, + data, + }); + + const $ = cheerio.load(html); + const el = $('[data-name="js-file-Li4="]'); + + const result = el + .find('[data-name="js-name"]') + .text(); + + const expected = '..'; + + t.equal(result, expected); + t.end(); +}); + +test('cloudfunc: getPathLink: /', (t) => { + const {pathLink} = template; + const result = getPathLink('/', '', pathLink); + + const expected = montag` + / + `; + + t.equal(result, expected); + t.end(); +}); + +test('cloudfunc: getPathLink: /hello/world', (t) => { + const {pathLink} = template; + const result = getPathLink('/hello/world', '', pathLink); + + const expected = montag` + /hello/ + `; + + t.equal(result, expected); + t.end(); +}); + +test('cloudfunc: getPathLink: prefix', (t) => { + const {pathLink} = template; + const result = getPathLink('/hello/world', '/cloudcmd', pathLink); + + const expected = montag` + /hello/ + `; + + t.equal(result, expected); + t.end(); +}); + +test('cloudfunc: getSize: dir', (t) => { + const type = 'directory'; + const size = 0; + + const result = _getSize({ + type, + size, + }); + + const expected = '<dir>'; + + t.equal(result, expected); + t.end(); +}); + +test('cloudfunc: getSize: link: dir', (t) => { + const type = 'directory-link'; + const size = 0; + + const result = _getSize({ + type, + size, + }); + + const expected = '<link>'; + + t.equal(result, expected); + t.end(); +}); + +test('cloudfunc: getSize: link: file', (t) => { + const type = 'file-link'; + const size = 0; + + const result = _getSize({ + type, + size, + }); + + const expected = '<link>'; + + t.equal(result, expected); + t.end(); +}); + +test('cloudfunc: getSize: file', (t) => { + const type = 'file'; + const size = '100.00kb'; + + const result = _getSize({ + type, + size, + }); + + const expected = '100.00kb'; + + t.equal(result, expected); + t.end(); +}); + +test('cloudfunc: buildFromJSON: showDotFiles: false', (t) => { + const data = { + path: '/media/', + files: [{ + date: '30.08.2016', + mode: 'rwx rwx rwx', + name: '.floppy', + owner: 'root', + size: '7b', + type: 'directory-link', + }], + }; + + const html = buildFromJSON({ + prefix: '', + template, + data, + showDotFiles: false, + }); + + const $ = cheerio.load(html); + const el = $('[data-name="js-file-LmZsb3BweQ=="]'); + + const result = el + .find('[data-name="js-name"]') + .text(); + + const expected = ''; + + t.equal(result, expected); + t.end(); +}); + +test('cloudfunc: buildFromJSON: name: {{ }}', (t) => { + const data = { + path: '/media/', + files: [{ + date: '30.08.2016', + mode: 'rwx rwx rwx', + name: '{{}}', + owner: 'root', + size: '7b', + type: 'file', + }], + }; + + const html = buildFromJSON({ + prefix: '', + template, + data, + showDotFiles: false, + }); + + const $ = cheerio.load(html); + const el = $('[data-name="js-file-JTdCJTdCJTdEJTdE"]'); + + const result = el + .find('[data-name="js-name"]') + .text(); + + const expected = '{{}}'; + + t.equal(result, expected); + t.end(); +}); + +test('cloudfunc: _getDataName', (t) => { + const result = _getDataName('s'); + const expected = 'data-name="js-file-cw==" '; + + t.equal(result, expected); + t.end(); +}); + +test('cloudfunc: formatMsg: name', (t) => { + const result = formatMsg('hello', 'world'); + const expected = 'hello: ok("world")'; + + t.equal(result, expected, 'should format message with name'); + t.end(); +}); + +test('cloudfunc: formatMsg: no name', (t) => { + const result = formatMsg('hello'); + const expected = 'hello: ok'; + + t.equal(result, expected, 'should format message without name'); + t.end(); +}); + +test('cloudfunc: getTitle: no options', (t) => { + const result = getTitle(); + + t.ok(result, 'should return a title string even without options'); + t.end(); +}); + +test('cloudfunc: getTitle: with name', (t) => { + const result = getTitle({ + name: 'MyName', + }); + + t.match(result, 'MyName', 'should return title with name'); + t.end(); +}); + +test('cloudfunc: getHeaderField: sort not name', (t) => { + const result = getHeaderField('size', 'asc', 'name'); + + t.equal(result, 'name', 'should return plain name when sort does not match'); + t.end(); +}); + +test('cloudfunc: getHeaderField: sort name asc', (t) => { + const result = getHeaderField('name', 'asc', 'name'); + + t.equal(result, 'name', 'should return plain name when name asc'); + t.end(); +}); + +test('cloudfunc: getDotDot: root', (t) => { + const result = getDotDot('/'); + + t.equal(result, '/', 'should return / for root path'); + t.end(); +}); + +test('cloudfunc: getPathLink: /a/b/c', (t) => { + const {pathLink} = template; + const result = getPathLink('/a/b/c/', '', pathLink); + + t.ok(result, 'should build path link for 3-segment path'); + t.end(); +}); + +test('cloudfunc: getPathLink: no url', (t) => { + const [error] = tryCatch(getPathLink); + + t.equal(error.message, 'url could not be empty!', 'should throw when url is empty'); + t.end(); +}); + +test('cloudfunc: getPathLink: no template', (t) => { + const [error] = tryCatch(getPathLink, '/'); + + t.equal(error.message, 'template could not be empty!', 'should throw when template is empty'); + t.end(); +}); + +test('cloudfunc: getHeaderField: sort name desc', (t) => { + const result = getHeaderField('name', 'desc', 'name'); + const expected = 'name↓'; + + t.equal(result, expected, 'should return name with down arrow'); + t.end(); +}); + +test('cloudfunc: getDotDot: normal path', (t) => { + const result = getDotDot('/hello/world/'); + const expected = '/hello'; + + t.equal(result, expected, 'should return parent directory'); + t.end(); +}); + +test('cloudfunc: buildFromJSON: formatDate', (t) => { + const data = { + path: '/media/', + files: [{ + date: '30.08.2016', + mode: 'rwx rwx rwx', + name: '{{}}', + owner: 'root', + size: '7b', + type: 'file', + }], + }; + + const oldFormatter = dateFormatter(); + + const formatDate = (str) => { + const [day, month, year] = str.split('.'); + const date = new Date(year, month - 1, day); + + return date.toLocaleDateString('en-US'); + }; + + dateFormatter(formatDate); + + const html = buildFromJSON({ + prefix: '', + template, + data, + showDotFiles: false, + }); + + dateFormatter(oldFormatter); + + const $ = cheerio.load(html); + const el = $('[data-name="js-file-JTdCJTdCJTdEJTdE"]'); + + const result = el + .find('[data-name="js-date"]') + .text(); + + const expected = '8/30/2016'; + + t.equal(result, expected); + t.end(); +}); diff --git a/common/datetime.js b/common/datetime.js new file mode 100644 index 00000000..d7982ab4 --- /dev/null +++ b/common/datetime.js @@ -0,0 +1,31 @@ +import shortdate from 'shortdate'; + +export default (date) => { + date = date || new Date(); + check(date); + + const timeStr = shorttime(date); + const dateStr = shortdate(date); + + return `${dateStr} ${timeStr}`; +}; + +const addZero = (a) => { + if (a > 9) + return a; + + return `0${a}`; +}; + +function shorttime(date) { + const seconds = addZero(date.getSeconds()); + const minutes = addZero(date.getMinutes()); + const hours = addZero(date.getHours()); + + return `${hours}:${minutes}:${seconds}`; +} + +function check(date) { + if (!(date instanceof Date)) + throw Error('date should be instanceof Date!'); +} diff --git a/common/datetime.spec.js b/common/datetime.spec.js new file mode 100644 index 00000000..e3edb2ef --- /dev/null +++ b/common/datetime.spec.js @@ -0,0 +1,50 @@ +import {test} from 'supertape'; +import {tryCatch} from 'try-catch'; +import datetime from './datetime.js'; + +test('common: datetime', (t) => { + const dateStr = 'Fri, 17 Aug 2018 10:56:48'; + const result = datetime(new Date(dateStr)); + + const expected = '2018.08.17 10:56:48'; + + t.equal(result, expected); + t.end(); +}); + +test('common: datetime: no arg', (t) => { + const {Date} = globalThis; + + let called = false; + + globalThis.Date = class extends Date { + constructor() { + super(); + called = true; + } + }; + + datetime(); + + globalThis.Date = Date; + + t.ok(called, 'should call new Date'); + t.end(); +}); + +test('common: 0 before number', (t) => { + const dateStr = 'Fri, 17 Aug 2018 10:56:08'; + const result = datetime(new Date(dateStr)); + + const expected = '2018.08.17 10:56:08'; + + t.equal(result, expected); + t.end(); +}); + +test('common: datetime: wrong args', (t) => { + const [error] = tryCatch(datetime, {}); + + t.equal(error.message, 'date should be instanceof Date!', 'should throw'); + t.end(); +}); diff --git a/common/entity.js b/common/entity.js index 0aa9ab40..690bbd7a 100644 --- a/common/entity.js +++ b/common/entity.js @@ -1,4 +1,31 @@ -'use strict'; +const Entities = { + '<': '<', + '>': '>', + '"': '"', + '{': '{', + '}': '}', +}; -module.exports = require('../server/common/entity'); +const keys = Object.keys(Entities); +export const encode = (str) => { + for (const code of keys) { + const char = Entities[code]; + const reg = RegExp(char, 'g'); + + str = str.replace(reg, code); + } + + return str; +}; + +export const decode = (str) => { + for (const code of keys) { + const char = Entities[code]; + const reg = RegExp(code, 'g'); + + str = str.replace(reg, char); + } + + return str; +}; diff --git a/common/entity.spec.js b/common/entity.spec.js new file mode 100644 index 00000000..79313f7c --- /dev/null +++ b/common/entity.spec.js @@ -0,0 +1,34 @@ +import {test} from 'supertape'; +import * as entity from '#common/entity'; + +test('cloudcmd: entity: encode', (t) => { + const result = entity.encode(' '); + const expected = '<hello> '; + + t.equal(result, expected, 'should encode entity'); + t.end(); +}); + +test('cloudcmd: entity: {{}}', (t) => { + const result = entity.encode('{{}}'); + const expected = '{{}}'; + + t.equal(result, expected, 'should encode entity'); + t.end(); +}); + +test('cloudcmd: entity: decode', (t) => { + const result = entity.decode('<hello> '); + const expected = ' '; + + t.equal(result, expected, 'should decode entity'); + t.end(); +}); + +test('cloudcmd: entity: encode quote', (t) => { + const result = entity.encode('"hello"'); + const expected = '"hello"'; + + t.equal(result, expected, 'should encode entity'); + t.end(); +}); diff --git a/common/omit.js b/common/omit.js new file mode 100644 index 00000000..284c2f5b --- /dev/null +++ b/common/omit.js @@ -0,0 +1,12 @@ +const difference = (a, b) => new Set(a).difference(new Set(b)); +const {keys} = Object; + +export const omit = (a, list) => { + const result = {}; + + for (const key of difference(keys(a), list)) { + result[key] = a[key]; + } + + return result; +}; diff --git a/common/omit.spec.js b/common/omit.spec.js new file mode 100644 index 00000000..ff70541c --- /dev/null +++ b/common/omit.spec.js @@ -0,0 +1,18 @@ +import {test} from 'supertape'; +import {omit} from '#common/omit'; + +test('cloudcmd: common: omit', (t) => { + const a = { + hello: 1, + world: 2, + }; + + const result = omit(a, ['world']); + + const expected = { + hello: 1, + }; + + t.deepEqual(result, expected); + t.end(); +}); diff --git a/common/store.js b/common/store.js deleted file mode 100644 index 88b1ca13..00000000 --- a/common/store.js +++ /dev/null @@ -1,4 +0,0 @@ -'use strict'; - -module.exports = require('../server/common/store'); - diff --git a/common/try-to-promise-all.js b/common/try-to-promise-all.js new file mode 100644 index 00000000..1dcfa3a8 --- /dev/null +++ b/common/try-to-promise-all.js @@ -0,0 +1,12 @@ +import {tryToCatch} from 'try-to-catch'; + +const all = Promise.all.bind(Promise); + +export default async (a) => { + const [e, result = []] = await tryToCatch(all, a); + + return [ + e, + ...result, + ]; +}; diff --git a/common/try-to-promise-all.spec.js b/common/try-to-promise-all.spec.js new file mode 100644 index 00000000..eafb036c --- /dev/null +++ b/common/try-to-promise-all.spec.js @@ -0,0 +1,29 @@ +import {test} from 'supertape'; +import tryToPromiseAll from './try-to-promise-all.js'; + +const resolve = Promise.resolve.bind(Promise); +const reject = Promise.reject.bind(Promise); + +test('commons: try-to-promise-all', async (t) => { + const [, ...result] = await tryToPromiseAll([ + resolve('a'), + resolve('b'), + ]); + + const expected = [ + 'a', + 'b', + ]; + + t.deepEqual(result, expected); + t.end(); +}); + +test('commons: try-to-promise-all: error', async (t) => { + const [e] = await tryToPromiseAll([ + reject('a'), + ]); + + t.equal(e, 'a'); + t.end(); +}); diff --git a/common/util.js b/common/util.js index ecd25390..422b3c22 100644 --- a/common/util.js +++ b/common/util.js @@ -1,66 +1,9 @@ -'use strict'; +import exec from 'execon'; -const exec = require('execon'); -const rendy = require('rendy'); -const jonny = require('jonny'); -const itype = require('itype/legacy'); +const isString = (a) => typeof a === 'string'; -const Scope = global || window; - -module.exports.getStrBigFirst = getStrBigFirst; -module.exports.kebabToCamelCase = kebabToCamelCase; - -/** - * copy objFrom properties to target - * - * @target - * @objFrom - */ -const extend = (target, objFrom) => { - const isFunc = itype.function(objFrom); - const isArray = Array.isArray(objFrom); - const isObj = itype.object(target); - let ret = isObj ? target : {}; - - if (isArray) - objFrom.forEach((item) => { - ret = Util.extend(target, item); - }); - - else if (objFrom) { - const obj = isFunc ? new objFrom() : objFrom; - let keys = Object.keys(obj); - - if (!keys.length) { - const proto = Object.getPrototypeOf(objFrom); - keys = Object.keys(proto); - } - - keys.forEach((name) => { - ret[name] = obj[name]; - }); - } - - return ret; -}; - -module.exports.extend = extend; - -/** - * extend proto - * - * @obj - */ -module.exports.extendProto = (obj) => { - const F = () => {}; - F.prototype = extend({}, obj); - return new F(); -}; - -module.exports.json = jonny; - -module.exports.escapeRegExp = (str) => { - const isStr = typeof str === 'string'; +export const escapeRegExp = (str) => { + const isStr = isString(str); if (isStr) str = str.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&'); @@ -71,27 +14,24 @@ module.exports.escapeRegExp = (str) => { /** * get regexp from wild card */ -module.exports.getRegExp = (wildcard = '*') => { - const escaped = '^' + wildcard // search from start of line - .replace('.', '\\.') - .replace('*', '.*') - .replace('?', '.?') + '$'; // search to end of line +export const getRegExp = (wildcard) => { + const escaped = `^${wildcard // search from start of line + .replace(/\./g, '\\.') + .replace(/\*/g, '.*') + .replace('?', '.?')}$`; - const regExp = new RegExp(escaped); - - return regExp; + // search to end of line + return RegExp(escaped); }; -module.exports.exec = exec; - /** * function gets file extension * * @param name * @return ext */ -module.exports.getExt = (name) => { - const isStr = typeof name === 'string' +export const getExt = (name) => { + const isStr = isString(name); if (!isStr) return ''; @@ -105,37 +45,40 @@ module.exports.getExt = (name) => { }; /** - * find object by name in arrray + * find object by name in array * * @param array * @param name */ -module.exports.findObjByNameInArr = (array, name) => { +export const findObjByNameInArr = (array, name) => { let ret; - if (!Array.isArray(array)) + if (!Array.isArray(array)) throw Error('array should be array!'); - - if (typeof name !== 'string') + + if (!isString(name)) throw Error('name should be string!'); array.some((item) => { - let is = item.name === name; + const is = item.name === name; const isArray = Array.isArray(item); - if (is) + if (is) { ret = item; - else if (isArray) - item.some((item) => { - is = item.name === name; - - if (is) - ret = item.data; - - return is; - }); + return is; + } - return is; + if (!isArray) + return is; + + return item.some((item) => { + const is = item.name === name; + + if (is) + ret = item.data; + + return is; + }); }); return ret; @@ -145,9 +88,7 @@ module.exports.findObjByNameInArr = (array, name) => { * start timer * @param name */ -module.exports.time = (name) => { - const console = Scope.console; - +export const time = (name) => { exec.ifExist(console, 'time', [name]); }; @@ -155,28 +96,6 @@ module.exports.time = (name) => { * stop timer * @param name */ -module.exports.timeEnd = (name) => { - const console = Scope.console; - +export const timeEnd = (name) => { exec.ifExist(console, 'timeEnd', [name]); }; - -function getStrBigFirst(str) { - if (!str) - throw Error('str could not be empty!'); - - const first = str[0].toUpperCase(); - return first + str.slice(1); -} - -function kebabToCamelCase(str) { - if (!str) - throw Error('str could not be empty!'); - - return str - .split('-') - .map(getStrBigFirst) - .join('') - .replace(/.js$/, ''); -} - diff --git a/common/util.spec.js b/common/util.spec.js new file mode 100644 index 00000000..5a19a8be --- /dev/null +++ b/common/util.spec.js @@ -0,0 +1,138 @@ +import test from 'supertape'; +import {tryCatch} from 'try-catch'; +import { + findObjByNameInArr, + getRegExp, + escapeRegExp, + getExt, + time, + timeEnd, +} from '#common/util'; + +test('getExt: no extension', (t) => { + const EXT = ''; + const name = 'file-without-extension'; + const ext = getExt(name); + + t.equal(ext, EXT, 'should return "" when extension is none'); + t.end(); +}); + +test('getExt: return extension', (t) => { + const EXT = '.png'; + const name = 'picture.png'; + const ext = getExt(name); + + t.equal(ext, EXT, 'should return ".png" in files "picture.png"'); + t.end(); +}); + +test('util: getExt: no name', (t) => { + const ext = getExt(); + + t.equal(ext, '', 'should return empty string'); + t.end(); +}); + +test('util: findObjByNameInArr: no array', (t) => { + const [error] = tryCatch(findObjByNameInArr); + + t.equal(error.message, 'array should be array!', 'should throw when no array'); + t.end(); +}); + +test('util: findObjByNameInArr: no name', (t) => { + const [error] = tryCatch(findObjByNameInArr, []); + + t.equal(error.message, 'name should be string!', 'should throw when no array'); + t.end(); +}); + +test('util: findObjByNameInArr: object', (t) => { + const name = 'hello'; + const obj = { + name, + }; + + const array = [obj]; + + const result = findObjByNameInArr(array, name); + + t.equal(result, obj, 'should return obj'); + t.end(); +}); + +test('util: findObjByNameInArr: array', (t) => { + const name = 'hello'; + const data = 'abc'; + + const item = { + name, + data, + }; + + const obj = { + name: 'world', + }; + + const array = [ + name, + [obj, item], + ]; + + const result = findObjByNameInArr(array, name); + + t.equal(result, data, 'should return data'); + t.end(); +}); + +test('util: getRegExp', (t) => { + const reg = getRegExp('help?o.*'); + + t.deepEqual(reg, /^help.?o\..*$/, 'should return regexp'); + t.end(); +}); + +test('util: getRegExp: dots', (t) => { + const reg = getRegExp('h.*el?o.*'); + + t.deepEqual(reg, /^h\..*el.?o\..*$/, 'should return regexp'); + t.end(); +}); + +test('util: getRegExp: no', (t) => { + const reg = getRegExp(''); + + t.deepEqual(reg, /^$/, 'should return regexp'); + t.end(); +}); + +test('util: escapeRegExp: no str', (t) => { + const result = escapeRegExp(1); + const expected = 1; + + t.equal(result, expected); + t.end(); +}); + +test('util: escapeRegExp', (t) => { + const result = escapeRegExp('#hello'); + const expected = '\\#hello'; + + t.equal(result, expected); + t.end(); +}); + +test('util: time', (t) => { + const [error] = tryCatch(time, 'test'); + + t.notOk(error, 'should not throw'); + t.end(); +}); + +test('util: timeEnd', (t) => { + const [error] = tryCatch(timeEnd, 'test'); + + t.notOk(error, 'should not throw'); + t.end(); +}); diff --git a/css/columns/name-size-date-time.css b/css/columns/name-size-date-time.css new file mode 100644 index 00000000..f46e63f8 --- /dev/null +++ b/css/columns/name-size-date-time.css @@ -0,0 +1,26 @@ +.name { + width: 35%; +} + +.size { + float: none; +} + +.owner { + display: none; +} + +.mode { + display: none; +} + +.date { + float: right; + width: 19%; +} + +.time { + display: inline; + float: right; + width: 20%; +} diff --git a/css/columns/name-size-date.css b/css/columns/name-size-date.css new file mode 100644 index 00000000..9248f700 --- /dev/null +++ b/css/columns/name-size-date.css @@ -0,0 +1,25 @@ +.name { + width: 55%; +} + +.size { + float: none; +} + +.owner { + display: none; +} + +.mode { + display: none; +} + +.date { + float: right; + width: 19%; +} + +.time { + display: none; +} + diff --git a/css/columns/name-size-time.css b/css/columns/name-size-time.css new file mode 100644 index 00000000..1bbd59de --- /dev/null +++ b/css/columns/name-size-time.css @@ -0,0 +1,24 @@ +.name { + width: 55%; +} + +.size { + float: none; +} + +.owner { + display: none; +} + +.mode { + display: none; +} + +.date { + display: none; +} + +.time { + float: right; + width: 19%; +} diff --git a/css/columns/name-size.css b/css/columns/name-size.css new file mode 100644 index 00000000..c02472a5 --- /dev/null +++ b/css/columns/name-size.css @@ -0,0 +1,25 @@ +.name { + width: 77%; +} + +.size { + float: none; + margin-right: 0; +} + +.owner { + display: none; +} + +.mode { + display: none; +} + +.date { + display: none; +} + +.time { + display: none; +} + diff --git a/css/config.css b/css/config.css index c1668fa9..4804374a 100644 --- a/css/config.css +++ b/css/config.css @@ -1,5 +1,7 @@ .config { white-space: normal; + overflow: hidden; + width: 250px; } .list li { @@ -16,15 +18,50 @@ padding: 0 12px; font-size: 16px; line-height: 1.5; - color: #555; + color: var(--column-color); + background: var(--internal-background); border: 1px solid #ccc; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); - -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); - box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); - -webkit-transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s; - -moz-transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s; - -o-transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s; - transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s; + -webkit-box-shadow: inset 0 1px 1px rgb(0 0 0 / 7.5%); + -moz-box-shadow: inset 0 1px 1px rgb(0 0 0 / 7.5%); + box-shadow: inset 0 1px 1px rgb(0 0 0 / 7.5%); + -webkit-transition: + border-color ease-in-out 0.15s, + box-shadow ease-in-out 0.15s; + -moz-transition: + border-color ease-in-out 0.15s, + box-shadow ease-in-out 0.15s; + -o-transition: + border-color ease-in-out 0.15s, + box-shadow ease-in-out 0.15s; + transition: + border-color ease-in-out 0.15s, + box-shadow ease-in-out 0.15s; +} + +.config .form-control::-moz-placeholder { + color: #999; +} + +.config .form-control::-ms-input-placeholder { + color: #999; +} + +.config .form-control::-webkit-input-placeholder { + color: #999; +} + +.config .form-control:focus { + border-color: #66afe9; + outline: 0; + -webkit-box-shadow: + inset 0 1px 1px rgb(0 0 0 / 7.5%), + 0 0 1px rgb(102 175 233 / 60%); + -moz-box-shadow: + inset 0 1px 1px rgb(0 0 0 / 7.5%), + 0 0 1px rgb(102 175 233 / 60%); + box-shadow: + inset 0 1px 1px rgb(0 0 0 / 7.5%), + 0 0 1px rgb(102 175 233 / 60%); } .config .form-control:focus:invalid:focus { @@ -34,37 +71,9 @@ box-shadow: 0 0 6px #f8b9b7; } -.config .form-control:focus { - border-color: #66afe9; - outline: 0; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 1px rgba(102, 175, 233, 0.6); - -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 1px rgba(102, 175, 233, 0.6); - box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 1px rgba(102, 175, 233, 0.6); -} - -.config .form-control:-moz-placeholder { - color: #999; -} - -.config .form-control::-moz-placeholder { - color: #999; -} - -.config .form-control:-ms-input-placeholder { - color: #999; -} - -.config .form-control::-webkit-input-placeholder { - color: #999; -} - .config .list { - padding : 0; - margin : 5%; -} - -.config { - width : 250px; + padding: 0; + margin: 5%; } .config .full-width { diff --git a/css/help.css b/css/help.css index 42602618..6728c589 100644 --- a/css/help.css +++ b/css/help.css @@ -1,12 +1,12 @@ .help { - margin : 25px; - white-space : normal; + margin: 25px; + white-space: normal; } .help li { - list-style-type : disc; + list-style-type: disc; } .help img { - max-width : 100%; + max-width: 100%; } diff --git a/css/icons.css b/css/icons.css index aece5439..ca4a1181 100644 --- a/css/icons.css +++ b/css/icons.css @@ -1,134 +1,144 @@ .icon-help::before { - font-family : 'Fontello'; - content : '\e801 '; + font-family: 'Fontello'; + content: '\e801 '; } .icon-rename::before { - font-family : 'Fontello'; - content : '\e802 '; + font-family: 'Fontello'; + content: '\e802 '; } .icon-view::before { - font-family : 'Fontello'; - content : '\e803 '; + font-family: 'Fontello'; + content: '\e803 '; } .icon-edit::before { - font-family : 'Fontello'; - content : '\e804 '; + font-family: 'Fontello'; + content: '\e804 '; } .icon-copy::before { - font-family : 'Fontello'; - content : '\e805 '; + font-family: 'Fontello'; + content: '\e805 '; } .icon-move::before { - font-family : 'Fontello'; - content : '\e806 '; + font-family: 'Fontello'; + content: '\e806 '; } .icon-directory::before { - font-family : 'Fontello'; - content : '\e807 '; + font-family: 'Fontello'; + content: '\e807 '; } .icon-delete::before { - font-family : 'Fontello'; - content : '\e808 '; + font-family: 'Fontello'; + content: '\e808 '; } .icon-menu::before { - font-family : 'Fontello'; - content : '\e809 '; + font-family: 'Fontello'; + content: '\e809 '; } .icon-config::before { - font-family : 'Fontello'; - content : '\e80a '; + font-family: 'Fontello'; + content: '\e80a '; } .icon-console::before { - font-family : 'Fontello'; - content : '\e80b '; + font-family: 'Fontello'; + content: '\e80b '; } .icon-contact::before { - font-family : 'Fontello'; - content : '\e80c '; + font-family: 'Fontello'; + content: '\e80c '; } .icon-file::before { - font-family : 'Fontello'; - content : '\e80d '; + font-family: 'Fontello'; + content: '\e80d '; } .icon-upload-to-cloud::before { - font-family : 'Fontello'; - content : '\e80e '; + font-family: 'Fontello'; + content: '\e80e '; } .icon-upload-from-cloud::before { - font-family : 'Fontello'; - content : '\e80f '; + font-family: 'Fontello'; + content: '\e80f '; } .icon-download::before { - font-family : 'Fontello'; - content : '\e810 '; + font-family: 'Fontello'; + content: '\e810 '; } .icon-new::before { - font-family : 'Fontello'; - content : '\e811 '; + font-family: 'Fontello'; + content: '\e811 '; +} + +.icon-toggle-file-selection::before { + font-family: 'Fontello'; + content: '\e81f '; } .icon-unselect-all::before { - font-family : 'Fontello'; - content : '\e812 '; + font-family: 'Fontello'; + content: '\e812 '; } .icon-pack::before { - font-family : 'Fontello'; - content : '\e813 '; + font-family: 'Fontello'; + content: '\e813 '; } .icon-extract::before { - font-family : 'Fontello'; - content : '\e814 '; + font-family: 'Fontello'; + content: '\e814 '; } -.icon-clear::before { - font-family : 'Fontello'; - content : '\e815 '; +.icon-copy-to-clipboard::before { + font-family: 'Fontello'; + content: '\e815 '; } .icon-refresh::before { - font-family : 'Fontello'; - content : '\e816 '; + font-family: 'Fontello'; + content: '\e816 '; } .icon-cut::before { - font-family : 'Fontello'; - content : '\e817 '; + font-family: 'Fontello'; + content: '\e817 '; } .icon-paste::before { - font-family : 'Fontello'; - content : '\e818 '; + font-family: 'Fontello'; + content: '\e818 '; } .icon-upload::before { - font-family : 'Fontello'; - content : '\e819 '; + font-family: 'Fontello'; + content: '\e819 '; } .icon-log-out::before { - font-family : 'Fontello'; - content : '\e81a '; + font-family: 'Fontello'; + content: '\e81a '; } .icon-terminal::before { - font-family : 'Fontello'; - content : '\e81b '; + font-family: 'Fontello'; + content: '\e81b '; +} + +.icon-user-menu::before { + font-family: 'Fontello'; + content: '\e81c '; } diff --git a/css/main.css b/css/main.css new file mode 100644 index 00000000..6b901a8e --- /dev/null +++ b/css/main.css @@ -0,0 +1,7 @@ +@import url(./reset.css); +@import url(./urls.css); +@import url(./style.css); +@import url(./icons.css); +@import url(./help.css); +@import url(./query.css); +@import url(./supports.css); diff --git a/css/nojs.css b/css/nojs.css index 1df4bd12..350ac4e6 100644 --- a/css/nojs.css +++ b/css/nojs.css @@ -1,4 +1,5 @@ -.path-icon, .keyspanel { +.path-icon, +.keyspanel { display: none; } diff --git a/css/query.css b/css/query.css index 5384d9b6..509f1b45 100644 --- a/css/query.css +++ b/css/query.css @@ -1,4 +1,31 @@ -@media only screen and (max-height: 900px) and (max-width: 600px) { +@media only screen and (width >= 1600px) { + .name { + width: 40%; + } + + .size { + width: 10%; + } + + .date { + width: 15%; + } + + .owner { + width: 12%; + } + + .mode { + width: 15%; + } +} + +:root { + --min-one-panel-width: 1155px; + --is-mobile: 0; +} + +@media only screen and (height <= 900px) and (width <= 600px) { .fm { height: 85%; } @@ -8,7 +35,7 @@ } } -@media only screen and (min-height: 550px) and (max-width: 600px) { +@media only screen and (height >= 550px) and (width <= 600px) { .fm { height: 80%; } @@ -18,43 +45,49 @@ } } -@media only screen and (max-height: 750px) and (max-width: 600px) { +@media only screen and (height <= 750px) and (width <= 600px) { .fm { height: 75%; } } -@media only screen and (max-height: 450px) and (max-width: 600px) { +@media only screen and (height <= 450px) and (width <= 600px) { .fm { height: 75%; } } -@media only screen and (max-height: 550px) and (max-width: 600px) { +@media only screen and (width <= 600px) { + :root { + --is-mobile: 1; + } +} + +@media only screen and (height <= 550px) and (width <= 600px) { .fm { height: 65%; } } -@media only screen and (max-height: 550px) and (max-width: 550px) { +@media only screen and (height <= 550px) and (width <= 550px) { .fm { - height: 55%; + height: 70%; } } -@media only screen and (min-height: 850px) and (min-width: 650px) { +@media only screen and (height >= 850px) and (width >= 650px) { .fm { height: 95%; } } -@media only screen and (max-height: 850px) { +@media only screen and (height <= 850px) { .files { height: 90%; } } -@media only screen and (max-height: 700px) and (min-width: 600px) { +@media only screen and (height <= 700px) and (width >= 600px) { .fm { height: 85%; } @@ -64,13 +97,13 @@ } } -@media only screen and (max-height: 450px) { +@media only screen and (height <= 450px) { .fm { height: 65%; } } -@media only screen and (max-height: 640px) and (max-width: 360px) { +@media only screen and (height <= 640px) and (width <= 360px) { .fm { height: 75%; } @@ -80,7 +113,9 @@ } } -@media only screen and (max-height: 360px) and (max-width: 640px) { +/* iphone 6 landscape */ +@media only screen and (device-width >= 375px) and (device-width <= 667px) and (orientation: landscape), + only screen and (height <= 360px) and (width <= 640px) { .fm { height: 55%; } @@ -90,34 +125,45 @@ } } -@media only screen and (max-width: 600px) { +@media only screen and (width <= 600px) { .panel { font-size: 26px; } /* текущий файл под курсором */ .current-file { - background-color: rgba(49, 123, 249, .40); + background-color: var(--border-color); color: white; } /* делаем иконки под курсом белыми */ .current-file a { color: white; } - .current-file .text-file::before { - color: white; + + .file::before { + color: rgb(26 224 124 / 56%); + content: '\e80d'; + } + + .file-link::before { + color: rgb(26 224 124 / 56%); + content: '\e81d'; } /* меняем иконки на шрифтовые */ .mini-icon { - color : rgba(246, 224, 124, 0.56); - font : 16px 'Fontello'; + color: rgb(246 224 124 / 56%); + font: 16px 'Fontello'; background-image: none; - padding : 1%; + padding: 1%; } - .size, .date, .owner, .mode { - display: none; + .size, + .date, + .owner, + .time, + .mode { + display: none !important; } .name { @@ -129,15 +175,26 @@ content: '\e807'; } - .text-file::before { - color: rgba(26, 224, 124, 0.56); - content: '\e80d'; + .directory-link::before { + content: '\e81e'; } - .text-file { + .file, + .file-link { background-image: none; } + .archive, + .archive-link { + background-image: none; + } + + .archive::before, + .archive-link { + color: rgb(26 224 124 / 56%); + content: '\e81d'; + } + /* убираем заголовок */ .fm-header { display: none; @@ -149,24 +206,26 @@ } } -@media only screen and (min-width: 601px) and (max-width: 785px) { +@media only screen and (width >= 601px) and (width <= 785px) { .cmd-button { width: 13%; } } -@media only screen and (min-width: 786px) and (max-width: 1155px) { +@media only screen and (width >= 786px) and (width <= 1155px) { .cmd-button { width: 10%; } } -@media only screen and (max-width: 1155px) { +@media only screen and (width <= 1155px) { .panel { width: 98%; } /* если правая панель не помещаеться - прячем её */ - .panel-right, .cmd-button#f5, .cmd-button#f6 { + .panel-right, + .cmd-button#f5, + .cmd-button#f6 { display: none; } } @@ -179,7 +238,8 @@ border: none; } - .keyspanel, .panel-right { + .keyspanel, + .panel-right { display: none; } diff --git a/css/style.css b/css/style.css index f9c70fc9..10820444 100644 --- a/css/style.css +++ b/css/style.css @@ -1,17 +1,19 @@ html { - height : 94%; + height: 94%; } body { - width : 100%; - height : 95%; - overflow : hidden; - background-color : white; + width: 100%; + height: 95%; + overflow: hidden; + background-color: var(--background); } -body, pre, code { - font-family : 'Droid Sans Mono', 'Ubuntu Mono', 'Consolas', monospace; - font-size : 16px; +body, +pre, +code { + font-family: 'Droid Sans Mono', 'Ubuntu Mono', 'Consolas', monospace; + font-size: 16px; } .hidden { @@ -22,31 +24,34 @@ body, pre, code { display: none; } -.fm, .keyspanel { - cursor : default; - -webkit-tap-highlight-color: rgba(0, 0, 0, 0); - -webkit-user-select : none; - -moz-user-select : none; - -ms-user-select : none; - -o-user-select : none; - user-select : none; +.fm, +.keyspanel { + cursor: default; + -webkit-tap-highlight-color: rgb(0 0 0 / 0%); + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + -o-user-select: none; + user-select: none; } .links { - -webkit-user-select : initial; - -moz-user-select : initial; - -ms-user-select : initial; - -o-user-select : initial; - user-select : text; + -webkit-user-select: initial; + -moz-user-select: initial; + -ms-user-select: initial; + -o-user-select: initial; + user-select: text; + color: var(--column-color); } -.panel, .cmd-button { +.panel, +.cmd-button { border: 1px solid; - border-color: rgba(49, 123, 249, 0.4); + border-color: var(--border-color); } .icon { - margin-left : 0.5%; + margin-left: 0.5%; cursor: default; } @@ -56,7 +61,7 @@ body, pre, code { .path-icon { position: relative; - color: #222; + color: var(--icon-color); } .path-icon:active { @@ -64,41 +69,41 @@ body, pre, code { } .path-icon:hover { - color : #06e; + color: #06e; cursor: pointer; } .error::before { - font-family : 'Fontello'; - font-size : 14px; - color : rgb(222, 41, 41); - cursor : default; - content : '\e800'; + font-family: 'Fontello'; + font-size: 14px; + color: rgb(222 41 41); + cursor: default; + content: '\e800'; } .loading { - position : relative; - display : inline-block; - width : 16px; - height : 16px; - vertical-align : middle; + position: relative; + display: inline-block; + width: 16px; + height: 16px; + vertical-align: middle; } .loading::after { - position : relative; - bottom : 5px; - left : 16px; - font-size : 10px; - color : rgb(49, 123, 249); - content : attr(data-progress); + position: relative; + bottom: 5px; + left: 16px; + font-size: 10px; + color: var(--link-color); + content: attr(data-progress); } .cmd-button { width: 5%; height: 30px; margin: 20px 2px 0; - color: #222; - background-color: white; + color: var(--icon-color); + background-color: var(--button-background); transition: ease 0.1s; } @@ -109,7 +114,7 @@ body, pre, code { .cmd-button:active { color: white; - background-color: rgb(49, 123, 249); + background-color: var(--link-color); transition: ease 0.1s; } @@ -117,6 +122,16 @@ body, pre, code { outline: 0; } +a { + text-decoration: none; +} + +a:hover, +a:active { + color: #06e; + text-decoration: none; +} + .links a { color: red; } @@ -136,13 +151,14 @@ body, pre, code { } .fm { - width : 98%; + width: 98%; height: 90%; margin: 26px auto 0; } .fm-header { font-weight: bold; + color: var(--column-color); } .panel-left { @@ -150,15 +166,30 @@ body, pre, code { } .current-file { - box-shadow: 0 0 0 1px rgba(49, 123, 249, 0.4) inset; + box-shadow: 0 0 0 1px var(--border-color) inset; } .cut-file { opacity: 0.7; } -.selected-file, .selected-file .name > a { - color: rgb(254, 159, 224); +.name { + float: left; + width: 26%; +} + +.name a { + color: var(--link-color); +} + +.name a:hover { + cursor: default; +} + +.selected-file, +.selected-file > span, +.selected-file .name > a { + color: rgb(254 159 224); } .panel-right { @@ -176,54 +207,55 @@ body, pre, code { } .selected-panel { - border-color: rgba(254, 159, 224, .40); + border-color: rgb(254 159 224 / 40%); } .keyspanel { text-align: center; } -.name { - float: left; - width: 26%; -} - -.name a:hover { - cursor: default; -} - .size { float: left; width: 12%; margin-right: 27px; text-align: right; + color: var(--column-color); } .date { float: left; width: 19%; + color: var(--column-color); +} + +.time { + color: var(--column-color); + display: none; } .owner { - display : inline-block; - width : 13%; + display: inline-block; + width: 12%; + /* when inline-block * vertical align should be * set top to prevent additional * spaces behind lines */ - vertical-align : top; + vertical-align: top; + color: var(--column-color); } .mode { float: right; - width: 18%; + width: 22%; + color: var(--column-color); } .reduce-text { - overflow : hidden; - text-overflow : ellipsis; - white-space : nowrap; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; } .files { @@ -232,17 +264,9 @@ body, pre, code { margin: 0; overflow-y: auto; list-style-type: none; + -webkit-overflow-scrolling: touch; } .files li { overflow: hidden; } - -a { - text-decoration: none; -} - -a:hover, a:active { - color: #06e; - text-decoration: none; -} diff --git a/css/supports.css b/css/supports.css index bf470c2d..ea2084d2 100644 --- a/css/supports.css +++ b/css/supports.css @@ -1,6 +1,6 @@ @supports (overflow: overlay) { .files { - overflow-y: overlay; + overflow-y: auto; } .fm-header { diff --git a/css/terminal.css b/css/terminal.css new file mode 100644 index 00000000..e7b1fea6 --- /dev/null +++ b/css/terminal.css @@ -0,0 +1,3 @@ +.terminal { + height: 100%; +} diff --git a/css/themes/dark.css b/css/themes/dark.css new file mode 100644 index 00000000..311a8093 --- /dev/null +++ b/css/themes/dark.css @@ -0,0 +1,49 @@ +:root { + --link-color: #317bf9; + --border-color: rgb(49 123 249 / 40%); + --background: #22272e; + --column-color: #727e8c; + --icon-color: #478be6; + --button-background: #22272e; + --internal-background: #373e47; +} + +.view { + background: var(--internal-background) !important; + color: var(--column-color) !important; +} +.view a { + color: var(--link-color) !important; +} + +.smalltalk .page, +.smalltalk header, +.smalltalk .button-strip button, +.smalltalk input { + background: var(--internal-background) !important; + color: var(--link-color) !important; + text-shadow: none !important; +} + +.cloudcmd-user-menu, +.cloudcmd-user-menu-button { + background: var(--internal-background) !important; + color: var(--link-color) !important; +} + +.jqconsole { + background: #373e47 !important; +} + +.jqconsole-prompt { + color: var(--column-color) !important; +} + +.log-msg { + color: var(--column-color) !important; +} + +.menu { + color: var(--link-color) !important; + background: var(--internal-background) !important; +} diff --git a/css/themes/light.css b/css/themes/light.css new file mode 100644 index 00000000..e95eb441 --- /dev/null +++ b/css/themes/light.css @@ -0,0 +1,9 @@ +:root { + --link-color: blue; + --selected-menu-item-color: #317bf9; + --border-color: rgb(49 123 249 / 40%); + --background: white; + --column-color: black; + --icon-color: #222; + --button-background: white; +} diff --git a/css/urls.css b/css/urls.css index e071784c..be90e235 100644 --- a/css/urls.css +++ b/css/urls.css @@ -17,28 +17,47 @@ } @font-face { - font-family : 'Droid Sans Mono'; - src : url(https://themes.googleusercontent.com/static/fonts/droidsansmono/v5/ns-m2xQYezAtqh7ai59hJTwtzT4qNq-faudv5qbO9-U.eot); - src : + font-family: 'Droid Sans Mono'; + src: url(https://themes.googleusercontent.com/static/fonts/droidsansmono/v5/ns-m2xQYezAtqh7ai59hJTwtzT4qNq-faudv5qbO9-U.eot); + src: local('Droid Sans Mono'), local('DroidSansMono'), url(../font/DroidSansMono.eot) format('embedded-opentype'), - url(https://themes.googleusercontent.com/static/fonts/droidsansmono/v5/ns-m2xQYezAtqh7ai59hJTwtzT4qNq-faudv5qbO9-U.eot?#iefix) format('embedded-opentype'), - url(https://themes.googleusercontent.com/static/fonts/droidsansmono/v5/ns-m2xQYezAtqh7ai59hJTwtzT4qNq-faudv5qbO9-U.eot) format('embedded-opentype'), + url(https://themes.googleusercontent.com/static/fonts/droidsansmono/v5/ns-m2xQYezAtqh7ai59hJTwtzT4qNq-faudv5qbO9-U.eot?#iefix) + format('embedded-opentype'), + url(https://themes.googleusercontent.com/static/fonts/droidsansmono/v5/ns-m2xQYezAtqh7ai59hJTwtzT4qNq-faudv5qbO9-U.eot) + format('embedded-opentype'), url(../font/DroidSansMono.woff2) format('woff2'), url(../font/DroidSansMono.woff) format('woff'), - url(https://themes.googleusercontent.com/static/fonts/droidsansmono/v5/ns-m2xQYezAtqh7ai59hJUYuTAAIFFn5GTWtryCmBQ4.woff) format('woff'), + url(https://themes.googleusercontent.com/static/fonts/droidsansmono/v5/ns-m2xQYezAtqh7ai59hJUYuTAAIFFn5GTWtryCmBQ4.woff) + format('woff'), local('Consolas'); - font-style : normal; - font-weight : 400; + font-style: normal; + font-weight: 400; } .directory { - background-image: url(../img/dir.png); + background-image: url(../img/directory.png); } -.text-file { - background-image: url(../img/txt.png); +.directory-link { + background-image: url(../img/directory-link.png); +} + +.file { + background-image: url(../img/file.png); +} + +.file-link { + background-image: url(../img/file-link.png); +} + +.archive { + background-image: url(../img/archive.png); +} + +.archive-link { + background-image: url(../img/archive-link.png); } .loading-svg { @@ -48,4 +67,3 @@ .loading-gif { background: url(../img/spinner.gif); } - diff --git a/css/user-menu.css b/css/user-menu.css new file mode 100644 index 00000000..792747f4 --- /dev/null +++ b/css/user-menu.css @@ -0,0 +1,23 @@ +.cloudcmd-user-menu { + font-size: 16px; + font-family: 'Droid Sans Mono', 'Ubuntu Mono', 'Consolas', monospace; + border: 0; +} + +.cloudcmd-user-menu:focus { + outline: 0; +} + +.cloudcmd-user-menu > option:checked { + box-shadow: 20px -20px 0 2px var(--selected-menu-item-color) inset; +} + +.cloudcmd-user-menu-button { + display: block; + width: 100%; + font-size: 16px; + padding: 2px; + -webkit-appearance: none; + border: 0; + overflow: auto; +} diff --git a/css/view.css b/css/view.css index 93cd8c4b..b6fb20ed 100644 --- a/css/view.css +++ b/css/view.css @@ -1,7 +1,8 @@ .view { - height: 100%; font-size: 16px; white-space: pre; + height: 100%; + overflow: auto; } .view:focus { @@ -14,23 +15,12 @@ } .view-overlay { - display : block; - background : rgba(255, 255, 255, 0.1); + display: block; + background: rgb(255 255 255 / 10%); } -.fancybox-wrap { - /* - * when search element with - * document.elementFromPoint - */ - z-index: 1; -} - -.fancybox-overlay { - z-index: 0; -} - -.media, video { +.media, +video { width: 100%; } diff --git a/deno.json b/deno.json new file mode 100644 index 00000000..64c1bde2 --- /dev/null +++ b/deno.json @@ -0,0 +1,14 @@ +{ + "tasks": { + "start": "deno run -P=cloudcmd bin/cloudcmd.mjs" + }, + "permissions": { + "cloudcmd": { + "env": true, + "read": true, + "sys": true, + "net": true, + "run": true + } + } +} diff --git a/docker-compose.yml b/docker-compose.yml index e358cb83..0fb72a34 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,4 +1,4 @@ -version: '2' +version: "2" services: web: ports: @@ -7,4 +7,3 @@ services: - ~:/root - /:/mnt/fs image: coderaiser/cloudcmd - diff --git a/docker/Dockerfile b/docker/Dockerfile new file mode 100644 index 00000000..7c5d7b64 --- /dev/null +++ b/docker/Dockerfile @@ -0,0 +1,29 @@ +FROM node + +LABEL maintainer="Coderaiser" +LABEL org.opencontainers.image.source="https://github.com/coderaiser/cloudcmd" + +RUN mkdir -p /usr/src/cloudcmd + +WORKDIR /usr/src/cloudcmd + +COPY package.json /usr/src/cloudcmd/ + +RUN curl -fsSL https://bun.com/install | bash && \ + ln -s /root/.bun/bin/bun /usr/local/bin/bun && \ + chmod +x /usr/local/bin/bun && \ + bun r gritty --omit dev && \ + bun i gritty --omit dev && \ + bun pm cache rm + +COPY . /usr/src/cloudcmd + +WORKDIR / + +ENV cloudcmd_terminal=true +ENV cloudcmd_terminal_path=gritty +ENV cloudcmd_open=false + +EXPOSE 8000 + +ENTRYPOINT ["/usr/src/cloudcmd/bin/cloudcmd.js"] diff --git a/docker/Dockerfile.alpine b/docker/Dockerfile.alpine new file mode 100644 index 00000000..5e38ab8a --- /dev/null +++ b/docker/Dockerfile.alpine @@ -0,0 +1,34 @@ +FROM node:alpine + +LABEL maintainer="Coderaiser" +LABEL org.opencontainers.image.source="https://github.com/coderaiser/cloudcmd" + +RUN mkdir -p /usr/src/cloudcmd + +WORKDIR /usr/src/cloudcmd + +COPY package.json /usr/src/cloudcmd/ + +RUN apk update && \ + apk add --no-cache curl bash make g++ python3 && \ + curl -fsSL https://bun.sh/install | bash && \ + ln -s ~/.bun/bin/bun /usr/local/bin/bun && \ + chmod +x /usr/local/bin/bun && \ + bun r gritty --omit dev && \ + bun i gritty --omit dev && \ + bun pm cache rm && \ + apk del make g++ python3 && \ + rm -rf /usr/include /tmp/* /var/cache/apk/* + +COPY . /usr/src/cloudcmd + +WORKDIR / + +ENV cloudcmd_terminal=true +ENV cloudcmd_terminal_path=gritty +ENV cloudcmd_open=false +ENV cloudcmd_vim=true + +EXPOSE 8000 + +ENTRYPOINT ["/usr/src/cloudcmd/bin/cloudcmd.js"] diff --git a/docker/Dockerfile.io b/docker/Dockerfile.io new file mode 100644 index 00000000..d5a24459 --- /dev/null +++ b/docker/Dockerfile.io @@ -0,0 +1,113 @@ +FROM ubuntu:resolute + +LABEL maintainer="Coderaiser" +LABEL org.opencontainers.image.source="https://github.com/coderaiser/cloudcmd" + +RUN mkdir -p /usr/local/share/cloudcmd + +WORKDIR /usr/local/share/cloudcmd + +COPY package.json /usr/local/share/cloudcmd/ + +ENV DEBIAN_FRONTEND=noninteractive \ + NVM_DIR=/usr/local/share/nvm \ + npm_config_cache=/tmp/npm-cache \ + GOPATH=/usr/local/share/go \ + PATH=/usr/local/share/bun/bin:$PATH \ + BUN_INSTALL=/usr/local/share/bun \ + NPM_CONFIG_CACHE=/tmp/.npm \ + NPM_CONFIG_PREFIX=/usr/local \ + NPM_CONFIG_PACKAGE_LOCK=false \ + PALABRA_DIR=/usr/local/share \ + XDG_CONFIG_HOME=/usr/local/etc + +ARG UBUNTU_DEPS="libatomic1 curl wget git net-tools iproute2 software-properties-common" +ARG RUST_DEPS="build-essential" +ARG DEPS="pv gcc gdb strace upx-ucl less ffmpeg net-tools netcat-openbsd mc far2l iputils-ping vim bat fzf locales sudo command-not-found ncdu aptitude htop btop hexyl tmux" +ARG PALABRA_DEPS="nvm node rust go deno fasm nvchad rizin yara gdu f4 typos shellcheck gh" +ARG BUN_DEPS="palabra wisdom nupdate version-io redrun superc8 supertape madrun redlint putout renamify-cli runny redfork cline" + +RUN apt-get update && \ + apt-get upgrade -y && \ + apt-get autoremove && \ + apt-get install -y ${UBUNTU_DEPS} ${RUST_DEPES} ${DEPS} && \ + echo "> Install git" && \ + add-apt-repository ppa:git-core/ppa -y && \ + echo "> Update command-not-found database. Run 'sudo apt update' to populate it." && \ + apt-get update && \ + apt-get upgrade -y && \ + apt-get autoremove && \ + apt-get clean && \ + echo "> create user" && \ + useradd -m -s /bin/bash -u 1337 instalador && \ + chown -R instalador /usr/local && \ + chown -R instalador /tmp + +USER instalador + +RUN echo "> install bun" && \ + curl https://bun.sh/install | bash && \ + echo "> install npm globals" && \ + bun i ${BUN_DEPS} -g && \ + echo "> install rust go deno bun fasm nvim" && \ + bun ${BUN_INSTALL}/bin/palabra i ${PALABRA_DEPS} && \ + echo "> install node" && \ + . $NVM_DIR/nvm.sh + +USER root + +RUN echo "> remove user" && \ + userdel -r instalador && \ + echo "> install gritty" && \ + bun r gritty --omit dev && \ + bun i gritty --omit dev && \ + bun pm cache rm && \ + echo "> setup cloudcmd" && \ + ln -s /usr/local/share/cloudcmd/bin/cloudcmd.js /usr/local/bin/cloudcmd && \ + echo "> setup git" && \ + git config --global core.whitespace -trailing-space && \ + git config --global pull.rebase true && \ + git config --global init.defaultBranch master && \ + echo "> configure bash" && \ + echo "alias ls='ls --color=auto'" >> /etc/bash.bashrc && \ + echo "alias buni='bun i --no-save'" >> /etc/bash.bashrc && \ + echo "alias bat='batcat'" >> /etc/bash.bashrc && \ + echo ". /usr/local/share/nvm/nvm.sh" >> /etc/bash.bashrc && \ + echo ". /usr/share/bash-completion/completions/git" >> /etc/bash.bashrc && \ + echo 'PS1="\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ "' >> /etc/bash.bashrc && \ + echo "> setup inputrc" && \ + echo "set editing-mode vi" >> /etc/inputrc && \ + echo "TAB: menu-complete" >> /etc/inputrc && \ + echo "set UTF-8" && \ + echo " > configure languages" && \ + echo "en_US.UTF-8 UTF-8" > /etc/locale.gen && \ + echo "ru_RU.UTF-8 UTF-8" >> /etc/locale.gen && \ + echo "uk_UA.UTF-8 UTF-8" >> /etc/locale.gen && \ + echo "es_ES.UTF-8 UTF-8" >> /etc/locale.gen && \ + echo "ja_JP.UTF-8 UTF-8" >> /etc/locale.gen && \ + echo "el_GR.UTF-8 UTF-8" >> /etc/locale.gen && \ + locale-gen + +COPY . /usr/local/share/cloudcmd + +WORKDIR / + +ENV cloudcmd_terminal=true \ + cloudcmd_terminal_path=gritty \ + cloudcmd_vim=true \ + cloudcmd_open=false \ + PATH=node_modules/.bin:$PATH \ + PATH=~/.local/bin:$PATH \ + BUN_INSTALL_CACHE_DIR=/tmp/bun-cache \ + DENO_DIR=/tmp/deno-cache \ + LANG=en_US.UTF-8 \ + LANGUAGE=en_US:en \ + LC_ALL=en_US.UTF-8 \ + TERM=xterm-256color \ + XDG_CACHE_HOME=/tmp \ + XDG_DATA_HOME=/usr/local/share \ + XDG_CONFIG_HOME=~/.config + +EXPOSE 8000 + +ENTRYPOINT ["/usr/local/share/cloudcmd/bin/cloudcmd.js"] diff --git a/docker/Dockerfile.slim b/docker/Dockerfile.slim new file mode 100644 index 00000000..c6f273b8 --- /dev/null +++ b/docker/Dockerfile.slim @@ -0,0 +1,39 @@ +FROM node:slim AS build + +RUN mkdir -p /usr/src/cloudcmd/ + +WORKDIR /usr/src/cloudcmd + +COPY package.json /usr/src/cloudcmd/ + +RUN apt-get update && \ + apt-get install -y build-essential python3 libncurses5-dev pkg-config && \ + apt-get install -y --no-install-recommends curl ca-certificates unzip && \ + curl -fsSL https://bun.sh/install | bash && \ + ln -s ~/.bun/bin/bun /usr/local/bin/bun && \ + chmod +x /usr/local/bin/bun && \ + bun r gritty --omit dev && \ + bun i gritty --omit dev && \ + ~/.bun/bin/bun pm cache rm && \ + rm -rf /var/lib/apt/lists/* + +COPY . /usr/src/cloudcmd + +FROM node:slim AS runtime + +COPY --from=build /usr/src/cloudcmd /usr/src/cloudcmd +COPY --from=build /root/.bun /root/.bun + +LABEL maintainer="Coderaiser" +LABEL org.opencontainers.image.source="https://github.com/coderaiser/cloudcmd" + +WORKDIR / + +ENV cloudcmd_terminal=true +ENV cloudcmd_terminal_path=gritty +ENV cloudcmd_open=false +ENV PATH="/root/.bun/bin:$PATH" + +EXPOSE 8000 + +ENTRYPOINT ["/usr/src/cloudcmd/bin/cloudcmd.js"] diff --git a/eslint.config.js b/eslint.config.js new file mode 100644 index 00000000..22add654 --- /dev/null +++ b/eslint.config.js @@ -0,0 +1,31 @@ +import {safeAlign} from 'eslint-plugin-putout'; +import {defineConfig} from 'eslint/config'; +import globals from 'globals'; +import {matchToFlat} from '@putout/eslint-flat'; + +export const match = { + 'bin/release.js': { + 'no-console': 'off', + 'n/hashbang': 'off', + }, + 'client/dom/index.*': { + 'no-multi-spaces': 'off', + }, + 'client/**': { + 'n/no-unsupported-features/node-builtins': 'off', + }, +}; +export default defineConfig([ + safeAlign, { + ignores: ['**/fixture'], + rules: { + 'key-spacing': 'off', + }, + }, { + files: ['{client,common,static}/**/*.js'], + languageOptions: { + globals: globals.browser, + }, + }, + ...matchToFlat(match), +]); diff --git a/font/fontello.eot b/font/fontello.eot index ae073b83..e144bd82 100644 Binary files a/font/fontello.eot and b/font/fontello.eot differ diff --git a/font/fontello.json b/font/fontello.json index 7271a684..c8bad6be 100644 --- a/font/fontello.json +++ b/font/fontello.json @@ -1,228 +1,258 @@ -{ - "name": "fontello", - "css_prefix_text": "icon-", - "css_use_suffix": false, - "hinting": true, - "units_per_em": 1000, - "ascent": 850, - "glyphs": [ - { - "uid": "b035c28eba2b35c6ffe92aee8b0df507", - "css": "attention-circled", - "code": 59392, - "src": "fontawesome" - }, - { - "uid": "17ebadd1e3f274ff0205601eef7b9cc4", - "css": "help-circled", - "code": 59393, - "src": "fontawesome" - }, - { - "uid": "67f793f91864e379458a92ccc61d9ccf", - "css": "sort-alphabet", - "code": 59394, - "src": "typicons" - }, - { - "uid": "60617c8adc1e7eb3c444a5491dd13f57", - "css": "attention-circled-1", - "code": 59395, - "src": "custom_icons", - "selected": false, - "svg": { - "path": "M429 71Q545 71 644 129T800 285T857 500T800 715T644 871T429 929T213 871T58 715T0 500T58 285T213 129T429 71ZM500 767V661Q500 653 495 648T483 643H376Q368 643 363 648T357 661V767Q357 775 363 780T376 786H483Q490 786 495 780T500 767ZM499 575L509 229Q509 222 503 219Q498 214 490 214H367Q359 214 354 219Q348 222 348 229L358 575Q358 581 363 585T377 589H480Q488 589 493 585T499 575Z", - "width": 857.1 - }, - "search": [ - "attention-circled" - ] - }, - { - "uid": "c5fd349cbd3d23e4ade333789c29c729", - "css": "eye", - "code": 59395, - "src": "fontawesome" - }, - { - "uid": "41087bc74d4b20b55059c60a33bf4008", - "css": "edit", - "code": 59396, - "src": "fontawesome" - }, - { - "uid": "9347a40928618e76958fa67e5333f1c5", - "css": "doc-text-1", - "code": 59397, - "src": "custom_icons", - "selected": false, - "svg": { - "path": "M212 542L212 452L492 452L492 542L212 542ZM600 50Q642 50 671 79T700 150L700 850Q700 890 671 920T600 950L100 950Q60 950 30 920T0 850L0 150Q0 108 30 79T100 50L600 50ZM600 850L600 150L100 150L100 850L600 850ZM490 258L490 346L210 346L210 258L490 258ZM490 650L490 738L210 738L210 650L490 650Z", - "width": 700 - }, - "search": [ - "doc-text" - ] - }, - { - "uid": "c8585e1e5b0467f28b70bce765d5840c", - "css": "docs", - "code": 59397, - "src": "fontawesome" - }, - { - "uid": "6405321f27abab4a505476c917d8c748", - "css": "folder-1", - "code": 59398, - "src": "custom_icons", - "selected": false, - "svg": { - "path": "M954 350Q986 350 994 362T1000 398L958 850Q956 874 946 887T904 900L98 900Q46 900 42 850L0 398Q-2 374 6 362T46 350L954 350ZM920 240L930 280L84 280L98 148Q102 128 118 114T154 100L318 100Q370 100 404 134L434 164Q466 200 520 200L860 200Q880 200 898 212T920 240Z", - "width": 1001 - }, - "search": [ - "folder" - ] - }, - { - "uid": "6020aff067fc3c119cdd75daa5249220", - "css": "exchange", - "code": 59398, - "src": "fontawesome" - }, - { - "uid": "2ba2063e74ee7b74f6c46a949d37a130", - "css": "cog-2", - "code": 59399, - "src": "custom_icons", - "selected": false, - "svg": { - "path": "M0 498Q0 460 7 415Q57 419 102 396T172 328Q197 283 195 233T165 142Q229 86 315 56Q338 97 379 122T469 146T558 122T622 56Q707 86 772 142Q751 181 751 227T774 313Q798 354 839 377T926 400Q937 449 937 498Q937 530 930 572Q885 573 846 597T783 660Q758 704 760 752T786 841Q720 901 641 934Q618 892 577 867T487 842Q434 842 391 870T327 944Q245 918 174 862Q202 821 204 771T181 676Q154 630 107 606T9 589Q0 548 0 498ZM293 498Q293 571 344 622T469 673T593 622T644 498T593 374T469 322T344 374T293 498Z", - "width": 937.5 - }, - "search": [ - "cog-1" - ] - }, - { - "uid": "0ccb084ddeeae372673793ed0b45bb4a", - "css": "folder", - "code": 59399, - "src": "entypo" - }, - { - "uid": "f48ae54adfb27d8ada53d0fd9e34ee10", - "css": "trash", - "code": 59400, - "src": "fontawesome" - }, - { - "uid": "559647a6f430b3aeadbecd67194451dd", - "css": "menu", - "code": 59401, - "src": "fontawesome" - }, - { - "uid": "7336247ba3db350dec8d6c0a47cef966", - "css": "cog-1", - "code": 59402, - "src": "mfglabs" - }, - { - "uid": "fa10777b2d88cc64cd6e4f26ef0e5264", - "css": "terminal", - "code": 59403, - "src": "fontawesome" - }, - { - "uid": "85528017f1e6053b2253785c31047f44", - "css": "comment", - "code": 59404, - "src": "fontawesome" - }, - { - "uid": "1189604bf305b6b03a74685ce60e6632", - "css": "doc-text", - "code": 59405, - "src": "entypo" - }, - { - "uid": "de2fc7a5c986ab8c622f63455d7cf814", - "css": "upload-cloud", - "code": 59406, - "src": "fontawesome" - }, - { - "uid": "f5999a012fc3752386635ec02a858447", - "css": "download-cloud", - "code": 59407, - "src": "fontawesome" - }, - { - "uid": "9a76bc135eac17d2c8b8ad4a5774fc87", - "css": "download", - "code": 59408, - "src": "fontawesome" - }, - { - "uid": "9e0404ba55575a540164db9a5ad511df", - "css": "doc-new", - "code": 59409, - "src": "elusive" - }, - { - "uid": "823a9e02e643318116fea40a00190e4e", - "css": "asterisk", - "code": 59410, - "src": "fontawesome" - }, - { - "uid": "3c24ee33c9487bbf18796ca6dffa1905", - "css": "resize-small", - "code": 59411, - "src": "fontawesome" - }, - { - "uid": "e594fc6e5870b4ab7e49f52571d52577", - "css": "resize-full", - "code": 59412, - "src": "fontawesome" - }, - { - "uid": "ebc57fa8400e4ede049ac5dc665210e1", - "css": "eraser", - "code": 59413, - "src": "fontawesome" - }, - { - "uid": "3bd18d47a12b8709e9f4fe9ead4f7518", - "css": "arrows-ccw", - "code": 59414, - "src": "entypo" - }, - { - "uid": "8772331a9fec983cdb5d72902a6f9e0e", - "css": "scissors", - "code": 59415, - "src": "fontawesome" - }, - { - "uid": "b429436ec5a518c78479d44ef18dbd60", - "css": "paste", - "code": 59416, - "src": "fontawesome" - }, - { - "uid": "eeec3208c90b7b48e804919d0d2d4a41", - "css": "upload", - "code": 59417, - "src": "fontawesome" - }, - { - "uid": "2d76f2c8d13be40694ecadfea7fb83c3", - "css": "logout", - "code": 59418, - "src": "entypo" - } - ] -} +{ + "name": "fontello", + "css_prefix_text": "icon-", + "css_use_suffix": false, + "hinting": true, + "units_per_em": 1000, + "ascent": 850, + "glyphs": [ + { + "uid": "b035c28eba2b35c6ffe92aee8b0df507", + "css": "attention-circled", + "code": 59392, + "src": "fontawesome" + }, + { + "uid": "17ebadd1e3f274ff0205601eef7b9cc4", + "css": "help-circled", + "code": 59393, + "src": "fontawesome" + }, + { + "uid": "67f793f91864e379458a92ccc61d9ccf", + "css": "sort-alphabet", + "code": 59394, + "src": "typicons" + }, + { + "uid": "c5fd349cbd3d23e4ade333789c29c729", + "css": "eye", + "code": 59395, + "src": "fontawesome" + }, + { + "uid": "41087bc74d4b20b55059c60a33bf4008", + "css": "edit", + "code": 59396, + "src": "fontawesome" + }, + { + "uid": "c8585e1e5b0467f28b70bce765d5840c", + "css": "docs", + "code": 59397, + "src": "fontawesome" + }, + { + "uid": "6020aff067fc3c119cdd75daa5249220", + "css": "exchange", + "code": 59398, + "src": "fontawesome" + }, + { + "uid": "0ccb084ddeeae372673793ed0b45bb4a", + "css": "folder", + "code": 59399, + "src": "entypo" + }, + { + "uid": "f48ae54adfb27d8ada53d0fd9e34ee10", + "css": "trash", + "code": 59400, + "src": "fontawesome" + }, + { + "uid": "559647a6f430b3aeadbecd67194451dd", + "css": "menu", + "code": 59401, + "src": "fontawesome" + }, + { + "uid": "7336247ba3db350dec8d6c0a47cef966", + "css": "cog-1", + "code": 59402, + "src": "mfglabs" + }, + { + "uid": "fa10777b2d88cc64cd6e4f26ef0e5264", + "css": "terminal", + "code": 59403, + "src": "fontawesome" + }, + { + "uid": "85528017f1e6053b2253785c31047f44", + "css": "comment", + "code": 59404, + "src": "fontawesome" + }, + { + "uid": "1189604bf305b6b03a74685ce60e6632", + "css": "doc-text", + "code": 59405, + "src": "entypo" + }, + { + "uid": "de2fc7a5c986ab8c622f63455d7cf814", + "css": "upload-cloud", + "code": 59406, + "src": "fontawesome" + }, + { + "uid": "f5999a012fc3752386635ec02a858447", + "css": "download-cloud", + "code": 59407, + "src": "fontawesome" + }, + { + "uid": "9a76bc135eac17d2c8b8ad4a5774fc87", + "css": "download", + "code": 59408, + "src": "fontawesome" + }, + { + "uid": "9e0404ba55575a540164db9a5ad511df", + "css": "doc-new", + "code": 59409, + "src": "elusive" + }, + { + "uid": "823a9e02e643318116fea40a00190e4e", + "css": "asterisk", + "code": 59410, + "src": "fontawesome" + }, + { + "uid": "3c24ee33c9487bbf18796ca6dffa1905", + "css": "resize-small", + "code": 59411, + "src": "fontawesome" + }, + { + "uid": "e594fc6e5870b4ab7e49f52571d52577", + "css": "resize-full", + "code": 59412, + "src": "fontawesome" + }, + { + "uid": "3bd18d47a12b8709e9f4fe9ead4f7518", + "css": "arrows-ccw", + "code": 59414, + "src": "entypo" + }, + { + "uid": "8772331a9fec983cdb5d72902a6f9e0e", + "css": "scissors", + "code": 59415, + "src": "fontawesome" + }, + { + "uid": "b429436ec5a518c78479d44ef18dbd60", + "css": "paste", + "code": 59416, + "src": "fontawesome" + }, + { + "uid": "eeec3208c90b7b48e804919d0d2d4a41", + "css": "upload", + "code": 59417, + "src": "fontawesome" + }, + { + "uid": "2d76f2c8d13be40694ecadfea7fb83c3", + "css": "logout", + "code": 59418, + "src": "entypo" + }, + { + "uid": "e92e6cad2da0ee4bc374a1ef4c6ab12b", + "css": "terminal-1", + "code": 59419, + "src": "websymbols" + }, + { + "uid": "b95cfc96d48a72dd665e0ab109880b5e", + "css": "clipboard", + "code": 59413, + "src": "entypo" + }, + { + "uid": "f805bb95d40c7ef2bc51b3d50d4f2e5c", + "css": "th-list", + "code": 59420, + "src": "fontawesome" + }, + { + "uid": "e15f0d620a7897e2035c18c80142f6d9", + "css": "link-ext", + "code": 59421, + "src": "fontawesome" + }, + { + "uid": "e35de5ea31cd56970498e33efbcb8e36", + "css": "link-ext-alt", + "code": 59422, + "src": "fontawesome" + }, + { + "uid": "12f4ece88e46abd864e40b35e05b11cd", + "css": "ok", + "code": 59423, + "src": "fontawesome" + }, + { + "uid": "60617c8adc1e7eb3c444a5491dd13f57", + "css": "attention-circled-1", + "code": 59395, + "src": "custom_icons", + "selected": false, + "svg": { + "path": "M429 71Q545 71 644 129T800 285T857 500T800 715T644 871T429 929T213 871T58 715T0 500T58 285T213 129T429 71ZM500 767V661Q500 653 495 648T483 643H376Q368 643 363 648T357 661V767Q357 775 363 780T376 786H483Q490 786 495 780T500 767ZM499 575L509 229Q509 222 503 219Q498 214 490 214H367Q359 214 354 219Q348 222 348 229L358 575Q358 581 363 585T377 589H480Q488 589 493 585T499 575Z", + "width": 857.1 + }, + "search": [ + "attention-circled" + ] + }, + { + "uid": "9347a40928618e76958fa67e5333f1c5", + "css": "doc-text-1", + "code": 59397, + "src": "custom_icons", + "selected": false, + "svg": { + "path": "M212 542L212 452L492 452L492 542L212 542ZM600 50Q642 50 671 79T700 150L700 850Q700 890 671 920T600 950L100 950Q60 950 30 920T0 850L0 150Q0 108 30 79T100 50L600 50ZM600 850L600 150L100 150L100 850L600 850ZM490 258L490 346L210 346L210 258L490 258ZM490 650L490 738L210 738L210 650L490 650Z", + "width": 700 + }, + "search": [ + "doc-text" + ] + }, + { + "uid": "6405321f27abab4a505476c917d8c748", + "css": "folder-1", + "code": 59398, + "src": "custom_icons", + "selected": false, + "svg": { + "path": "M954 350Q986 350 994 362T1000 398L958 850Q956 874 946 887T904 900L98 900Q46 900 42 850L0 398Q-2 374 6 362T46 350L954 350ZM920 240L930 280L84 280L98 148Q102 128 118 114T154 100L318 100Q370 100 404 134L434 164Q466 200 520 200L860 200Q880 200 898 212T920 240Z", + "width": 1001 + }, + "search": [ + "folder" + ] + }, + { + "uid": "2ba2063e74ee7b74f6c46a949d37a130", + "css": "cog-2", + "code": 59399, + "src": "custom_icons", + "selected": false, + "svg": { + "path": "M0 498Q0 460 7 415Q57 419 102 396T172 328Q197 283 195 233T165 142Q229 86 315 56Q338 97 379 122T469 146T558 122T622 56Q707 86 772 142Q751 181 751 227T774 313Q798 354 839 377T926 400Q937 449 937 498Q937 530 930 572Q885 573 846 597T783 660Q758 704 760 752T786 841Q720 901 641 934Q618 892 577 867T487 842Q434 842 391 870T327 944Q245 918 174 862Q202 821 204 771T181 676Q154 630 107 606T9 589Q0 548 0 498ZM293 498Q293 571 344 622T469 673T593 622T644 498T593 374T469 322T344 374T293 498Z", + "width": 937.5 + }, + "search": [ + "cog-1" + ] + } + ] +} \ No newline at end of file diff --git a/font/fontello.svg b/font/fontello.svg index d57b1f5d..ff664681 100644 --- a/font/fontello.svg +++ b/font/fontello.svg @@ -1,7 +1,7 @@ -Copyright (C) 2017 by original authors @ fontello.com +Copyright (C) 2024 by original authors @ fontello.com @@ -48,7 +48,7 @@ - + @@ -61,6 +61,14 @@ + + + + + + + + - \ No newline at end of file + diff --git a/font/fontello.ttf b/font/fontello.ttf index e79f2905..bfec5c43 100644 Binary files a/font/fontello.ttf and b/font/fontello.ttf differ diff --git a/font/fontello.woff b/font/fontello.woff index 61c5a5f4..a23a854d 100644 Binary files a/font/fontello.woff and b/font/fontello.woff differ diff --git a/font/fontello.woff2 b/font/fontello.woff2 index b4d6b0af..f0210ad6 100644 Binary files a/font/fontello.woff2 and b/font/fontello.woff2 differ diff --git a/html/index.html b/html/index.html index b080e389..d366ed1c 100644 --- a/html/index.html +++ b/html/index.html @@ -5,21 +5,25 @@ - + - {{ title }} - - + + + -
{{ fm }}
+
{{ fm }}
- + @@ -29,12 +33,23 @@ - +
- + + + diff --git a/img/archive-link.png b/img/archive-link.png new file mode 100644 index 00000000..b134c2b8 Binary files /dev/null and b/img/archive-link.png differ diff --git a/img/archive.png b/img/archive.png new file mode 100644 index 00000000..fd4bbccd Binary files /dev/null and b/img/archive.png differ diff --git a/img/directory-link.png b/img/directory-link.png new file mode 100644 index 00000000..a28afa79 Binary files /dev/null and b/img/directory-link.png differ diff --git a/img/dir.png b/img/directory.png similarity index 100% rename from img/dir.png rename to img/directory.png diff --git a/img/favicon/favicon-256.png b/img/favicon/favicon-256.png new file mode 100644 index 00000000..4e01d43c Binary files /dev/null and b/img/favicon/favicon-256.png differ diff --git a/img/file-link.png b/img/file-link.png new file mode 100644 index 00000000..0667fa5e Binary files /dev/null and b/img/file-link.png differ diff --git a/img/txt.png b/img/file.png similarity index 100% rename from img/txt.png rename to img/file.png diff --git a/img/logo/cloudcmd-hq.png b/img/logo/cloudcmd-hq.png new file mode 100644 index 00000000..8e4d1d3b Binary files /dev/null and b/img/logo/cloudcmd-hq.png differ diff --git a/img/screen/config.png b/img/screen/config.png index 5510f0f5..deb4ed8f 100644 Binary files a/img/screen/config.png and b/img/screen/config.png differ diff --git a/img/screen/console.png b/img/screen/console.png index e5feebc3..665d6668 100644 Binary files a/img/screen/console.png and b/img/screen/console.png differ diff --git a/img/screen/edit.png b/img/screen/edit.png index eadd8d33..e61c148d 100644 Binary files a/img/screen/edit.png and b/img/screen/edit.png differ diff --git a/img/screen/menu.png b/img/screen/menu.png index 69f72a03..9c4ef201 100644 Binary files a/img/screen/menu.png and b/img/screen/menu.png differ diff --git a/img/screen/one-file-panel.png b/img/screen/one-file-panel.png new file mode 100644 index 00000000..e95fd4bc Binary files /dev/null and b/img/screen/one-file-panel.png differ diff --git a/img/screen/one-panel-mode.png b/img/screen/one-panel-mode.png deleted file mode 100644 index b2f4a791..00000000 Binary files a/img/screen/one-panel-mode.png and /dev/null differ diff --git a/img/screen/terminal.png b/img/screen/terminal.png index 911a9d08..d38ab47f 100644 Binary files a/img/screen/terminal.png and b/img/screen/terminal.png differ diff --git a/img/screen/view.png b/img/screen/view.png index 6c9ea67b..98e3e7e4 100644 Binary files a/img/screen/view.png and b/img/screen/view.png differ diff --git a/json/config.json b/json/config.json index 38638b36..3bbb65f4 100644 --- a/json/config.json +++ b/json/config.json @@ -1,31 +1,50 @@ { + "name": "", "auth": false, "username": "root", "password": "2b64f2e3f9fee1942af9ff60d40aa5a719db33b8ba8dd4864bb4f11e25ca2bee00907de32a59429602336cac832c8f2eeff5177cc14c864dd116c8bf6ca5d9a9", "algo": "sha512WithRSAEncryption", "editor": "edward", + "menu": "aleman", "packer": "tar", "diff": true, - "zip" : true, - "localStorage": true, + "zip": true, "buffer": true, "dirStorage": false, - "minify": false, - "online": true, - "open": false, - "cache": true, - "showKeysPanel": true, + "online": false, + "open": true, + "keysPanel": true, "port": 8000, "ip": null, "root": "/", "prefix": "", - "progress": true, - "htmlDialogs": true, - "configDialog": true, - "onePanelMode": false, + "prefixSocket": "", + "contact": true, + "confirmCopy": true, + "confirmMove": true, "configDialog": true, + "configAuth": true, + "configPort": true, + "oneFilePanel": false, "console": true, + "syncConsolePath": false, "terminal": false, - "terminalPath": "" + "terminalPath": "", + "terminalCommand": "", + "terminalAutoRestart": true, + "showDotFiles": true, + "showConfig": false, + "showFileName": false, + "vim": false, + "columns": "name-size-date-owner-mode", + "theme": "light", + "export": false, + "exportToken": "root", + "import": false, + "importToken": "root", + "importUrl": "http://localhost:8000", + "importListen": false, + "log": true, + "dropbox": false, + "dropboxToken": "" } - diff --git a/json/css.json b/json/css.json deleted file mode 100644 index 1ff17fdf..00000000 --- a/json/css.json +++ /dev/null @@ -1,8 +0,0 @@ -[ - "reset", - "style", - "icons", - "help", - "query", - "supports" -] diff --git a/json/help.json b/json/help.json index cbb6e27b..44f79248 100644 --- a/json/help.json +++ b/json/help.json @@ -7,29 +7,71 @@ "-u, --username ": "set username", "-p, --password ": "set password", "-c, --config ": "configuration file path", + "--show-config ": "show config values", + "--show-dot-files ": "show dot files", + "--show-file-name ": "show file name in view and edit", "--editor ": "set editor: \"dword\", \"edward\" or \"deepword\"", "--packer ": "set packer: \"tar\" or \"zip\"", "--root ": "set root directory", "--prefix ": "set url prefix", + "--prefix-socket ": "set prefix for socket connection", "--port ": "set port number", - "--minify ": "enable minification", - "--progress ": "show progress of file operations", - "--html-dialogs ": "use html dialogs", - "--one-panel-mode ": "set one panel mode", + "--confirm-copy ": "confirm copy", + "--confirm-move ": "confirm move", + "--open ": "open web browser when server started", + "--name ": "set tab name in web browser", + "--menu ": "set menu: \"supermenu\" or \"aleman\"", + "--one-file-panel ": "show one file panel", + "--keys-panel ": "show keys panel", "--config-dialog ": "enable config dialog", + "--config-auth ": "enable auth change in config dialog", + "--config-port ": "enable port change in config dialog", "--console ": "enable console", + "--sync-console-path ": "sync console path", + "--contact ": "enable contact", "--terminal ": "enable terminal", "--terminal-path ": "set terminal path", - "--open ": "open web browser when server started", + "--terminal-command ": "set command to run in terminal (shell by default)", + "--terminal-auto-restart ": "restart command on exit", + "--vim ": "enable vim hot keys", + "--columns ": "set visible columns", + "--theme ": "set theme 'light' or 'dark'", + "--export ": "enable export of config through a server", + "--export-token ": "authorization token used by export server", + "--import ": "enable import of config", + "--import-url ": "url of an export server", + "--import-token ": "authorization token used to connect to export server", + "--import-listen ": "enable listen on config updates from import server", + "--dropbox ": "enable dropbox integration", + "--dropbox-token ": "set dropbox token", + "--log ": "enable logging", + "--no-show-config ": "do not show config values", "--no-server ": "do not start server", "--no-auth ": "disable authorization", "--no-online ": "load scripts from local server", "--no-open ": "do not open web browser when server started", - "--no-minify ": "disable minification", - "--no-progress ": "do not show progress of file operations", - "--no-html-dialogs ": "do not use html dialogs", - "--no-one-panel-mode ": "unset one panel mode", + "--no-name ": "set default tab name in web browser", + "--no-one-file-panel ": "show two file panels", + "--no-keys-panel ": "hide keys panel", + "--no-confirm-copy ": "do not confirm copy", + "--no-confirm-move ": "do not confirm move", "--no-config-dialog ": "disable config dialog", + "--no-config-auth ": "disable auth change in config dialog", + "--no-config-port ": "disable port change in config dialog", "--no-console ": "disable console", - "--no-terminal ": "disable terminal" + "--no-sync-console-path ": "do not sync console path", + "--no-contact ": "disable contact", + "--no-terminal ": "disable terminal", + "--no-terminal-command ": "set default shell to run in terminal", + "--no-terminal-auto-restart ": "do not restart command on exit", + "--no-vim ": "disable vim hot keys", + "--no-columns ": "set default visible columns", + "--no-export ": "disable export config through a server", + "--no-import ": "disable import of config", + "--no-import-listen ": "disable listen on config updates from import server", + "--no-show-dot-files ": "do not show dot files", + "--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" } diff --git a/json/modules.json b/json/modules.json index 5252ceb7..6ed586d1 100644 --- a/json/modules.json +++ b/json/modules.json @@ -4,50 +4,27 @@ "edit-file", "edit-file-vim", "edit-names", + "edit-names-vim", "menu", "view", "help", "markdown", "config", "contact", + "command-line", "upload", "operation", "konsole", "terminal", - "cloud" + "terminal-run", + "cloud", + "user-menu" ], "remote": [{ - "name": "jquery", - "version": "3.2.1", - "local": "/modules/jquery/dist/jquery.min.js", - "remote": "//ajax.googleapis.com/ajax/libs/jquery/{{ version }}/jquery.min.js" - }, { "name": "socket", - "version": "2.0.1", + "version": "4.0.1", "local": "/socket.io/socket.io.js", "remote": "https://cdnjs.cloudflare.com/ajax/libs/socket.io/{{ version }}/socket.io.js" - }, { - "name": "fancybox", - "version": "2.1.6", - "local": [ - "/modules/fancybox/source/jquery.fancybox.css", - "/modules/fancybox/source/jquery.fancybox.pack.js" - ], - "remote": [ - "//cdnjs.cloudflare.com/ajax/libs/fancybox/{{ version }}/css/jquery.fancybox.min.css", - "//cdnjs.cloudflare.com/ajax/libs/fancybox/{{ version }}/js/jquery.fancybox.min.js" - ] - }, { - "name": "menu", - "version": "1.0.2", - "local": [ - "/modules/menu/menu-io.min.css", - "/modules/menu/menu-io.min.js" - ], - "remote": [ - "//cdn.jsdelivr.net/menu-io/{{ version }}/menu-io.min.js", - "//cdn.jsdelivr.net/menu-io/{{ version }}/menu-io.min.css" - ] }], "data": { "FilePicker": { diff --git a/man/cloudcmd.1 b/man/cloudcmd.1 index 0cceb1d9..dab36a2c 100644 --- a/man/cloudcmd.1 +++ b/man/cloudcmd.1 @@ -30,31 +30,74 @@ programs in browser from any computer, mobile or tablet device. -u, --username set username -p, --password set password -c, --config configuration file path - --editor set editor: "dword", "edward" or "deepword" + --show-config show config values + --show-dot-files show dot files + --show-file-name show file name in view and edit modes + --editor set editor: "dword", "edward", "deepword" or "qword" + --menu set menu: "supermenu" or "aleman" --packer set packer: "tar" or "zip" --root set root directory --prefix set url prefix + --prefix-socket set prefix for socket connection --port set port number - --minify enable minification - --progress show progress of file operations - --html-dialogs use html dialogs + --confirm-copy confirm copy + --confirm-move confirm move --open open web browser when server started - --one-panel-mode set one panel mode + --name set tab name in web browser + --one-file-panel show one file panel + --keys-panel show keys panel + --contact enable contact --config-dialog enable config dialog + --config-auth enable auth change in config dialog + --config-port enable port change in config dialog --console enable console + --sync-console-path sync console path --terminal enable terminal --terminal-path set terminal path - --no-auth disable authorization + --terminal-command set command to run in terminal (shell by default) + --terminal-auto-restart restart command on exit + --vim enable vim hot keys + --columns set visible columns + --theme set theme 'light' or 'dark' + --export enable export of config through a server + --export-token authorization token used by export server + --import enable import of config + --import-url url of an import server + --import-token authorization token used to connect to export server + --import-listen enable listen on config updates from import server + --dropbox enable dropbox integration + --dropbox-token set dropbox token + --log enable logging + --no-show-config do not show config values + --no-show-dot-files do not show dot files --no-server do not start server + --no-auth disable authorization --no-online load scripts from local server --no-open do not open web browser when server started - --no-minify disable minification - --no-progress do not show progress of file operations - --no-html-dialogs do not use html dialogs - --no-one-panel-mode unset one panel mode + --no-name set default tab name in web browser + --no-one-file-panel show two file panels + --no-keys-panel hide keys panel + --no-confirm-copy do not confirm copy + --no-confirm-move do not confirm move + --no-contact disable contact --no-config-dialog disable config dialog + --no-config-auth disable auth change in config dialog + --no-config-port disable port change in config dialog --no-console disable console + --no-sync-console-path do not sync console path --no-terminal disable terminal + --no-terminal-command set default shell to run in terminal + --no-terminal-auto-restart do not restart command on exit + --no-vim disable vim hot keys + --no-columns set visible default columns + --no-export disable export of config through a server + --no-import disable import of config + --no-import-url url of an import server + --no-import-listen disable listen on config updates from import server + --no-show-file-name do not show file name in view and edit modes + --no-dropbox disable dropbox integration + --no-dropbox-token unset dropbox token + --no-log disable logging .SH RESOURCES AND DOCUMENTATION diff --git a/manifest.yml b/manifest.yml index 97b2810f..c10c360d 100644 --- a/manifest.yml +++ b/manifest.yml @@ -1,4 +1,3 @@ ---- applications: .: name: cloudcmd @@ -7,7 +6,7 @@ applications: info: mem: 512M description: Node.js Application - exec: + exec: null url: ${name}.${target-base} mem: 128M instances: 2 diff --git a/modules/domtokenlist-shim/.bower.json b/modules/domtokenlist-shim/.bower.json deleted file mode 100644 index 302d2e21..00000000 --- a/modules/domtokenlist-shim/.bower.json +++ /dev/null @@ -1,39 +0,0 @@ -{ - "name": "domtokenlist-shim", - "description": "A super strict shim/polyfill for DOMTokenList", - "main": "dist/domtokenlist.js", - "license": "MIT", - "ignore": [ - "**/.*", - "*.json", - "*.md", - "gulpfile.js", - "src", - "tests", - "node_modules", - "bower_components", - "test" - ], - "keywords": [ - "classlist", - "domtokenlist", - "polyfill", - "rellist", - "shim" - ], - "authors": [ - "Jonathan Wilsson ", - "Bogdan Chadkin " - ], - "homepage": "https://github.com/jwilsson/domtokenlist", - "version": "1.1.1", - "_release": "1.1.1", - "_resolution": { - "type": "version", - "tag": "v1.1.1", - "commit": "83b9acb080e47a5dcdaa75f2351a0602ab8351b5" - }, - "_source": "https://github.com/jwilsson/domtokenlist.git", - "_target": "~1.1.0", - "_originalSource": "domtokenlist-shim" -} \ No newline at end of file diff --git a/modules/domtokenlist-shim/bower.json b/modules/domtokenlist-shim/bower.json deleted file mode 100644 index 938c8b10..00000000 --- a/modules/domtokenlist-shim/bower.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "name": "domtokenlist-shim", - "description": "A super strict shim/polyfill for DOMTokenList", - "main": "dist/domtokenlist.js", - "license": "MIT", - "ignore": [ - "**/.*", - "*.json", - "*.md", - "gulpfile.js", - "src", - "tests", - "node_modules", - "bower_components", - "test" - ], - "keywords": [ - "classlist", - "domtokenlist", - "polyfill", - "rellist", - "shim" - ], - "authors": [ - "Jonathan Wilsson ", - "Bogdan Chadkin " - ], - "homepage": "https://github.com/jwilsson/domtokenlist" -} diff --git a/modules/domtokenlist-shim/browserstack-logo.svg b/modules/domtokenlist-shim/browserstack-logo.svg deleted file mode 100644 index 0f24cc33..00000000 --- a/modules/domtokenlist-shim/browserstack-logo.svg +++ /dev/null @@ -1,12954 +0,0 @@ - - - - - - - - - - - -]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - eJzsveuuHMl1LvgE+Q41PwxIB2Yp4x6pMQzs2hePZnSDWpZtGAcNir3V4jGbbLDZ8tE8/Xzfiois -zFhR+9KkNDJMJtQiq7Iy47JirW/d/+7/+PUXL66+evf7+xfuOB+mv/u76/f3Lz+8e//Tg3x6+Nmb -N99/9+E9P/rRb358MOk446arn+Uv642/u3//3et3b3/Kr4x8ecdf/+jq22/f3P/48KMf45Pfvv7w -5h6f/fzd1++O3371hx+39+CHNy8/4CsTfzL7nxh/MD81y+HXv+ANL9/+6eV3373+f+Vrlx0+O737 -/u1Xr99+fXr3v/Ghy4cXwflDdMvhhckRN/xfr39z/11/19FYE2yI1jsT+RN3zGZxyxySzUvA7/Mx -p2z9vCR+Ig874muzmJDmmAKefPPu1fff3L/98Ov3717df/fd9bs3795/99PD9Z9fvj384uXX+Obl -4d/u37x595+H05uXr/5jwiKFL+9ev7nHenzz8gMGwtW5+pmxX56+f/3mq19+/83v77FSNjl+7L6U -R/7zd3gWHsu/8+P05c++wSdf3H/4gBnhhVzh61/82/+zHQdmWa8f/ftv7r9+LRuGtf2fP65Pfv/u -229evv+P77hL/mhdios3S16cObxwJhydcSablM1ssZyzPaZoHdbDZuPs4YW1GLs1M36RljjX8f72 -/ptv32D3ZJndEo8BD5v5f9t/1HuxDnLfC+OPfsGfOefoY/bYD5+PMSbjZ5dnBxpIMR/DjD+LMS5g -AGY+OmdzWKJZYo6mPPO8I/d/en3/nz89/PLd2/uy7FfvP3xRCMf7eS7/Ld/85vs39+//+e3rD1iL -yI+Wsu6/ePfV/Rtsxvr7uzcvZbnlMuf/lht++/L91/cfQGvv3nz/Qcg/tzdgX3/+8s/3JA5TXvCr -b+/f/vbd72SML5w9+rgkY0HR+P/EFcGhmn2cjXPOLDgDR0f6zKBAUCnOA3YHVBrxlyyDSPg/Lstm -dGY7Or6Qr2vjSKCZX4OKfvX+9dev3/50mQ8v0mwLef3T+9dfnakLT83lP/K4Y57ljzGLnRe7PPWT -Rf6kaEI23j7lk7JSWPQPH+7f1pXDSbn+xYby5+MvvsBMbt9+df3uG+78d2QJoPe3OAxv3n1dvlv/ -Lt/g599/W1ZF/v0liOTX71+/5TOnX8o3+ctfv/keX/3T+3fff/uzt394N/2o8L7f3b8CgwMdfXX4 -1e//F/4Bdian8fDb9y9f4QH493rP8eXrb3/84OMwuff3h/Ilfin/bP//+K9v7v8APnL+efn09u2f -7t+8+3bz2PWTl2+/OvzLy/ffPv7oX795+fbl+4N8vj7556//hG9eYqXOzz5/9oSHgvK+xeLIT+SW -7gUP3LD56gkvevnhj2C592+/+m59dvnnfuDls8ef98Ur0uD7w+n999/98fDbd+/erI/df7U+vX4s -n/L+v413/Fp+8PZXb8sC6TfVG/o3gff9zb0Fd19+A778W3769cs3b15//f7lt398/Wr0gsH365vK -d88hrD9/8/t3b15/982Znjaf/Prl+w+vX725/+LP3324/+bJm3u4/eo1mNyFY/zgPV/858sPr/74 -89e/f//y/ev7B08fN+APr99+Bdr/4vvXH+7PC/Tum2+J6A5f/PHlt/cyjQ9/vJM7v1gfGL4E698y -9xcvJnM4vd2w/n96//Kr15AaAKL//Pbty2/A1r+uHx2M/fE0/BRy0B5OX03/Pv3DlJaUU0rAg8kn -lwyg4V28jTfxOp7iVSQ0STHGAFzjoo0mzuEu3IabcB1O4SosIYcUYgjBBwc8aqYw+zt/62/89fSP -03z4uy9P7/Gi+Yinm7lI9XgIFPH4CqLvy9FXp+/wC7vENLvzx2be/Gb0JX51ulkXri3NA4LSzhdX -8+4l0fbhi//4MxZx8w+8sa4dxD2nNc1YReCkf8TWrJPNAANewAZRhCtARk/i4dtkEdZbBA31Kzf8 -9tFl2EzzV+9fvv36/u8rysdUuw/wuNBIZQ4/8Irja9r89R/x/NPpdH26Od2e7q7na3Ntr921vw7X -8Tpd5+vl+ur6+vrm+vb67ma+MTf2xt34m3ATb9JNvllurm5ON9c3Nze3N3e38625tbduuvW34Tbe -ptssz8fdT7/849e0+StIve0/Fso9cPnnX5P6aLe+Mrnsc8gRGl/OS77Kp3ydb/JtvlugcADA+gWK -BhQdItSr5bRcLzfL7XJ3NV+ZK3vlrvxVuIpX6SpfLVdXV6er6+nq5ur26u40n8zJntzJn8IpntIp -n5bT1elUFjQ964qPXdPgw82edItsP+3VP/ChPXzwkqWBIrS4K3dy1+7G3bo7bBoUAu+898FHn3z2 -i7/yJ38N6rn1d9hGqvMejDSCoUItBHM9gcnegNnexXkC57XgwB6cGHoluPIC7nwCl74Bt75LMzg3 -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 -oWu952Qx0njVAylaKUOfN73GmT724u1SL4hAsrJxDCspiyVRyeqS2hVRrSlEkfVgd9j6cw9LOCyL -8qCFI2701AtQmElmkFyGAbTkuc03hQ/YlLGPs9/kZaP7Yk+4YTETbPvpOBzDdFmvsrzXidI/+/Vs -c/acbMWqynwFntBQ+pJUj97BpFIEFIfpiSK1o81ESjKdd62Nd/khDjao8+ePsgQhlqQKDO7e0L88 -Vy6hxKL1V/hIwjUh7q/yWzN+UbVUqahwLO5d+O1sLK8TeeHK4z229WAde1pBNeZTL0xkFCVDnJAq -XTMfnSEDsWKYZnP7xi0AYcjt0fp520aeLmXdXco63GGT6+3gKrSEnl6CuGihO3OddJKXmRwtaegi -J3yCX/J0UuySzrOEM4dkL7yELvOvZnUuuBZDUQR63YS/GNcDloPbyiiwdPGOBCfUqOiIRYNg1Lkl -y2WWBAttEjSmFAS7dUv56eMBx19YhuDDMT3PZPq7qAuSx1dS7B4Q01eYEBBo9kTuwa5FcyJHhEDE -2fEu0S/RCJPwGg7XQmmh52aYy/OERGNYpNo+GbymF7fvbvKHQvq7SxLQpAXPk0Ou9g== - - - qzicPyXYR5Tbr9Ju/8jBEvaw/T2hVv/j15Rk3v7sz9/+4e+/frL89hd/9cMP//z2Z3/5i7/95Y8/ -fvf73377i3/59u+++913v/zxu19/e/7ATvW639/88je//fbTD7/7j29/+Kdv//rXv/nxv/z+h3/9 -3RcXt3/yCtLbX/zdd7/8YmiG+uH33/7n33z/7d9+9/tffffbH7/9P777Dxu3vf3FL37744ve/Ncv -/59//s4u6PMPv3r8DQlKN001RN7Xzvjff3P+/u9/8+sf/+dXf7b3/PzdP/347fn1/+vvf/it36P+ -tSv7299/92+/+e7fz4X987/81Lj//Yff/bHD/t0P//6Tw3Irz335zXf/8sVd+cM34n/77jf/43/+ -+PJx/vXP/pe//EX99q9/+2v/Q/7d+fe3//WH3/7teWl/PO/tz39uzX/13f84v+ndgZ/9199xZNmR -v/r9v/7L/4xx/uz//O1vf/n9d79+G3/+s/T2l+f//+HffyY6+b8+/us//+wLCnl6+9/P//h/T9O/ -v7W3v3n7v/7v9PZr/vLvfvbzs3Ch/sjC/g20hp+jiUHOeETb5y/bxCs488vnd3/7qs3/9rePq/pv -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 -cwRpeuafYtgS72hoRuLQFyt8ugyIueOz0UaYP98pBdL13RaGa3rkKNMKtkSov5rpUPx9RBPsDSM5 -tUUSiE0vocln7/3QqlG2Wk0j0ITJYCI0zhpfc8oOLDqvy7u9uK+69F079nuukKSed07Srv0OkCId -6fAuNbbbaCkZGvNj1JweA6yraqPcxWdvdoSYHqLPdTTvvG8AlWzkAj8yJqB9T7dvuVcfw69+Zn1b -joSCk0N2uigF7Yxm9sbV0l3eWjyeR0JguhzCTg+q8DRQCI0ykIpYLaCp27bQsYXp0RWrEg8xLPG4 -dT9XaAuUd38fgLyhGJa2eRcR5b2qN44VM1qLXfO2ksLV1PEbsN5v0A3LRmO7Uj+93QuQ722crK4e -fXe6q3Zv3jjXfTPtj3egCxSU6tUUoDky4ufcuiKh6mOSlrqj/p7mq1HhzD0a5410k4npqueMIkoJ -SSBYlA8ptuo7UFrn/Tx1r7zxBuvNELA7VxN0sAvYe/mw9V32yXEjND42Fq7Opp5XbKYE9PJsS67S -wQiV4TPx28JpE7IhWM/rDx3tvbCaDbBvCC+w//S+6360znn+Gt2Tvjde8DqM+rbYGA== - - - Z/9caMz3E4gaMM2YpPgA/z9p7/kd15HkC37YD3t2d3R23tuZfTPT0z2anlYbtdQNb0hKFL0DQYAA -4b0p770veIJWlERJpOgdPFDeGziCJDzKXldVANX93t+xkVV1C5TpN7tnP9ShlKjKmzczMuL3i4yI -pKMvy1HJ8HyaxxSWZpJhC/IzZyqZ72aOhlEF830eVZg9MEFfLS2mD8kKyrKRg+jL+dnaTmW0li9P -1yynDyWzmDbdmInQezfkAA23LD93kJ8JXcnkvNJ5DlkmhmYGwDwdz0L7FlFzQT4dzoZuLM5+N5ub -nw5Hodv2E2aKSrOBI+nf51IF8rJqNh/FkNCDzdYXKs/PuYTSQcdldAdlGauVDbUsz054fhZEZb+d -lYRSWk+jOJsMckNClz3MT4dhFeVEMSs0dJhKRba5uDAXVZnJL0SN+6kGxZlyYGlZLsqFztHuPtSc -V0Cf/GczNsrRhXwFdJxkSab8WXoEuSCo9EEj3UE2xRINtyD7sMJ3Qioy9ZlRW/YAIx1JlvUSpLde -OT3Y3NzmuGQ6NKuc3qToUij6XUv2OyjIpSuUIr9vRbY5rzwX14MCmGmlUpZPRyYV5WUnDF1XRAtN -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 -vClik9OJbJk00y8tA0/Oa8r/YNXVv+foqf6rWVP8J/dg42f36Rfehfr8MQGctjXMOO3srvtwnF/8 -uyHGxd89pV/83StJ2Z8DD5jHlofYpz03Wj6PTXIuR8aZZxOTxO9+6Tgwpzn/jtlQ+r5roO6TCcXF -d0GTqxCTgrE1zC+OjPGvLD9p/941WPvXOVXZO/PKij+YDLXv3+s8+28T0spPFx/TTsYnpfVbr7lF -i4/bvlm8C5qrh/4crPk4+KDpa/g+f0mOiZrXx3UizwPW8dURQWnS3N29PiKscPTX/m2ce+5fRzkX -f3+7/cR/s05+/P8sPKo/vTFSe2BOefI//LcqPkoZKecSs53APS0HE1OUkxkzuzxrVTBiU4KylFnF -iZuV3MBdzpHgHfL3wdv1f/MMVn+09LBlf2qaV2bqr/+h5qc//y/fYPWxrF2rCjzuPDWpufQ/qy9r -9228qPkieLPk3aUHtV8g8/yqO8xjf4kM06uzwJvro4yTi49bvnFeu/qeY6Doz0bN5T9Yuqo/HCQf -+9/9dQf+ff0Z9Yz/QdO+KUXR718Li383Jrr6n/Pq6j+O8c7//iXtxH+Oa4v/QD3z0f9rUpfv34Ga -9t5l/OTor/rQ2lX2rklf9qdp2ZX/Pc678O+z6uoPH3FKPrrfeuq/114KLk8o6j8A5Pidp6/ivfVH -rd/NKYr+NMz45V9c+gvvBO8zT9m6GMcW7wkuxiblTaBvv649afs2fKvx04WbLfsc3TV/temr3gve -ov88JW373NNNIvTxyNJj6k/bLwVF4Yf0g8G7nQeC99sOTqmO/7fnRvnftl8p6teeCov8tynfrb8Q -XFh/xT61/pL688rz9v3LT1u/Dd6t+dzaW/yepav0L/47/KO+u5xfVp6zT4QfdO73DjZ/6rvZ/IWt -r/7jGW3dR/eo5/99iHfpnZXntDNrr7jn3QONHxn1Ve9OyK6+M68ve9/eV/5X7/XyTzZG2n8e0V58 -76Xg7HuxKUUn9GCFG36Wraf8XedAzV9BDz4Zl57/7xeik++oqn74twnFlU/RWUHN6pPW/cuPwPee -tewP3av7Grz2q5UnFz+0dJ3848oo+ULULGiOTHFLtsCD3Dc6v1q6T/vJd5305cK9zp8gX+4391R/ -AtnyF4KDwg9bDqwOcc56bnV8Y+1p/NB9o3XfwlP22Y0xcSXBWUb9lT8sPyMf9txs+w== - - - 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 -+axLr3ffd+SV7ns+3dg758Sm0uKTmx/tPrn9e9859drIysMvrrxt3z/d+2cvDcs//ORXi23sP3Rm -V2n5ie0DS8B/vOvj54fmfvTM2gcO/lvBPfriUuPc7hXfPLur597ze9b0ngXZc+mNx9aD3/Dk6dfX -DR56ZXj5e7/qveujZ7umH35xBcb7MGZ1x5Ft3XdePjCy+vJbT/zg3N41g2deX730/L41xVPbR1ce -27R60dGNvbMPv9g149jWzjsu7CsXrhx48l8vHvzfz3+0qXj/sa3995/dVcqd31Vacfi53Iy9P5ov -dvyw/Rsfbsjfe3zr979zZNOTI3t/mp/11i+Xep+//9TTJ3eO5PEe2Su7wC/Z1TEHbLv5Z/eMrjq/ -77v/cnHf4989sbXnnsMbl7kfv7DUOrxxxW0nt6247fKbqx64+s7q7k+3LHMPvbTMBlt+9ZWDT/0Y -e8xc3I35zsL9J7asmn3lrdWdV99Zs/byu0/86Oieka4PXx5eCPbMwrNbBuefeGHp9Ne/P/Orrzx6 -+397++f33/TJq91g5w49+P5vCnfs+P78/3Hw5w9PP/zSitlX965bfWlv/6ITm8AGeX6ZeW7H0JJL -ux4pXnr98UeO71j94P5f5Kw9P1lxy94fL7wZ9vO2371TKlx9q5S78ma5++zO0pIrr3/nexe2Pzpw -buvAnMPPLf76Oz9dNO3QL1ZYJ18uzDq7tavtyp7BJZf2DXef3z288sLro6sugM13alvPXUdeWf7N -cztz91x8vf8B4MlHLoCtf3r7aO7TjeDf/nJ5y6FfPXTTB7986Cagy1nguyw6u2skd2bn8HLMPx5+ -aWUb7Oc3wVecf+gFsItfLM4+/FJ50enNjw3gmbf9/7z4rzavv+dPNvRZf3j42SXe5yBDr771+HdP -7XrqiYMbyvM+fqW86NRr64pnwT4Be2TxoeeW3PLhcw+0HHpp+e1n937nh2f2PvWDo9vLuTO71vQe -fnnNik+eX33f2W2judNbB+Z98sJS49ONK+SxzV1t54H3zmwbXHhyU9e3jr3aNevD36y4/ezWvvkY -5zn+8sPuYdARh18Zuv/jF0cWfLhheO57/54X+//x4b9+cXTWH71YnvGVd3684GsXdxXuu7x39bLj -W1bdfeilrtth/x46vS1/19GXH5YHf/HQzR890yHPvFKcexH8nXM7n3zy2LY1ne/9tufvD/57h/v+ -L5ZOP7ep587z23vnHAe75cMNWOvbOf30lqGHP/5N6f4d31v6l0de6pwBfl3X5bdW56/sX91zcuvK -O45t6pl9dtfgw6d2j+ZP7/n+jz599dHeN57Oe+/+eoX18XNL7LO7CvMvvVHMXXqz2HNm98DSD0Gm -fvD8Cv/cvrXlo9tLSz7c0GEffmGlf+rVQvuFfX0P/+794ZHP31nz2PGdpf6Ptva2Y99H4MMngW+X -vvPvD9/y+j/Pbzn4i8W3n9kKdtP2daPvPts5Y9ePH7jpnec677r63j9sOrVj3eD7v+78+/efXnTz -0RcWfR18prvP7x0ufPbeEz+6sG+0/P5zS42PN3bddXJHuf/83lLnkVeX+Uc2LwPfvvvujzctsz95 -ueP2K2+vexR8o3Wndg0tPbu71HXl7dFHL+0v957f3j33zI7uOSd3l1Ye2TOcO7pzZOXRzcX7P30+ -77/z0wXT9v7DvX/3xtMP3nkY/Pnjrw1gDcqyN5/uunXL95f85fGdo4NXDq5/6uKuNd0Xdgw+cPqV -nllXdq/u+PyNNasv7y6vuLhnaPmRrX3tR7c80vXpy491gz4Fulpx6/l9S2+79GbPnKtvFpdf3jey -6sqeJ586vWlwwenNfe1nN5ceOL9pTcepjavuffdn9/3Na48bf3zwn+5uPrWlcM/FfSOFK2889vj5 -XUPLPnh+ifHGz+7878deXPiN869133Flz+qHL+8d7T61vfzQcTwfAHxyAuZz4uUO7/DzQJMv9nzr -yMt9dx3funrh+T2PlsBHLp3fNbLyxOb+2Qd/vuwbR18u3HFh90jXhd1re3f94+K/2Pnd3Nff+9nI -nOMvrAZ7ddWcj34z9xuHn1/sHnl1bcfHG0ceOPva4yNndzz5yAfPr54NNsDQ5TfXjF5+a6R06a3h -PrDLSsd3rl721q9WmEc2jC5551cjD2x+bP6fffDz3O3n0cbb0nf/pb1DedSPF/eO9n78XOG2Yy8X -2i7sHs6d2zGyEn31IxtWeoeefagFfJSZZ8C+Ab+o7+jmR7o+fG713W8/PTr73V8NLzjxSmnJiZc7 -Z7z2ven//cNfz73pkw3LzJPbBxad2rF+5JMNq2Yde2n14rNbR7vPbhlZ+e5PO/znhmf++cZHZv3l -gV+umv4B4PDp9uHlh17s/tbef7z/L09v7rnr4p6BBy7vLy67+sbq3KcvLvvWnh/O+csDP+t0z+55 -ZOTcG2tL5/YNPnx6W/ddsKa3nn61C/s4Lvsc9OTF15946vArpYUHf134e/Dxuk9s6vzWme3Lv3X0 -lQe9bd+/7asfbVgij2/tnXfitf4HwfZac3Rb/5wjW7rbTu/qn39u5+oHwS9dfGYX6Kmdy2779JVl -/vm95cLVg9/9Oejh9Uc39d59Zf/o4Odvj6w+u61n7hs/XHDz+z+e3XzgJ/f8+bFNuTv+4931P/z8 -vcf/+eS28sMfP997N+zj/Zd2DT50bsfgkqMvd9z10YYF7sfP5247trV37sU3Hn38yltP/vAM2D2H -Yd2Obem57+K+Uu4o2KTHX1xiXdjVu/Ds3vLK0/uGO8/tHy1egD09tWP10hNbC3MvHyiPgK34yNUD -/Suuvtm3+Mjmvnve+82q246+OvTQmZ0jvVfefvKfL765ZugoyPRPNhZmHnm1fzbo9eXn9o30v/HL -h60zW1Yv+mzHY+XL29as/AzsQpjj4vM7utrO7lr5zY9eeOjrZ0E/Hdm0ev6nLxfvOba5v/3zA6Wu -//Nheejz9wdWXtzX98ChDcvlB79Y3nrq5cH5p18dXX7spd67j7/SOXP/j+f8xZZHZ37l/Z8suhns -54c+exPmvXMY/I6R3PFto8tPbVu96NKe/nmntz5onNy04GvHX13uH3u1OPvktrWdhzcNg79SnPvh -cw9+feuTM/7w3Z8unnbsBTwXNwyy8JHRy/uKy8F/nX95/7rSpb1rBs5s7b7r/V/f+zdv/ezbX/3o -V13OyZfWd57c/N01J19b13MKderG/vvObRnJX9j11JPgK3Ud3rDcPvJS94xjrw4/8NmB7/zb1QOP -/++LQEen96xecn7v6ocvoC8E/vWl7aUVp17tbf/4WfDrNq6653cH1q0/u7u4+PKb5Z4rbw91n3pt -cNHJzeXFF3eDX721564PfrXwb89t62r/j/3r11147ZHih8+ucA/9dvHNeI7t/WcLt3/wm9Jdxzat -73n3+dLsA890u0de6r3z0+d77vh8f7nw/xxcM/LZm8MDJ0CeHHtloP30lseHLu58Yu27v+xxNz/+ -wP/cUL73K2BLiou7Hhu+vH/9o+deX9P74cbuGW88vcQ8g3ES8PU+3LDMeu/Zh772/jMPfv3Qc8tv -vbjn8e+c2/+jTWdfX1c+tqnvHpQjF18bWnry5YeMj3599/98+8dtXwF/6Dbwm+ec3Q== - - - vQZoBfzqXesGj2zqvef41r4553avGbh6cP13rh58/B/Pge8MtDn9k5cKbWd3ri2c3T3c+ebPH/76 -mT3D3f/5/ronfnegBPJyYMn/ObB27Wdvr+5Bv/OjF1a6Hzzf8623/n05yIu+e89vH8p9vq933n8d -KK78r/eKXed3r5j19k/n/vlbT3eYJ3eMrDqxY7TvvV+utF5Z/+2vPjMo/+jNf1vQem5HKfcf7657 -/HfvrXn03O7VD2NPgcv7R3o/e2t0CHyzb/+8+2/+YMdj0//01Mu5tt+9Ozry2ftr1x/Z1Hn3279c -+Dfn9o6MfHboH1773aEnnj69o3vRtjXmH21eN/MrH2H90paB+87sHFoO6+sdfrE49/Iba4qfvV3u -ARt39oVdi/7+3Z9/669+0vlXf3Bow/y/O/ZS9zev7BhecWXn0MNX9pSWXto5+MCl3d13Xdid+9a5 -11bedv71gUXv/7b71o9+M7zg+Obvr7/8xrrVn79T6r5woGfu0e1L5ev/MverR54tzLq8Y/3qt3+R -v/2FtTP+9Px21CvF+05vHLr/M9B9l/cV5lzY033X0Y2dtx57uTgHZNf6s2BXn9naM+vgL9r+5M2f -fOuPsB/jmR2lh7AGFePrH23sv/Od33T7Hz7TO+M/9pU6/t93V3df2td9/9Et877xwYZv/ynIOfPz -A2vXXdq/ZuDYK92zDj49p/mjZ+ZNO7epOPfqzkcGLu97dPjo9tULzu1e13d533d/ePnNp/7h1K7y -ykMbHrjp/V/Oaz62Mf/Ni7seLX329uM/OLd7pPPcnpHOz99Z/51L+4ZyJ1/u+ua7P7t/2ubHZdPr -P7jj/z4KNsxn+1av/E9Y/xM7++ZcPTha+t0H6564vP/R0fPga5/fOfDAJxseav1tyfyDPf8w839d -3jW04viLxXvBj/m7D3694K8/fbHDBztj2Wevry9/vm9d6cjmVXd/8EKne+q1Nd0X96xZdX7X4KJT -2/ra33vmoZve//WiaVf398z+bH8ReLW0BGPrx8BeO7V5+KFz20aWXtwFsntX7+zTrw2A3b96/tV9 -j4xc3f/ImvOg9z9+edUdJ7YNLz+3e7T76huPrrkI8BM7h/Ofbu69B+teTr46An7+wD2fPv+w8e7P -5/6v93/x4M2X9g91fv7uo09cPrD+ifP71wyexXzra08MH9/12NCFg0/+4+WDj3//NNhMH7+cu/Xw -xpXe2R2PDp7f853vnQTf8eCzef/Mnscevfruo08d37J0xo4n2v7442eWfOPEtuXeyR1dd+J6H9jQ -f8dr/9Jrf/zSU2svv/mDX18Av/f05gdu+fg39/75mz+d+cfgC95+6fVH1l5956l/e+vXnd/cMHrP -n3zyfGkh+Krr/uu9J/71P94eKR15aan70W8ebDn0fId1BnQ57FXhvWfzt76LPQh+23HHlb2PPPqf -Bx5Zfxl8uFPbV87a++M7/2zLU7f/8ZkdvSs+P/TkLy4dWFPGeMiJlwrtYDt973eH1v/TZ2+Wey/v -Li2F9Wh/+6cd3zi6qbjgCthFB346/6+fGzL/r10/mPk/Dj2z0Piv94v5/2+K/KyY7Al8UT8ZIvX2 -kyFSbz8ZIvX2kyFSbz8ZIvX2kyFSbz8ZIvX2kyFSbz8ZIvX2kyFSbz8ZIvX2kyFSbz8ZIvX2kyFS -bz8ZIvX2kyFSbz8ZIvX2kyFSbz8ZIvX2kyFSbz8ZIvX2kyFSbz8ZIvX2kyFSbz8ZIvX2kyFSbz8Z -IvX2kyFSbz8ZIvX2kyFSbz8ZIvX2kyFSbz8ZIvX2kyFSbz8ZIvX2kyFSbz8ZIvX2kyFSbz8ZIvX2 -kyFSbz8ZIvX2kyFSbz8ZIvX2kyFSbz8ZIvX2kyFSbz8ZIvX2kyFSbz8ZIvX2kyFSbz8ZIvX2s+LY -FPm5r3mK/PzhtGl3DHTO6ih3NC2+q2najLvlcvj3vI6hcr7UdF/TtOW3zCiVZxVy5UJxoKO0tvlW -ABmtwm6+ZV6+o6/5Jn6yGR5qnlMqdBcGADg/19GXv7n5G/DodPj/JqPZbDbo/xavbWpxXdtttYRt -ep6A/4hm13OtVikNS1qGNITV3I8PSa/V8oQjPNs2PCf9UB8+5AHM9n3Pc23HseEhm97yfdP1Ddfl -h1Kfq+qh1Od6mh5oGmi6v8lvvunm5sUPNC2M/Abr5uG6zSwND/XM7SjDkgwEi7n8vuLA3FJhoFwY -6G5pYfDMPCxV9A9N9w3iX0yD/zR/0Z3fLvThHtwS/Aprf8vi2e33FTvz+GtsU675h+nNN63p7xuA -P7XAtEqFlcPl/BDuDexrqSPxRK6n0NdZyg/g30XzLXcPlMO/4f+U1w7Svt5kGsa0m5tvWThQyAF4 -Pow70B1/dKSjb5if7ckXunvK1396oKOfHoa56Me/Uc84jRY6yz1Vo6SennCMiitX5XPlmcXhgU6Y -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 -LbkgPL6F0aM0xuMbAyfXGI9vIly/7ijm9TlrNYfC9RtR9zA22/bwrLh+ozV5djy4CFy/YW/4Sx1J -PF/9VgN1vhNJHHcNx+H6jY43D2YRnB/Xb3C3Q2vxvHh8Z0vSGI7HdwHXp4vqNzkeX5MipnHdG3Su -xtmg+MKK1Mlw/QYc2wrVr6oYmhzXr1sqNQpXdGJcv9FqzhAeOzOu32hUv4m7NtW4fhP6+hri+jWo -e70AXL/RqH5nxuM7VxVuIC01rt/5i+H7UP36vjIRrp92Jfej+g3rcnZWXL/R6V3BK3ZuXL/RiU6B -T+ncuH7GufSh+o3uC9cc1+/8fsvBHTt7zdMQu3ICXL+e4LJQ/c6dPRjg+o3kiD4EkMlw/UYrhpX1 -Ojmu3+iC2PpFnhjXb3CRIaqf0scad7IaxPUbrgRVOsyYTlYNcf0a6TAT4/r1n6QO4Iyorh1yP21c -v9GPw8gqzgsriK3e/RXjeXgzSkd7vGtnfIR9pf6uOioGbyV+O9y1OzrxPihbHOCmDo/1ojc3b/zq -r4OvfFP1p+YGXsj2z97GRCuPD7Pufj4asER3Tlj75k7+nsazcn968e2jK9HK3re8Ig== - - - Yj3V9JWHN++1o7mj6ZWDt798cvz3/c2b39+XT3cX5pZ/zM+u/V6Ltr8+unP595+1bPrd/pcE//p0 -eyYtrm1fffj497P097fXb6dm8rTtD4qHm3vtB+3j6XRny39ae/Zt99aX5w+zV3+/OHyU/n45d/jX -lVd35v3Gv5dePHvwbfX79b2fh7fmjn5/zH/PHN8+yh5Nv3p0a/ZKMreVzfz19t69+T9/X37rf747 -XK3vvtR23tx98fzldHvxw+1p9/X3y8XryeztaHPtwVq0+dfB/Wgru/rs+PhTOXd8Ury6d3L5Q/b5 -JP389km30vLF4o2V5VftZKe81Cl7+3fl+OTdT4LNlZer2motQwbqS6+92flY3jl4+osGdRcCkniS -fz7FMwt3bu/ctzZLNgPLPb3Kc0muTA9dq1Q0zu3PHj65/PLNi5tXjo5XNq86//XP5e9fpr+wkvR+ -pzh0+s/SL/+I+WoPj6QmcfrO5osXM9GVwy9i7z/5Oaiy/wquD5b2ZL2vaK7nb+1bGsSatQ83s5n1 -P1MzG282D/cEQHP9/dazvezR+pdLt1dOr9+/vXLy5dpmefnbk7uvbicfsG1HN7e+v9x7d2c7m/6M -cV7+7gxbwWfOxYvfcpYyvv5w+9rO9LGs6s6Pn+TkOw9evfq4ePfl3jb/hQU/+d5m0e5SZdbfTF8f -i+UUrZzOMRvh42kliVfS9mznX/Gc+I6xI/kRfswXpOoXAufeL/x4Y0kkzOVZvGJvj/GL9XbnP9xc -2bzrHhYYdjta3Fia+bM5t33vXrw0+/ePuwfffpfRys18XibKyb2PF9bja+v/7K/E+MONxb4/7F9Z -vzE10/nT+nLvT27tze6tzh/udb/3oP97y1fu/d3ZmEfzEBk/v8VbO5f2u79b7BFPzcRbH9oH3T8t -942z9Ws14u9Wav0ofRSxyuhHvJ3tOP7oqrE/f5jpjv10sSL5/Cumhv50uc8He8XN3pxjutXTdkV0 -kK1znKcRk8OO44Ptx/JjPezBm7dxfVavNxdXHj7/luCvL5bkr24+W/3S+eiLducr0fyVInLfn8/c -XSrnwR3Ryyv99v6nxborYMUMg/6jwO+DYVcqjh8cdGpm0mGjvmHjlcsn1xd3rx1nN3f9ozv5+y9z -vH/Es5h/83y6ZpvXb12XBT4lV65f/7T5cf7tAzf/58u3zia8WuodndvYvkHuftWuNmvjzb2YT/oV -t3HwOK3/9X3XVfmW+Peftx9EVXF35/c/1v9yX1MOkVZDfHxzmyO+abNy46f7+H0nqv7bj3+e1WN/ -mt/r8t0b189j7tO1L/92/+S79/Nz31o+vZpe55tzjQkLz9a+t78u3Hly8NfOxoN70897IqUb1lnv -ugmuDtQkdkTYWjLz595h56PvV2QZyVW362W2ydVrb9P6Xxv7/3Tpkpru5Y874Wwer794PzWzufH9 -0sGdZy/ezd79vHz7FZ/t65LZVkuB019ZdSsHlYjBcPDVAQnaFXAdCdqfN96ToYEEXX3/+Ofc3Vdr -D++vzX8/ZruCbHvtbtR+oSVoCEA8KwvH3V+4U0i72vnOFX/ys17G3rfF6lTX9j6cRCvfLrVX/rn0 -5GpypfxxGkVz7ZOaNSE3JSVcPK/40c9LwXN8991t/rgKrS/GK3KTQnGpe/Dv8N+8pHDZbouGxySc -tvgkKI7oc9heGeJd2o6M038mr9iDOebB/o6XoqNPnQN9sFBJk6X1mc/d3y3Vv9uNydMPwBv5y+31 -T9/ufBmQrztRlH5+wGN4EAs74/Qrybj2m+rU18eUgvjA65/yyHDp7+7UGtfW+lL1u+rd2LpXkXCz -/l37fuloM95e3ow5QNwnc7dvPUtkLU8XAl3Q1gT7tcc0dKz03uvB11xYCl+58fzul+jLzNHG8fGN -g6v9ioygXl9/8KqrZ2y79ReffU/zlN8R0vhhZ4BPM+EAfz4/+S1ov8WfSo+8+sbd71Om5XfTN14z -VeLZKXXQ3YFeEzsn7FTwpH+A9OdmOEBy7+0PsV6rIZ4PYvdW0qt+yjc/zrr5H2s51eE5MNrXiHw+ -X/9u//dC/btvlxZxoz+nXXb9MhBH5ojVqqXrRg9C+/arhX0w/uIm/tBeltuku050RFgXMbqrdL4X -fZPnImjd33cfcaKX+KfXg0045nrnsjf9c+VupeYdr71+29HwoBh+vvLsHZjPb4W41bQNejv2Z5qf -na4205+8vcp9mu60Gykv92bTbwfhDehswe1kcQBF/FNnC/xKrVt25/OtD01KGjdUm7Bx8ry7Ce96 -SvfitT9vH3e3IGh+stTbgqmZoZuQ3H46N1dvwv6txzpFnVtQf3S6/0j0FmAtwSZUeBbC/WvzD7qb -sP2+fenf3QZ8UGXmVUycP/7W7UPi/sT9m3Dw+OEwPpitmktU83ZfnwasNHSAPut1tir4HsaN43mR -ivHWojUHufuNltHPDGdYRp9uWT1CkywDT9C3leA0emfRvZUjljHXfxrn4ek5qeHtnkb/EE12Qobo -baW1jA4n31r9dtQZYiEAZJ/r7cSIOYySTsLY9Y5F2xvPP3fbzhwNUs5X/ZSqFjov1roH//p9cDg9 -unPzWL/UPS+P4VFon3OIiseMG39GHuvfiXPyWP9OnGuI/hs/hEEoLfuHUGzad13Ps5VzchadHTvX -EPON9gED8PSHDHFO+ds3QPe+Yy3nOo353mkMvfG9OVR9rsJZTCJ/qwH6jhOL4I6ddRm9y9VgGTKH -qUBwzQ8TXI3n0OhFnp7dePe0HsKdfBgcYuGc97PvRV7o8eXQnRg9h6Hv0KC0HLETC/3v0Pmk5UIT -vhz1Di2M5som0nLBrb2O7/X9+P509X7vx+TK6vqDvh9v7e7sdH9cFJ9n37ksDnrbF2uPaffHKl27 -+2MVn+j8WLm+ej8OzGuRXTX6Z7ZYzUyCR4f/Hq5UxnOfWUR3/fL98s30crH8ZnrxoL09vfR4fkn8 -Hgw8dV1j2+1OyGAn61vLVdGeo8PT24XorV3v0oc+W3T/yo93lW9m9sbrtOMN+Chm7XLHn/ruhD92 -XYTbs93M4XQbZsrmn+8MFLG9yXZliTM5YalaUPXjertdT7T+z1Z6boLk1stfax1z3M913Z3z+Eqf -g7U87TogHyz2/2FnsevafNDv2lz6kHddQw9633ufXLn29U7ne4/jqZnextTOk60bC73f9XtwYe/3 -/YEe3M4fYPnjRoMX994tVj6A9yf//sEfnsXy49QMOG8av3hyuzf2x9qh8mRT9psX8nBNzAbGkgoe -aAEee3wMkscrvPFL+MDvK/hxV4ZdqFw1K0/eJuI7FVvsxeLizcvXL/PvZOc2TO/XOz338qfOVz5h -l7M3yxsr+9evrn49mt3dvH7X/xvYn4ypPe1PELCzbtxOiYkerU8ybKQxIDBspy+nDDt/v3haFlub -t2cPX2zc+3JjuvbDvN6LO2zzos8p6ea/f7zcca/u++4W7OMrp6UcHeXY58fLEj6oPQifd1dql/Tn -vSj+vHNvHv96G9c+s88f3M3yHizjlc/7SedfX7wMUB/xt2cy3rKE8/Hj3kon23bl29uo868PcXc+ -n93srZ2bNSt9+5L0/eHDdPKx9p0+/D1Tr+Xbj0wM3GStSIprhx/m/1r/O9t8PDWz9r24XPQ5h+Rq -MmOgWlDv/1T55Z08iGjldK/d/ehBzTSnH6J4K749h3/tx51/fXF99+UAQuMZVnj6r1fzSU9fbi7M -37yWv1y+9HDz08OZsnLYXv14kkf3txbpd36f1bdyL7os9nzPg1nlKlQ+zP+cB1NssdqH+Z/zYE71 -Z7v9xzyYlXe038/4n/Bgdryj9GEGHsz/dXMqz8u0lRdF2lp59uf74fHj43++/nPUWpq6NrVy514c -7x59+bl5fHj44vB/nm78PPjz4/DotLXaWrnzfP3evSLdODz4+eWwJSlX6ae8KzOW68nWfN0feB/w -hoojf23jr3Lr2/blZzf2N/6KXt/suw6VVvXrxe/ppb//3Z6a4aM6M7308cvb6SW3+Xx6bvtkiT++ -rlxF1aNqhn9FGi1c3jg8Xvtzd/HhzqsggiE+ovLTi60bUzN3X60dPru9cvL1+sr2nTcPNt5svnx+ -e+U0+imvch11Hchx6IvNG6F8aAanV6fnrz/y08srsy8Z0t/AWq5sFCvTS/O3b/O396cXn156xPU9 -4h9uTS/fSb5MLz3c255e+H35mI7Qol9EXHWL9VXrPXabHz92WPHJTxGvU1WUO176+vWmhDRqOclr -J1GWzrVbkR+ZeDlX/+vfQ1EP5mt9YPY3gW62F+sfV+foQdtelh+ZAr/j6yH+2l097dzhe1EvRtqT -4GcKuPbCrX1iLAy49v4QqApnVxSqYPXZVIWzKwrVU3k2VeHsisLUzLA3fXbEm35WHaF2wzQd8Zzq -QS3GGigIk6gHTOltpiBMoh5gLQ0VhEnUg/5nf7SCMIl6ADV5qIIwOm+lEwxaHfY41OJ/4f0mTp8P -wN700ssPdyEUX+1Nzz96M1fLzT+rTyhSYWzN33oxPf/P95vTy0dP31GWlnwXroQGVnVgN15Xog6X -5o448BZ6RtLzXzXR/u/lTnqKn+ulp3QzSmZFM6C0XKyl5ZOrP/qlZf2Ez7rZ29Pv5dgpLdfbS2JH -u/d/rt9b+WfvtF0pHP8srS5KSBFy7O59qzQettejB8Hp8w+7+Ep+3BOtlRx7X1+BQK6K5gCRypmJ -z+5bpTkMGGBRT3vpN/i2VufJGw8lM07clkWVaRBv7c4VXe2lVoW2vnru2KMq5QEa2+2VjfvXf0YY -53FUCc8+ib216+QgJHkjLHxc78+khTDvvb6VgR2WkXRzEwLg1yp57u6HtBudfBo4eypbfrk/xHlQ -PFAx0tO5k+4QT3SMdGGr7bfv/OhEYn92AKYGgrnLD/uCuXPl62QgmJtdnp5Zu7IxIhq8ttI3QLy5 -txVL9Lkq4F6rrz04XZT1lX9u7t4V5YCMdlP4vPO7l787v3t9vPLP46PFXhKIsNxAqkIdn6scV2Mi -dCpIKSKsClLecEPitKI/1/G5qZkgQtdzpDX1SQYORStOS4di40ht/Ku7CR/6t0D8YfUWvOnfAsxm -sBXBt+JXg0jt8Dht17M7KmQxyo+33N2E+qN1TqIcSYMtuHE6YbD61uqT0wZx2v5gdRixr8qfJwj5 -V4WbGACn35Ab1RACPddsDlUarB5CYLMmWYaUGXSulOzYmZexu7pypqi5vpVL5enCJDxNU3oxGKDe -saY7Qct7edwy9q8/6g2QvP0eF/2lPPHSr/XIXEbDrWSiZywDnFza2l5b7AKOTM0svD1OfvdRwtyf -ryk3/40XDWiSms/3P85OyGNQUOYm47Ed3+4NMJTHRg7x4XY0KY/N/j03GY9FR/NDeKzxEDuLS2MZ -pH8AWcQgj33I25OcBuz5GyvWAOCxpkNs7Vwaf13tAeoWEVT4Gss+ew4f2vZWcg7i6g== - - - G3saUDDH3vhRc2Cq9a/VyU6DWu3orZT3ZdQytpc3z3Y31ByyHbrGJ7kb27eeuTFzOL65Eve9yNv+ -tL17vW+Izx9mJnsDPn9dXOy8yCNnMWIOv+LhTBXMob774SwOruTLE3HEwfKNdm8r+6TlmJeof4hs -3bziQ+egpeXBrXu3+n/cfny7/8enu3fqJOg0rlI/epBqMtdiefrAb9xa/Li38Wd/a2f9/X0psqk8 -DOntnuPpHWzILydiclSu6l5C5c2tV2Jcz/W5ue9+WL1eW3yPD49qD8jet2X3cfvLktjcnRT49yd/ -i5FamY/Jrd1LlTXd8S5dnpU2FRIfqOpButGB2uoWfwbmWv34/uRQ/HGzYt3Ufhg+TF+7Zm//RAOH -f98fBr3+fX/YjbtR3gftAQc8ZPZffcb1+SpDhtaFVHLsgipDhtaFVEnQF1QZMrQupNeode7H8BKO -8UUhuiSkf7ypmZEjNqkHaVANwpKRCetBGlSDcC0T1oM0qAZhyciE9SANqkHoUZywHqRBNQhuZbce -hOZq2p9FfnXlaiWz6ov08Kj+Dx8fLlS7OHvj+UJdwbb557vIKbololpOvbq73/H1QXmXTIq5yjUI -m1XyLHppFytuY/ntotSwdd2Ky1KfKmVsrILdqy/A1oP5us1curkSNNXo9gJI70UdNzyj850QvaRq -UMrjYZqbW+3ESFZlGXP9Mvnm7aXKMVgJz5v3VvrCle1+YQdTqfbmhbEW8EEdrryx0InTQo7xSlXP -BOTYciXCKnn3a3VFZBe/UrsdD+VVkTBLb+xerKVTG3nyv25OXZuaYbTy492jL/2RyqmZGfzm+eHp -n18kSD+uHX7952hn/78Pj6fiVvW/CP/j/83LVuyKlktT/JDytzufp+aEthXPt3aOpqLWnbtTMx9X -7hyfbvxzcPrPz6P94/9urfJXew93du9ttFZb1X/wEf/BtdYcphR9BDX+NM8Y6ce4tbL28+d3/uX5 -5qvW3f/56+fxaav6xst/Tv75/P2w9eJna/358/H0/XRY/kdOD/9v77+wsju/8K8N/L/HU1E7i8ok -x6LaWeKK2Mm/yjSp/5VkeVzgz9+monozMMZ/44f7+Me/+NV/teKo9bD19n3U+sLxn01lSdEu8sL5 -qMxzV5St5TRJ2kVcJmWU8hdp68dUDKLYxalLM+eTODOIdgyiJCvbrkx9jnmlkc9BpD/XiMj43F/c -o1/Yn69TrijaaR5lUR7HLsLZ53mUtKPSpbGPkiIqsQRFs1xkedkuo9wXaZnFZYwx5zbnWwvc8s62 -V//7Zk07jdvelXFU+KzAms1dUkTWLsVFhmmkmAHnl6fmBjQiMj73V81Jdw6n/oB9IpcnvmIgV6Qx -5sB/VkzDdfrWwymXZe3UlXma+dQlPm4tOxxRnGFP88xHLuNaDaLSt7M0iaIIGx67pOV82i7AnHnq -i8j7FPOL03YSJ3ER50UcOd9yLmonRZLHKZaWJd4gOZiKMXBR5phinEdFEhtEce7bDrMrfVwWZWLN -xiAJV4VPaSKftDNctLwssV0RZIyajXPgNRdH+C/yMosSY1WK5GBK744eR+9xOJsGZ3VAHmhHaZQr -eQFOqVkAR+/SHGtP8jxNsqgoCg7l2+A4l7nCF1mS89g1UZG3fYKhMfMiTfOWA1ti57OiLF3uY4fj -irJ2FOcuivDLNMex4/zyJAUr5liJScJjd7jyGVibRD4ziIzjCmdjHXuwKvvYY4jaCD9inAzcoyaj -T0styjp1tTl6HL3FwWQanFR96BAGmVxtHLWP6svePX/70NOiXYIxEyykKPyQQ88hetIoK6Gf+8KX -LU4xTqKizCDKXZFUF5AfKrIMMqpIcSviNti1xH9W5BDlBgn2J4IE47S5FVlZGkRxgcsf4e5HGMpl -1mwMknBVOHRNlODq4BZBSEZRCSJjNvquq1VZd13tToNTV7MZf1bVsXcPvU/al64r4y32iSGLPARR -WiR4VoZc9AiLKHIPYRNDXjnv2p7vUZJ7vMvePHLfjr13+LHEf5kPOXIIwjzCpcEO+cIiwlcgwDJI -yhjnwLc7nIxBEa6JEkURQZ6mRVnwEcXNBR/rybiijV3APpR8aAtrUSEJT1xtjhrHuOfhbMafVHXi -GVmpOujId26871x5OXPXTvDf5bggUeSTSmSAsePE4dJEmRy5oinA3NAsMihd0M1q2Z6UBeaXlVFh -XU9eiBxXCv+LUmzTkDP37ZxrgAh0+GbDMw9mYx364KLsM8+xzNKVBagyEBmTgbaJBzXOszRKvDMX -FZLUsn1wc9Q4eovVbMaeVHjJ4+57HuHZ70p2cGAGyeIzRyVJpEXZxrg+B4clLpcj10Q5plzm+DmG -6PBg0wSyC2+pw8QSzJPnkLadL6E1pz4lb7s4g/ylAMJ1iPLMIOGR41O4WDmU7TQtnEFknFU4G4Mk -XJV95mk7LvM4wmJ9TL1Jz0adlV6VdeZqd9Q4eo/VbMafVXXoKfai1tmjwkWdY+/qdkPOHfucUGuB -hoAn0j73LIfamHk8E3iXUvBh4tpQUrCJZZpBZ+BhYEMSLhX6ZkkS3IoI25znPk3jJDdIeO4lJTUU -nphCLTOI4hKLhVkG3a6AtLRmY5CEq+K5KyJIVBgKYAL8AsQtYzbWXQ9WZZ272p0m5x7OZvxZVeee -O9c999zXT3l7QHs3hsrxVIB9oGBgp5Mhx160cbNgJ0N9LAtKeLxuGS1nKJM+Lsxj56XEtYDyVKT2 -ocdJ21FfxfVySWoRidSFuh5huBRS0JqLJgnXVD8lg0QUqXj9CgjGEtesZcwGorqE0oepQFyXxppC -Ah652hk1inHk4VzGnxOPnF4afBHPP96bAnYHrEl5CigDMjFCXJyLcm4QlW3Yg7D/ygj7SI2lbJfY -nCQG4xRiJOozhcIANdbj50jMEutQY/A8GJ7LTRNzGONQw8kYJMGizENNYQPR7oW4hrWMT+nZeN+G -/VVgnXhIXWIsKqTAl/TeqGH0DqvJjD+pg6m1z12H0trfU3FrbvfoaP/H4ZfW1+P9L/+wFCN28zVB -vy+T/3ft6xSeIzBcCvUuKWG75PKXZfXbatFQVnwaQU/szgTbmGYF3URrP8QrtLY2NeA7rJ1APSci -xE5SVE7Gb/+fF//f4sW/+nybLonasDGg3qZFnIu7Ks3aEbSTHM8QnkCeLKYG0YW3J4ccTFxle6YJ -eCxNXZbQqeNy6KJx7ME+eIBr1Yymc4n1pKXnJsDkLpO4pLcqdXlFAvsW2j/e6ySW/YYozukJjjD5 -OK+/BKU7j6GopaUTYQ3OxH+D/Yb6Wz2bdA2DCIZbnIiRhrfY8UtZ4riVacJVYkcKrDJ38qW0naUx -2CHBrOmKdWnUhtlXYLeTwldrKsTQiim+uTW+bNPqo4OtgOktDI0TpaKYRbDCqkFiKA45FPcsLbKO -mhjjbKHEw6os6i8lJcy9snCOrlCQpNVGRWC1asJ4kGK88RldOuOPicdqRjTmlqM2tAbo0fOtleen -x/8cfW3Nra3dOTj48+PZz9N90vbFHnanytbcfGvvVeU3XvhTedqbBx9oqWGtUJrpq4vrK4Nbh1tE -nUUcyCYNjgx74EEGXZokaQEtPXYwmKP6fEp662lVQ0USEjzJmBcdMBVfBiTY/TJr41pmjB6UsTdo -dqYSueUugz6V5qWzvpVEBW8aOAMqHPUukNByxJZ4x0PLLRLePYgP6LJZDG0R07GIPJQCGnew8uIs -adHTmWaUOEmSetFBswx3CRoKOJiOhRYnHNHMjMg/RVzpT1BewXlFRhkin7KIYFAk1DfyFFoMl46P -wbTMQJZFlVYILZl+whjTg1KCj4Hr44xe5kiOKndtvi4JvgWR4gwC2XJ6qgsoxE7mEpAUULkgTLCm -iFJZVoQrDW0tonNf/A8QKXmaQp+GzoTpu5LuGTx04CT6NwySgymDJ0KinSmDt9THNIcWeGMyTC/B -U5DlQygoqyBByihKW+sN7sJ36nutDWFTuVYMLRQ5551BrJXYDSw5I/Pg2sDGgWDhc5+nlUsyJIIA -hOGKcRIwlESYyF8RI0VyooUzSejHBGdATODFyeXAFBEkMWQW7hEkHQyzljEbyCTyBaznCJKtZSwq -oDiQ0BzsNlwAnD0UY02zIzTQumFixzHdAcaXCgbWsiLDDYjqG5zRn4brh+9HNMlMEphZUZ7EeD6T -sp5NQIQdhmxLKYYjPKv1dDQR3oAI0jgi27eMGYcnZSw8JFlvwhbkIGMssjiueBLhzcB9F+7J2pWE -w6mVUWwQUR7gtYhT3H+YNowgaaIkcmBz3AO8gHkhDu0czyCEFRSAIoIKYJJQzmQM9OL+ZsJhmibB -MDEZzOEp5JfUZHI+lB7CEYNk3EW9qJDE5LGQyGQy9TF98DkVMEh/iPq4wJRtEggi8GqO7bN5jM7N -JMEtTRmNwJHaNFDxsFBILsaAjfmGJ9WALag2LOz2vfUbU9CHIDDKPMOD7uJiQDrizYIyBGaCiIaF -4GmqF9CzSoOIJGmUJoyeuPrrHREKZskp9U2SSobmOE0nT6YmyvACRdAcsQQshHfSIsLRFAXU1iSh -LWTMGBQ+h7zD1uPuZi1j5SEJp4OnDBvuS8h12AQG0Y4Q5ZghtVjo5s78GBX+LM8yHzNQYM1YUwQL -r6YTEvk21KgU1wiCLUvq6UB/SMHITDvIbSKHxyqGPgxZntWyxtF3Ah2fHjOoHXSUZNg8B4U9LmoN -p4AgwnljrfgNuJx6HDR0T53XGySYM9RmqDa40fSYV9IxHIcacQINGo853qHM2B164XJKb3l/hCKB -EYLDS6maRKIDJUkbZgP9pZA+onuDyFGjh6yCysMv0TGHVwzSFC+bq0g8AzVQqKCgZEJC2Y9HHaZ1 -VI8CS9PDBMEhe/kSwy8J1Q4IsEpryzEwdK+S0dtC2AILL2IsC8aiK3xNJNEcWAYwn3AlaFLgVfVZ -iXUlZUUC/Rp7BdbGeQkJTiCjgY5nyVUkUEM9hENC3Uf2OMf24HX0WGx1DpCUmC6tKKhlHAa/AG9C -F4TRU0XH8dpE2J0SUrzkwmEkUXxAwS3JJgbJgfANriwmws3JzHEMJoVdV+LhgD1ZQOxZJNAzM1i/ -CWO7qStsZg/lxc4QokDuqOuppZe65iHJehNR+X1QwCZ0JPrcQw7RC1FHM2FpgHHB0fQf/BCuZX4O -tLaMx9qSKHcufIRDTnHkwtg8flgnce1+z6nuQ1ljaAOMY5F4GNxQOxOoeZCUnQsSEEFQZbgsMJlo -grSM2cBEwJph8OJtTH3LWBQYErYq3yZaSNVVTBnOSTPqY3lljnTuGUSFJ2MnODnIA/wKLOEG5ELB -3K1W4lNYVFB7aCfgfmgKfIimJCQEQ/IQccYgKT0RTJDhg5Fn1kygGpZ4bnO6C3xFoleU4u5imzzj -c7GLjY0R9y5WXkBAYZut3TVI9CkZROFp68kontGLCnmPn1KbU6RtZt7FlC1glJbeYA== - - - MD0sRbwSmF2Jx9c4ppCEDKFOW42jeUZNZvyFOqhtLPwX7ZyiIsL9TGTiUFxhy2RiW2NrePewOEeV -D2I9z0WaYauh2OeMBnrcdFk/XwxsML/jDIvXIjFOVRPhfS8py2DcYJUtazbM58BnaLLTdjVWRVen -L7JIXH6V4PSUiYVEz7P6xe08GTC7sVc4M6ic0CvwfsA6r/INajFelJ47bdy9AQJ+hpGxiAZuBMLM -GAOsg0uU0GOSFLk5j6iN6YrHKinzwl4PeAeHTW3ASQqNsS8gIZvjlcb7UIWhwt01SAwJqYnC0zZm -E/KMXlXIe9w+tTvQ12NaF/TipBkkit7hwmFkOi7pPM69efkCEn5KnbYeR/GMms34G2UZGLjDUPJg -vsIuySzvyw+hYWYT1NOkjJ1FRJLYwypnRK5MUu2iIUUE9SvnVkTVZg26aLARmDDUSuhAWEDha06K -aXnFEZ10ohrTwKX7OEpSnuIQIk/HGb4TUS4n+msVDVSkiOFdEGbGnGEEFwwUu5KaWWktHCS4Din0 -Ih87HxskWFfGlKOCnvSC+r3lByONp2FKjzaUN+tb9CtiEJfwhsaxMWFQRAXjH3xBJYNGb3JKZSrC -s0mzJRqwZDBHurx3hMh55oJDY8Vo/So/Pu9FrJZtH9NMThjP6reqXARbohQKXDFcOZ+AJzKDhHuT -8paDJ3JGBKxxdoSI0f1EUjaTxPoYfTFUI/k6VSENzpgcUqTQmalpQv5F4PKSXuSksryClZMHY+qa -UcSMkEzGYVZjyVwvhm68cA4/ntOpWaalWGcGTYbFY8tT8l9lp+htZqwMQkksqTi1djlnAkZMfzRG -Tktr5SChOwfHnBdsPGduM8RFxtg4VZa4k8EWbjMdtgVkTElVxlkjwc7BcUEi5rR5EnPKFF5FjgPB -QWSVvqa3uQCnxmkM3QGsIXm8egvF8VJiYHoTCvsoyqRNF0riM7xZyZBtBpFj0i7zcqu0AsUbIEkZ -mGO0KMqtlYOCjxpOilEziwTLYuYLXyaoQzkmbW8znbVFRt9HhIttbjNIwFqYCg4Vioe1zSCBNhmL -iyWSzEZjm0vGuzBwkTOzoTTlILO0IlAxJlCWpSFWSjwtUA7xFqfYRkvIkYT/Lpl1XXvAApL1Bo9N -YKHhbGg407KGjKmEYhCs+CFEeN7jPGbIWQQaiHB7S15yPKCuZZPQqYCJQE3A1bM+5RjjyGUkJ/nD -PvLMlIPdwYTetHa3ZnJd6IxPyG0k8kwmppc6kxxFEPmCWYWJVLi0SFI4MFJJ3aWjgQQkVK4pxFMq -P4XxKc4H+4drDUkECdHJFE3ooqWSVOAKY/a4sCUzCBhgSap1ZTHdI07eEZDgDuGyRryxRZEZJPhU -DL7BjYwla1aeXT0O3qeMFo9jLqSvZ4OL4+jdgZizSPic4zJg06EnuUw+pYkK5tNC6cMry4xOPDys -m4Gd76gSlYYRxlUxJBvTQxcXtWXAR4aeGcbK+KWIZRx4xKkjJTVNv2+cx6kPAk8NGAsGKvQ+x7Ny -EEIOtwOXN5eHLqcjq8SNK3NYFYVFgreaogyyrcQOysINIugoDPxAYU994jEO3rCEYW5fYjqltqih -hjDJHBeaD5htlsv2Ydsg+aDUZcYgjvH3FPclj5hZ0OrzP0KO4tBBwiXCfvbUDKPYmCw+RC8l1Ctw -Ds6iEwKDMoUbQN0WAtsmgQSlKxScluZC4rHomFtadvaFl5WZBkUi9g6njP8GdnfOOpyO4wPaUsGg -WSZ1ZV4qgrLE4UnJOnl3LCfBjmX4Viorh2FScBCYSYlFEtNzCI3TJw7X1VUkEUtCoBHAusprJgan -svgooZCuzC/8woGYyeVYFqunEohZSY51dQhxIHbFw8SKIJBwFbJKZQlIyDaYDwQU5EdCRrXGiYo2 -Eylcgneh8LUxOBDHtkiYWQLDoeCZVvJG0eSsbsB505dHNYeTgXqJY+NVlUWF1qDBoVConIc1CPUO -e1WxaKXP+Zx32NdEQZzISzp4ltMyKiufRBgQhz3b9jwlfAlcWft0CnqGwRb4fm6SKMvJICo8Mz89 -LyNkRyKs4yHUsfyMiZOGE4VLJ5tgskxstZ0xlOp4FDJIzgKsaDl1fASNhso5Pkx7qXLGSO4Lkyag -A5gPWvB2BvYgrhIml+PB5LNYPRVRm7EB7DG/Ja8tiKAfOgYnmMuklTLPXB265grew6hONObDBQ6F -9IBGaJEoY98iCiJ8MhlMA0KMOfq11y+TTHysHK+FkGAXS1zXAgp0ndMceA89U3oy5rrIhRVdKvBC -Qp4x7QbCPC8LU+76iPWkRSphwk66VyB3WWuI9ztNWS9q0Xga+pAdGXPta0WU8pGpzFBY+RsvaQsx -A7W4Y6XtD4WG2qY9Cq0Aql8lowb9oaTw9KdLQLd6ZYMLZpEwU4sBEUZNOh/SNIPPI+dSsAgTb0Wa -1zmCeIdz0FB7cLIm3jTHoo24k2s4QMJTYmoQODynH8QnBtGOEOHgsAt8HnxpfQwkCUsDPYVWVGfJ -OMZ4IDglWdMmGQyaWzQ51UNcXUY7oEmThCHelN/1ovHmTGST0mlsR1JNBpKLhYoMgNTKDl2xnjH0 -Mk7lU1CcxUImb8d1EViZ8a3L5DuSHgepy3z1rFbyBjxIZE8wLnMVmCVoOavIn3jBKd8dMzWkFlaP -AwWkZN0Tn3BxfzNizrwqug7pX4PJggUwAsWSaF8reSVkDsZ22F/ZPRAxPxRTz+hUrvXbhAGcjLn8 -HEe0vpL6o4/FkAyVRZIwkJRRK847ijS2HnyGDzopzBLmIjuyJjHuqPYps1VKei8KWkFkUj7hBW3E -yooGUc4oNUu8oMe1LBJYEaxioPEJldXiY5AkeMUY64WAkfngjsNGjDPmL1auAQjvgiYu1oDz4S6n -rCPlG5UyW956AnCg2N4Eyn+ap856bSoeDRhQjZMwsYP1iZDokaRW0lWHqxpjA2FDxK0GD0PHry8T -x13j3PM6VlxC1yzpo/Q0MPiGgM2gKDm6YWC0155niEDmPbGOHBztsfl8uVIJISeVTsN4OE6SN7kW -uBT72HwoJalBwg3IabbQkuWx5NY4uFyeC6GnxjlnzUZLnnBVB5bkARH2DQ8UFsk7Z4kMbCQuUkae -wv00SVj8CsaAHQ8WToeInvBpNOQgr0Emac1cl7WqkOTAOtCQaMd619THQFKy+ANvbBSlzpqySRIu -3SAKt9B4ZcODGM+mhrMcu91mVh6bRuDu5IYDA8zNTDb8lb7y3HuLiCRpyRR0WBh5ajhybYpBR65B -o11fFlHgSDImHLqjjIVr35fH1zFWiduIVyC2fV8kKqKYjhEvhYTGx5g6ktB1DyWksiDUlA0S5fuy -iDqJNhEs18q6J1E1tIOpUwwh8hS19EhAqGexZQ1ndPdiC+lrq4IJoWYHNsX505qjE9YIqGPKsF6o -R5Oxwc5GvBwPSZt8Qm0QRpW5OdBU8CbglWIgxdcqZJWMwzBG9QaBCKIXWg0epzKrNd4qGSeSsjwZ -B5odbVUWPaeWUiyqVcwHOMGDX48iyTh5iTPOxGmWJ23RS/GfwmL2rV42DlZWSvSDC2dmEG4jDKxK -wHaScXD78dsWSTImTcm3Xa32Vsk4mHSJgUnCvBK+bTAa61EGIpqcTtyWOAFuRVI7PzrZOCx4zmHg -U1X2JX0A2I/KDz4QOvWMxKQ5Aw1Qc1KnCA6EZzLxxDkn9UB6DM2enTwcVxl1Bkk3D6dgs5LSZnPl -4rVpBgSOvpdKaun7rV28DURk6ONlhCOnWYJXulZRAsfrD2FXMh5Dz+DZOkSKU3bi/Mxrdi0kczqX -tCtDdaWLkMYLeDWuQjsgwWcj3hX6QLCbBb1IMLOgwuMI6rgEOANPaZFLq5cdIYKlDR2ZYcoq1AoL -jIEMyJ6IYUDP8GwZwQ7yfP7iISSeCQUlCx6jOkuExee8dbjBcnmgPtI1GTPn2XVUL9oh+BlrKcEl -1OiwXWlMnViqcLgsGM3UcnJG73xJrwhOhU+e62zOAAk+xfRdfishU3fcwME4JeuGYJgyLOpqjZxV -15k84/iPLBIejFRmQ6RVHiuDCPa/cxIq90xkgQTBqnAyOcMSWe3a4UlCRoFFoX5zVS6XmCDlSK0F -DeT3QnlnDVYpbJsXHSM3YxYzX/4kl+PkpWJNEj5FyScqBePJkPiMsIBzGJwF43iq8pU7FKZe5lkU -TkMpMUlUJr9BxMoVtrhgyxsq0jzwDM8Y7BKwjmi1KeuNYNlB1aXPB+tmLI8zw/ZUMbiQpDrNlD5e -DuWcN4jAzLh5np2Z6DuQLPyYzpKMpd5MeQaJuGVgySQQDlWZGxiyYPVTIUEQfIpErH+GVMB0xBLB -qqBawcxgjiueIJJkPCPo4jR9KhIfO3bgoKZWCklSMM0SkjsVgRnuDT/FuB0dYw7CvqzL3zKmo0Bf -j13BOpq06hYT8zWEqIoropKJnPhHFmHfZel0CkOG0stXk+Rsf8bqn4gkEdUiPB6MGOV1/Rv9rJBJ -OWclu6y4lIldEZmQxhFeMsyeeRlkEpYU1aUZEQPwWEIRUxstmYhWpnRhpVWeV0hCSSBhXjz6SZJU -rS/UOEzUYC083pyoev8wZWwC7jQtVLrSNQk1jAQriBjVSkVzMohgxeKr7Lsh7i/OBn9M6HGHeVVU -dlUkFSqOLgYn1zOtUz7SjusaArvEqWdkTdk/XzWDg+BPWLO2rGoqeJ7MFXJM4PEdJzifA4aIMnrj -yF8ZAxoJmzOJT1euMDS6iFnMMFpTk0TVRhlE4WNE1nGUWjG1oiSxTGqcp6iGCVinLC2SapNztrYR -93bprHEg6mG/lGXJPjjVp1IWe9JMTajutRq8noEhA4Oa5QxQW8HJUWf+zCsvilzSyfHepow70Ksi -bruiNIjSOGrTR4ALDF0nq/uIRMxT5MMf85YZJBEdJgkdlY6ubWy5JmIvNawdLyMNMpoxNhH0ToYA -qcgV8jE60KCVsb6ik++GMSC3IHSwUpIwSpPw9ZRjCSnIASzloGOGEYs4N4jIkYwsgTvpLyxKi4gk -EoUVjSuqM7EjBpKYuES3ikXCHEvpfcA0+YojNZFrk7Mcow7M/NoxiWLKqpLxTrZTa1lTZjezAnvB -6jdHCayXHpBUxxXsYUBTnVZ4FOG3jAONKS4cl4TbZXIPX1TM3eHqs5jZ5p6UT1YBSR4zYc1mHj5i -GcWzx5k5+RSkN+ORMaubKwooI7GUVxS89jGzJJiwEvNqO4OEs2GJWJEyMAgyi2hHiCAfYZYwF0E8 -sfpj1M6xE1BX8yptXs1YUwyuu5pNQBNu4M4QouAgIG0lcM74ZydFKzhO1rozCkZBWticw5gy3m2W -vuA33mYdtnGj1pRBUS5iaySSeKrxTk4jsZjdIAkuzcGURRRcvx2TKLzGxpRDYWAsXUsevYda8BhH -oYScPlAlKi2SAZFrcg91fSZTSF+d3Nncw0SzRKpbGc+rWCNjZJ+B4yytXyi8yMyF5A== - - - loCCSVOseohYfO01hck8AY3JO+GX9GmCApYyqy5oW/ohJPSy4rChoEmdnkXEcDo7GTGJMSps1ino -9/AiYqlxWayjnllj4QHJepM3PbC6U/bFg96fQn1KEzNv9YcQxYykMI3Krs2GtGlLcg/NfbZ3VZ4F -m2LQlWnRwGAo0pTeJ+8quQkiaN30GtFX6IYQRW12doQ5D/Fa1onIYPqIjmjPnAUYfW22uWCILe9U -Sw7oXVgetBR2mcvoW7AC8OQB6fmYUAzQa2KN42jA8CqU9C7mlYoExVGaSdA4sUhCi5qf0kRBuNyY -TeiBh97YpvMJFhFdOJYnvzoJbEvM3By2PTOIqpPI2NaWLdt8p5Rm8GMggQYPzR+KROW3CN39Nkng -7reIVLa3QRSa5+QLBrMSdqVx3XL9/jgQ94c6i6NpnnXSaIJ4EmzpNrvkQcBBC4jscSJ2M4HhhFUm -eS3IaYLxZBgUxWmVkMjYBogchjurCTM9BicPeVrIoZf02WTsbpzV9lOQz8RD5xWXHNbahZjzjrCq -lT0rUiGRmlGYD9DEapIBxyo/hSsCi4eZSC7u1K0ONCrYESLHDqxszZgUtVFYwOZmeR3NJ6Eo2BOS -dkfHG5wygpvRZZvGQsI8U6ydjWZq33QiXXbo9yrT+mYxJAypwytc6xsl498pDzXmHeaJl3wCU1dF -oQNHeZrw0WPWIfk0NyjIXLhX7L4R0fvrjKSO1Ods7Z3RCspqp3O4JIOE+WGe6fO46tKzzCBSTlqb -ZlCUgkkgw3KWfCRmQw2SYOvB5XRg22m4DWR/pxWGdf2C7IQfJlGYRWnTDORcWFIlyNywpJNKE+HJ -Y3sc0yOpExpEO3KPqUYltHTSyjEYfizhyxuLG9hXgfEwv8MiCZIYOB9FBB0pZ9Q6Zgs7ikItVWjF -M8YjaRa+tKRTSMJPMfuJ4ZAU+llijqMPIkwZbnDoRnAU+mW7hPHjJOFWYtK6mpZECRVNPtCVXyFM -tSMJU/pS6aeQ16lAeODxhtPLSBXXIFHpYxZR4Po1ZhOWtxmr0slWKUwvcB0MuoKGX2FINbA0c/7p -g/RMITFETcYWYwxiJ6y/SDUFPsQiIUw+ZyVRHlmj8CFmTkZBydmpcWFxCSwj7AZXnTOkwHQV+o/L -Opu2yDkww2SVo5UFVGzvwzZoUafZSQSqSHy0uNRCwjbKMPPZRr0iYdV5RnwEptfyUwU1qFxq2+vX -MmNzYXBoVAXkUnrqmIfMZBxXFU0OJp7iuuJcKK1y3KIky+smlZDcJV4oiMQEfMPMPyg3bOKVR3X6 -asb6PCbf0NdECjwHBX0k0L/TioTXULqXOeHrtCqhwntO97G3Oj6ljBcyhZxPeFzpEgOhPesog/Bg -SpOVGYr4BRO+9RjSsw0H6zOpU2ipqCkpYlYPsUAtie1iU+E7J7yB/ZdYQU6/NvQKXG7PSleSYAzv -pdC4DjImsMVw32J2bzUIjNumaLAcqiGUgxF3zZhJztQ3GFYlCzYza0WUDikG8Ky8qZ5SvTFByxZj -b8NQoHFCOhvOOGc9juKWsKuLwXXsmS797n0aMTR8MKWZN7QCjBugSPRFCmOFvG3qSmJRbP4se0oo -hJ0p42oXSZvV6xCeuJZUYbWAYNVNxsP0vPzeEjQgYXUZawaIzyDzUQILWg+2O2ebEJdTh9VST1la -xnlqi03LYDWOluSsbGXmLQRoyi7zDd650ONeQhWFxIvY2yotrTJSvIxlynIQJkFQI7HqP0lCLwvT -zXk4tdcBn2UH/EhYHySsGHOORQPeLABN2YmIMVZsblnlh+S0DDMmEmb0TZADYFqzdym9+XV30CCv -0qLROq1FMqDSgoC9XtjbzOfOyhcgCVQyOjbYBMbKOyAbEXoCrw7Vt8RbroodIcKN4/9ydtCwPsYQ -vCgipXQkMWZsUgRbrGmCXnM7Q2gG+i4a8w17IRrr1n0XjR3UjReNk1AfU6epZmxR9K/7wOKswecG -UyklBYtXxrvULNStiFLWbzo2GCo7Xun+ok6SSMPQWCqdrLQ1XhiWH9N9XEaFN0gOpjJGiyFRGQn3 -sbdrlEnk2cc+wpZlVmIbKVI2MspzdqqvozQ5RSQdUVksFCw+Zl1HXrjUWDg2sJSaICiubPtRe3r4 -k6N8igVtKoskT4i4GNIG3bqbpCE0D8RzXhYdJ2YuzWWYzAVxSJKcZq5jQ6E0NS4MSdj/KGfnEJ9Y -cmu9iQTs90/+6fz/KvCvc4JlMRcby4Mcp0JVIWtoIuYEeRYoskw28wZYFmP8OfYwxysGqZoasFKK -xALLUkQa7UjNxiAJV2WhJmFTsbvYKHbsIsMas4nwUrC4hr5v5y0IMEVigWXpcfQeh7NpcFbnB8ti -gUJJZoU+z4puE0OHGX4FxQ/uM6RnYYBleT6TBKUr6fOKLbAsRWKBZSki47jC2Rgk4arsY0+kIQmk -QpyyCNuYjTouvSrj2PXuqHH0HoezaXBW54fLgkbDrszsHAwlrrChkzzjn+xxBEM4NtGyeANZCiFQ -Amz2qHGlFImFlqWINMpVOBmDIlyTBZbFGkg8nNKPLk8LCyzLuOtqUdZdV5vT5NDD2Yw/qXOCZbGK -xKUwbsD9+G+GnTiTBksWbtOxFhtoWcaRh8BS5pGHAFX6yBX8jZqNQRKuyoLRwVPfps9COhrQiDNm -E8dEbuFrwtC5BZelSCy4LD2OcebhbMaf1bnhsigyWM4qVjmzZi28LOY7s5CYFfsYrjDwssyLPggt -ZZ56CFHV6NSD2VinHqzKPvVSSuYK1oayY4Axm5jtAVJaqzE70lurCkkswCw9jt5jNZvxZ3VexCyK -DCbowlBnaUJuQuiwjoXtyNlehKV9BmKWZ5TNR7E4cFJvIWYpEgsxSxEZhxXOxjr0YFX2oTNcl0uN -A7QICzFLH5ZelXXoanfUOHqP1WzGn9UEiFms3oPpDcPbQ33xNmIWyynTlGAXVKzL3EDM8mxnhfsX -M1iYlhZiliKxELMUkUa6UrMxSMJVWYhZFKq4E1lKhTxKLMQs87IHq7LOXe1Ok3MPZzP+rM6PmMXK -Tmwv29vlbAQz5LoTF4eJHQXRIgoDMcs49kF0KevQFUaVHkUB0ei5aJJwTRagjchUtgjFEpiPaCBm -UcFikhZT4VjzrNcUEliIWXoU48jDuYw/pxGIWSzoLSWRwZUFU50slCKagbAG8DsnHlkDpcg40wDQ -xzzUEBeo0aGGkzEONViUeajMJmJpBCsU2CjcmA0sZCaAxqzGdZmBUqQoLJQiPYzeYTWZ8Sf1fwwx -q55JIQCzsFIuCDDr/7Pi/8WsOBowyycERslKVl7WUGgKMEs6YTCPgF2C8A4ZgFn8LtOsisjTZ+UN -wCyqOZCGKVQdEKUmYJZ8KfHse1Gww7QBmMUJS59a+p/xdBuAWdL8gy3UsbmFr14OBZjl2Ts8oWqQ -MKgYG4hZnjlTNBdK5kzGBmCWZxoKc8eol1cFOhowS74k0Vj2UqQ7NATM4oRxaz32JWfk1EDMCs/p -P4yYpbF/uAom5aRsyOXK2ATCIhEzh6ltZzXM0CBWESnY5pudtljooCGPQgoDBSsksUCwQhqNXUX9 -i9V8nppcllkYWHKdsiSWjq01oIdBxCpZl9FZCSb1BgaWF+y1kpXsDAA7AwOLGhETTZ2kwKU2Bpao -TThb7C4YOy1NDCxxDUuhb8kmWyF6lU8FrIoFirBFU4ugaEOnZioTb4vgMYQkktLP+lAIONYQagQs -L1H8lAmkVHacgYClSCwELEVkIWDpj2nWZLsK5gA6BsAsjCzWqFP4sAJNskUtCCx1DYZjYEmrHXao -xIQSMo+FgaWINHYVnQKYG3tJstogMUkSupuJKE/YYWkybhCBeQpwRsls2MzCwKKUYSNa1rpk9FDo -RQUUFj5RSGPBE6kvKcwgUpQsNIy9zNckgYWHHcmko6sNTyQ9kdjJgfUWqdQZ2ETsKAyaiJWFxnzD -czKWHZJYCFiKyEbAogeMbiDp3EAADwsBSxFZCFiKSENX0a+OXaQPqmCszSJJpWUdKxULajUtCwLL -E8uSzRv4XEN3MCCwPKuy2CkphnKQOAsCS5GYLBYSmTymPqYPPqVKFeHiVBnCQ0gck4ZYhOt9bHNZ -Jp0CCZCdyjIsFCwSFQnbcRUFS+ctNgtPqwFrNELB6knIjO1fbRQsRaSBqXpilFUyRWGS1HIUdzur -8Pg0DeFhS2LXsXOfJMfYRFUD+MyzNZgxYci9IiPALPuZRbkBgqVILBAsRWSBYBkfC7F69IwtioGF -W7hAlPjsU8WLVLBLjAWCZREpECx+jm3bwECs07RQsLgsQTvi682cGY2CpUgsFCw9jkLBUtujULDY -Zoqdg3PpXewrpJUQBYtENFwLsSMiCwVLOloxAzqWbLrcQMHi/sVeuinkbAzasmCwqLgx9yRmdlvq -bBgsaUGZQzFnB5Scd0LBYFFxY/TRETWXLa41DBZHKWLPtuPSXa5lwGCRBhwZMZ+fCdUGDBYfmJS9 -Q1mqQEtHw2ApEgsGS4+j2TSVDokRjaaUfTUtkhQTdtJpLI8rmBVNFAgMCwXLkDvqfmrppe55SGKh -YCmisShYjFJKLRkbMOOemShYfGWJMFnkTILPEwPiio4Nz9QsYjgnhUmB884ISR35uBauBhEEFdhc -QDZoyRqTYYdRyR4DI8ZsR68Xxe4nOD+mrfi4qK5iiGjUu2eerfedgYLVkwuS/28gvIQUBgqWGkQB -PemZKMAoa0UKeErvjIKv0vtrkOhzMoiC49aTUTyjFxXynoWCxfAbcbQi8DXeHg2CxV5rEV/WiD6G -KLFOKSSxQLD0OJplwrmMv07DMbC4QYzFSWdf+p0sDCyfMak7pVOCunhpAFwpm9ciMY5UEzEntGBo -vowEXlrPhnDujmmjJXtA5wYOkXgvGbmiFy+vwalCPKPee5FjPmluYGD1ZDhEJytvrLsXkFg4WMY4 -IdaTMZsQM8palcKe0rujEKz0HhskhpjUROGZ69koztGrCjnQQsKizg4LkNFn/CGykLDY/o7EzFuG -ZmYhYSkSCwnLGEdxjprN+HvVBAlLeWEsJCxFpJGwQleNRsJSrhoLCouSnDmhDL8SnciEwjKJQigs -9TkLC0vNWmFh6aUrLCzDJaawsAyPmMbC0t9SWFhqwgoLy9pmBYbVs2jYBD2zwbB6mj+7rYh8DcCw -etZVGmPbDSyskMKCwgppLCQs9SUFhCWzhW3N3AI2NDCAsNSqLSAsSVgUM89hAoUJhGXRhEBY1haH -QFh6hxUQllq4wsEytljBYBlbrFCw1JcUCJaergLBsrZYgWAZ26dAsAwaBYJlbbECwdJ8EYJgqYUr -DCxjixUElrHFCgFLfykEwNJbrACwrC1WAFiW9FMIWEqYKAQsLZEUApYiMRCwFM1YBCwVrLAQsDwB -YPB3eTTBhgYCFkk8NSC8VnRZGoAhXgRSxF4OTDKUJqEKAYvqLTtxcDOzTIrHNAIWeQ== - - - lqV77Kgit1cjYBkkIfCS+pSFgEV1gMoCGwlk7IinEbC4LvaNh1BPPVPoNAKWIrEQsIxxQuQqmQ0R -xgo2nY0sBCzxV5O52FUX5kTLQsCi6obdyplAygo9DYAVml8a/4oU9JzxIhR5hbQV4l8pz7gFgEUi -eozY44TdPTVuFR0ldOywMZW0BLVIpGqJn2bmko1/JcEiAkFJ11y2Zlb4V6EtrdGFtEGu8K/UIAr/ -qud6jGOBmdf4V2qyFv6V5MQ6qdpIYTuUBv6VVEXQYwgZhTMrDPwrBmn533s2OJD4hYa/on/AMVSR -0pVfQdOF8FekoQeBtg4+ZcFfaRIFfyWeiJKtBeOEgb2WBX9Fk4rdavmIp8yR0/BXYdxKo1+FFBb4 -lRpFgVap+LVBkgpoFcvwyEaywwYRs+VzRww3aR6vwa+UAWiwJ0igRrA1IZFNKlETgl8ZESINfqVi -4Rq0Svpzl2x3kUkZokWijSWLKCMIkaSL0+9rgF8p54kGvzKcMBr8So+jwK/ohJHqtpyc7hPzLQue -zbHgV+K3wVYTPoHYZCb4VaiMadAqSl32EKA7XXoXWSTKvreIgtieBr8Sl4SAWpalJMdp8CvDaajB -r5TzUYFfKXmpwK8MoatgOfQoIfiVoH0IUltJk7IwwK+sFSnwK+UG1bBV6oZZJAJIxN7iWVqhkZg0 -A2+jAr8iBat5Y3ZbYKRZgwYpEgv8ShFZ4Ff6Ywo6hiRZ4YnGk+YCrmmSBPFyi6ikbRXxFmKtFvoV -tRj252d0B4xuoV+RpIBskjJoWNstC/2KWpX0JYTezy6lBgCWchxpACzDAaUBsIxxQgAsiZbn7HCZ -MkPFAsCiLHFsMUTToIYPUwBYot4mbDKLy8gEQg2ApXRFDYDFUdjlz0tdftVuXwFgcVUlJktlF69Z -ZgJgUb1lc4mcRVsZhZtJ4p2k7+K6RRYAlpemqsQ6Y1pahY2hALAEUIPdvVm+BpFjAGDpZ0ABYFnP -ieZBNY4CwOJzkkj/SMZg2Yh7/OMwHACLWwJG5UWhsVWYAFhSNsLuzNR0GDbQAFhy1JJon/LZcwYA -liKxALD0OAoAS8/GkD7BqiwALDKMoz+SrdvpvLCkBpQCsGJKZ2nmbAEFG4rIoVFRFQvZ0id8Ho3Z -sGUNMx/ZM8In5qoCEgsASxFZAFj6Ywq4Sk/ZINFLN4jCLTRmEx7EeDZtBIBlOMk1npQi0qhUocPF -olDeW4NI+71sogFPkjHjwB1lLFw5vjQ+jnZ8aZgd9SUF1aOna5IEji+LqJNhwzbnLjfRr0yiEP1K -28IK/Uqpdgr9ylAQFfqVHiVEv9Kbo9Cvekk4xI3JbPSrXhIOFiHoFQr9SmvFCv2ql4Tj+LDZ6Fe9 -JBxmf6Q2/FUvCUf64SYG/FUvCacQ2DoD/kqFMS34q14WDhtf0kBR8FcqYqoBsIzIq4bAMsZRXNrN -whEKCyerl4UTE4jGZnbt5bWIAqGjb6eSXPqSay9vAzE5FgRL+V4tECxxQFL5YRG9r7l2AARLq68K -BEvuNztD0qpKUxsFi2p55ktHDCnp4WKhYJGIYDA0kQlJZ6BgmSSDKFgkSSmMI25WKWq5QsGqzkES -LBlWKg0ULFmXiyTeIT04NQqWIrFQsIxxQvQqUe8Z83ARNavcImEQMcb2Cg6QSGiDJmMTRVaROl4R -AwSLOgNEsRcBwtaLGgTLyPDVMFhi7abCAmwEWZgwWCSKiHBODxe7Bmn8KgoPWrswfplsZ+FgGdn8 -BhGrVxz9HYThiy0cLFYnUVGDlo7/j55ThYOlSCwcLEWkcbCoGEIzIhRixmbLBg6WZ39pZlqmzCqV -90vjYJGILwiz/umyMHCwSMLOkAUeHzbjVChYamcsFCxWo9FuZGIqC7NMFCxpvBJnkL901cKm0ihY -QpLR7KE1y2b5CgWLJI7t2mJCqdogWKxkcKx1cDR4Bc0tBMGqKsDo4WZLLGqkCgRLkVggWHocBV4l -hqLgmmP0uLRJJOswTdlMibA2FggWFQCYCTnDLpkvDAwsMfwdywVSiuhEY2DxBYyZpoLdo6OrZWFg -qaoKCwNLnNgwT0VKYVIGwBW1fvaXZg4zWCMzSVR1lEEUvkUaA0tb1QoDy7LOFQaWHkdhYImzFwfD -sDk1HwMDywhcjsHA4gMN5R8bTGy3woTACmk0rpAkAzriZlfJASaJAI4wGYf+K5EbmshTe6GHgG1d -ShvEiEQiEoinFuWlgYBFErr1MmaAMwys0JsUhYWApYgsBCz9LQVKRRLos9IgUfoL2iRkKew6vVU2 -AhaVfqbJxIWA8dkIWNJyiA3WuYFpYSFg8daz/IIoAfS3WSsfpDDwr0ISC/5Kfcg4TJiB7NAAaZDT -grJJsDj292W2m7M5J2EoAfI68UwDj23O4dtF/ZDtdSGlDfwrkhCxB7Nl3yBv4F8pEgv/ShFZ+FfG -x0JYIWPKFsnA0i0MI7WJFoaRcRgh7JI+0QC8yeAcheRjsI4CBFIfUqhCmtFNkoELY0EYqatnQRjp -K2zMOBQExsK11NEbqIWOcQxKwOnDVGLSIhkQtybnCOR3RnuSGbOJzTnETXFEK2Vn09gAvxKjmBNh -7b70RVfoV4rE5J2QyGQe9TF9oOz9T+ucjX6hfZokKV0YBNWN8tgN4Z6MMXVq7Lg0BJowuYeehYix -X7y8nviyxpSDR9ZY+SCFBX8V0oxFvzL8mBr9ShFp3KrQpWBRKD+mRSTtcaEaOXYl9ib8lUkUwl/x -c2KORAQYhH6s4K+UyqXhrwzVTQNO6XEUbJX0TaOviW5KaaZukASmtAV/pQLmxmxC/7uGvzKc/Rpg -xnD2a6Aa/TEFoaKc/RaJcvZbRCrD2yAKrXINf6WiQBpgxogmaaAaY5wQ/oqzidmcpBRBbcFfiS+T -rjeM7coKkyqEv1L5TBr+SkgSxuVKXpPMgL9SjlUL/kr1KLDgr0jERnb4GgzfLDbwryRWQ49VJh0t -nIF/JUYljptpEyw9bFn4V/LE0xhjSppPLfyr0FWu8a+0w13jX6lRFCaVXpImYbAp8gKJIdFNC//K -cNBaRKE0DQGwDJEcAGAZ/tkG4n84AJZKULAAsIw0SptoIPHCEixB+oYloFSuiEbAMnJFNAKW/phC -rlI5HgZJmMVgIWBR68BGZE66nScWApbY8DFRLPI4NgGwQgoL/0qNYpxnkC/c4MgbwV8ZZbQacEol -22nYKkkgyzGzkinOuU2iEsgsosDla8wmrGkzVqXTrTRoihJqGnpFSRqF4GLIKwUEo0ZRaDKSasG2 -k/THscRNo9LQawcFlJAzMD1iG/6qyulhA2PqgsRuVRg5ktHDLE+CGTFZTWPtiI3FHHe642gPWPBX -KvfUwr/yUvPqGHvBkyAbGEAIkYLZmTCHU2morJGI+CXIPC+gyEVq41+pbFmNi6TietZpqvigxmnS -4yiwJxU91aBRRmWmBp/ibaBfkZnDMXM/FIIVNbacBXo4zigzcLLMW6do2FqZqZPEaUosGCxKF8YU -nAghIszoFRFKBEOVUquW2DBYqmmLsb9hNNA4J50UZ5y3HkdxTdjXxeA+dkMHR/GJzGt0KsXEoTlg -3ARFom9UGC20cLD4VCQEpYmYn50mJg4WiVIKa0hMbH1q4GBJ7Q0rCvGUOtaPGRInE4irVMr4yqLC -5VKSiyh4eEQjWlSViFTiT5lc+jwN000LYzWOFumEjYUyV1kVsYWDZRa6j8TBsqxuhYOlVTyFgyXO -h4gCCto5m2tpHCzL7FZAWLytjolwrNpjUzcDwUrlV5o0WrnVNIFuq/CX9MIVjpNRYKsRoYwKW40s -pT+m8KnUjA0KvcmaKOw5Z2Fhha0XjQkHHRGNdavWi8YGqt6LxjmEX1JHGU7WIhhYsgGDFT43FgyW -kd6mYbBUWaeGwQqTzjQKlk5v0yBYOr1NYWCFJBoCi7OlIyD2gu5qYWAZ2W0KA0t8J2IYsdIuy0wM -LONaahAscnnMbSJWOWSVAYKl7ooGwbKszvHir3ZT9rqY7qxNzdy5l368e/RlZ/+/D4+Xl6dmZp7s -fz18cbz/z/fD46mvJ/v/47C1f3TEXqiHv/CX1tfjw5PTn8eHrZO/f/4Xf4P/pEM+M3P38ebU/wbQ -B0TQ - - - diff --git a/modules/domtokenlist-shim/dist/domtokenlist.js b/modules/domtokenlist-shim/dist/domtokenlist.js deleted file mode 100644 index d8f6e9cd..00000000 --- a/modules/domtokenlist-shim/dist/domtokenlist.js +++ /dev/null @@ -1,211 +0,0 @@ -/*! DOMTokenlist shim | Copyright 2015 Jonathan Wilsson and Bogdan Chadkin. */ -;(function (window) { - 'use strict'; - - if (!window.DOMTokenList) { - return; - } - - var el = document.createElement('a').classList; - var dtp = DOMTokenList.prototype; - var add = dtp.add; - var remove = dtp.remove; - var toggle = dtp.toggle; - - el.add('c1', 'c2'); - - // Older versions of the HTMLElement.classList spec didn't allow multiple - // arguments, easy to test for - var iterateArg = function (fn) { - return function () { - var tokens = arguments; - var i; - - for (i = 0; i < tokens.length; i += 1) { - fn.call(this, tokens[i]); - } - }; - }; - - if (!el.contains('c2')) { - dtp.add = iterateArg(add); - dtp.remove = iterateArg(remove); - } - - // Older versions of the spec didn't have a forcedState argument for - // `toggle` either, test by checking the return value after forcing - if (!el.toggle('c1', true)) { - dtp.toggle = function (cls, force) { - if (force === undefined) { - return toggle.call(this, cls); - } - - (force ? add : remove).call(this, cls); - return !!force; - }; - } -}(window)); - -;(function (window) { - 'use strict'; - - var arr = []; - - var inArray = function (array, value) { - var i; - - if (arr.indexOf) { - return arr.indexOf.call(array, value); - } - - for (i = 0; i < array.length; i++) { - if (array[i] === value) { - return i; - } - } - - return -1; - }; - - var validateToken = function (token) { - var whitespace = /[\u0009\u000A\u000C\u000D\u0020]/; - - if (token === '' || whitespace.test(token)) { - throw new Error('Token must not be empty or contain whitespace.'); - } - }; - - var DOMTokenList = function (element, prop) { - var inst = this; - var i; - var values = []; - - if (element && prop) { - inst.element = element; - inst.prop = prop; - - if (element[prop]) { - values = element[prop].replace(/^\s+|\s+$/g, '').split(/\s+/); - - for (i = 0; i < values.length; i++) { - inst[i] = values[i]; - } - } - } - - inst.length = values.length; - }; - - DOMTokenList.prototype = { - add: function () { - var inst = this; - var i; - var tokens = arguments; - - for (i = 0; i < tokens.length; i++) { - validateToken(tokens[i]); - - if (!inst.contains(tokens[i])) { - arr.push.call(inst, tokens[i]); - } - } - - if (inst.element) { - inst.element[inst.prop] = inst; - } - }, - - contains: function (token) { - validateToken(token); - - return inArray(this, token) !== -1; - }, - - item: function (index) { - return this[index] || null; - }, - - remove: function () { - var tokens = arguments; - var inst = this; - var key; - var i; - - for (i = 0; i < tokens.length; i++) { - validateToken(tokens[i]); - - key = inArray(inst, tokens[i]); - - if (key !== -1) { - arr.splice.call(inst, key, 1); - } - } - - if (inst.element) { - inst.element[inst.prop] = inst; - } - }, - - toggle: function (token, force) { - var inst = this; - - if (inst.contains(token)) { - if (force) { - return true; - } - - inst.remove(token); - - return false; - } else { - if (force === false) { - return false; - } - - inst.add(token); - - return true; - } - }, - - toString: function () { - return arr.join.call(this, ' '); - } - }; - - window.DOMTokenList = DOMTokenList; -}(window)); - -;(function () { - 'use strict'; - - if ('classList' in document.createElement('a') && !window.QUnit) { - return; - } - - Object.defineProperty(Element.prototype, 'classList', { - get: function () { - return new DOMTokenList(this, 'className'); - } - }); -}()); - -;(function () { - 'use strict'; - - if ('relList' in document.createElement('a') && !window.QUnit) { - return; - } - - var i; - var elements = [HTMLAnchorElement, HTMLAreaElement, HTMLLinkElement]; - var getter = function () { - return new DOMTokenList(this, 'rel'); - }; - - for (i = 0; i < elements.length; i++) { - Object.defineProperty(elements[i].prototype, 'relList', { - get: getter - }); - } -}()); diff --git a/modules/domtokenlist-shim/dist/domtokenlist.min.js b/modules/domtokenlist-shim/dist/domtokenlist.min.js deleted file mode 100644 index a684da66..00000000 --- a/modules/domtokenlist-shim/dist/domtokenlist.min.js +++ /dev/null @@ -1,2 +0,0 @@ -/*! DOMTokenlist shim | Copyright 2015 Jonathan Wilsson and Bogdan Chadkin. */ -!function(t){"use strict";if(t.DOMTokenList){var e=document.createElement("a").classList,n=DOMTokenList.prototype,r=n.add,i=n.remove,o=n.toggle;e.add("c1","c2");var c=function(t){return function(){var e,n=arguments;for(e=0;e=1.10", - "jquery-mousewheel": "~3.1.3" - }, - "homepage": "https://github.com/fancyapps/fancyBox", - "version": "2.1.6", - "_release": "2.1.6", - "_resolution": { - "type": "version", - "tag": "v2.1.6", - "commit": "c00852a5394ef18517598bfa3b9e885cdf5c7450" - }, - "_source": "https://github.com/fancyapps/fancyBox.git", - "_target": "^2.1.6", - "_originalSource": "fancybox" -} \ No newline at end of file diff --git a/modules/fancybox/CHANGELOG.md b/modules/fancybox/CHANGELOG.md deleted file mode 100644 index b0d847e2..00000000 --- a/modules/fancybox/CHANGELOG.md +++ /dev/null @@ -1,125 +0,0 @@ -fancyBox - Changelog -========= - -### Version 2.1.5 - June 14, 2013 -* Fixed #493 - Broken slideshow -* Fixed #556 - Parent option -* Retina graphics (#564) and retina display support (#420) -* Improved "lock" feature - -### Version 2.1.4 - January 10, 2013 -* Update to be compatible with jQuery v1.9 -* Small changes that should fix usability issues for certain users - -### Version 2.1.3 - October 23, 2012 - -* Fixed #426 - Broken IE7 -* Fixed #423 - Background flickering on iOS -* Fixed #418 - Automatically Grow/Shrink and Center -* Updated the script to work with jQuery 1.6 -* Media helper supports YouTube video series - -### Version 2.1.2 - October 15, 2012 - -* Fixed #414 - Don't allow nextClick if there is only one item -* Fixed #397 - Button helper 'Menu' not visible in IE7 -* Overlay can be opened/closed manually: -* $.fancybox.helpers.overlay.open(); -* $.fancybox.helpers.overlay.open({closeClick : false}); -* $.fancybox.helpers.overlay.close(); -* Optimized for Internet Explorer 10 (Windows 8) - -### Version 2.1.1 - October 01, 2012 - -* Fixed #357 - Converting values like 'auto' in getScalar() -* Fixed #358 - Updated overlay background image -* New "fancybox-href" and "fancybox-title" HTML5 data-attributes (#317) -* Improved helpers: -* - now they can have a property 'defaults' that contains default settings -* - updated vimeo and youtube parsers for media helper -* Content locking now can be turned off - -### Version 2.1.0 - August 20, 2012 - -* Fixed #103 - DOM element re-injection after closing -* Fixed #188 - navigation keys inside editable content -* New animation directions (see https://github.com/fancyapps/fancyBox/issues/233#issuecomment-5512453) -* New option "iframe" - it is now possible to separate scrolling for iframe and wrapping element; choose to preload -* New option "swf" - brings back functionality from fancyBox v1 -* Improved media helper - better support for vimeo and youtube; links are now configurable -* Rewritten overlay helper: -* - new option "showEarly" - toggles if should be open before of after content is loaded -* - Facebook-style (https://github.com/fancyapps/fancyBox/issues/24) and therefore uses image for background -* Option "padding" accepts array (e.g., padding: [15, 50, 10, 5]) -* One of dimensions (width or height) can now be set to "auto" (option "autoSize" needs to be "false") -* Updated callbacks: -* - "beforeClose" is now called only once -* - "afterLoad" receives current and previous object as arguments -* Method "$.fancybox.update();" recalculates content width/height -* Updated to work with jQuery v1.8 - -### Version 2.0.6 - April 16, 2012 - -* Fixed #188 - keystrokes in contenteditable -* Fixed #171 - non-images should not be preloaded -* Fixed #158 - 'closeClick: true' breaks gallery navigation -* New "media" helper - detects and displays various media types -* New option "groupAttr" - name of group selector attribute, default is "data-fancybox-group" -* New feature - selector expressions in URLs, see #170 -* Improved 'overlay' helper to use "position: fixed" -* Improved autoSize, fixed wrong height in some cases -* Improved centering and iframe scrolling for iOS -* Updated markup, new element '.fancybox-skin' is now used for styling - -### Version 2.0.5 - February 21, 2012 - -* Fixed #155 - easing for prev/next animations -* Fixed #153 - overriding "keys" options -* Fixed #147 - IE7 problem with #hash links -* Fixed #130 - changing dynamically data-fancybox-group -* Fixed #126 - obey minWidth/minHeight -* Fixed #118 - placement of loading icon and navigation arrows -* Fixed #101 - "index" option not working -* Fixed #94 - "orig" option not working -* Fixed #80 - does not work on IE6 -* Fixed #72 - can't set overlay opacity to 0 -* Fixed #63 - properly set gallery index -* New option "autoCenter" - toggles centering on window resize or scroll, disabled for mobile devices by default -* New option "autoResize" - toggles responsivity, disabled for mobile devices by default -* New option "preload" - number of images to preload -* New feature to target mobile/desktop browsers using CSS, see #108 -* Changed ajax option defaults to "{ dataType: 'html', headers: { 'X-fancyBox': true } }", see #150 and #128 -* Updated loading icon for IE7, IE8 -* Calculates height of the iframe if 'autoSize' is set to 'true' and the iframe is on the same domain as the main page - -### Version 2.0.4 - December 12, 2011 - -* Fixed #47 - fix overriding properties -* New option "position" to thumbnail and button helpers - - -### Version 2.0.3 - November 29, 2011 - -* Fixed #29 - broken elastic transitions - - -### Version 2.0.2 - November 28, 2011 - -* Fixed slideshow -* Fixed scrollbars issue when displayed a very tall image -* New option "nextClick" - navigate to next gallery item when user clicks the content -* New option "modal" - to disable navigation and closing -* Add 'metadata' plugin support -* Add ability to create groups using 'data-fancybox-group' attribute -* Updated manual usage to match earlier releases - - -### Version 2.0.1 - November 23, 2011 - -* Fixed keyboard events inside form elements -* Fixed manual usage - - -### Version 2.0.0 - November 21, 2011 - -First release - completely rewritten, many new features and updated graphics. \ No newline at end of file diff --git a/modules/fancybox/README.md b/modules/fancybox/README.md deleted file mode 100644 index 08a91074..00000000 --- a/modules/fancybox/README.md +++ /dev/null @@ -1,244 +0,0 @@ -fancyBox -======== - -fancyBox is a tool that offers a nice and elegant way to add zooming functionality for images, html content and multi-media on your webpages. - -More information and examples: http://www.fancyapps.com/fancybox/ - -License: http://www.fancyapps.com/fancybox/#license - -Copyright (c) 2012 Janis Skarnelis - janis@fancyapps.com - - -How to use ----------- - -To get started, download the plugin, unzip it and copy files to your website/application directory. -Load files in the section of your HTML document. Make sure you also add the jQuery library. - -```html - - - - - -``` - -Create your links with a `title` (or `data-fancybox-title`) if you want a title to be shown, and add a class: - -```html - -``` - -If you have a set of related items that you would like to group, -additionally include a group name in the `rel` (or `data-fancybox-group`) attribute: - -```html - - -``` - -Initialise the script like this: - -```html - -``` - -May also be passed an optional options object which will extend the default values. Example: - -```html - -``` - -Tip: Automatically group and apply fancyBox to all images: - -```js -$("a[href$='.jpg'],a[href$='.jpeg'],a[href$='.png'],a[href$='.gif']").attr('rel', 'gallery').fancybox(); -``` - -Script uses the `href` attribute of the matched elements to obtain the location of the content and to figure out content type you want to display. -You can specify type directly by adding classname (fancybox.image, fancybox.iframe, etc) or `data-fancybox-type` attribute: - -```html -//Ajax: -Example -//or -Example - -//Iframe: -Example - -//Inline (will display an element with `id="example"`) -Example - -//SWF: -Example - -//Image: -Example -``` - -Note, ajax requests are subject to the [same origin policy](http://en.wikipedia.org/wiki/Same_origin_policy). -If fancyBox will not be able to get content type, it will try to guess based on 'href' and will quit silently if would not succeed. -(this is different from previsous versions where 'ajax' was used as default type or an error message was displayed). - -Advanced --------- - -### Helpers - -Helpers provide a simple mechanism to extend the capabilities of fancyBox. There are two built-in helpers - 'overlay' and 'title'. -You can disable them, set custom options or enable other helpers. Examples: - -```js -//Disable title helper -$(".fancybox").fancybox({ - helpers: { - title: null - } -}); - -//Disable overlay helper -$(".fancybox").fancybox({ - helpers: { - overlay : null - } -}); - -//Change title position and overlay color -$(".fancybox").fancybox({ - helpers: { - title : { - type : 'inside' - }, - overlay : { - css : { - 'background' : 'rgba(255,255,255,0.5)' - } - } - } -}); - -//Enable thumbnail helper and set custom options -$(".fancybox").fancybox({ - helpers: { - thumbs : { - width: 50, - height: 50 - } - } -}); -``` - -### API - -Also available are event driven callback methods. The `this` keyword refers to the current or upcoming object (depends on callback method). Here is how you can change title: - -```js -$(".fancybox").fancybox({ - beforeLoad : function() { - this.title = 'Image ' + (this.index + 1) + ' of ' + this.group.length + (this.title ? ' - ' + this.title : ''); - - /* - "this.element" refers to current element, so you can, for example, use the "alt" attribute of the image to store the title: - this.title = $(this.element).find('img').attr('alt'); - */ - } -}); -``` - -It`s possible to open fancyBox programmatically in various ways: - -```js -//HTML content: -$.fancybox( '

Lorem Lipsum

Lorem lipsum

', { - title : 'Custom Title' -}); - -//DOM element: -$.fancybox( $("#inline"), { - title : 'Custom Title' -}); - -//Custom object: -$.fancybox({ - href: 'example.jpg', - title : 'Custom Title' -}); - -//Array of objects: -$.fancybox([ - { - href: 'example1.jpg', - title : 'Custom Title 1' - }, - { - href: 'example2.jpg', - title : 'Custom Title 2' - } -], { - padding: 0 -}); -``` - -There are several methods that allow you to interact with and manipulate fancyBox, example: - -```js -//Close fancybox: -$.fancybox.close(); -``` - -There is a simply way to access wrapping elements using JS: - -```js -$.fancybox.wrap -$.fancybox.skin -$.fancybox.outer -$.fancybox.inner -``` - -You can override CSS to customize the look. For example, make navigation arrows always visible, -change width and move them outside of area (use this snippet after including fancybox.css): - -```css -.fancybox-nav span { - visibility: visible; -} - -.fancybox-nav { - width: 80px; -} - -.fancybox-prev { - left: -80px; -} - -.fancybox-next { - right: -80px; -} -``` - -In that case, you might want to increase space around box: - -```js -$(".fancybox").fancybox({ - margin : [20, 60, 20, 60] -}); -``` - -Bug tracker ------------ - -Have a bug? Please create an issue on GitHub at https://github.com/fancyapps/fancyBox/issues diff --git a/modules/fancybox/source/blank.gif b/modules/fancybox/source/blank.gif deleted file mode 100644 index 35d42e80..00000000 Binary files a/modules/fancybox/source/blank.gif and /dev/null differ diff --git a/modules/fancybox/source/fancybox_loading.gif b/modules/fancybox/source/fancybox_loading.gif deleted file mode 100644 index a03a40c0..00000000 Binary files a/modules/fancybox/source/fancybox_loading.gif and /dev/null differ diff --git a/modules/fancybox/source/fancybox_loading@2x.gif b/modules/fancybox/source/fancybox_loading@2x.gif deleted file mode 100644 index 9205aeb0..00000000 Binary files a/modules/fancybox/source/fancybox_loading@2x.gif and /dev/null differ diff --git a/modules/fancybox/source/fancybox_overlay.png b/modules/fancybox/source/fancybox_overlay.png deleted file mode 100644 index a4391396..00000000 Binary files a/modules/fancybox/source/fancybox_overlay.png and /dev/null differ diff --git a/modules/fancybox/source/fancybox_sprite.png b/modules/fancybox/source/fancybox_sprite.png deleted file mode 100644 index fd8d5ca5..00000000 Binary files a/modules/fancybox/source/fancybox_sprite.png and /dev/null differ diff --git a/modules/fancybox/source/fancybox_sprite@2x.png b/modules/fancybox/source/fancybox_sprite@2x.png deleted file mode 100644 index d0e4779f..00000000 Binary files a/modules/fancybox/source/fancybox_sprite@2x.png and /dev/null differ diff --git a/modules/fancybox/source/helpers/fancybox_buttons.png b/modules/fancybox/source/helpers/fancybox_buttons.png deleted file mode 100644 index 07872072..00000000 Binary files a/modules/fancybox/source/helpers/fancybox_buttons.png and /dev/null differ diff --git a/modules/fancybox/source/helpers/jquery.fancybox-buttons.css b/modules/fancybox/source/helpers/jquery.fancybox-buttons.css deleted file mode 100644 index 302d6d5b..00000000 --- a/modules/fancybox/source/helpers/jquery.fancybox-buttons.css +++ /dev/null @@ -1,97 +0,0 @@ -#fancybox-buttons { - position: fixed; - left: 0; - width: 100%; - z-index: 8050; -} - -#fancybox-buttons.top { - top: 10px; -} - -#fancybox-buttons.bottom { - bottom: 10px; -} - -#fancybox-buttons ul { - display: block; - width: 166px; - height: 30px; - margin: 0 auto; - padding: 0; - list-style: none; - border: 1px solid #111; - border-radius: 3px; - -webkit-box-shadow: inset 0 0 0 1px rgba(255,255,255,.05); - -moz-box-shadow: inset 0 0 0 1px rgba(255,255,255,.05); - box-shadow: inset 0 0 0 1px rgba(255,255,255,.05); - background: rgb(50,50,50); - background: -moz-linear-gradient(top, rgb(68,68,68) 0%, rgb(52,52,52) 50%, rgb(41,41,41) 50%, rgb(51,51,51) 100%); - background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,rgb(68,68,68)), color-stop(50%,rgb(52,52,52)), color-stop(50%,rgb(41,41,41)), color-stop(100%,rgb(51,51,51))); - background: -webkit-linear-gradient(top, rgb(68,68,68) 0%,rgb(52,52,52) 50%,rgb(41,41,41) 50%,rgb(51,51,51) 100%); - background: -o-linear-gradient(top, rgb(68,68,68) 0%,rgb(52,52,52) 50%,rgb(41,41,41) 50%,rgb(51,51,51) 100%); - background: -ms-linear-gradient(top, rgb(68,68,68) 0%,rgb(52,52,52) 50%,rgb(41,41,41) 50%,rgb(51,51,51) 100%); - background: linear-gradient(to bottom, rgb(68,68,68) 0%,rgb(52,52,52) 50%,rgb(41,41,41) 50%,rgb(51,51,51) 100%); - filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#444444', endColorstr='#222222',GradientType=0 ); -} - -#fancybox-buttons ul li { - float: left; - margin: 0; - padding: 0; -} - -#fancybox-buttons a { - display: block; - width: 30px; - height: 30px; - text-indent: -9999px; - background-color: transparent; - background-image: url('fancybox_buttons.png'); - background-repeat: no-repeat; - outline: none; - opacity: 0.8; -} - -#fancybox-buttons a:hover { - opacity: 1; -} - -#fancybox-buttons a.btnPrev { - background-position: 5px 0; -} - -#fancybox-buttons a.btnNext { - background-position: -33px 0; - border-right: 1px solid #3e3e3e; -} - -#fancybox-buttons a.btnPlay { - background-position: 0 -30px; -} - -#fancybox-buttons a.btnPlayOn { - background-position: -30px -30px; -} - -#fancybox-buttons a.btnToggle { - background-position: 3px -60px; - border-left: 1px solid #111; - border-right: 1px solid #3e3e3e; - width: 35px -} - -#fancybox-buttons a.btnToggleOn { - background-position: -27px -60px; -} - -#fancybox-buttons a.btnClose { - border-left: 1px solid #111; - width: 35px; - background-position: -56px 0px; -} - -#fancybox-buttons a.btnDisabled { - opacity : 0.4; - cursor: default; -} diff --git a/modules/fancybox/source/helpers/jquery.fancybox-buttons.js b/modules/fancybox/source/helpers/jquery.fancybox-buttons.js deleted file mode 100644 index 352bb5f0..00000000 --- a/modules/fancybox/source/helpers/jquery.fancybox-buttons.js +++ /dev/null @@ -1,122 +0,0 @@ - /*! - * Buttons helper for fancyBox - * version: 1.0.5 (Mon, 15 Oct 2012) - * @requires fancyBox v2.0 or later - * - * Usage: - * $(".fancybox").fancybox({ - * helpers : { - * buttons: { - * position : 'top' - * } - * } - * }); - * - */ -;(function ($) { - //Shortcut for fancyBox object - var F = $.fancybox; - - //Add helper object - F.helpers.buttons = { - defaults : { - skipSingle : false, // disables if gallery contains single image - position : 'top', // 'top' or 'bottom' - tpl : '
' - }, - - list : null, - buttons: null, - - beforeLoad: function (opts, obj) { - //Remove self if gallery do not have at least two items - - if (opts.skipSingle && obj.group.length < 2) { - obj.helpers.buttons = false; - obj.closeBtn = true; - - return; - } - - //Increase top margin to give space for buttons - obj.margin[ opts.position === 'bottom' ? 2 : 0 ] += 30; - }, - - onPlayStart: function () { - if (this.buttons) { - this.buttons.play.attr('title', 'Pause slideshow').addClass('btnPlayOn'); - } - }, - - onPlayEnd: function () { - if (this.buttons) { - this.buttons.play.attr('title', 'Start slideshow').removeClass('btnPlayOn'); - } - }, - - afterShow: function (opts, obj) { - var buttons = this.buttons; - - if (!buttons) { - this.list = $(opts.tpl).addClass(opts.position).appendTo('body'); - - buttons = { - prev : this.list.find('.btnPrev').click( F.prev ), - next : this.list.find('.btnNext').click( F.next ), - play : this.list.find('.btnPlay').click( F.play ), - toggle : this.list.find('.btnToggle').click( F.toggle ), - close : this.list.find('.btnClose').click( F.close ) - } - } - - //Prev - if (obj.index > 0 || obj.loop) { - buttons.prev.removeClass('btnDisabled'); - } else { - buttons.prev.addClass('btnDisabled'); - } - - //Next / Play - if (obj.loop || obj.index < obj.group.length - 1) { - buttons.next.removeClass('btnDisabled'); - buttons.play.removeClass('btnDisabled'); - - } else { - buttons.next.addClass('btnDisabled'); - buttons.play.addClass('btnDisabled'); - } - - this.buttons = buttons; - - this.onUpdate(opts, obj); - }, - - onUpdate: function (opts, obj) { - var toggle; - - if (!this.buttons) { - return; - } - - toggle = this.buttons.toggle.removeClass('btnDisabled btnToggleOn'); - - //Size toggle button - if (obj.canShrink) { - toggle.addClass('btnToggleOn'); - - } else if (!obj.canExpand) { - toggle.addClass('btnDisabled'); - } - }, - - beforeClose: function () { - if (this.list) { - this.list.remove(); - } - - this.list = null; - this.buttons = null; - } - }; - -}(jQuery)); diff --git a/modules/fancybox/source/helpers/jquery.fancybox-media.js b/modules/fancybox/source/helpers/jquery.fancybox-media.js deleted file mode 100644 index 99e62127..00000000 --- a/modules/fancybox/source/helpers/jquery.fancybox-media.js +++ /dev/null @@ -1,201 +0,0 @@ -/*! - * Media helper for fancyBox - * version: 1.0.6 (Fri, 14 Jun 2013) - * @requires fancyBox v2.0 or later - * - * Usage: - * $(".fancybox").fancybox({ - * helpers : { - * media: true - * } - * }); - * - * Set custom URL parameters: - * $(".fancybox").fancybox({ - * helpers : { - * media: { - * youtube : { - * params : { - * autoplay : 0 - * } - * } - * } - * } - * }); - * - * Or: - * $(".fancybox").fancybox({, - * helpers : { - * media: true - * }, - * youtube : { - * autoplay: 0 - * } - * }); - * - * Supports: - * - * Youtube - * http://www.youtube.com/watch?v=opj24KnzrWo - * http://www.youtube.com/embed/opj24KnzrWo - * http://youtu.be/opj24KnzrWo - * http://www.youtube-nocookie.com/embed/opj24KnzrWo - * Vimeo - * http://vimeo.com/40648169 - * http://vimeo.com/channels/staffpicks/38843628 - * http://vimeo.com/groups/surrealism/videos/36516384 - * http://player.vimeo.com/video/45074303 - * Metacafe - * http://www.metacafe.com/watch/7635964/dr_seuss_the_lorax_movie_trailer/ - * http://www.metacafe.com/watch/7635964/ - * Dailymotion - * http://www.dailymotion.com/video/xoytqh_dr-seuss-the-lorax-premiere_people - * Twitvid - * http://twitvid.com/QY7MD - * Twitpic - * http://twitpic.com/7p93st - * Instagram - * http://instagr.am/p/IejkuUGxQn/ - * http://instagram.com/p/IejkuUGxQn/ - * Google maps - * http://maps.google.com/maps?q=Eiffel+Tower,+Avenue+Gustave+Eiffel,+Paris,+France&t=h&z=17 - * http://maps.google.com/?ll=48.857995,2.294297&spn=0.007666,0.021136&t=m&z=16 - * http://maps.google.com/?ll=48.859463,2.292626&spn=0.000965,0.002642&t=m&z=19&layer=c&cbll=48.859524,2.292532&panoid=YJ0lq28OOy3VT2IqIuVY0g&cbp=12,151.58,,0,-15.56 - */ -;(function ($) { - "use strict"; - - //Shortcut for fancyBox object - var F = $.fancybox, - format = function( url, rez, params ) { - params = params || ''; - - if ( $.type( params ) === "object" ) { - params = $.param(params, true); - } - - $.each(rez, function(key, value) { - url = url.replace( '$' + key, value || '' ); - }); - - if (params.length) { - url += ( url.indexOf('?') > 0 ? '&' : '?' ) + params; - } - - return url; - }; - - //Add helper object - F.helpers.media = { - defaults : { - youtube : { - matcher : /(youtube\.com|youtu\.be|youtube-nocookie\.com)\/(watch\?v=|v\/|u\/|embed\/?)?(videoseries\?list=(.*)|[\w-]{11}|\?listType=(.*)&list=(.*)).*/i, - params : { - autoplay : 1, - autohide : 1, - fs : 1, - rel : 0, - hd : 1, - wmode : 'opaque', - enablejsapi : 1, - ps: 'docs', - controls: 1 - }, - type : 'iframe', - url : '//www.youtube.com/embed/$3' - }, - vimeo : { - matcher : /(?:vimeo(?:pro)?.com)\/(?:[^\d]+)?(\d+)(?:.*)/, - params : { - autoplay : 1, - hd : 1, - show_title : 1, - show_byline : 1, - show_portrait : 0, - fullscreen : 1 - }, - type : 'iframe', - url : '//player.vimeo.com/video/$1' - }, - metacafe : { - matcher : /metacafe.com\/(?:watch|fplayer)\/([\w\-]{1,10})/, - params : { - autoPlay : 'yes' - }, - type : 'swf', - url : function( rez, params, obj ) { - obj.swf.flashVars = 'playerVars=' + $.param( params, true ); - - return '//www.metacafe.com/fplayer/' + rez[1] + '/.swf'; - } - }, - dailymotion : { - matcher : /dailymotion.com\/video\/(.*)\/?(.*)/, - params : { - additionalInfos : 0, - autoStart : 1 - }, - type : 'swf', - url : '//www.dailymotion.com/swf/video/$1' - }, - twitvid : { - matcher : /twitvid\.com\/([a-zA-Z0-9_\-\?\=]+)/i, - params : { - autoplay : 0 - }, - type : 'iframe', - url : '//www.twitvid.com/embed.php?guid=$1' - }, - twitpic : { - matcher : /twitpic\.com\/(?!(?:place|photos|events)\/)([a-zA-Z0-9\?\=\-]+)/i, - type : 'image', - url : '//twitpic.com/show/full/$1/' - }, - instagram : { - matcher : /(instagr\.am|instagram\.com)\/p\/([a-zA-Z0-9_\-]+)\/?/i, - type : 'image', - url : '//$1/p/$2/media/?size=l' - }, - google_maps : { - matcher : /maps\.google\.([a-z]{2,3}(\.[a-z]{2})?)\/(\?ll=|maps\?)(.*)/i, - type : 'iframe', - url : function( rez ) { - return '//maps.google.' + rez[1] + '/' + rez[3] + '' + rez[4] + '&output=' + (rez[4].indexOf('layer=c') > 0 ? 'svembed' : 'embed'); - } - } - }, - - beforeLoad : function(opts, obj) { - var url = obj.href || '', - type = false, - what, - item, - rez, - params; - - for (what in opts) { - if (opts.hasOwnProperty(what)) { - item = opts[ what ]; - rez = url.match( item.matcher ); - - if (rez) { - type = item.type; - params = $.extend(true, {}, item.params, obj[ what ] || ($.isPlainObject(opts[ what ]) ? opts[ what ].params : null)); - - url = $.type( item.url ) === "function" ? item.url.call( this, rez, params, obj ) : format( item.url, rez, params ); - - break; - } - } - } - - if (type) { - obj.href = url; - obj.type = type; - - obj.autoHeight = false; - } - } - }; - -}(jQuery)); diff --git a/modules/fancybox/source/helpers/jquery.fancybox-thumbs.css b/modules/fancybox/source/helpers/jquery.fancybox-thumbs.css deleted file mode 100644 index 63d29436..00000000 --- a/modules/fancybox/source/helpers/jquery.fancybox-thumbs.css +++ /dev/null @@ -1,55 +0,0 @@ -#fancybox-thumbs { - position: fixed; - left: 0; - width: 100%; - overflow: hidden; - z-index: 8050; -} - -#fancybox-thumbs.bottom { - bottom: 2px; -} - -#fancybox-thumbs.top { - top: 2px; -} - -#fancybox-thumbs ul { - position: relative; - list-style: none; - margin: 0; - padding: 0; -} - -#fancybox-thumbs ul li { - float: left; - padding: 1px; - opacity: 0.5; -} - -#fancybox-thumbs ul li.active { - opacity: 0.75; - padding: 0; - border: 1px solid #fff; -} - -#fancybox-thumbs ul li:hover { - opacity: 1; -} - -#fancybox-thumbs ul li a { - display: block; - position: relative; - overflow: hidden; - border: 1px solid #222; - background: #111; - outline: none; -} - -#fancybox-thumbs ul li img { - display: block; - position: relative; - border: 0; - padding: 0; - max-width: none; -} \ No newline at end of file diff --git a/modules/fancybox/source/helpers/jquery.fancybox-thumbs.js b/modules/fancybox/source/helpers/jquery.fancybox-thumbs.js deleted file mode 100644 index 1aec7df8..00000000 --- a/modules/fancybox/source/helpers/jquery.fancybox-thumbs.js +++ /dev/null @@ -1,165 +0,0 @@ - /*! - * Thumbnail helper for fancyBox - * version: 1.0.7 (Mon, 01 Oct 2012) - * @requires fancyBox v2.0 or later - * - * Usage: - * $(".fancybox").fancybox({ - * helpers : { - * thumbs: { - * width : 50, - * height : 50 - * } - * } - * }); - * - */ -;(function ($) { - //Shortcut for fancyBox object - var F = $.fancybox; - - //Add helper object - F.helpers.thumbs = { - defaults : { - width : 50, // thumbnail width - height : 50, // thumbnail height - position : 'bottom', // 'top' or 'bottom' - source : function ( item ) { // function to obtain the URL of the thumbnail image - var href; - - if (item.element) { - href = $(item.element).find('img').attr('src'); - } - - if (!href && item.type === 'image' && item.href) { - href = item.href; - } - - return href; - } - }, - - wrap : null, - list : null, - width : 0, - - init: function (opts, obj) { - var that = this, - list, - thumbWidth = opts.width, - thumbHeight = opts.height, - thumbSource = opts.source; - - //Build list structure - list = ''; - - for (var n = 0; n < obj.group.length; n++) { - list += '
  • '; - } - - this.wrap = $('
    ').addClass(opts.position).appendTo('body'); - this.list = $('
      ' + list + '
    ').appendTo(this.wrap); - - //Load each thumbnail - $.each(obj.group, function (i) { - var el = obj.group[ i ], - href = thumbSource( el ); - - if (!href) { - return; - } - - $("").on("load", function () { - var width = this.width, - height = this.height, - widthRatio, heightRatio, parent; - - if (!that.list || !width || !height) { - return; - } - - //Calculate thumbnail width/height and center it - widthRatio = width / thumbWidth; - heightRatio = height / thumbHeight; - - parent = that.list.children().eq(i).find('a'); - - if (widthRatio >= 1 && heightRatio >= 1) { - if (widthRatio > heightRatio) { - width = Math.floor(width / heightRatio); - height = thumbHeight; - - } else { - width = thumbWidth; - height = Math.floor(height / widthRatio); - } - } - - $(this).css({ - width : width, - height : height, - top : Math.floor(thumbHeight / 2 - height / 2), - left : Math.floor(thumbWidth / 2 - width / 2) - }); - - parent.width(thumbWidth).height(thumbHeight); - - $(this).hide().appendTo(parent).fadeIn(300); - - }) - .attr('src', href) - .attr('title', el.title); - }); - - //Set initial width - this.width = this.list.children().eq(0).outerWidth(true); - - this.list.width(this.width * (obj.group.length + 1)).css('left', Math.floor($(window).width() * 0.5 - (obj.index * this.width + this.width * 0.5))); - }, - - beforeLoad: function (opts, obj) { - //Remove self if gallery do not have at least two items - if (obj.group.length < 2) { - obj.helpers.thumbs = false; - - return; - } - - //Increase bottom margin to give space for thumbs - obj.margin[ opts.position === 'top' ? 0 : 2 ] += ((opts.height) + 15); - }, - - afterShow: function (opts, obj) { - //Check if exists and create or update list - if (this.list) { - this.onUpdate(opts, obj); - - } else { - this.init(opts, obj); - } - - //Set active element - this.list.children().removeClass('active').eq(obj.index).addClass('active'); - }, - - //Center list - onUpdate: function (opts, obj) { - if (this.list) { - this.list.stop(true).animate({ - 'left': Math.floor($(window).width() * 0.5 - (obj.index * this.width + this.width * 0.5)) - }, 150); - } - }, - - beforeClose: function () { - if (this.wrap) { - this.wrap.remove(); - } - - this.wrap = null; - this.list = null; - this.width = 0; - } - } - -}(jQuery)); diff --git a/modules/fancybox/source/jquery.fancybox.css b/modules/fancybox/source/jquery.fancybox.css deleted file mode 100644 index fb2c6dd2..00000000 --- a/modules/fancybox/source/jquery.fancybox.css +++ /dev/null @@ -1,275 +0,0 @@ -/*! fancyBox v2.1.5 fancyapps.com | fancyapps.com/fancybox/#license */ -.fancybox-wrap, -.fancybox-skin, -.fancybox-outer, -.fancybox-inner, -.fancybox-image, -.fancybox-wrap iframe, -.fancybox-wrap object, -.fancybox-nav, -.fancybox-nav span, -.fancybox-tmp -{ - padding: 0; - margin: 0; - border: 0; - outline: none; - vertical-align: top; -} - -.fancybox-wrap { - position: absolute; - top: 0; - left: 0; - -webkit-transform: translate3d(0, 0, 0); - transform: translate3d(0, 0, 0); - z-index: 8020; -} - -.fancybox-skin { - position: relative; - background: #f9f9f9; - color: #444; - text-shadow: none; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; -} - -.fancybox-opened { - z-index: 8030; -} - -.fancybox-opened .fancybox-skin { - -webkit-box-shadow: 0 10px 25px rgba(0, 0, 0, 0.5); - -moz-box-shadow: 0 10px 25px rgba(0, 0, 0, 0.5); - box-shadow: 0 10px 25px rgba(0, 0, 0, 0.5); -} - -.fancybox-outer, .fancybox-inner { - position: relative; -} - -.fancybox-inner { - overflow: hidden; -} - -.fancybox-type-iframe .fancybox-inner { - -webkit-overflow-scrolling: touch; -} - -.fancybox-error { - color: #444; - font: 14px/20px "Helvetica Neue",Helvetica,Arial,sans-serif; - margin: 0; - padding: 15px; - white-space: nowrap; -} - -.fancybox-image, .fancybox-iframe { - display: block; - width: 100%; - height: 100%; -} - -.fancybox-image { - max-width: 100%; - max-height: 100%; -} - -#fancybox-loading, .fancybox-close, .fancybox-prev span, .fancybox-next span { - background-image: url(fancybox_sprite.png); -} - -#fancybox-loading { - position: fixed; - top: 50%; - left: 50%; - margin-top: -22px; - margin-left: -22px; - background-position: 0 -108px; - opacity: 0.8; - cursor: pointer; - z-index: 8060; -} - -#fancybox-loading div { - width: 44px; - height: 44px; - background: url(fancybox_loading.gif) center center no-repeat; -} - -.fancybox-close { - position: absolute; - top: -18px; - right: -18px; - width: 36px; - height: 36px; - cursor: pointer; - z-index: 8040; -} - -.fancybox-nav { - position: absolute; - top: 0; - width: 40%; - height: 100%; - cursor: pointer; - text-decoration: none; - background: transparent url(blank.gif); /* helps IE */ - -webkit-tap-highlight-color: rgba(0,0,0,0); - z-index: 8040; -} - -.fancybox-prev { - left: 0; -} - -.fancybox-next { - right: 0; -} - -.fancybox-nav span { - position: absolute; - top: 50%; - width: 36px; - height: 34px; - margin-top: -18px; - cursor: pointer; - z-index: 8040; - visibility: hidden; -} - -.fancybox-prev span { - left: 10px; - background-position: 0 -36px; -} - -.fancybox-next span { - right: 10px; - background-position: 0 -72px; -} - -.fancybox-nav:hover span { - visibility: visible; -} - -.fancybox-tmp { - position: absolute; - top: -99999px; - left: -99999px; - max-width: 99999px; - max-height: 99999px; - overflow: visible !important; -} - -/* Overlay helper */ - -.fancybox-lock { - overflow: visible !important; - width: auto; -} - -.fancybox-lock body { - overflow: hidden !important; -} - -.fancybox-lock-test { - overflow-y: hidden !important; -} - -.fancybox-overlay { - position: absolute; - top: 0; - left: 0; - overflow: hidden; - display: none; - z-index: 8010; - background: url(fancybox_overlay.png); -} - -.fancybox-overlay-fixed { - position: fixed; - bottom: 0; - right: 0; -} - -.fancybox-lock .fancybox-overlay { - overflow: auto; - overflow-y: scroll; -} - -/* Title helper */ - -.fancybox-title { - visibility: hidden; - font: normal 13px/20px "Helvetica Neue",Helvetica,Arial,sans-serif; - position: relative; - text-shadow: none; - z-index: 8050; -} - -.fancybox-opened .fancybox-title { - visibility: visible; -} - -.fancybox-title-float-wrap { - position: absolute; - bottom: 0; - right: 50%; - margin-bottom: -35px; - z-index: 8050; - text-align: center; -} - -.fancybox-title-float-wrap .child { - display: inline-block; - margin-right: -100%; - padding: 2px 20px; - background: transparent; /* Fallback for web browsers that doesn't support RGBa */ - background: rgba(0, 0, 0, 0.8); - -webkit-border-radius: 15px; - -moz-border-radius: 15px; - border-radius: 15px; - text-shadow: 0 1px 2px #222; - color: #FFF; - font-weight: bold; - line-height: 24px; - white-space: nowrap; -} - -.fancybox-title-outside-wrap { - position: relative; - margin-top: 10px; - color: #fff; -} - -.fancybox-title-inside-wrap { - padding-top: 10px; -} - -.fancybox-title-over-wrap { - position: absolute; - bottom: 0; - left: 0; - color: #fff; - padding: 10px; - background: #000; - background: rgba(0, 0, 0, .8); -} - -/*Retina graphics!*/ -@media only screen and (-webkit-min-device-pixel-ratio: 1.5), - only screen and (min--moz-device-pixel-ratio: 1.5), - only screen and (min-device-pixel-ratio: 1.5){ - - #fancybox-loading, .fancybox-close, .fancybox-prev span, .fancybox-next span { - background-image: url(fancybox_sprite@2x.png); - background-size: 44px 152px; /*The size of the normal image, half the size of the hi-res image*/ - } - - #fancybox-loading div { - background-image: url(fancybox_loading@2x.gif); - background-size: 24px 24px; /*The size of the normal image, half the size of the hi-res image*/ - } -} \ No newline at end of file diff --git a/modules/fancybox/source/jquery.fancybox.js b/modules/fancybox/source/jquery.fancybox.js deleted file mode 100755 index d126de49..00000000 --- a/modules/fancybox/source/jquery.fancybox.js +++ /dev/null @@ -1,2018 +0,0 @@ -/*! - * fancyBox - jQuery Plugin - * version: 2.1.5 (Fri, 14 Jun 2013) - * requires jQuery v1.6 or later - * - * Examples at http://fancyapps.com/fancybox/ - * License: www.fancyapps.com/fancybox/#license - * - * Copyright 2012 Janis Skarnelis - janis@fancyapps.com - * - */ - -;(function (window, document, $, undefined) { - "use strict"; - - var H = $("html"), - W = $(window), - D = $(document), - F = $.fancybox = function () { - F.open.apply( this, arguments ); - }, - IE = navigator.userAgent.match(/msie/i), - didUpdate = null, - isTouch = document.createTouch !== undefined, - - isQuery = function(obj) { - return obj && obj.hasOwnProperty && obj instanceof $; - }, - isString = function(str) { - return str && $.type(str) === "string"; - }, - isPercentage = function(str) { - return isString(str) && str.indexOf('%') > 0; - }, - isScrollable = function(el) { - return (el && !(el.style.overflow && el.style.overflow === 'hidden') && ((el.clientWidth && el.scrollWidth > el.clientWidth) || (el.clientHeight && el.scrollHeight > el.clientHeight))); - }, - getScalar = function(orig, dim) { - var value = parseInt(orig, 10) || 0; - - if (dim && isPercentage(orig)) { - value = F.getViewport()[ dim ] / 100 * value; - } - - return Math.ceil(value); - }, - getValue = function(value, dim) { - return getScalar(value, dim) + 'px'; - }; - - $.extend(F, { - // The current version of fancyBox - version: '2.1.5', - - defaults: { - padding : 15, - margin : 20, - - width : 800, - height : 600, - minWidth : 100, - minHeight : 100, - maxWidth : 9999, - maxHeight : 9999, - pixelRatio: 1, // Set to 2 for retina display support - - autoSize : true, - autoHeight : false, - autoWidth : false, - - autoResize : true, - autoCenter : !isTouch, - fitToView : true, - aspectRatio : false, - topRatio : 0.5, - leftRatio : 0.5, - - scrolling : 'auto', // 'auto', 'yes' or 'no' - wrapCSS : '', - - arrows : true, - closeBtn : true, - closeClick : false, - nextClick : false, - mouseWheel : true, - autoPlay : false, - playSpeed : 3000, - preload : 3, - modal : false, - loop : true, - - ajax : { - dataType : 'html', - headers : { 'X-fancyBox': true } - }, - iframe : { - scrolling : 'auto', - preload : true - }, - swf : { - wmode: 'transparent', - allowfullscreen : 'true', - allowscriptaccess : 'always' - }, - - keys : { - next : { - 13 : 'left', // enter - 34 : 'up', // page down - 39 : 'left', // right arrow - 40 : 'up' // down arrow - }, - prev : { - 8 : 'right', // backspace - 33 : 'down', // page up - 37 : 'right', // left arrow - 38 : 'down' // up arrow - }, - close : [27], // escape key - play : [32], // space - start/stop slideshow - toggle : [70] // letter "f" - toggle fullscreen - }, - - direction : { - next : 'left', - prev : 'right' - }, - - scrollOutside : true, - - // Override some properties - index : 0, - type : null, - href : null, - content : null, - title : null, - - // HTML templates - tpl: { - wrap : '
    ', - image : '', - iframe : '', - error : '

    The requested content cannot be loaded.
    Please try again later.

    ', - closeBtn : '', - next : '', - prev : '', - loading : '
    ' - }, - - // Properties for each animation type - // Opening fancyBox - openEffect : 'fade', // 'elastic', 'fade' or 'none' - openSpeed : 250, - openEasing : 'swing', - openOpacity : true, - openMethod : 'zoomIn', - - // Closing fancyBox - closeEffect : 'fade', // 'elastic', 'fade' or 'none' - closeSpeed : 250, - closeEasing : 'swing', - closeOpacity : true, - closeMethod : 'zoomOut', - - // Changing next gallery item - nextEffect : 'elastic', // 'elastic', 'fade' or 'none' - nextSpeed : 250, - nextEasing : 'swing', - nextMethod : 'changeIn', - - // Changing previous gallery item - prevEffect : 'elastic', // 'elastic', 'fade' or 'none' - prevSpeed : 250, - prevEasing : 'swing', - prevMethod : 'changeOut', - - // Enable default helpers - helpers : { - overlay : true, - title : true - }, - - // Callbacks - onCancel : $.noop, // If canceling - beforeLoad : $.noop, // Before loading - afterLoad : $.noop, // After loading - beforeShow : $.noop, // Before changing in current item - afterShow : $.noop, // After opening - beforeChange : $.noop, // Before changing gallery item - beforeClose : $.noop, // Before closing - afterClose : $.noop // After closing - }, - - //Current state - group : {}, // Selected group - opts : {}, // Group options - previous : null, // Previous element - coming : null, // Element being loaded - current : null, // Currently loaded element - isActive : false, // Is activated - isOpen : false, // Is currently open - isOpened : false, // Have been fully opened at least once - - wrap : null, - skin : null, - outer : null, - inner : null, - - player : { - timer : null, - isActive : false - }, - - // Loaders - ajaxLoad : null, - imgPreload : null, - - // Some collections - transitions : {}, - helpers : {}, - - /* - * Static methods - */ - - open: function (group, opts) { - if (!group) { - return; - } - - if (!$.isPlainObject(opts)) { - opts = {}; - } - - // Close if already active - if (false === F.close(true)) { - return; - } - - // Normalize group - if (!$.isArray(group)) { - group = isQuery(group) ? $(group).get() : [group]; - } - - // Recheck if the type of each element is `object` and set content type (image, ajax, etc) - $.each(group, function(i, element) { - var obj = {}, - href, - title, - content, - type, - rez, - hrefParts, - selector; - - if ($.type(element) === "object") { - // Check if is DOM element - if (element.nodeType) { - element = $(element); - } - - if (isQuery(element)) { - obj = { - href : element.data('fancybox-href') || element.attr('href'), - title : $('
    ').text( element.data('fancybox-title') || element.attr('title') || '' ).html(), - isDom : true, - element : element - }; - - if ($.metadata) { - $.extend(true, obj, element.metadata()); - } - - } else { - obj = element; - } - } - - href = opts.href || obj.href || (isString(element) ? element : null); - title = opts.title !== undefined ? opts.title : obj.title || ''; - - content = opts.content || obj.content; - type = content ? 'html' : (opts.type || obj.type); - - if (!type && obj.isDom) { - type = element.data('fancybox-type'); - - if (!type) { - rez = element.prop('class').match(/fancybox\.(\w+)/); - type = rez ? rez[1] : null; - } - } - - if (isString(href)) { - // Try to guess the content type - if (!type) { - if (F.isImage(href)) { - type = 'image'; - - } else if (F.isSWF(href)) { - type = 'swf'; - - } else if (href.charAt(0) === '#') { - type = 'inline'; - - } else if (isString(element)) { - type = 'html'; - content = element; - } - } - - // Split url into two pieces with source url and content selector, e.g, - // "/mypage.html #my_id" will load "/mypage.html" and display element having id "my_id" - if (type === 'ajax') { - hrefParts = href.split(/\s+/, 2); - href = hrefParts.shift(); - selector = hrefParts.shift(); - } - } - - if (!content) { - if (type === 'inline') { - if (href) { - content = $( isString(href) ? href.replace(/.*(?=#[^\s]+$)/, '') : href ); //strip for ie7 - - } else if (obj.isDom) { - content = element; - } - - } else if (type === 'html') { - content = href; - - } else if (!type && !href && obj.isDom) { - type = 'inline'; - content = element; - } - } - - $.extend(obj, { - href : href, - type : type, - content : content, - title : title, - selector : selector - }); - - group[ i ] = obj; - }); - - // Extend the defaults - F.opts = $.extend(true, {}, F.defaults, opts); - - // All options are merged recursive except keys - if (opts.keys !== undefined) { - F.opts.keys = opts.keys ? $.extend({}, F.defaults.keys, opts.keys) : false; - } - - F.group = group; - - return F._start(F.opts.index); - }, - - // Cancel image loading or abort ajax request - cancel: function () { - var coming = F.coming; - - if (coming && false === F.trigger('onCancel')) { - return; - } - - F.hideLoading(); - - if (!coming) { - return; - } - - if (F.ajaxLoad) { - F.ajaxLoad.abort(); - } - - F.ajaxLoad = null; - - if (F.imgPreload) { - F.imgPreload.onload = F.imgPreload.onerror = null; - } - - if (coming.wrap) { - coming.wrap.stop(true, true).trigger('onReset').remove(); - } - - F.coming = null; - - // If the first item has been canceled, then clear everything - if (!F.current) { - F._afterZoomOut( coming ); - } - }, - - // Start closing animation if is open; remove immediately if opening/closing - close: function (event) { - F.cancel(); - - if (false === F.trigger('beforeClose')) { - return; - } - - F.unbindEvents(); - - if (!F.isActive) { - return; - } - - if (!F.isOpen || event === true) { - $('.fancybox-wrap').stop(true).trigger('onReset').remove(); - - F._afterZoomOut(); - - } else { - F.isOpen = F.isOpened = false; - F.isClosing = true; - - $('.fancybox-item, .fancybox-nav').remove(); - - F.wrap.stop(true, true).removeClass('fancybox-opened'); - - F.transitions[ F.current.closeMethod ](); - } - }, - - // Manage slideshow: - // $.fancybox.play(); - toggle slideshow - // $.fancybox.play( true ); - start - // $.fancybox.play( false ); - stop - play: function ( action ) { - var clear = function () { - clearTimeout(F.player.timer); - }, - set = function () { - clear(); - - if (F.current && F.player.isActive) { - F.player.timer = setTimeout(F.next, F.current.playSpeed); - } - }, - stop = function () { - clear(); - - D.unbind('.player'); - - F.player.isActive = false; - - F.trigger('onPlayEnd'); - }, - start = function () { - if (F.current && (F.current.loop || F.current.index < F.group.length - 1)) { - F.player.isActive = true; - - D.bind({ - 'onCancel.player beforeClose.player' : stop, - 'onUpdate.player' : set, - 'beforeLoad.player' : clear - }); - - set(); - - F.trigger('onPlayStart'); - } - }; - - if (action === true || (!F.player.isActive && action !== false)) { - start(); - } else { - stop(); - } - }, - - // Navigate to next gallery item - next: function ( direction ) { - var current = F.current; - - if (current) { - if (!isString(direction)) { - direction = current.direction.next; - } - - F.jumpto(current.index + 1, direction, 'next'); - } - }, - - // Navigate to previous gallery item - prev: function ( direction ) { - var current = F.current; - - if (current) { - if (!isString(direction)) { - direction = current.direction.prev; - } - - F.jumpto(current.index - 1, direction, 'prev'); - } - }, - - // Navigate to gallery item by index - jumpto: function ( index, direction, router ) { - var current = F.current; - - if (!current) { - return; - } - - index = getScalar(index); - - F.direction = direction || current.direction[ (index >= current.index ? 'next' : 'prev') ]; - F.router = router || 'jumpto'; - - if (current.loop) { - if (index < 0) { - index = current.group.length + (index % current.group.length); - } - - index = index % current.group.length; - } - - if (current.group[ index ] !== undefined) { - F.cancel(); - - F._start(index); - } - }, - - // Center inside viewport and toggle position type to fixed or absolute if needed - reposition: function (e, onlyAbsolute) { - var current = F.current, - wrap = current ? current.wrap : null, - pos; - - if (wrap) { - pos = F._getPosition(onlyAbsolute); - - if (e && e.type === 'scroll') { - delete pos.position; - - wrap.stop(true, true).animate(pos, 200); - - } else { - wrap.css(pos); - - current.pos = $.extend({}, current.dim, pos); - } - } - }, - - update: function (e) { - var type = (e && e.originalEvent && e.originalEvent.type), - anyway = !type || type === 'orientationchange'; - - if (anyway) { - clearTimeout(didUpdate); - - didUpdate = null; - } - - if (!F.isOpen || didUpdate) { - return; - } - - didUpdate = setTimeout(function() { - var current = F.current; - - if (!current || F.isClosing) { - return; - } - - F.wrap.removeClass('fancybox-tmp'); - - if (anyway || type === 'load' || (type === 'resize' && current.autoResize)) { - F._setDimension(); - } - - if (!(type === 'scroll' && current.canShrink)) { - F.reposition(e); - } - - F.trigger('onUpdate'); - - didUpdate = null; - - }, (anyway && !isTouch ? 0 : 300)); - }, - - // Shrink content to fit inside viewport or restore if resized - toggle: function ( action ) { - if (F.isOpen) { - F.current.fitToView = $.type(action) === "boolean" ? action : !F.current.fitToView; - - // Help browser to restore document dimensions - if (isTouch) { - F.wrap.removeAttr('style').addClass('fancybox-tmp'); - - F.trigger('onUpdate'); - } - - F.update(); - } - }, - - hideLoading: function () { - D.unbind('.loading'); - - $('#fancybox-loading').remove(); - }, - - showLoading: function () { - var el, viewport; - - F.hideLoading(); - - el = $(F.opts.tpl.loading).click(F.cancel).appendTo('body'); - - // If user will press the escape-button, the request will be canceled - D.bind('keydown.loading', function(e) { - if ((e.which || e.keyCode) === 27) { - e.preventDefault(); - - F.cancel(); - } - }); - - if (!F.defaults.fixed) { - viewport = F.getViewport(); - - el.css({ - position : 'absolute', - top : (viewport.h * 0.5) + viewport.y, - left : (viewport.w * 0.5) + viewport.x - }); - } - - F.trigger('onLoading'); - }, - - getViewport: function () { - var locked = (F.current && F.current.locked) || false, - rez = { - x: W.scrollLeft(), - y: W.scrollTop() - }; - - if (locked && locked.length) { - rez.w = locked[0].clientWidth; - rez.h = locked[0].clientHeight; - - } else { - // See http://bugs.jquery.com/ticket/6724 - rez.w = isTouch && window.innerWidth ? window.innerWidth : W.width(); - rez.h = isTouch && window.innerHeight ? window.innerHeight : W.height(); - } - - return rez; - }, - - // Unbind the keyboard / clicking actions - unbindEvents: function () { - if (F.wrap && isQuery(F.wrap)) { - F.wrap.unbind('.fb'); - } - - D.unbind('.fb'); - W.unbind('.fb'); - }, - - bindEvents: function () { - var current = F.current, - keys; - - if (!current) { - return; - } - - // Changing document height on iOS devices triggers a 'resize' event, - // that can change document height... repeating infinitely - W.bind('orientationchange.fb' + (isTouch ? '' : ' resize.fb') + (current.autoCenter && !current.locked ? ' scroll.fb' : ''), F.update); - - keys = current.keys; - - if (keys) { - D.bind('keydown.fb', function (e) { - var code = e.which || e.keyCode, - target = e.target || e.srcElement; - - // Skip esc key if loading, because showLoading will cancel preloading - if (code === 27 && F.coming) { - return false; - } - - // Ignore key combinations and key events within form elements - if (!e.ctrlKey && !e.altKey && !e.shiftKey && !e.metaKey && !(target && (target.type || $(target).is('[contenteditable]')))) { - $.each(keys, function(i, val) { - if (current.group.length > 1 && val[ code ] !== undefined) { - F[ i ]( val[ code ] ); - - e.preventDefault(); - return false; - } - - if ($.inArray(code, val) > -1) { - F[ i ] (); - - e.preventDefault(); - return false; - } - }); - } - }); - } - - if ($.fn.mousewheel && current.mouseWheel) { - F.wrap.bind('mousewheel.fb', function (e, delta, deltaX, deltaY) { - var target = e.target || null, - parent = $(target), - canScroll = false; - - while (parent.length) { - if (canScroll || parent.is('.fancybox-skin') || parent.is('.fancybox-wrap')) { - break; - } - - canScroll = isScrollable( parent[0] ); - parent = $(parent).parent(); - } - - if (delta !== 0 && !canScroll) { - if (F.group.length > 1 && !current.canShrink) { - if (deltaY > 0 || deltaX > 0) { - F.prev( deltaY > 0 ? 'down' : 'left' ); - - } else if (deltaY < 0 || deltaX < 0) { - F.next( deltaY < 0 ? 'up' : 'right' ); - } - - e.preventDefault(); - } - } - }); - } - }, - - trigger: function (event, o) { - var ret, obj = o || F.coming || F.current; - - if (obj) { - if ($.isFunction( obj[event] )) { - ret = obj[event].apply(obj, Array.prototype.slice.call(arguments, 1)); - } - - if (ret === false) { - return false; - } - - if (obj.helpers) { - $.each(obj.helpers, function (helper, opts) { - if (opts && F.helpers[helper] && $.isFunction(F.helpers[helper][event])) { - F.helpers[helper][event]($.extend(true, {}, F.helpers[helper].defaults, opts), obj); - } - }); - } - } - - D.trigger(event); - }, - - isImage: function (str) { - return isString(str) && str.match(/(^data:image\/.*,)|(\.(jp(e|g|eg)|gif|png|bmp|webp|svg)((\?|#).*)?$)/i); - }, - - isSWF: function (str) { - return isString(str) && str.match(/\.(swf)((\?|#).*)?$/i); - }, - - _start: function (index) { - var coming = {}, - obj, - href, - type, - margin, - padding; - - index = getScalar( index ); - obj = F.group[ index ] || null; - - if (!obj) { - return false; - } - - coming = $.extend(true, {}, F.opts, obj); - - // Convert margin and padding properties to array - top, right, bottom, left - margin = coming.margin; - padding = coming.padding; - - if ($.type(margin) === 'number') { - coming.margin = [margin, margin, margin, margin]; - } - - if ($.type(padding) === 'number') { - coming.padding = [padding, padding, padding, padding]; - } - - // 'modal' propery is just a shortcut - if (coming.modal) { - $.extend(true, coming, { - closeBtn : false, - closeClick : false, - nextClick : false, - arrows : false, - mouseWheel : false, - keys : null, - helpers: { - overlay : { - closeClick : false - } - } - }); - } - - // 'autoSize' property is a shortcut, too - if (coming.autoSize) { - coming.autoWidth = coming.autoHeight = true; - } - - if (coming.width === 'auto') { - coming.autoWidth = true; - } - - if (coming.height === 'auto') { - coming.autoHeight = true; - } - - /* - * Add reference to the group, so it`s possible to access from callbacks, example: - * afterLoad : function() { - * this.title = 'Image ' + (this.index + 1) + ' of ' + this.group.length + (this.title ? ' - ' + this.title : ''); - * } - */ - - coming.group = F.group; - coming.index = index; - - // Give a chance for callback or helpers to update coming item (type, title, etc) - F.coming = coming; - - if (false === F.trigger('beforeLoad')) { - F.coming = null; - - return; - } - - type = coming.type; - href = coming.href; - - if (!type) { - F.coming = null; - - //If we can not determine content type then drop silently or display next/prev item if looping through gallery - if (F.current && F.router && F.router !== 'jumpto') { - F.current.index = index; - - return F[ F.router ]( F.direction ); - } - - return false; - } - - F.isActive = true; - - if (type === 'image' || type === 'swf') { - coming.autoHeight = coming.autoWidth = false; - coming.scrolling = 'visible'; - } - - if (type === 'image') { - coming.aspectRatio = true; - } - - if (type === 'iframe' && isTouch) { - coming.scrolling = 'scroll'; - } - - // Build the neccessary markup - coming.wrap = $(coming.tpl.wrap).addClass('fancybox-' + (isTouch ? 'mobile' : 'desktop') + ' fancybox-type-' + type + ' fancybox-tmp ' + coming.wrapCSS).appendTo( coming.parent || 'body' ); - - $.extend(coming, { - skin : $('.fancybox-skin', coming.wrap), - outer : $('.fancybox-outer', coming.wrap), - inner : $('.fancybox-inner', coming.wrap) - }); - - $.each(["Top", "Right", "Bottom", "Left"], function(i, v) { - coming.skin.css('padding' + v, getValue(coming.padding[ i ])); - }); - - F.trigger('onReady'); - - // Check before try to load; 'inline' and 'html' types need content, others - href - if (type === 'inline' || type === 'html') { - if (!coming.content || !coming.content.length) { - return F._error( 'content' ); - } - - } else if (!href) { - return F._error( 'href' ); - } - - if (type === 'image') { - F._loadImage(); - - } else if (type === 'ajax') { - F._loadAjax(); - - } else if (type === 'iframe') { - F._loadIframe(); - - } else { - F._afterLoad(); - } - }, - - _error: function ( type ) { - $.extend(F.coming, { - type : 'html', - autoWidth : true, - autoHeight : true, - minWidth : 0, - minHeight : 0, - scrolling : 'no', - hasError : type, - content : F.coming.tpl.error - }); - - F._afterLoad(); - }, - - _loadImage: function () { - // Reset preload image so it is later possible to check "complete" property - var img = F.imgPreload = new Image(); - - img.onload = function () { - this.onload = this.onerror = null; - - F.coming.width = this.width / F.opts.pixelRatio; - F.coming.height = this.height / F.opts.pixelRatio; - - F._afterLoad(); - }; - - img.onerror = function () { - this.onload = this.onerror = null; - - F._error( 'image' ); - }; - - img.src = F.coming.href; - - if (img.complete !== true) { - F.showLoading(); - } - }, - - _loadAjax: function () { - var coming = F.coming; - - F.showLoading(); - - F.ajaxLoad = $.ajax($.extend({}, coming.ajax, { - url: coming.href, - error: function (jqXHR, textStatus) { - if (F.coming && textStatus !== 'abort') { - F._error( 'ajax', jqXHR ); - - } else { - F.hideLoading(); - } - }, - success: function (data, textStatus) { - if (textStatus === 'success') { - coming.content = data; - - F._afterLoad(); - } - } - })); - }, - - _loadIframe: function() { - var coming = F.coming, - iframe = $(coming.tpl.iframe.replace(/\{rnd\}/g, new Date().getTime())) - .attr('scrolling', isTouch ? 'auto' : coming.iframe.scrolling) - .attr('src', coming.href); - - // This helps IE - $(coming.wrap).bind('onReset', function () { - try { - $(this).find('iframe').hide().attr('src', '//about:blank').end().empty(); - } catch (e) {} - }); - - if (coming.iframe.preload) { - F.showLoading(); - - iframe.one('load', function() { - $(this).data('ready', 1); - - // iOS will lose scrolling if we resize - if (!isTouch) { - $(this).bind('load.fb', F.update); - } - - // Without this trick: - // - iframe won't scroll on iOS devices - // - IE7 sometimes displays empty iframe - $(this).parents('.fancybox-wrap').width('100%').removeClass('fancybox-tmp').show(); - - F._afterLoad(); - }); - } - - coming.content = iframe.appendTo( coming.inner ); - - if (!coming.iframe.preload) { - F._afterLoad(); - } - }, - - _preloadImages: function() { - var group = F.group, - current = F.current, - len = group.length, - cnt = current.preload ? Math.min(current.preload, len - 1) : 0, - item, - i; - - for (i = 1; i <= cnt; i += 1) { - item = group[ (current.index + i ) % len ]; - - if (item.type === 'image' && item.href) { - new Image().src = item.href; - } - } - }, - - _afterLoad: function () { - var coming = F.coming, - previous = F.current, - placeholder = 'fancybox-placeholder', - current, - content, - type, - scrolling, - href, - embed; - - F.hideLoading(); - - if (!coming || F.isActive === false) { - return; - } - - if (false === F.trigger('afterLoad', coming, previous)) { - coming.wrap.stop(true).trigger('onReset').remove(); - - F.coming = null; - - return; - } - - if (previous) { - F.trigger('beforeChange', previous); - - previous.wrap.stop(true).removeClass('fancybox-opened') - .find('.fancybox-item, .fancybox-nav') - .remove(); - } - - F.unbindEvents(); - - current = coming; - content = coming.content; - type = coming.type; - scrolling = coming.scrolling; - - $.extend(F, { - wrap : current.wrap, - skin : current.skin, - outer : current.outer, - inner : current.inner, - current : current, - previous : previous - }); - - href = current.href; - - switch (type) { - case 'inline': - case 'ajax': - case 'html': - if (current.selector) { - content = $('
    ').html(content).find(current.selector); - - } else if (isQuery(content)) { - if (!content.data(placeholder)) { - content.data(placeholder, $('
    ').insertAfter( content ).hide() ); - } - - content = content.show().detach(); - - current.wrap.bind('onReset', function () { - if ($(this).find(content).length) { - content.hide().replaceAll( content.data(placeholder) ).data(placeholder, false); - } - }); - } - break; - - case 'image': - content = current.tpl.image.replace(/\{href\}/g, href); - break; - - case 'swf': - content = ''; - embed = ''; - - $.each(current.swf, function(name, val) { - content += ''; - embed += ' ' + name + '="' + val + '"'; - }); - - content += ''; - break; - } - - if (!(isQuery(content) && content.parent().is(current.inner))) { - current.inner.append( content ); - } - - // Give a chance for helpers or callbacks to update elements - F.trigger('beforeShow'); - - // Set scrolling before calculating dimensions - current.inner.css('overflow', scrolling === 'yes' ? 'scroll' : (scrolling === 'no' ? 'hidden' : scrolling)); - - // Set initial dimensions and start position - F._setDimension(); - - F.reposition(); - - F.isOpen = false; - F.coming = null; - - F.bindEvents(); - - if (!F.isOpened) { - $('.fancybox-wrap').not( current.wrap ).stop(true).trigger('onReset').remove(); - - } else if (previous.prevMethod) { - F.transitions[ previous.prevMethod ](); - } - - F.transitions[ F.isOpened ? current.nextMethod : current.openMethod ](); - - F._preloadImages(); - }, - - _setDimension: function () { - var viewport = F.getViewport(), - steps = 0, - canShrink = false, - canExpand = false, - wrap = F.wrap, - skin = F.skin, - inner = F.inner, - current = F.current, - width = current.width, - height = current.height, - minWidth = current.minWidth, - minHeight = current.minHeight, - maxWidth = current.maxWidth, - maxHeight = current.maxHeight, - scrolling = current.scrolling, - scrollOut = current.scrollOutside ? current.scrollbarWidth : 0, - margin = current.margin, - wMargin = getScalar(margin[1] + margin[3]), - hMargin = getScalar(margin[0] + margin[2]), - wPadding, - hPadding, - wSpace, - hSpace, - origWidth, - origHeight, - origMaxWidth, - origMaxHeight, - ratio, - width_, - height_, - maxWidth_, - maxHeight_, - iframe, - body; - - // Reset dimensions so we could re-check actual size - wrap.add(skin).add(inner).width('auto').height('auto').removeClass('fancybox-tmp'); - - wPadding = getScalar(skin.outerWidth(true) - skin.width()); - hPadding = getScalar(skin.outerHeight(true) - skin.height()); - - // Any space between content and viewport (margin, padding, border, title) - wSpace = wMargin + wPadding; - hSpace = hMargin + hPadding; - - origWidth = isPercentage(width) ? (viewport.w - wSpace) * getScalar(width) / 100 : width; - origHeight = isPercentage(height) ? (viewport.h - hSpace) * getScalar(height) / 100 : height; - - if (current.type === 'iframe') { - iframe = current.content; - - if (current.autoHeight && iframe && iframe.data('ready') === 1) { - try { - if (iframe[0].contentWindow.document.location) { - inner.width( origWidth ).height(9999); - - body = iframe.contents().find('body'); - - if (scrollOut) { - body.css('overflow-x', 'hidden'); - } - - origHeight = body.outerHeight(true); - } - - } catch (e) {} - } - - } else if (current.autoWidth || current.autoHeight) { - inner.addClass( 'fancybox-tmp' ); - - // Set width or height in case we need to calculate only one dimension - if (!current.autoWidth) { - inner.width( origWidth ); - } - - if (!current.autoHeight) { - inner.height( origHeight ); - } - - if (current.autoWidth) { - origWidth = inner.width(); - } - - if (current.autoHeight) { - origHeight = inner.height(); - } - - inner.removeClass( 'fancybox-tmp' ); - } - - width = getScalar( origWidth ); - height = getScalar( origHeight ); - - ratio = origWidth / origHeight; - - // Calculations for the content - minWidth = getScalar(isPercentage(minWidth) ? getScalar(minWidth, 'w') - wSpace : minWidth); - maxWidth = getScalar(isPercentage(maxWidth) ? getScalar(maxWidth, 'w') - wSpace : maxWidth); - - minHeight = getScalar(isPercentage(minHeight) ? getScalar(minHeight, 'h') - hSpace : minHeight); - maxHeight = getScalar(isPercentage(maxHeight) ? getScalar(maxHeight, 'h') - hSpace : maxHeight); - - // These will be used to determine if wrap can fit in the viewport - origMaxWidth = maxWidth; - origMaxHeight = maxHeight; - - if (current.fitToView) { - maxWidth = Math.min(viewport.w - wSpace, maxWidth); - maxHeight = Math.min(viewport.h - hSpace, maxHeight); - } - - maxWidth_ = viewport.w - wMargin; - maxHeight_ = viewport.h - hMargin; - - if (current.aspectRatio) { - if (width > maxWidth) { - width = maxWidth; - height = getScalar(width / ratio); - } - - if (height > maxHeight) { - height = maxHeight; - width = getScalar(height * ratio); - } - - if (width < minWidth) { - width = minWidth; - height = getScalar(width / ratio); - } - - if (height < minHeight) { - height = minHeight; - width = getScalar(height * ratio); - } - - } else { - width = Math.max(minWidth, Math.min(width, maxWidth)); - - if (current.autoHeight && current.type !== 'iframe') { - inner.width( width ); - - height = inner.height(); - } - - height = Math.max(minHeight, Math.min(height, maxHeight)); - } - - // Try to fit inside viewport (including the title) - if (current.fitToView) { - inner.width( width ).height( height ); - - wrap.width( width + wPadding ); - - // Real wrap dimensions - width_ = wrap.width(); - height_ = wrap.height(); - - if (current.aspectRatio) { - while ((width_ > maxWidth_ || height_ > maxHeight_) && width > minWidth && height > minHeight) { - if (steps++ > 19) { - break; - } - - height = Math.max(minHeight, Math.min(maxHeight, height - 10)); - width = getScalar(height * ratio); - - if (width < minWidth) { - width = minWidth; - height = getScalar(width / ratio); - } - - if (width > maxWidth) { - width = maxWidth; - height = getScalar(width / ratio); - } - - inner.width( width ).height( height ); - - wrap.width( width + wPadding ); - - width_ = wrap.width(); - height_ = wrap.height(); - } - - } else { - width = Math.max(minWidth, Math.min(width, width - (width_ - maxWidth_))); - height = Math.max(minHeight, Math.min(height, height - (height_ - maxHeight_))); - } - } - - if (scrollOut && scrolling === 'auto' && height < origHeight && (width + wPadding + scrollOut) < maxWidth_) { - width += scrollOut; - } - - inner.width( width ).height( height ); - - wrap.width( width + wPadding ); - - width_ = wrap.width(); - height_ = wrap.height(); - - canShrink = (width_ > maxWidth_ || height_ > maxHeight_) && width > minWidth && height > minHeight; - canExpand = current.aspectRatio ? (width < origMaxWidth && height < origMaxHeight && width < origWidth && height < origHeight) : ((width < origMaxWidth || height < origMaxHeight) && (width < origWidth || height < origHeight)); - - $.extend(current, { - dim : { - width : getValue( width_ ), - height : getValue( height_ ) - }, - origWidth : origWidth, - origHeight : origHeight, - canShrink : canShrink, - canExpand : canExpand, - wPadding : wPadding, - hPadding : hPadding, - wrapSpace : height_ - skin.outerHeight(true), - skinSpace : skin.height() - height - }); - - if (!iframe && current.autoHeight && height > minHeight && height < maxHeight && !canExpand) { - inner.height('auto'); - } - }, - - _getPosition: function (onlyAbsolute) { - var current = F.current, - viewport = F.getViewport(), - margin = current.margin, - width = F.wrap.width() + margin[1] + margin[3], - height = F.wrap.height() + margin[0] + margin[2], - rez = { - position: 'absolute', - top : margin[0], - left : margin[3] - }; - - if (current.autoCenter && current.fixed && !onlyAbsolute && height <= viewport.h && width <= viewport.w) { - rez.position = 'fixed'; - - } else if (!current.locked) { - rez.top += viewport.y; - rez.left += viewport.x; - } - - rez.top = getValue(Math.max(rez.top, rez.top + ((viewport.h - height) * current.topRatio))); - rez.left = getValue(Math.max(rez.left, rez.left + ((viewport.w - width) * current.leftRatio))); - - return rez; - }, - - _afterZoomIn: function () { - var current = F.current; - - if (!current) { - return; - } - - F.isOpen = F.isOpened = true; - - F.wrap.css('overflow', 'visible').addClass('fancybox-opened').hide().show(0); - - F.update(); - - // Assign a click event - if ( current.closeClick || (current.nextClick && F.group.length > 1) ) { - F.inner.css('cursor', 'pointer').bind('click.fb', function(e) { - if (!$(e.target).is('a') && !$(e.target).parent().is('a')) { - e.preventDefault(); - - F[ current.closeClick ? 'close' : 'next' ](); - } - }); - } - - // Create a close button - if (current.closeBtn) { - $(current.tpl.closeBtn).appendTo(F.skin).bind('click.fb', function(e) { - e.preventDefault(); - - F.close(); - }); - } - - // Create navigation arrows - if (current.arrows && F.group.length > 1) { - if (current.loop || current.index > 0) { - $(current.tpl.prev).appendTo(F.outer).bind('click.fb', F.prev); - } - - if (current.loop || current.index < F.group.length - 1) { - $(current.tpl.next).appendTo(F.outer).bind('click.fb', F.next); - } - } - - F.trigger('afterShow'); - - // Stop the slideshow if this is the last item - if (!current.loop && current.index === current.group.length - 1) { - - F.play( false ); - - } else if (F.opts.autoPlay && !F.player.isActive) { - F.opts.autoPlay = false; - - F.play(true); - } - }, - - _afterZoomOut: function ( obj ) { - obj = obj || F.current; - - $('.fancybox-wrap').trigger('onReset').remove(); - - $.extend(F, { - group : {}, - opts : {}, - router : false, - current : null, - isActive : false, - isOpened : false, - isOpen : false, - isClosing : false, - wrap : null, - skin : null, - outer : null, - inner : null - }); - - F.trigger('afterClose', obj); - } - }); - - /* - * Default transitions - */ - - F.transitions = { - getOrigPosition: function () { - var current = F.current, - element = current.element, - orig = current.orig, - pos = {}, - width = 50, - height = 50, - hPadding = current.hPadding, - wPadding = current.wPadding, - viewport = F.getViewport(); - - if (!orig && current.isDom && element.is(':visible')) { - orig = element.find('img:first'); - - if (!orig.length) { - orig = element; - } - } - - if (isQuery(orig)) { - pos = orig.offset(); - - if (orig.is('img')) { - width = orig.outerWidth(); - height = orig.outerHeight(); - } - - } else { - pos.top = viewport.y + (viewport.h - height) * current.topRatio; - pos.left = viewport.x + (viewport.w - width) * current.leftRatio; - } - - if (F.wrap.css('position') === 'fixed' || current.locked) { - pos.top -= viewport.y; - pos.left -= viewport.x; - } - - pos = { - top : getValue(pos.top - hPadding * current.topRatio), - left : getValue(pos.left - wPadding * current.leftRatio), - width : getValue(width + wPadding), - height : getValue(height + hPadding) - }; - - return pos; - }, - - step: function (now, fx) { - var ratio, - padding, - value, - prop = fx.prop, - current = F.current, - wrapSpace = current.wrapSpace, - skinSpace = current.skinSpace; - - if (prop === 'width' || prop === 'height') { - ratio = fx.end === fx.start ? 1 : (now - fx.start) / (fx.end - fx.start); - - if (F.isClosing) { - ratio = 1 - ratio; - } - - padding = prop === 'width' ? current.wPadding : current.hPadding; - value = now - padding; - - F.skin[ prop ]( getScalar( prop === 'width' ? value : value - (wrapSpace * ratio) ) ); - F.inner[ prop ]( getScalar( prop === 'width' ? value : value - (wrapSpace * ratio) - (skinSpace * ratio) ) ); - } - }, - - zoomIn: function () { - var current = F.current, - startPos = current.pos, - effect = current.openEffect, - elastic = effect === 'elastic', - endPos = $.extend({opacity : 1}, startPos); - - // Remove "position" property that breaks older IE - delete endPos.position; - - if (elastic) { - startPos = this.getOrigPosition(); - - if (current.openOpacity) { - startPos.opacity = 0.1; - } - - } else if (effect === 'fade') { - startPos.opacity = 0.1; - } - - F.wrap.css(startPos).animate(endPos, { - duration : effect === 'none' ? 0 : current.openSpeed, - easing : current.openEasing, - step : elastic ? this.step : null, - complete : F._afterZoomIn - }); - }, - - zoomOut: function () { - var current = F.current, - effect = current.closeEffect, - elastic = effect === 'elastic', - endPos = {opacity : 0.1}; - - if (elastic) { - endPos = this.getOrigPosition(); - - if (current.closeOpacity) { - endPos.opacity = 0.1; - } - } - - F.wrap.animate(endPos, { - duration : effect === 'none' ? 0 : current.closeSpeed, - easing : current.closeEasing, - step : elastic ? this.step : null, - complete : F._afterZoomOut - }); - }, - - changeIn: function () { - var current = F.current, - effect = current.nextEffect, - startPos = current.pos, - endPos = { opacity : 1 }, - direction = F.direction, - distance = 200, - field; - - startPos.opacity = 0.1; - - if (effect === 'elastic') { - field = direction === 'down' || direction === 'up' ? 'top' : 'left'; - - if (direction === 'down' || direction === 'right') { - startPos[ field ] = getValue(getScalar(startPos[ field ]) - distance); - endPos[ field ] = '+=' + distance + 'px'; - - } else { - startPos[ field ] = getValue(getScalar(startPos[ field ]) + distance); - endPos[ field ] = '-=' + distance + 'px'; - } - } - - // Workaround for http://bugs.jquery.com/ticket/12273 - if (effect === 'none') { - F._afterZoomIn(); - - } else { - F.wrap.css(startPos).animate(endPos, { - duration : current.nextSpeed, - easing : current.nextEasing, - complete : F._afterZoomIn - }); - } - }, - - changeOut: function () { - var previous = F.previous, - effect = previous.prevEffect, - endPos = { opacity : 0.1 }, - direction = F.direction, - distance = 200; - - if (effect === 'elastic') { - endPos[ direction === 'down' || direction === 'up' ? 'top' : 'left' ] = ( direction === 'up' || direction === 'left' ? '-' : '+' ) + '=' + distance + 'px'; - } - - previous.wrap.animate(endPos, { - duration : effect === 'none' ? 0 : previous.prevSpeed, - easing : previous.prevEasing, - complete : function () { - $(this).trigger('onReset').remove(); - } - }); - } - }; - - /* - * Overlay helper - */ - - F.helpers.overlay = { - defaults : { - closeClick : true, // if true, fancyBox will be closed when user clicks on the overlay - speedOut : 200, // duration of fadeOut animation - showEarly : true, // indicates if should be opened immediately or wait until the content is ready - css : {}, // custom CSS properties - locked : !isTouch, // if true, the content will be locked into overlay - fixed : true // if false, the overlay CSS position property will not be set to "fixed" - }, - - overlay : null, // current handle - fixed : false, // indicates if the overlay has position "fixed" - el : $('html'), // element that contains "the lock" - - // Public methods - create : function(opts) { - var parent; - - opts = $.extend({}, this.defaults, opts); - - if (this.overlay) { - this.close(); - } - - parent = F.coming ? F.coming.parent : opts.parent; - - this.overlay = $('
    ').appendTo( parent && parent.length ? parent : 'body' ); - this.fixed = false; - - if (opts.fixed && F.defaults.fixed) { - this.overlay.addClass('fancybox-overlay-fixed'); - - this.fixed = true; - } - }, - - open : function(opts) { - var that = this; - - opts = $.extend({}, this.defaults, opts); - - if (this.overlay) { - this.overlay.unbind('.overlay').width('auto').height('auto'); - - } else { - this.create(opts); - } - - if (!this.fixed) { - W.bind('resize.overlay', $.proxy( this.update, this) ); - - this.update(); - } - - if (opts.closeClick) { - this.overlay.bind('click.overlay', function(e) { - if ($(e.target).hasClass('fancybox-overlay')) { - if (F.isActive) { - F.close(); - } else { - that.close(); - } - - return false; - } - }); - } - - this.overlay.css( opts.css ).show(); - }, - - close : function() { - W.unbind('resize.overlay'); - - if (this.el.hasClass('fancybox-lock')) { - $('.fancybox-margin').removeClass('fancybox-margin'); - - this.el.removeClass('fancybox-lock'); - - W.scrollTop( this.scrollV ).scrollLeft( this.scrollH ); - } - - $('.fancybox-overlay').remove().hide(); - - $.extend(this, { - overlay : null, - fixed : false - }); - }, - - // Private, callbacks - - update : function () { - var width = '100%', offsetWidth; - - // Reset width/height so it will not mess - this.overlay.width(width).height('100%'); - - // jQuery does not return reliable result for IE - if (IE) { - offsetWidth = Math.max(document.documentElement.offsetWidth, document.body.offsetWidth); - - if (D.width() > offsetWidth) { - width = D.width(); - } - - } else if (D.width() > W.width()) { - width = D.width(); - } - - this.overlay.width(width).height(D.height()); - }, - - // This is where we can manipulate DOM, because later it would cause iframes to reload - onReady : function (opts, obj) { - var overlay = this.overlay; - - $('.fancybox-overlay').stop(true, true); - - if (!overlay) { - this.create(opts); - } - - if (opts.locked && this.fixed && obj.fixed) { - obj.locked = this.overlay.append( obj.wrap ); - obj.fixed = false; - } - - if (opts.showEarly === true) { - this.beforeShow.apply(this, arguments); - } - }, - - beforeShow : function(opts, obj) { - if (obj.locked && !this.el.hasClass('fancybox-lock')) { - if (this.fixPosition !== false) { - $('*:not(object)').filter(function(){ - return ($(this).css('position') === 'fixed' && !$(this).hasClass("fancybox-overlay") && !$(this).hasClass("fancybox-wrap") ); - }).addClass('fancybox-margin'); - } - - this.el.addClass('fancybox-margin'); - - this.scrollV = W.scrollTop(); - this.scrollH = W.scrollLeft(); - - this.el.addClass('fancybox-lock'); - - W.scrollTop( this.scrollV ).scrollLeft( this.scrollH ); - } - - this.open(opts); - }, - - onUpdate : function() { - if (!this.fixed) { - this.update(); - } - }, - - afterClose: function (opts) { - // Remove overlay if exists and fancyBox is not opening - // (e.g., it is not being open using afterClose callback) - if (this.overlay && !F.coming) { - this.overlay.fadeOut(opts.speedOut, $.proxy( this.close, this )); - } - } - }; - - /* - * Title helper - */ - - F.helpers.title = { - defaults : { - type : 'float', // 'float', 'inside', 'outside' or 'over', - position : 'bottom' // 'top' or 'bottom' - }, - - beforeShow: function (opts) { - var current = F.current, - text = current.title, - type = opts.type, - title, - target; - - if ($.isFunction(text)) { - text = text.call(current.element, current); - } - - if (!isString(text) || $.trim(text) === '') { - return; - } - - title = $('
    ' + text + '
    '); - - switch (type) { - case 'inside': - target = F.skin; - break; - - case 'outside': - target = F.wrap; - break; - - case 'over': - target = F.inner; - break; - - default: // 'float' - target = F.skin; - - title.appendTo('body'); - - if (IE) { - title.width( title.width() ); - } - - title.wrapInner(''); - - //Increase bottom margin so this title will also fit into viewport - F.current.margin[2] += Math.abs( getScalar(title.css('margin-bottom')) ); - break; - } - - title[ (opts.position === 'top' ? 'prependTo' : 'appendTo') ](target); - } - }; - - // jQuery plugin initialization - $.fn.fancybox = function (options) { - var index, - that = $(this), - selector = this.selector || '', - run = function(e) { - var what = $(this).blur(), idx = index, relType, relVal; - - if (!(e.ctrlKey || e.altKey || e.shiftKey || e.metaKey) && !what.is('.fancybox-wrap')) { - relType = options.groupAttr || 'data-fancybox-group'; - relVal = what.attr(relType); - - if (!relVal) { - relType = 'rel'; - relVal = what.get(0)[ relType ]; - } - - if (relVal && relVal !== '' && relVal !== 'nofollow') { - what = selector.length ? $(selector) : that; - what = what.filter('[' + relType + '="' + relVal + '"]'); - idx = what.index(this); - } - - options.index = idx; - - // Stop an event from bubbling if everything is fine - if (F.open(what, options) !== false) { - e.preventDefault(); - } - } - }; - - options = options || {}; - index = options.index || 0; - - if (!selector || options.live === false) { - that.unbind('click.fb-start').bind('click.fb-start', run); - - } else { - D.undelegate(selector, 'click.fb-start').delegate(selector + ":not('.fancybox-item, .fancybox-nav')", 'click.fb-start', run); - } - - this.filter('[data-fancybox-start=1]').trigger('click'); - - return this; - }; - - // Tests that need a body at doc ready - D.ready(function() { - var w1, w2; - - if ( $.scrollbarWidth === undefined ) { - // http://benalman.com/projects/jquery-misc-plugins/#scrollbarwidth - $.scrollbarWidth = function() { - var parent = $('
    ').appendTo('body'), - child = parent.children(), - width = child.innerWidth() - child.height( 99 ).innerWidth(); - - parent.remove(); - - return width; - }; - } - - if ( $.support.fixedPosition === undefined ) { - $.support.fixedPosition = (function() { - var elem = $('
    ').appendTo('body'), - fixed = ( elem[0].offsetTop === 20 || elem[0].offsetTop === 15 ); - - elem.remove(); - - return fixed; - }()); - } - - $.extend(F.defaults, { - scrollbarWidth : $.scrollbarWidth(), - fixed : $.support.fixedPosition, - parent : $('body') - }); - - //Get real width of page scroll-bar - w1 = $(window).width(); - - H.addClass('fancybox-lock-test'); - - w2 = $(window).width(); - - H.removeClass('fancybox-lock-test'); - - $("").appendTo("head"); - }); - -}(window, document, jQuery)); diff --git a/modules/fancybox/source/jquery.fancybox.pack.js b/modules/fancybox/source/jquery.fancybox.pack.js deleted file mode 100755 index 2db12808..00000000 --- a/modules/fancybox/source/jquery.fancybox.pack.js +++ /dev/null @@ -1,46 +0,0 @@ -/*! fancyBox v2.1.5 fancyapps.com | fancyapps.com/fancybox/#license */ -(function(s,H,f,w){var K=f("html"),q=f(s),p=f(H),b=f.fancybox=function(){b.open.apply(this,arguments)},J=navigator.userAgent.match(/msie/i),C=null,t=H.createTouch!==w,u=function(a){return a&&a.hasOwnProperty&&a instanceof f},r=function(a){return a&&"string"===f.type(a)},F=function(a){return r(a)&&0
    ',image:'',iframe:'",error:'

    The requested content cannot be loaded.
    Please try again later.

    ',closeBtn:'',next:'',prev:''},openEffect:"fade",openSpeed:250,openEasing:"swing",openOpacity:!0, -openMethod:"zoomIn",closeEffect:"fade",closeSpeed:250,closeEasing:"swing",closeOpacity:!0,closeMethod:"zoomOut",nextEffect:"elastic",nextSpeed:250,nextEasing:"swing",nextMethod:"changeIn",prevEffect:"elastic",prevSpeed:250,prevEasing:"swing",prevMethod:"changeOut",helpers:{overlay:!0,title:!0},onCancel:f.noop,beforeLoad:f.noop,afterLoad:f.noop,beforeShow:f.noop,afterShow:f.noop,beforeChange:f.noop,beforeClose:f.noop,afterClose:f.noop},group:{},opts:{},previous:null,coming:null,current:null,isActive:!1, -isOpen:!1,isOpened:!1,wrap:null,skin:null,outer:null,inner:null,player:{timer:null,isActive:!1},ajaxLoad:null,imgPreload:null,transitions:{},helpers:{},open:function(a,d){if(a&&(f.isPlainObject(d)||(d={}),!1!==b.close(!0)))return f.isArray(a)||(a=u(a)?f(a).get():[a]),f.each(a,function(e,c){var l={},g,h,k,n,m;"object"===f.type(c)&&(c.nodeType&&(c=f(c)),u(c)?(l={href:c.data("fancybox-href")||c.attr("href"),title:f("
    ").text(c.data("fancybox-title")||c.attr("title")).html(),isDom:!0,element:c}, -f.metadata&&f.extend(!0,l,c.metadata())):l=c);g=d.href||l.href||(r(c)?c:null);h=d.title!==w?d.title:l.title||"";n=(k=d.content||l.content)?"html":d.type||l.type;!n&&l.isDom&&(n=c.data("fancybox-type"),n||(n=(n=c.prop("class").match(/fancybox\.(\w+)/))?n[1]:null));r(g)&&(n||(b.isImage(g)?n="image":b.isSWF(g)?n="swf":"#"===g.charAt(0)?n="inline":r(c)&&(n="html",k=c)),"ajax"===n&&(m=g.split(/\s+/,2),g=m.shift(),m=m.shift()));k||("inline"===n?g?k=f(r(g)?g.replace(/.*(?=#[^\s]+$)/,""):g):l.isDom&&(k=c): -"html"===n?k=g:n||g||!l.isDom||(n="inline",k=c));f.extend(l,{href:g,type:n,content:k,title:h,selector:m});a[e]=l}),b.opts=f.extend(!0,{},b.defaults,d),d.keys!==w&&(b.opts.keys=d.keys?f.extend({},b.defaults.keys,d.keys):!1),b.group=a,b._start(b.opts.index)},cancel:function(){var a=b.coming;a&&!1===b.trigger("onCancel")||(b.hideLoading(),a&&(b.ajaxLoad&&b.ajaxLoad.abort(),b.ajaxLoad=null,b.imgPreload&&(b.imgPreload.onload=b.imgPreload.onerror=null),a.wrap&&a.wrap.stop(!0,!0).trigger("onReset").remove(), -b.coming=null,b.current||b._afterZoomOut(a)))},close:function(a){b.cancel();!1!==b.trigger("beforeClose")&&(b.unbindEvents(),b.isActive&&(b.isOpen&&!0!==a?(b.isOpen=b.isOpened=!1,b.isClosing=!0,f(".fancybox-item, .fancybox-nav").remove(),b.wrap.stop(!0,!0).removeClass("fancybox-opened"),b.transitions[b.current.closeMethod]()):(f(".fancybox-wrap").stop(!0).trigger("onReset").remove(),b._afterZoomOut())))},play:function(a){var d=function(){clearTimeout(b.player.timer)},e=function(){d();b.current&&b.player.isActive&& -(b.player.timer=setTimeout(b.next,b.current.playSpeed))},c=function(){d();p.unbind(".player");b.player.isActive=!1;b.trigger("onPlayEnd")};!0===a||!b.player.isActive&&!1!==a?b.current&&(b.current.loop||b.current.index=c.index?"next":"prev"],b.router=e||"jumpto",c.loop&&(0>a&&(a=c.group.length+a%c.group.length),a%=c.group.length),c.group[a]!==w&&(b.cancel(),b._start(a)))},reposition:function(a,d){var e=b.current,c=e?e.wrap:null,l;c&&(l=b._getPosition(d),a&&"scroll"===a.type?(delete l.position,c.stop(!0,!0).animate(l,200)):(c.css(l),e.pos=f.extend({},e.dim,l)))}, -update:function(a){var d=a&&a.originalEvent&&a.originalEvent.type,e=!d||"orientationchange"===d;e&&(clearTimeout(C),C=null);b.isOpen&&!C&&(C=setTimeout(function(){var c=b.current;c&&!b.isClosing&&(b.wrap.removeClass("fancybox-tmp"),(e||"load"===d||"resize"===d&&c.autoResize)&&b._setDimension(),"scroll"===d&&c.canShrink||b.reposition(a),b.trigger("onUpdate"),C=null)},e&&!t?0:300))},toggle:function(a){b.isOpen&&(b.current.fitToView="boolean"===f.type(a)?a:!b.current.fitToView,t&&(b.wrap.removeAttr("style").addClass("fancybox-tmp"), -b.trigger("onUpdate")),b.update())},hideLoading:function(){p.unbind(".loading");f("#fancybox-loading").remove()},showLoading:function(){var a,d;b.hideLoading();a=f('
    ').click(b.cancel).appendTo("body");p.bind("keydown.loading",function(a){27===(a.which||a.keyCode)&&(a.preventDefault(),b.cancel())});b.defaults.fixed||(d=b.getViewport(),a.css({position:"absolute",top:0.5*d.h+d.y,left:0.5*d.w+d.x}));b.trigger("onLoading")},getViewport:function(){var a=b.current&& -b.current.locked||!1,d={x:q.scrollLeft(),y:q.scrollTop()};a&&a.length?(d.w=a[0].clientWidth,d.h=a[0].clientHeight):(d.w=t&&s.innerWidth?s.innerWidth:q.width(),d.h=t&&s.innerHeight?s.innerHeight:q.height());return d},unbindEvents:function(){b.wrap&&u(b.wrap)&&b.wrap.unbind(".fb");p.unbind(".fb");q.unbind(".fb")},bindEvents:function(){var a=b.current,d;a&&(q.bind("orientationchange.fb"+(t?"":" resize.fb")+(a.autoCenter&&!a.locked?" scroll.fb":""),b.update),(d=a.keys)&&p.bind("keydown.fb",function(e){var c= -e.which||e.keyCode,l=e.target||e.srcElement;if(27===c&&b.coming)return!1;e.ctrlKey||e.altKey||e.shiftKey||e.metaKey||l&&(l.type||f(l).is("[contenteditable]"))||f.each(d,function(d,l){if(1h[0].clientWidth||h[0].clientHeight&&h[0].scrollHeight>h[0].clientHeight),h=f(h).parent();0!==c&&!k&&1g||0>l)&&b.next(0>g?"up":"right"),d.preventDefault())}))},trigger:function(a,d){var e,c=d||b.coming||b.current;if(c){f.isFunction(c[a])&&(e=c[a].apply(c,Array.prototype.slice.call(arguments,1)));if(!1===e)return!1;c.helpers&&f.each(c.helpers,function(d,e){if(e&& -b.helpers[d]&&f.isFunction(b.helpers[d][a]))b.helpers[d][a](f.extend(!0,{},b.helpers[d].defaults,e),c)})}p.trigger(a)},isImage:function(a){return r(a)&&a.match(/(^data:image\/.*,)|(\.(jp(e|g|eg)|gif|png|bmp|webp|svg)((\?|#).*)?$)/i)},isSWF:function(a){return r(a)&&a.match(/\.(swf)((\?|#).*)?$/i)},_start:function(a){var d={},e,c;a=m(a);e=b.group[a]||null;if(!e)return!1;d=f.extend(!0,{},b.opts,e);e=d.margin;c=d.padding;"number"===f.type(e)&&(d.margin=[e,e,e,e]);"number"===f.type(c)&&(d.padding=[c,c, -c,c]);d.modal&&f.extend(!0,d,{closeBtn:!1,closeClick:!1,nextClick:!1,arrows:!1,mouseWheel:!1,keys:null,helpers:{overlay:{closeClick:!1}}});d.autoSize&&(d.autoWidth=d.autoHeight=!0);"auto"===d.width&&(d.autoWidth=!0);"auto"===d.height&&(d.autoHeight=!0);d.group=b.group;d.index=a;b.coming=d;if(!1===b.trigger("beforeLoad"))b.coming=null;else{c=d.type;e=d.href;if(!c)return b.coming=null,b.current&&b.router&&"jumpto"!==b.router?(b.current.index=a,b[b.router](b.direction)):!1;b.isActive=!0;if("image"=== -c||"swf"===c)d.autoHeight=d.autoWidth=!1,d.scrolling="visible";"image"===c&&(d.aspectRatio=!0);"iframe"===c&&t&&(d.scrolling="scroll");d.wrap=f(d.tpl.wrap).addClass("fancybox-"+(t?"mobile":"desktop")+" fancybox-type-"+c+" fancybox-tmp "+d.wrapCSS).appendTo(d.parent||"body");f.extend(d,{skin:f(".fancybox-skin",d.wrap),outer:f(".fancybox-outer",d.wrap),inner:f(".fancybox-inner",d.wrap)});f.each(["Top","Right","Bottom","Left"],function(a,b){d.skin.css("padding"+b,x(d.padding[a]))});b.trigger("onReady"); -if("inline"===c||"html"===c){if(!d.content||!d.content.length)return b._error("content")}else if(!e)return b._error("href");"image"===c?b._loadImage():"ajax"===c?b._loadAjax():"iframe"===c?b._loadIframe():b._afterLoad()}},_error:function(a){f.extend(b.coming,{type:"html",autoWidth:!0,autoHeight:!0,minWidth:0,minHeight:0,scrolling:"no",hasError:a,content:b.coming.tpl.error});b._afterLoad()},_loadImage:function(){var a=b.imgPreload=new Image;a.onload=function(){this.onload=this.onerror=null;b.coming.width= -this.width/b.opts.pixelRatio;b.coming.height=this.height/b.opts.pixelRatio;b._afterLoad()};a.onerror=function(){this.onload=this.onerror=null;b._error("image")};a.src=b.coming.href;!0!==a.complete&&b.showLoading()},_loadAjax:function(){var a=b.coming;b.showLoading();b.ajaxLoad=f.ajax(f.extend({},a.ajax,{url:a.href,error:function(a,e){b.coming&&"abort"!==e?b._error("ajax",a):b.hideLoading()},success:function(d,e){"success"===e&&(a.content=d,b._afterLoad())}}))},_loadIframe:function(){var a=b.coming, -d=f(a.tpl.iframe.replace(/\{rnd\}/g,(new Date).getTime())).attr("scrolling",t?"auto":a.iframe.scrolling).attr("src",a.href);f(a.wrap).bind("onReset",function(){try{f(this).find("iframe").hide().attr("src","//about:blank").end().empty()}catch(a){}});a.iframe.preload&&(b.showLoading(),d.one("load",function(){f(this).data("ready",1);t||f(this).bind("load.fb",b.update);f(this).parents(".fancybox-wrap").width("100%").removeClass("fancybox-tmp").show();b._afterLoad()}));a.content=d.appendTo(a.inner);a.iframe.preload|| -b._afterLoad()},_preloadImages:function(){var a=b.group,d=b.current,e=a.length,c=d.preload?Math.min(d.preload,e-1):0,f,g;for(g=1;g<=c;g+=1)f=a[(d.index+g)%e],"image"===f.type&&f.href&&((new Image).src=f.href)},_afterLoad:function(){var a=b.coming,d=b.current,e,c,l,g,h;b.hideLoading();if(a&&!1!==b.isActive)if(!1===b.trigger("afterLoad",a,d))a.wrap.stop(!0).trigger("onReset").remove(),b.coming=null;else{d&&(b.trigger("beforeChange",d),d.wrap.stop(!0).removeClass("fancybox-opened").find(".fancybox-item, .fancybox-nav").remove()); -b.unbindEvents();e=a.content;c=a.type;l=a.scrolling;f.extend(b,{wrap:a.wrap,skin:a.skin,outer:a.outer,inner:a.inner,current:a,previous:d});g=a.href;switch(c){case "inline":case "ajax":case "html":a.selector?e=f("
    ").html(e).find(a.selector):u(e)&&(e.data("fancybox-placeholder")||e.data("fancybox-placeholder",f('
    ').insertAfter(e).hide()),e=e.show().detach(),a.wrap.bind("onReset",function(){f(this).find(e).length&&e.hide().replaceAll(e.data("fancybox-placeholder")).data("fancybox-placeholder", -!1)}));break;case "image":e=a.tpl.image.replace(/\{href\}/g,g);break;case "swf":e='',h="",f.each(a.swf,function(a,b){e+='';h+=" "+a+'="'+b+'"'}),e+='"}u(e)&&e.parent().is(a.inner)||a.inner.append(e);b.trigger("beforeShow"); -a.inner.css("overflow","yes"===l?"scroll":"no"===l?"hidden":l);b._setDimension();b.reposition();b.isOpen=!1;b.coming=null;b.bindEvents();if(!b.isOpened)f(".fancybox-wrap").not(a.wrap).stop(!0).trigger("onReset").remove();else if(d.prevMethod)b.transitions[d.prevMethod]();b.transitions[b.isOpened?a.nextMethod:a.openMethod]();b._preloadImages()}},_setDimension:function(){var a=b.getViewport(),d=0,e=!1,c=!1,e=b.wrap,l=b.skin,g=b.inner,h=b.current,c=h.width,k=h.height,n=h.minWidth,v=h.minHeight,p=h.maxWidth, -q=h.maxHeight,t=h.scrolling,r=h.scrollOutside?h.scrollbarWidth:0,y=h.margin,z=m(y[1]+y[3]),s=m(y[0]+y[2]),w,A,u,D,B,G,C,E,I;e.add(l).add(g).width("auto").height("auto").removeClass("fancybox-tmp");y=m(l.outerWidth(!0)-l.width());w=m(l.outerHeight(!0)-l.height());A=z+y;u=s+w;D=F(c)?(a.w-A)*m(c)/100:c;B=F(k)?(a.h-u)*m(k)/100:k;if("iframe"===h.type){if(I=h.content,h.autoHeight&&1===I.data("ready"))try{I[0].contentWindow.document.location&&(g.width(D).height(9999),G=I.contents().find("body"),r&&G.css("overflow-x", -"hidden"),B=G.outerHeight(!0))}catch(H){}}else if(h.autoWidth||h.autoHeight)g.addClass("fancybox-tmp"),h.autoWidth||g.width(D),h.autoHeight||g.height(B),h.autoWidth&&(D=g.width()),h.autoHeight&&(B=g.height()),g.removeClass("fancybox-tmp");c=m(D);k=m(B);E=D/B;n=m(F(n)?m(n,"w")-A:n);p=m(F(p)?m(p,"w")-A:p);v=m(F(v)?m(v,"h")-u:v);q=m(F(q)?m(q,"h")-u:q);G=p;C=q;h.fitToView&&(p=Math.min(a.w-A,p),q=Math.min(a.h-u,q));A=a.w-z;s=a.h-s;h.aspectRatio?(c>p&&(c=p,k=m(c/E)),k>q&&(k=q,c=m(k*E)),cA||z>s)&&c>n&&k>v&&!(19p&&(c=p,k=m(c/E)),g.width(c).height(k),e.width(c+y),a=e.width(),z=e.height();else c=Math.max(n,Math.min(c,c-(a-A))),k=Math.max(v,Math.min(k,k-(z-s)));r&&"auto"===t&&kA||z>s)&&c>n&&k>v;c=h.aspectRatio?cv&&k
    ').appendTo(d&&d.lenth?d:"body");this.fixed=!1;a.fixed&&b.defaults.fixed&&(this.overlay.addClass("fancybox-overlay-fixed"),this.fixed=!0)},open:function(a){var d=this;a=f.extend({},this.defaults,a);this.overlay?this.overlay.unbind(".overlay").width("auto").height("auto"):this.create(a);this.fixed||(q.bind("resize.overlay",f.proxy(this.update,this)),this.update());a.closeClick&&this.overlay.bind("click.overlay", -function(a){if(f(a.target).hasClass("fancybox-overlay"))return b.isActive?b.close():d.close(),!1});this.overlay.css(a.css).show()},close:function(){q.unbind("resize.overlay");this.el.hasClass("fancybox-lock")&&(f(".fancybox-margin").removeClass("fancybox-margin"),this.el.removeClass("fancybox-lock"),q.scrollTop(this.scrollV).scrollLeft(this.scrollH));f(".fancybox-overlay").remove().hide();f.extend(this,{overlay:null,fixed:!1})},update:function(){var a="100%",b;this.overlay.width(a).height("100%"); -J?(b=Math.max(H.documentElement.offsetWidth,H.body.offsetWidth),p.width()>b&&(a=p.width())):p.width()>q.width()&&(a=p.width());this.overlay.width(a).height(p.height())},onReady:function(a,b){var e=this.overlay;f(".fancybox-overlay").stop(!0,!0);e||this.create(a);a.locked&&this.fixed&&b.fixed&&(b.locked=this.overlay.append(b.wrap),b.fixed=!1);!0===a.showEarly&&this.beforeShow.apply(this,arguments)},beforeShow:function(a,b){b.locked&&!this.el.hasClass("fancybox-lock")&&(!1!==this.fixPosition&&f("*").filter(function(){return"fixed"=== -f(this).css("position")&&!f(this).hasClass("fancybox-overlay")&&!f(this).hasClass("fancybox-wrap")}).addClass("fancybox-margin"),this.el.addClass("fancybox-margin"),this.scrollV=q.scrollTop(),this.scrollH=q.scrollLeft(),this.el.addClass("fancybox-lock"),q.scrollTop(this.scrollV).scrollLeft(this.scrollH));this.open(a)},onUpdate:function(){this.fixed||this.update()},afterClose:function(a){this.overlay&&!b.coming&&this.overlay.fadeOut(a.speedOut,f.proxy(this.close,this))}};b.helpers.title={defaults:{type:"float", -position:"bottom"},beforeShow:function(a){var d=b.current,e=d.title,c=a.type;f.isFunction(e)&&(e=e.call(d.element,d));if(r(e)&&""!==f.trim(e)){d=f('
    '+e+"
    ");switch(c){case "inside":c=b.skin;break;case "outside":c=b.wrap;break;case "over":c=b.inner;break;default:c=b.skin,d.appendTo("body"),J&&d.width(d.width()),d.wrapInner(''),b.current.margin[2]+=Math.abs(m(d.css("margin-bottom")))}d["top"===a.position?"prependTo": -"appendTo"](c)}}};f.fn.fancybox=function(a){var d,e=f(this),c=this.selector||"",l=function(g){var h=f(this).blur(),k=d,l,m;g.ctrlKey||g.altKey||g.shiftKey||g.metaKey||h.is(".fancybox-wrap")||(l=a.groupAttr||"data-fancybox-group",m=h.attr(l),m||(l="rel",m=h.get(0)[l]),m&&""!==m&&"nofollow"!==m&&(h=c.length?f(c):e,h=h.filter("["+l+'="'+m+'"]'),k=h.index(this)),a.index=k,!1!==b.open(h,a)&&g.preventDefault())};a=a||{};d=a.index||0;c&&!1!==a.live?p.undelegate(c,"click.fb-start").delegate(c+":not('.fancybox-item, .fancybox-nav')", -"click.fb-start",l):e.unbind("click.fb-start").bind("click.fb-start",l);this.filter("[data-fancybox-start=1]").trigger("click");return this};p.ready(function(){var a,d;f.scrollbarWidth===w&&(f.scrollbarWidth=function(){var a=f('
    ').appendTo("body"),b=a.children(),b=b.innerWidth()-b.height(99).innerWidth();a.remove();return b});f.support.fixedPosition===w&&(f.support.fixedPosition=function(){var a=f('
    ').appendTo("body"), -b=20===a[0].offsetTop||15===a[0].offsetTop;a.remove();return b}());f.extend(b.defaults,{scrollbarWidth:f.scrollbarWidth(),fixed:f.support.fixedPosition,parent:f("body")});a=f(s).width();K.addClass("fancybox-lock-test");d=f(s).width();K.removeClass("fancybox-lock-test");f("").appendTo("head")})})(window,document,jQuery); \ No newline at end of file diff --git a/modules/findit/.bower.json b/modules/findit/.bower.json deleted file mode 100644 index 6b112de6..00000000 --- a/modules/findit/.bower.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "name": "findit", - "homepage": "https://github.com/coderaiser/domfs-findit", - "authors": [ - "coderaiser " - ], - "description": "Walk a directory tree in DOM File System", - "main": "lib/findit.js", - "moduleType": [ - "globals", - "node" - ], - "keywords": [ - "findit", - "DOM", - "File System" - ], - "license": "MIT", - "ignore": [ - "**/.*", - "node_modules", - "modules" - ], - "dependencies": { - "emitify": "^3.0.1" - }, - "version": "1.1.7", - "_release": "1.1.7", - "_resolution": { - "type": "version", - "tag": "v1.1.7", - "commit": "f30860d8ab233f2dfea1ffe45710d5cfa9d7b797" - }, - "_source": "https://github.com/coderaiser/domfs-findit.git", - "_target": "1.1.7", - "_originalSource": "findit" -} \ No newline at end of file diff --git a/modules/findit/ChangeLog b/modules/findit/ChangeLog deleted file mode 100644 index afb102a0..00000000 --- a/modules/findit/ChangeLog +++ /dev/null @@ -1,69 +0,0 @@ -2017.04.28, v1.1.7 - -feature: -- (bower) emitify v3.0.1 - - -2016.07.14, v1.1.6 - -feature: -- (emitify) v2.1.1 - - -2016.06.03, v1.1.5 - -feature: -- (bower) emitify v2.1.0 - - -2015.12.29, v1.1.4 - -feature: -- (bower) emitify v2.0.0 - - -2015.09.30, v1.1.3 - -feature: -- (bower) emitify v1.3.0 - - -2015.07.16, v1.1.2 - -fix: -- (findit) find -> self._find - - -2015.07.15, v1.1.1 - -fix: -- (dindit) enry -> entry - -feature: -- (package) main: domfs-findit -> findit - - -2015.07.14, v1.1.0 - -fix: -- (findit) dirs, first could be overwriting - - -2015.07.14, v1.0.3 - -fix: -- (findit) no end when entry file - - -2015.07.14, v1.0.2 - -fix: -- (findit) dirs could be more then 0 - - -2015.07.13, v1.0.1 - -fix: -- (findit) return -- (example) add () - diff --git a/modules/findit/LICENSE b/modules/findit/LICENSE deleted file mode 100644 index a103b669..00000000 --- a/modules/findit/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2015 coderaiser - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/modules/findit/README.md b/modules/findit/README.md deleted file mode 100644 index 88adde9e..00000000 --- a/modules/findit/README.md +++ /dev/null @@ -1,55 +0,0 @@ -# DOM File System Findit - -Similar to [node-findit](https://github.com/substack/node-findit "Node Findit") but for [Dom File System](https://developer.mozilla.org/en-US/docs/Web/API/FileSystem "Dom File System"). - -## Install - -``` -bower i findit --save -``` - -## How to use? - -Add `findit.js` and [emitify](https://github.com/coderaiser/emitify "Emitify"). -Or any other node-compitable [EventEmitter](https://iojs.org/api/events.html "Events") (set `window.Emitify = your_emitter` before using `findit`). - -```html - - -``` - -```js -var node = window; - -node.addEventListener('drop', function (e) { - var entry, - finder, - item = e.dataTransfer.items[0]; - - e.preventDefault(); - - entry = item.webkitGetAsEntry(); - - finder = findit(entry); - - finder.on('file', function(file, entry) { - console.log('file: ', file, entry); - }); - - finder.on('directory', function(file, entry) { - console.log('directory: ', file, entry); - }) - - finder.on('end', function() { - console.log('done'); - }) -}); - -node.addEventListener('dragover', function (e) { - e.preventDefault(); -}); -``` - -## License - -MIT diff --git a/modules/findit/bower.json b/modules/findit/bower.json deleted file mode 100644 index 97662f61..00000000 --- a/modules/findit/bower.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "name": "findit", - "homepage": "https://github.com/coderaiser/domfs-findit", - "authors": [ - "coderaiser " - ], - "description": "Walk a directory tree in DOM File System", - "main": "lib/findit.js", - "moduleType": [ - "globals", - "node" - ], - "keywords": [ - "findit", - "DOM", - "File System" - ], - "license": "MIT", - "ignore": [ - "**/.*", - "node_modules", - "modules" - ], - "dependencies": { - "emitify": "^3.0.1" - } -} diff --git a/modules/findit/example/index.html b/modules/findit/example/index.html deleted file mode 100644 index 458b14ae..00000000 --- a/modules/findit/example/index.html +++ /dev/null @@ -1,39 +0,0 @@ - - - - - diff --git a/modules/findit/lib/findit.js b/modules/findit/lib/findit.js deleted file mode 100644 index 11e14340..00000000 --- a/modules/findit/lib/findit.js +++ /dev/null @@ -1,60 +0,0 @@ -/* global Emitify */ - -(function(global) { - 'use strict'; - - if (typeof module !== 'undefined' && module.exports) - module.exports = findit; - else - global.findit = findit; - - function findit(entry) { - var emitter = Emitify(); - - setTimeout(function() { - FindIt(emitter, entry); - }, 0); - - return emitter; - } - - function FindIt(emitter, entry) { - if (!(this instanceof FindIt)) - return new FindIt(emitter, entry); - - this._dirs = 0; - this._first = true; - - this._find(emitter, entry); - } - - FindIt.prototype._find = function(emitter, entry) { - var self = this; - - if (entry.isFile) { - emitter.emit('file', entry.fullPath, entry); - - if (self._first) - emitter.emit('end'); - } else { - if (self._first) - self._first = false; - - emitter.emit('directory', entry.fullPath, entry); - - ++self._dirs; - - entry.createReader() - .readEntries(function(entries) { - [].forEach.call(entries, function(entry) { - self._find(emitter, entry); - }); - - --self._dirs; - - if (!self._dirs) - emitter.emit('end'); - }); - } - }; -})(this); diff --git a/modules/findit/package.json b/modules/findit/package.json deleted file mode 100644 index b3efc462..00000000 --- a/modules/findit/package.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "name": "findit", - "private": true, - "version": "1.1.7", - "description": "Walk a directory tree in DOM File System", - "main": "lib/findit.js", - "dependencies": {}, - "devDependencies": {}, - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" - }, - "repository": { - "type": "git", - "url": "git://github.com/coderaiser/domfs-findit.git" - }, - "keywords": [ - "findit", - "DOM", - "File System" - ], - "author": "coderaiser (http://coderaiser.github.io/)", - "license": "MIT", - "bugs": { - "url": "https://github.com/coderaiser/domfs-findit/issues" - }, - "homepage": "https://github.com/coderaiser/domfs-findit" -} diff --git a/modules/jquery/.bower.json b/modules/jquery/.bower.json deleted file mode 100644 index 2767bdbb..00000000 --- a/modules/jquery/.bower.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "name": "jquery", - "main": "dist/jquery.js", - "license": "MIT", - "ignore": [ - "package.json" - ], - "keywords": [ - "jquery", - "javascript", - "browser", - "library" - ], - "homepage": "https://github.com/jquery/jquery-dist", - "version": "3.2.1", - "_release": "3.2.1", - "_resolution": { - "type": "version", - "tag": "3.2.1", - "commit": "77d2a51d0520d2ee44173afdf4e40a9201f5964e" - }, - "_source": "https://github.com/jquery/jquery-dist.git", - "_target": ">=1.10", - "_originalSource": "jquery" -} \ No newline at end of file diff --git a/modules/jquery/AUTHORS.txt b/modules/jquery/AUTHORS.txt deleted file mode 100644 index c32c25f9..00000000 --- a/modules/jquery/AUTHORS.txt +++ /dev/null @@ -1,301 +0,0 @@ -Authors ordered by first contribution. - -John Resig -Gilles van den Hoven -Michael Geary -Stefan Petre -Yehuda Katz -Corey Jewett -Klaus Hartl -Franck Marcia -Jörn Zaefferer -Paul Bakaus -Brandon Aaron -Mike Alsup -Dave Methvin -Ed Engelhardt -Sean Catchpole -Paul Mclanahan -David Serduke -Richard D. Worth -Scott González -Ariel Flesler -Jon Evans -TJ Holowaychuk -Michael Bensoussan -Robert Katić -Louis-Rémi Babé -Earle Castledine -Damian Janowski -Rich Dougherty -Kim Dalsgaard -Andrea Giammarchi -Mark Gibson -Karl Swedberg -Justin Meyer -Ben Alman -James Padolsey -David Petersen -Batiste Bieler -Alexander Farkas -Rick Waldron -Filipe Fortes -Neeraj Singh -Paul Irish -Iraê Carvalho -Matt Curry -Michael Monteleone -Noah Sloan -Tom Viner -Douglas Neiner -Adam J. Sontag -Dave Reed -Ralph Whitbeck -Carl Fürstenberg -Jacob Wright -J. Ryan Stinnett -unknown -temp01 -Heungsub Lee -Colin Snover -Ryan W Tenney -Pinhook -Ron Otten -Jephte Clain -Anton Matzneller -Alex Sexton -Dan Heberden -Henri Wiechers -Russell Holbrook -Julian Aubourg -Gianni Alessandro Chiappetta -Scott Jehl -James Burke -Jonas Pfenniger -Xavi Ramirez -Jared Grippe -Sylvester Keil -Brandon Sterne -Mathias Bynens -Timmy Willison <4timmywil@gmail.com> -Corey Frang -Digitalxero -Anton Kovalyov -David Murdoch -Josh Varner -Charles McNulty -Jordan Boesch -Jess Thrysoee -Michael Murray -Lee Carpenter -Alexis Abril -Rob Morgan -John Firebaugh -Sam Bisbee -Gilmore Davidson -Brian Brennan -Xavier Montillet -Daniel Pihlstrom -Sahab Yazdani -avaly -Scott Hughes -Mike Sherov -Greg Hazel -Schalk Neethling -Denis Knauf -Timo Tijhof -Steen Nielsen -Anton Ryzhov -Shi Chuan -Berker Peksag -Toby Brain -Matt Mueller -Justin -Daniel Herman -Oleg Gaidarenko -Richard Gibson -Rafaël Blais Masson -cmc3cn <59194618@qq.com> -Joe Presbrey -Sindre Sorhus -Arne de Bree -Vladislav Zarakovsky -Andrew E Monat -Oskari -Joao Henrique de Andrade Bruni -tsinha -Matt Farmer -Trey Hunner -Jason Moon -Jeffery To -Kris Borchers -Vladimir Zhuravlev -Jacob Thornton -Chad Killingsworth -Nowres Rafid -David Benjamin -Uri Gilad -Chris Faulkner -Elijah Manor -Daniel Chatfield -Nikita Govorov -Wesley Walser -Mike Pennisi -Markus Staab -Dave Riddle -Callum Macrae -Benjamin Truyman -James Huston -Erick Ruiz de Chávez -David Bonner -Akintayo Akinwunmi -MORGAN -Ismail Khair -Carl Danley -Mike Petrovich -Greg Lavallee -Daniel Gálvez -Sai Lung Wong -Tom H Fuertes -Roland Eckl -Jay Merrifield -Allen J Schmidt Jr -Jonathan Sampson -Marcel Greter -Matthias Jäggli -David Fox -Yiming He -Devin Cooper -Paul Ramos -Rod Vagg -Bennett Sorbo -Sebastian Burkhard -Zachary Adam Kaplan -nanto_vi -nanto -Danil Somsikov -Ryunosuke SATO -Jean Boussier -Adam Coulombe -Andrew Plummer -Mark Raddatz -Isaac Z. Schlueter -Karl Sieburg -Pascal Borreli -Nguyen Phuc Lam -Dmitry Gusev -Michał Gołębiowski -Li Xudong -Steven Benner -Tom H Fuertes -Renato Oliveira dos Santos -ros3cin -Jason Bedard -Kyle Robinson Young -Chris Talkington -Eddie Monge -Terry Jones -Jason Merino -Jeremy Dunck -Chris Price -Guy Bedford -Amey Sakhadeo -Mike Sidorov -Anthony Ryan -Dominik D. Geyer -George Kats -Lihan Li -Ronny Springer -Chris Antaki -Marian Sollmann -njhamann -Ilya Kantor -David Hong -John Paul -Jakob Stoeck -Christopher Jones -Forbes Lindesay -S. Andrew Sheppard -Leonardo Balter -Roman Reiß -Benjy Cui -Rodrigo Rosenfeld Rosas -John Hoven -Philip Jägenstedt -Christian Kosmowski -Liang Peng -TJ VanToll -Senya Pugach -Aurelio De Rosa -Nazar Mokrynskyi -Amit Merchant -Jason Bedard -Arthur Verschaeve -Dan Hart -Bin Xin -David Corbacho -Veaceslav Grimalschi -Daniel Husar -Frederic Hemberger -Ben Toews -Aditya Raghavan -Victor Homyakov -Shivaji Varma -Nicolas HENRY -Anne-Gaelle Colom -George Mauer -Leonardo Braga -Stephen Edgar -Thomas Tortorini -Winston Howes -Jon Hester -Alexander O'Mara -Bastian Buchholz -Arthur Stolyar -Calvin Metcalf -Mu Haibao -Richard McDaniel -Chris Rebert -Gabriel Schulhof -Gilad Peleg -Martin Naumann -Marek Lewandowski -Bruno Pérel -Reed Loden -Daniel Nill -Yongwoo Jeon -Sean Henderson -Richard Kraaijenhagen -Connor Atherton -Gary Ye -Christian Grete -Liza Ramo -Julian Alexander Murillo -Joelle Fleurantin -Jae Sung Park -Jun Sun -Josh Soref -Henry Wong -Jon Dufresne -Martijn W. van der Lee -Devin Wilson -Steve Mao -Zack Hall -Bernhard M. Wiedemann -Todor Prikumov -Jha Naman -William Robinet -Alexander Lisianoi -Vitaliy Terziev -Joe Trumbull -Alexander K -Damian Senn -Ralin Chimev -Felipe Sateler -Christophe Tafani-Dereeper -Manoj Kumar -David Broder-Rodgers -Alex Louden -Alex Padilla -南漂一卒 -karan-96 diff --git a/modules/jquery/LICENSE.txt b/modules/jquery/LICENSE.txt deleted file mode 100644 index e4e5e00e..00000000 --- a/modules/jquery/LICENSE.txt +++ /dev/null @@ -1,36 +0,0 @@ -Copyright JS Foundation and other contributors, https://js.foundation/ - -This software consists of voluntary contributions made by many -individuals. For exact contribution history, see the revision history -available at https://github.com/jquery/jquery - -The following license applies to all parts of this software except as -documented below: - -==== - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -==== - -All files located in the node_modules and external directories are -externally maintained libraries used by this software which have their -own licenses; we recommend you read them, as their terms may differ from -the terms above. diff --git a/modules/jquery/README.md b/modules/jquery/README.md deleted file mode 100644 index 09a4273e..00000000 --- a/modules/jquery/README.md +++ /dev/null @@ -1,67 +0,0 @@ -# jQuery - -> jQuery is a fast, small, and feature-rich JavaScript library. - -For information on how to get started and how to use jQuery, please see [jQuery's documentation](http://api.jquery.com/). -For source files and issues, please visit the [jQuery repo](https://github.com/jquery/jquery). - -If upgrading, please see the [blog post for 3.2.1](https://blog.jquery.com/2017/03/20/jquery-3-2-1-now-available/). This includes notable differences from the previous version and a more readable changelog. - -## Including jQuery - -Below are some of the most common ways to include jQuery. - -### Browser - -#### Script tag - -```html - -``` - -#### Babel - -[Babel](http://babeljs.io/) is a next generation JavaScript compiler. One of the features is the ability to use ES6/ES2015 modules now, even though browsers do not yet support this feature natively. - -```js -import $ from "jquery"; -``` - -#### Browserify/Webpack - -There are several ways to use [Browserify](http://browserify.org/) and [Webpack](https://webpack.github.io/). For more information on using these tools, please refer to the corresponding project's documention. In the script, including jQuery will usually look like this... - -```js -var $ = require("jquery"); -``` - -#### AMD (Asynchronous Module Definition) - -AMD is a module format built for the browser. For more information, we recommend [require.js' documentation](http://requirejs.org/docs/whyamd.html). - -```js -define(["jquery"], function($) { - -}); -``` - -### Node - -To include jQuery in [Node](nodejs.org), first install with npm. - -```sh -npm install jquery -``` - -For jQuery to work in Node, a window with a document is required. Since no such window exists natively in Node, one can be mocked by tools such as [jsdom](https://github.com/tmpvar/jsdom). This can be useful for testing purposes. - -```js -require("jsdom").env("", function(err, window) { - if (err) { - console.error(err); - return; - } - - var $ = require("jquery")(window); -}); -``` diff --git a/modules/jquery/bower.json b/modules/jquery/bower.json deleted file mode 100644 index 95798d5a..00000000 --- a/modules/jquery/bower.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "name": "jquery", - "main": "dist/jquery.js", - "license": "MIT", - "ignore": [ - "package.json" - ], - "keywords": [ - "jquery", - "javascript", - "browser", - "library" - ] -} \ No newline at end of file diff --git a/modules/jquery/dist/jquery.min.js b/modules/jquery/dist/jquery.min.js deleted file mode 100644 index 644d35e2..00000000 --- a/modules/jquery/dist/jquery.min.js +++ /dev/null @@ -1,4 +0,0 @@ -/*! jQuery v3.2.1 | (c) JS Foundation and other contributors | jquery.org/license */ -!function(a,b){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){"use strict";var c=[],d=a.document,e=Object.getPrototypeOf,f=c.slice,g=c.concat,h=c.push,i=c.indexOf,j={},k=j.toString,l=j.hasOwnProperty,m=l.toString,n=m.call(Object),o={};function p(a,b){b=b||d;var c=b.createElement("script");c.text=a,b.head.appendChild(c).parentNode.removeChild(c)}var q="3.2.1",r=function(a,b){return new r.fn.init(a,b)},s=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,t=/^-ms-/,u=/-([a-z])/g,v=function(a,b){return b.toUpperCase()};r.fn=r.prototype={jquery:q,constructor:r,length:0,toArray:function(){return f.call(this)},get:function(a){return null==a?f.call(this):a<0?this[a+this.length]:this[a]},pushStack:function(a){var b=r.merge(this.constructor(),a);return b.prevObject=this,b},each:function(a){return r.each(this,a)},map:function(a){return this.pushStack(r.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(f.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(a<0?b:0);return this.pushStack(c>=0&&c0&&b-1 in a)}var x=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u="sizzle"+1*new Date,v=a.document,w=0,x=0,y=ha(),z=ha(),A=ha(),B=function(a,b){return a===b&&(l=!0),0},C={}.hasOwnProperty,D=[],E=D.pop,F=D.push,G=D.push,H=D.slice,I=function(a,b){for(var c=0,d=a.length;c+~]|"+K+")"+K+"*"),S=new RegExp("="+K+"*([^\\]'\"]*?)"+K+"*\\]","g"),T=new RegExp(N),U=new RegExp("^"+L+"$"),V={ID:new RegExp("^#("+L+")"),CLASS:new RegExp("^\\.("+L+")"),TAG:new RegExp("^("+L+"|[*])"),ATTR:new RegExp("^"+M),PSEUDO:new RegExp("^"+N),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+K+"*(even|odd|(([+-]|)(\\d*)n|)"+K+"*(?:([+-]|)"+K+"*(\\d+)|))"+K+"*\\)|)","i"),bool:new RegExp("^(?:"+J+")$","i"),needsContext:new RegExp("^"+K+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+K+"*((?:-\\d)?\\d*)"+K+"*\\)|)(?=[^-]|$)","i")},W=/^(?:input|select|textarea|button)$/i,X=/^h\d$/i,Y=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,$=/[+~]/,_=new RegExp("\\\\([\\da-f]{1,6}"+K+"?|("+K+")|.)","ig"),aa=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:d<0?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)},ba=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ca=function(a,b){return b?"\0"===a?"\ufffd":a.slice(0,-1)+"\\"+a.charCodeAt(a.length-1).toString(16)+" ":"\\"+a},da=function(){m()},ea=ta(function(a){return a.disabled===!0&&("form"in a||"label"in a)},{dir:"parentNode",next:"legend"});try{G.apply(D=H.call(v.childNodes),v.childNodes),D[v.childNodes.length].nodeType}catch(fa){G={apply:D.length?function(a,b){F.apply(a,H.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function ga(a,b,d,e){var f,h,j,k,l,o,r,s=b&&b.ownerDocument,w=b?b.nodeType:9;if(d=d||[],"string"!=typeof a||!a||1!==w&&9!==w&&11!==w)return d;if(!e&&((b?b.ownerDocument||b:v)!==n&&m(b),b=b||n,p)){if(11!==w&&(l=Z.exec(a)))if(f=l[1]){if(9===w){if(!(j=b.getElementById(f)))return d;if(j.id===f)return d.push(j),d}else if(s&&(j=s.getElementById(f))&&t(b,j)&&j.id===f)return d.push(j),d}else{if(l[2])return G.apply(d,b.getElementsByTagName(a)),d;if((f=l[3])&&c.getElementsByClassName&&b.getElementsByClassName)return G.apply(d,b.getElementsByClassName(f)),d}if(c.qsa&&!A[a+" "]&&(!q||!q.test(a))){if(1!==w)s=b,r=a;else if("object"!==b.nodeName.toLowerCase()){(k=b.getAttribute("id"))?k=k.replace(ba,ca):b.setAttribute("id",k=u),o=g(a),h=o.length;while(h--)o[h]="#"+k+" "+sa(o[h]);r=o.join(","),s=$.test(a)&&qa(b.parentNode)||b}if(r)try{return G.apply(d,s.querySelectorAll(r)),d}catch(x){}finally{k===u&&b.removeAttribute("id")}}}return i(a.replace(P,"$1"),b,d,e)}function ha(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function ia(a){return a[u]=!0,a}function ja(a){var b=n.createElement("fieldset");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function ka(a,b){var c=a.split("|"),e=c.length;while(e--)d.attrHandle[c[e]]=b}function la(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&a.sourceIndex-b.sourceIndex;if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function ma(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function na(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function oa(a){return function(b){return"form"in b?b.parentNode&&b.disabled===!1?"label"in b?"label"in b.parentNode?b.parentNode.disabled===a:b.disabled===a:b.isDisabled===a||b.isDisabled!==!a&&ea(b)===a:b.disabled===a:"label"in b&&b.disabled===a}}function pa(a){return ia(function(b){return b=+b,ia(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function qa(a){return a&&"undefined"!=typeof a.getElementsByTagName&&a}c=ga.support={},f=ga.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return!!b&&"HTML"!==b.nodeName},m=ga.setDocument=function(a){var b,e,g=a?a.ownerDocument||a:v;return g!==n&&9===g.nodeType&&g.documentElement?(n=g,o=n.documentElement,p=!f(n),v!==n&&(e=n.defaultView)&&e.top!==e&&(e.addEventListener?e.addEventListener("unload",da,!1):e.attachEvent&&e.attachEvent("onunload",da)),c.attributes=ja(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=ja(function(a){return a.appendChild(n.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=Y.test(n.getElementsByClassName),c.getById=ja(function(a){return o.appendChild(a).id=u,!n.getElementsByName||!n.getElementsByName(u).length}),c.getById?(d.filter.ID=function(a){var b=a.replace(_,aa);return function(a){return a.getAttribute("id")===b}},d.find.ID=function(a,b){if("undefined"!=typeof b.getElementById&&p){var c=b.getElementById(a);return c?[c]:[]}}):(d.filter.ID=function(a){var b=a.replace(_,aa);return function(a){var c="undefined"!=typeof a.getAttributeNode&&a.getAttributeNode("id");return c&&c.value===b}},d.find.ID=function(a,b){if("undefined"!=typeof b.getElementById&&p){var c,d,e,f=b.getElementById(a);if(f){if(c=f.getAttributeNode("id"),c&&c.value===a)return[f];e=b.getElementsByName(a),d=0;while(f=e[d++])if(c=f.getAttributeNode("id"),c&&c.value===a)return[f]}return[]}}),d.find.TAG=c.getElementsByTagName?function(a,b){return"undefined"!=typeof b.getElementsByTagName?b.getElementsByTagName(a):c.qsa?b.querySelectorAll(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){if("undefined"!=typeof b.getElementsByClassName&&p)return b.getElementsByClassName(a)},r=[],q=[],(c.qsa=Y.test(n.querySelectorAll))&&(ja(function(a){o.appendChild(a).innerHTML="",a.querySelectorAll("[msallowcapture^='']").length&&q.push("[*^$]="+K+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||q.push("\\["+K+"*(?:value|"+J+")"),a.querySelectorAll("[id~="+u+"-]").length||q.push("~="),a.querySelectorAll(":checked").length||q.push(":checked"),a.querySelectorAll("a#"+u+"+*").length||q.push(".#.+[+~]")}),ja(function(a){a.innerHTML="";var b=n.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&q.push("name"+K+"*[*^$|!~]?="),2!==a.querySelectorAll(":enabled").length&&q.push(":enabled",":disabled"),o.appendChild(a).disabled=!0,2!==a.querySelectorAll(":disabled").length&&q.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),q.push(",.*:")})),(c.matchesSelector=Y.test(s=o.matches||o.webkitMatchesSelector||o.mozMatchesSelector||o.oMatchesSelector||o.msMatchesSelector))&&ja(function(a){c.disconnectedMatch=s.call(a,"*"),s.call(a,"[s!='']:x"),r.push("!=",N)}),q=q.length&&new RegExp(q.join("|")),r=r.length&&new RegExp(r.join("|")),b=Y.test(o.compareDocumentPosition),t=b||Y.test(o.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},B=b?function(a,b){if(a===b)return l=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===n||a.ownerDocument===v&&t(v,a)?-1:b===n||b.ownerDocument===v&&t(v,b)?1:k?I(k,a)-I(k,b):0:4&d?-1:1)}:function(a,b){if(a===b)return l=!0,0;var c,d=0,e=a.parentNode,f=b.parentNode,g=[a],h=[b];if(!e||!f)return a===n?-1:b===n?1:e?-1:f?1:k?I(k,a)-I(k,b):0;if(e===f)return la(a,b);c=a;while(c=c.parentNode)g.unshift(c);c=b;while(c=c.parentNode)h.unshift(c);while(g[d]===h[d])d++;return d?la(g[d],h[d]):g[d]===v?-1:h[d]===v?1:0},n):n},ga.matches=function(a,b){return ga(a,null,null,b)},ga.matchesSelector=function(a,b){if((a.ownerDocument||a)!==n&&m(a),b=b.replace(S,"='$1']"),c.matchesSelector&&p&&!A[b+" "]&&(!r||!r.test(b))&&(!q||!q.test(b)))try{var d=s.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return ga(b,n,null,[a]).length>0},ga.contains=function(a,b){return(a.ownerDocument||a)!==n&&m(a),t(a,b)},ga.attr=function(a,b){(a.ownerDocument||a)!==n&&m(a);var e=d.attrHandle[b.toLowerCase()],f=e&&C.call(d.attrHandle,b.toLowerCase())?e(a,b,!p):void 0;return void 0!==f?f:c.attributes||!p?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},ga.escape=function(a){return(a+"").replace(ba,ca)},ga.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},ga.uniqueSort=function(a){var b,d=[],e=0,f=0;if(l=!c.detectDuplicates,k=!c.sortStable&&a.slice(0),a.sort(B),l){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return k=null,a},e=ga.getText=function(a){var b,c="",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=ga.selectors={cacheLength:50,createPseudo:ia,match:V,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(_,aa),a[3]=(a[3]||a[4]||a[5]||"").replace(_,aa),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||ga.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&ga.error(a[0]),a},PSEUDO:function(a){var b,c=!a[6]&&a[2];return V.CHILD.test(a[0])?null:(a[3]?a[2]=a[4]||a[5]||"":c&&T.test(c)&&(b=g(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(_,aa).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=y[a+" "];return b||(b=new RegExp("(^|"+K+")"+a+"("+K+"|$)"))&&y(a,function(a){return b.test("string"==typeof a.className&&a.className||"undefined"!=typeof a.getAttribute&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=ga.attr(d,a);return null==e?"!="===b:!b||(e+="","="===b?e===c:"!="===b?e!==c:"^="===b?c&&0===e.indexOf(c):"*="===b?c&&e.indexOf(c)>-1:"$="===b?c&&e.slice(-c.length)===c:"~="===b?(" "+e.replace(O," ")+" ").indexOf(c)>-1:"|="===b&&(e===c||e.slice(0,c.length+1)===c+"-"))}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),s=!i&&!h,t=!1;if(q){if(f){while(p){m=b;while(m=m[p])if(h?m.nodeName.toLowerCase()===r:1===m.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&s){m=q,l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),j=k[a]||[],n=j[0]===w&&j[1],t=n&&j[2],m=n&&q.childNodes[n];while(m=++n&&m&&m[p]||(t=n=0)||o.pop())if(1===m.nodeType&&++t&&m===b){k[a]=[w,n,t];break}}else if(s&&(m=b,l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),j=k[a]||[],n=j[0]===w&&j[1],t=n),t===!1)while(m=++n&&m&&m[p]||(t=n=0)||o.pop())if((h?m.nodeName.toLowerCase()===r:1===m.nodeType)&&++t&&(s&&(l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),k[a]=[w,t]),m===b))break;return t-=e,t===d||t%d===0&&t/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||ga.error("unsupported pseudo: "+a);return e[u]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?ia(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=I(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:ia(function(a){var b=[],c=[],d=h(a.replace(P,"$1"));return d[u]?ia(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),b[0]=null,!c.pop()}}),has:ia(function(a){return function(b){return ga(a,b).length>0}}),contains:ia(function(a){return a=a.replace(_,aa),function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:ia(function(a){return U.test(a||"")||ga.error("unsupported lang: "+a),a=a.replace(_,aa).toLowerCase(),function(b){var c;do if(c=p?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===o},focus:function(a){return a===n.activeElement&&(!n.hasFocus||n.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:oa(!1),disabled:oa(!0),checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return X.test(a.nodeName)},input:function(a){return W.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:pa(function(){return[0]}),last:pa(function(a,b){return[b-1]}),eq:pa(function(a,b,c){return[c<0?c+b:c]}),even:pa(function(a,b){for(var c=0;c=0;)a.push(d);return a}),gt:pa(function(a,b,c){for(var d=c<0?c+b:c;++d1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function va(a,b,c){for(var d=0,e=b.length;d-1&&(f[j]=!(g[j]=l))}}else r=wa(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):G.apply(g,r)})}function ya(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],h=g||d.relative[" "],i=g?1:0,k=ta(function(a){return a===b},h,!0),l=ta(function(a){return I(b,a)>-1},h,!0),m=[function(a,c,d){var e=!g&&(d||c!==j)||((b=c).nodeType?k(a,c,d):l(a,c,d));return b=null,e}];i1&&ua(m),i>1&&sa(a.slice(0,i-1).concat({value:" "===a[i-2].type?"*":""})).replace(P,"$1"),c,i0,e=a.length>0,f=function(f,g,h,i,k){var l,o,q,r=0,s="0",t=f&&[],u=[],v=j,x=f||e&&d.find.TAG("*",k),y=w+=null==v?1:Math.random()||.1,z=x.length;for(k&&(j=g===n||g||k);s!==z&&null!=(l=x[s]);s++){if(e&&l){o=0,g||l.ownerDocument===n||(m(l),h=!p);while(q=a[o++])if(q(l,g||n,h)){i.push(l);break}k&&(w=y)}c&&((l=!q&&l)&&r--,f&&t.push(l))}if(r+=s,c&&s!==r){o=0;while(q=b[o++])q(t,u,g,h);if(f){if(r>0)while(s--)t[s]||u[s]||(u[s]=E.call(i));u=wa(u)}G.apply(i,u),k&&!f&&u.length>0&&r+b.length>1&&ga.uniqueSort(i)}return k&&(w=y,j=v),t};return c?ia(f):f}return h=ga.compile=function(a,b){var c,d=[],e=[],f=A[a+" "];if(!f){b||(b=g(a)),c=b.length;while(c--)f=ya(b[c]),f[u]?d.push(f):e.push(f);f=A(a,za(e,d)),f.selector=a}return f},i=ga.select=function(a,b,c,e){var f,i,j,k,l,m="function"==typeof a&&a,n=!e&&g(a=m.selector||a);if(c=c||[],1===n.length){if(i=n[0]=n[0].slice(0),i.length>2&&"ID"===(j=i[0]).type&&9===b.nodeType&&p&&d.relative[i[1].type]){if(b=(d.find.ID(j.matches[0].replace(_,aa),b)||[])[0],!b)return c;m&&(b=b.parentNode),a=a.slice(i.shift().value.length)}f=V.needsContext.test(a)?0:i.length;while(f--){if(j=i[f],d.relative[k=j.type])break;if((l=d.find[k])&&(e=l(j.matches[0].replace(_,aa),$.test(i[0].type)&&qa(b.parentNode)||b))){if(i.splice(f,1),a=e.length&&sa(i),!a)return G.apply(c,e),c;break}}}return(m||h(a,n))(e,b,!p,c,!b||$.test(a)&&qa(b.parentNode)||b),c},c.sortStable=u.split("").sort(B).join("")===u,c.detectDuplicates=!!l,m(),c.sortDetached=ja(function(a){return 1&a.compareDocumentPosition(n.createElement("fieldset"))}),ja(function(a){return a.innerHTML="","#"===a.firstChild.getAttribute("href")})||ka("type|href|height|width",function(a,b,c){if(!c)return a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&ja(function(a){return a.innerHTML="",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||ka("value",function(a,b,c){if(!c&&"input"===a.nodeName.toLowerCase())return a.defaultValue}),ja(function(a){return null==a.getAttribute("disabled")})||ka(J,function(a,b,c){var d;if(!c)return a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),ga}(a);r.find=x,r.expr=x.selectors,r.expr[":"]=r.expr.pseudos,r.uniqueSort=r.unique=x.uniqueSort,r.text=x.getText,r.isXMLDoc=x.isXML,r.contains=x.contains,r.escapeSelector=x.escape;var y=function(a,b,c){var d=[],e=void 0!==c;while((a=a[b])&&9!==a.nodeType)if(1===a.nodeType){if(e&&r(a).is(c))break;d.push(a)}return d},z=function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c},A=r.expr.match.needsContext;function B(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()}var C=/^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i,D=/^.[^:#\[\.,]*$/;function E(a,b,c){return r.isFunction(b)?r.grep(a,function(a,d){return!!b.call(a,d,a)!==c}):b.nodeType?r.grep(a,function(a){return a===b!==c}):"string"!=typeof b?r.grep(a,function(a){return i.call(b,a)>-1!==c}):D.test(b)?r.filter(b,a,c):(b=r.filter(b,a),r.grep(a,function(a){return i.call(b,a)>-1!==c&&1===a.nodeType}))}r.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?r.find.matchesSelector(d,a)?[d]:[]:r.find.matches(a,r.grep(b,function(a){return 1===a.nodeType}))},r.fn.extend({find:function(a){var b,c,d=this.length,e=this;if("string"!=typeof a)return this.pushStack(r(a).filter(function(){for(b=0;b1?r.uniqueSort(c):c},filter:function(a){return this.pushStack(E(this,a||[],!1))},not:function(a){return this.pushStack(E(this,a||[],!0))},is:function(a){return!!E(this,"string"==typeof a&&A.test(a)?r(a):a||[],!1).length}});var F,G=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/,H=r.fn.init=function(a,b,c){var e,f;if(!a)return this;if(c=c||F,"string"==typeof a){if(e="<"===a[0]&&">"===a[a.length-1]&&a.length>=3?[null,a,null]:G.exec(a),!e||!e[1]&&b)return!b||b.jquery?(b||c).find(a):this.constructor(b).find(a);if(e[1]){if(b=b instanceof r?b[0]:b,r.merge(this,r.parseHTML(e[1],b&&b.nodeType?b.ownerDocument||b:d,!0)),C.test(e[1])&&r.isPlainObject(b))for(e in b)r.isFunction(this[e])?this[e](b[e]):this.attr(e,b[e]);return this}return f=d.getElementById(e[2]),f&&(this[0]=f,this.length=1),this}return a.nodeType?(this[0]=a,this.length=1,this):r.isFunction(a)?void 0!==c.ready?c.ready(a):a(r):r.makeArray(a,this)};H.prototype=r.fn,F=r(d);var I=/^(?:parents|prev(?:Until|All))/,J={children:!0,contents:!0,next:!0,prev:!0};r.fn.extend({has:function(a){var b=r(a,this),c=b.length;return this.filter(function(){for(var a=0;a-1:1===c.nodeType&&r.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?r.uniqueSort(f):f)},index:function(a){return a?"string"==typeof a?i.call(r(a),this[0]):i.call(this,a.jquery?a[0]:a):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(r.uniqueSort(r.merge(this.get(),r(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function K(a,b){while((a=a[b])&&1!==a.nodeType);return a}r.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return y(a,"parentNode")},parentsUntil:function(a,b,c){return y(a,"parentNode",c)},next:function(a){return K(a,"nextSibling")},prev:function(a){return K(a,"previousSibling")},nextAll:function(a){return y(a,"nextSibling")},prevAll:function(a){return y(a,"previousSibling")},nextUntil:function(a,b,c){return y(a,"nextSibling",c)},prevUntil:function(a,b,c){return y(a,"previousSibling",c)},siblings:function(a){return z((a.parentNode||{}).firstChild,a)},children:function(a){return z(a.firstChild)},contents:function(a){return B(a,"iframe")?a.contentDocument:(B(a,"template")&&(a=a.content||a),r.merge([],a.childNodes))}},function(a,b){r.fn[a]=function(c,d){var e=r.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=r.filter(d,e)),this.length>1&&(J[a]||r.uniqueSort(e),I.test(a)&&e.reverse()),this.pushStack(e)}});var L=/[^\x20\t\r\n\f]+/g;function M(a){var b={};return r.each(a.match(L)||[],function(a,c){b[c]=!0}),b}r.Callbacks=function(a){a="string"==typeof a?M(a):r.extend({},a);var b,c,d,e,f=[],g=[],h=-1,i=function(){for(e=e||a.once,d=b=!0;g.length;h=-1){c=g.shift();while(++h-1)f.splice(c,1),c<=h&&h--}),this},has:function(a){return a?r.inArray(a,f)>-1:f.length>0},empty:function(){return f&&(f=[]),this},disable:function(){return e=g=[],f=c="",this},disabled:function(){return!f},lock:function(){return e=g=[],c||b||(f=c=""),this},locked:function(){return!!e},fireWith:function(a,c){return e||(c=c||[],c=[a,c.slice?c.slice():c],g.push(c),b||i()),this},fire:function(){return j.fireWith(this,arguments),this},fired:function(){return!!d}};return j};function N(a){return a}function O(a){throw a}function P(a,b,c,d){var e;try{a&&r.isFunction(e=a.promise)?e.call(a).done(b).fail(c):a&&r.isFunction(e=a.then)?e.call(a,b,c):b.apply(void 0,[a].slice(d))}catch(a){c.apply(void 0,[a])}}r.extend({Deferred:function(b){var c=[["notify","progress",r.Callbacks("memory"),r.Callbacks("memory"),2],["resolve","done",r.Callbacks("once memory"),r.Callbacks("once memory"),0,"resolved"],["reject","fail",r.Callbacks("once memory"),r.Callbacks("once memory"),1,"rejected"]],d="pending",e={state:function(){return d},always:function(){return f.done(arguments).fail(arguments),this},"catch":function(a){return e.then(null,a)},pipe:function(){var a=arguments;return r.Deferred(function(b){r.each(c,function(c,d){var e=r.isFunction(a[d[4]])&&a[d[4]];f[d[1]](function(){var a=e&&e.apply(this,arguments);a&&r.isFunction(a.promise)?a.promise().progress(b.notify).done(b.resolve).fail(b.reject):b[d[0]+"With"](this,e?[a]:arguments)})}),a=null}).promise()},then:function(b,d,e){var f=0;function g(b,c,d,e){return function(){var h=this,i=arguments,j=function(){var a,j;if(!(b=f&&(d!==O&&(h=void 0,i=[a]),c.rejectWith(h,i))}};b?k():(r.Deferred.getStackHook&&(k.stackTrace=r.Deferred.getStackHook()),a.setTimeout(k))}}return r.Deferred(function(a){c[0][3].add(g(0,a,r.isFunction(e)?e:N,a.notifyWith)),c[1][3].add(g(0,a,r.isFunction(b)?b:N)),c[2][3].add(g(0,a,r.isFunction(d)?d:O))}).promise()},promise:function(a){return null!=a?r.extend(a,e):e}},f={};return r.each(c,function(a,b){var g=b[2],h=b[5];e[b[1]]=g.add,h&&g.add(function(){d=h},c[3-a][2].disable,c[0][2].lock),g.add(b[3].fire),f[b[0]]=function(){return f[b[0]+"With"](this===f?void 0:this,arguments),this},f[b[0]+"With"]=g.fireWith}),e.promise(f),b&&b.call(f,f),f},when:function(a){var b=arguments.length,c=b,d=Array(c),e=f.call(arguments),g=r.Deferred(),h=function(a){return function(c){d[a]=this,e[a]=arguments.length>1?f.call(arguments):c,--b||g.resolveWith(d,e)}};if(b<=1&&(P(a,g.done(h(c)).resolve,g.reject,!b),"pending"===g.state()||r.isFunction(e[c]&&e[c].then)))return g.then();while(c--)P(e[c],h(c),g.reject);return g.promise()}});var Q=/^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/;r.Deferred.exceptionHook=function(b,c){a.console&&a.console.warn&&b&&Q.test(b.name)&&a.console.warn("jQuery.Deferred exception: "+b.message,b.stack,c)},r.readyException=function(b){a.setTimeout(function(){throw b})};var R=r.Deferred();r.fn.ready=function(a){return R.then(a)["catch"](function(a){r.readyException(a)}),this},r.extend({isReady:!1,readyWait:1,ready:function(a){(a===!0?--r.readyWait:r.isReady)||(r.isReady=!0,a!==!0&&--r.readyWait>0||R.resolveWith(d,[r]))}}),r.ready.then=R.then;function S(){d.removeEventListener("DOMContentLoaded",S), -a.removeEventListener("load",S),r.ready()}"complete"===d.readyState||"loading"!==d.readyState&&!d.documentElement.doScroll?a.setTimeout(r.ready):(d.addEventListener("DOMContentLoaded",S),a.addEventListener("load",S));var T=function(a,b,c,d,e,f,g){var h=0,i=a.length,j=null==c;if("object"===r.type(c)){e=!0;for(h in c)T(a,b,h,c[h],!0,f,g)}else if(void 0!==d&&(e=!0,r.isFunction(d)||(g=!0),j&&(g?(b.call(a,d),b=null):(j=b,b=function(a,b,c){return j.call(r(a),c)})),b))for(;h1,null,!0)},removeData:function(a){return this.each(function(){X.remove(this,a)})}}),r.extend({queue:function(a,b,c){var d;if(a)return b=(b||"fx")+"queue",d=W.get(a,b),c&&(!d||Array.isArray(c)?d=W.access(a,b,r.makeArray(c)):d.push(c)),d||[]},dequeue:function(a,b){b=b||"fx";var c=r.queue(a,b),d=c.length,e=c.shift(),f=r._queueHooks(a,b),g=function(){r.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return W.get(a,c)||W.access(a,c,{empty:r.Callbacks("once memory").add(function(){W.remove(a,[b+"queue",c])})})}}),r.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.length\x20\t\r\n\f]+)/i,la=/^$|\/(?:java|ecma)script/i,ma={option:[1,""],thead:[1,"","
    "],col:[2,"","
    "],tr:[2,"","
    "],td:[3,"","
    "],_default:[0,"",""]};ma.optgroup=ma.option,ma.tbody=ma.tfoot=ma.colgroup=ma.caption=ma.thead,ma.th=ma.td;function na(a,b){var c;return c="undefined"!=typeof a.getElementsByTagName?a.getElementsByTagName(b||"*"):"undefined"!=typeof a.querySelectorAll?a.querySelectorAll(b||"*"):[],void 0===b||b&&B(a,b)?r.merge([a],c):c}function oa(a,b){for(var c=0,d=a.length;c-1)e&&e.push(f);else if(j=r.contains(f.ownerDocument,f),g=na(l.appendChild(f),"script"),j&&oa(g),c){k=0;while(f=g[k++])la.test(f.type||"")&&c.push(f)}return l}!function(){var a=d.createDocumentFragment(),b=a.appendChild(d.createElement("div")),c=d.createElement("input");c.setAttribute("type","radio"),c.setAttribute("checked","checked"),c.setAttribute("name","t"),b.appendChild(c),o.checkClone=b.cloneNode(!0).cloneNode(!0).lastChild.checked,b.innerHTML="",o.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue}();var ra=d.documentElement,sa=/^key/,ta=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,ua=/^([^.]*)(?:\.(.+)|)/;function va(){return!0}function wa(){return!1}function xa(){try{return d.activeElement}catch(a){}}function ya(a,b,c,d,e,f){var g,h;if("object"==typeof b){"string"!=typeof c&&(d=d||c,c=void 0);for(h in b)ya(a,h,c,d,b[h],f);return a}if(null==d&&null==e?(e=c,d=c=void 0):null==e&&("string"==typeof c?(e=d,d=void 0):(e=d,d=c,c=void 0)),e===!1)e=wa;else if(!e)return a;return 1===f&&(g=e,e=function(a){return r().off(a),g.apply(this,arguments)},e.guid=g.guid||(g.guid=r.guid++)),a.each(function(){r.event.add(this,b,e,d,c)})}r.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,n,o,p,q=W.get(a);if(q){c.handler&&(f=c,c=f.handler,e=f.selector),e&&r.find.matchesSelector(ra,e),c.guid||(c.guid=r.guid++),(i=q.events)||(i=q.events={}),(g=q.handle)||(g=q.handle=function(b){return"undefined"!=typeof r&&r.event.triggered!==b.type?r.event.dispatch.apply(a,arguments):void 0}),b=(b||"").match(L)||[""],j=b.length;while(j--)h=ua.exec(b[j])||[],n=p=h[1],o=(h[2]||"").split(".").sort(),n&&(l=r.event.special[n]||{},n=(e?l.delegateType:l.bindType)||n,l=r.event.special[n]||{},k=r.extend({type:n,origType:p,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&r.expr.match.needsContext.test(e),namespace:o.join(".")},f),(m=i[n])||(m=i[n]=[],m.delegateCount=0,l.setup&&l.setup.call(a,d,o,g)!==!1||a.addEventListener&&a.addEventListener(n,g)),l.add&&(l.add.call(a,k),k.handler.guid||(k.handler.guid=c.guid)),e?m.splice(m.delegateCount++,0,k):m.push(k),r.event.global[n]=!0)}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,n,o,p,q=W.hasData(a)&&W.get(a);if(q&&(i=q.events)){b=(b||"").match(L)||[""],j=b.length;while(j--)if(h=ua.exec(b[j])||[],n=p=h[1],o=(h[2]||"").split(".").sort(),n){l=r.event.special[n]||{},n=(d?l.delegateType:l.bindType)||n,m=i[n]||[],h=h[2]&&new RegExp("(^|\\.)"+o.join("\\.(?:.*\\.|)")+"(\\.|$)"),g=f=m.length;while(f--)k=m[f],!e&&p!==k.origType||c&&c.guid!==k.guid||h&&!h.test(k.namespace)||d&&d!==k.selector&&("**"!==d||!k.selector)||(m.splice(f,1),k.selector&&m.delegateCount--,l.remove&&l.remove.call(a,k));g&&!m.length&&(l.teardown&&l.teardown.call(a,o,q.handle)!==!1||r.removeEvent(a,n,q.handle),delete i[n])}else for(n in i)r.event.remove(a,n+b[j],c,d,!0);r.isEmptyObject(i)&&W.remove(a,"handle events")}},dispatch:function(a){var b=r.event.fix(a),c,d,e,f,g,h,i=new Array(arguments.length),j=(W.get(this,"events")||{})[b.type]||[],k=r.event.special[b.type]||{};for(i[0]=b,c=1;c=1))for(;j!==this;j=j.parentNode||this)if(1===j.nodeType&&("click"!==a.type||j.disabled!==!0)){for(f=[],g={},c=0;c-1:r.find(e,this,null,[j]).length),g[e]&&f.push(d);f.length&&h.push({elem:j,handlers:f})}return j=this,i\x20\t\r\n\f]*)[^>]*)\/>/gi,Aa=/\s*$/g;function Ea(a,b){return B(a,"table")&&B(11!==b.nodeType?b:b.firstChild,"tr")?r(">tbody",a)[0]||a:a}function Fa(a){return a.type=(null!==a.getAttribute("type"))+"/"+a.type,a}function Ga(a){var b=Ca.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function Ha(a,b){var c,d,e,f,g,h,i,j;if(1===b.nodeType){if(W.hasData(a)&&(f=W.access(a),g=W.set(b,f),j=f.events)){delete g.handle,g.events={};for(e in j)for(c=0,d=j[e].length;c1&&"string"==typeof q&&!o.checkClone&&Ba.test(q))return a.each(function(e){var f=a.eq(e);s&&(b[0]=q.call(this,e,f.html())),Ja(f,b,c,d)});if(m&&(e=qa(b,a[0].ownerDocument,!1,a,d),f=e.firstChild,1===e.childNodes.length&&(e=f),f||d)){for(h=r.map(na(e,"script"),Fa),i=h.length;l")},clone:function(a,b,c){var d,e,f,g,h=a.cloneNode(!0),i=r.contains(a.ownerDocument,a);if(!(o.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||r.isXMLDoc(a)))for(g=na(h),f=na(a),d=0,e=f.length;d0&&oa(g,!i&&na(a,"script")),h},cleanData:function(a){for(var b,c,d,e=r.event.special,f=0;void 0!==(c=a[f]);f++)if(U(c)){if(b=c[W.expando]){if(b.events)for(d in b.events)e[d]?r.event.remove(c,d):r.removeEvent(c,d,b.handle);c[W.expando]=void 0}c[X.expando]&&(c[X.expando]=void 0)}}}),r.fn.extend({detach:function(a){return Ka(this,a,!0)},remove:function(a){return Ka(this,a)},text:function(a){return T(this,function(a){return void 0===a?r.text(this):this.empty().each(function(){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||(this.textContent=a)})},null,a,arguments.length)},append:function(){return Ja(this,arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=Ea(this,a);b.appendChild(a)}})},prepend:function(){return Ja(this,arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=Ea(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return Ja(this,arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return Ja(this,arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},empty:function(){for(var a,b=0;null!=(a=this[b]);b++)1===a.nodeType&&(r.cleanData(na(a,!1)),a.textContent="");return this},clone:function(a,b){return a=null!=a&&a,b=null==b?a:b,this.map(function(){return r.clone(this,a,b)})},html:function(a){return T(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a&&1===b.nodeType)return b.innerHTML;if("string"==typeof a&&!Aa.test(a)&&!ma[(ka.exec(a)||["",""])[1].toLowerCase()]){a=r.htmlPrefilter(a);try{for(;c1)}});function _a(a,b,c,d,e){return new _a.prototype.init(a,b,c,d,e)}r.Tween=_a,_a.prototype={constructor:_a,init:function(a,b,c,d,e,f){this.elem=a,this.prop=c,this.easing=e||r.easing._default,this.options=b,this.start=this.now=this.cur(),this.end=d,this.unit=f||(r.cssNumber[c]?"":"px")},cur:function(){var a=_a.propHooks[this.prop];return a&&a.get?a.get(this):_a.propHooks._default.get(this)},run:function(a){var b,c=_a.propHooks[this.prop];return this.options.duration?this.pos=b=r.easing[this.easing](a,this.options.duration*a,0,1,this.options.duration):this.pos=b=a,this.now=(this.end-this.start)*b+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),c&&c.set?c.set(this):_a.propHooks._default.set(this),this}},_a.prototype.init.prototype=_a.prototype,_a.propHooks={_default:{get:function(a){var b;return 1!==a.elem.nodeType||null!=a.elem[a.prop]&&null==a.elem.style[a.prop]?a.elem[a.prop]:(b=r.css(a.elem,a.prop,""),b&&"auto"!==b?b:0)},set:function(a){r.fx.step[a.prop]?r.fx.step[a.prop](a):1!==a.elem.nodeType||null==a.elem.style[r.cssProps[a.prop]]&&!r.cssHooks[a.prop]?a.elem[a.prop]=a.now:r.style(a.elem,a.prop,a.now+a.unit)}}},_a.propHooks.scrollTop=_a.propHooks.scrollLeft={set:function(a){a.elem.nodeType&&a.elem.parentNode&&(a.elem[a.prop]=a.now)}},r.easing={linear:function(a){return a},swing:function(a){return.5-Math.cos(a*Math.PI)/2},_default:"swing"},r.fx=_a.prototype.init,r.fx.step={};var ab,bb,cb=/^(?:toggle|show|hide)$/,db=/queueHooks$/;function eb(){bb&&(d.hidden===!1&&a.requestAnimationFrame?a.requestAnimationFrame(eb):a.setTimeout(eb,r.fx.interval),r.fx.tick())}function fb(){return a.setTimeout(function(){ab=void 0}),ab=r.now()}function gb(a,b){var c,d=0,e={height:a};for(b=b?1:0;d<4;d+=2-b)c=ca[d],e["margin"+c]=e["padding"+c]=a;return b&&(e.opacity=e.width=a),e}function hb(a,b,c){for(var d,e=(kb.tweeners[b]||[]).concat(kb.tweeners["*"]),f=0,g=e.length;f1)},removeAttr:function(a){return this.each(function(){r.removeAttr(this,a)})}}),r.extend({attr:function(a,b,c){var d,e,f=a.nodeType;if(3!==f&&8!==f&&2!==f)return"undefined"==typeof a.getAttribute?r.prop(a,b,c):(1===f&&r.isXMLDoc(a)||(e=r.attrHooks[b.toLowerCase()]||(r.expr.match.bool.test(b)?lb:void 0)),void 0!==c?null===c?void r.removeAttr(a,b):e&&"set"in e&&void 0!==(d=e.set(a,c,b))?d:(a.setAttribute(b,c+""),c):e&&"get"in e&&null!==(d=e.get(a,b))?d:(d=r.find.attr(a,b), -null==d?void 0:d))},attrHooks:{type:{set:function(a,b){if(!o.radioValue&&"radio"===b&&B(a,"input")){var c=a.value;return a.setAttribute("type",b),c&&(a.value=c),b}}}},removeAttr:function(a,b){var c,d=0,e=b&&b.match(L);if(e&&1===a.nodeType)while(c=e[d++])a.removeAttribute(c)}}),lb={set:function(a,b,c){return b===!1?r.removeAttr(a,c):a.setAttribute(c,c),c}},r.each(r.expr.match.bool.source.match(/\w+/g),function(a,b){var c=mb[b]||r.find.attr;mb[b]=function(a,b,d){var e,f,g=b.toLowerCase();return d||(f=mb[g],mb[g]=e,e=null!=c(a,b,d)?g:null,mb[g]=f),e}});var nb=/^(?:input|select|textarea|button)$/i,ob=/^(?:a|area)$/i;r.fn.extend({prop:function(a,b){return T(this,r.prop,a,b,arguments.length>1)},removeProp:function(a){return this.each(function(){delete this[r.propFix[a]||a]})}}),r.extend({prop:function(a,b,c){var d,e,f=a.nodeType;if(3!==f&&8!==f&&2!==f)return 1===f&&r.isXMLDoc(a)||(b=r.propFix[b]||b,e=r.propHooks[b]),void 0!==c?e&&"set"in e&&void 0!==(d=e.set(a,c,b))?d:a[b]=c:e&&"get"in e&&null!==(d=e.get(a,b))?d:a[b]},propHooks:{tabIndex:{get:function(a){var b=r.find.attr(a,"tabindex");return b?parseInt(b,10):nb.test(a.nodeName)||ob.test(a.nodeName)&&a.href?0:-1}}},propFix:{"for":"htmlFor","class":"className"}}),o.optSelected||(r.propHooks.selected={get:function(a){var b=a.parentNode;return b&&b.parentNode&&b.parentNode.selectedIndex,null},set:function(a){var b=a.parentNode;b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex)}}),r.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){r.propFix[this.toLowerCase()]=this});function pb(a){var b=a.match(L)||[];return b.join(" ")}function qb(a){return a.getAttribute&&a.getAttribute("class")||""}r.fn.extend({addClass:function(a){var b,c,d,e,f,g,h,i=0;if(r.isFunction(a))return this.each(function(b){r(this).addClass(a.call(this,b,qb(this)))});if("string"==typeof a&&a){b=a.match(L)||[];while(c=this[i++])if(e=qb(c),d=1===c.nodeType&&" "+pb(e)+" "){g=0;while(f=b[g++])d.indexOf(" "+f+" ")<0&&(d+=f+" ");h=pb(d),e!==h&&c.setAttribute("class",h)}}return this},removeClass:function(a){var b,c,d,e,f,g,h,i=0;if(r.isFunction(a))return this.each(function(b){r(this).removeClass(a.call(this,b,qb(this)))});if(!arguments.length)return this.attr("class","");if("string"==typeof a&&a){b=a.match(L)||[];while(c=this[i++])if(e=qb(c),d=1===c.nodeType&&" "+pb(e)+" "){g=0;while(f=b[g++])while(d.indexOf(" "+f+" ")>-1)d=d.replace(" "+f+" "," ");h=pb(d),e!==h&&c.setAttribute("class",h)}}return this},toggleClass:function(a,b){var c=typeof a;return"boolean"==typeof b&&"string"===c?b?this.addClass(a):this.removeClass(a):r.isFunction(a)?this.each(function(c){r(this).toggleClass(a.call(this,c,qb(this),b),b)}):this.each(function(){var b,d,e,f;if("string"===c){d=0,e=r(this),f=a.match(L)||[];while(b=f[d++])e.hasClass(b)?e.removeClass(b):e.addClass(b)}else void 0!==a&&"boolean"!==c||(b=qb(this),b&&W.set(this,"__className__",b),this.setAttribute&&this.setAttribute("class",b||a===!1?"":W.get(this,"__className__")||""))})},hasClass:function(a){var b,c,d=0;b=" "+a+" ";while(c=this[d++])if(1===c.nodeType&&(" "+pb(qb(c))+" ").indexOf(b)>-1)return!0;return!1}});var rb=/\r/g;r.fn.extend({val:function(a){var b,c,d,e=this[0];{if(arguments.length)return d=r.isFunction(a),this.each(function(c){var e;1===this.nodeType&&(e=d?a.call(this,c,r(this).val()):a,null==e?e="":"number"==typeof e?e+="":Array.isArray(e)&&(e=r.map(e,function(a){return null==a?"":a+""})),b=r.valHooks[this.type]||r.valHooks[this.nodeName.toLowerCase()],b&&"set"in b&&void 0!==b.set(this,e,"value")||(this.value=e))});if(e)return b=r.valHooks[e.type]||r.valHooks[e.nodeName.toLowerCase()],b&&"get"in b&&void 0!==(c=b.get(e,"value"))?c:(c=e.value,"string"==typeof c?c.replace(rb,""):null==c?"":c)}}}),r.extend({valHooks:{option:{get:function(a){var b=r.find.attr(a,"value");return null!=b?b:pb(r.text(a))}},select:{get:function(a){var b,c,d,e=a.options,f=a.selectedIndex,g="select-one"===a.type,h=g?null:[],i=g?f+1:e.length;for(d=f<0?i:g?f:0;d-1)&&(c=!0);return c||(a.selectedIndex=-1),f}}}}),r.each(["radio","checkbox"],function(){r.valHooks[this]={set:function(a,b){if(Array.isArray(b))return a.checked=r.inArray(r(a).val(),b)>-1}},o.checkOn||(r.valHooks[this].get=function(a){return null===a.getAttribute("value")?"on":a.value})});var sb=/^(?:focusinfocus|focusoutblur)$/;r.extend(r.event,{trigger:function(b,c,e,f){var g,h,i,j,k,m,n,o=[e||d],p=l.call(b,"type")?b.type:b,q=l.call(b,"namespace")?b.namespace.split("."):[];if(h=i=e=e||d,3!==e.nodeType&&8!==e.nodeType&&!sb.test(p+r.event.triggered)&&(p.indexOf(".")>-1&&(q=p.split("."),p=q.shift(),q.sort()),k=p.indexOf(":")<0&&"on"+p,b=b[r.expando]?b:new r.Event(p,"object"==typeof b&&b),b.isTrigger=f?2:3,b.namespace=q.join("."),b.rnamespace=b.namespace?new RegExp("(^|\\.)"+q.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=e),c=null==c?[b]:r.makeArray(c,[b]),n=r.event.special[p]||{},f||!n.trigger||n.trigger.apply(e,c)!==!1)){if(!f&&!n.noBubble&&!r.isWindow(e)){for(j=n.delegateType||p,sb.test(j+p)||(h=h.parentNode);h;h=h.parentNode)o.push(h),i=h;i===(e.ownerDocument||d)&&o.push(i.defaultView||i.parentWindow||a)}g=0;while((h=o[g++])&&!b.isPropagationStopped())b.type=g>1?j:n.bindType||p,m=(W.get(h,"events")||{})[b.type]&&W.get(h,"handle"),m&&m.apply(h,c),m=k&&h[k],m&&m.apply&&U(h)&&(b.result=m.apply(h,c),b.result===!1&&b.preventDefault());return b.type=p,f||b.isDefaultPrevented()||n._default&&n._default.apply(o.pop(),c)!==!1||!U(e)||k&&r.isFunction(e[p])&&!r.isWindow(e)&&(i=e[k],i&&(e[k]=null),r.event.triggered=p,e[p](),r.event.triggered=void 0,i&&(e[k]=i)),b.result}},simulate:function(a,b,c){var d=r.extend(new r.Event,c,{type:a,isSimulated:!0});r.event.trigger(d,null,b)}}),r.fn.extend({trigger:function(a,b){return this.each(function(){r.event.trigger(a,b,this)})},triggerHandler:function(a,b){var c=this[0];if(c)return r.event.trigger(a,b,c,!0)}}),r.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(a,b){r.fn[b]=function(a,c){return arguments.length>0?this.on(b,null,a,c):this.trigger(b)}}),r.fn.extend({hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}}),o.focusin="onfocusin"in a,o.focusin||r.each({focus:"focusin",blur:"focusout"},function(a,b){var c=function(a){r.event.simulate(b,a.target,r.event.fix(a))};r.event.special[b]={setup:function(){var d=this.ownerDocument||this,e=W.access(d,b);e||d.addEventListener(a,c,!0),W.access(d,b,(e||0)+1)},teardown:function(){var d=this.ownerDocument||this,e=W.access(d,b)-1;e?W.access(d,b,e):(d.removeEventListener(a,c,!0),W.remove(d,b))}}});var tb=a.location,ub=r.now(),vb=/\?/;r.parseXML=function(b){var c;if(!b||"string"!=typeof b)return null;try{c=(new a.DOMParser).parseFromString(b,"text/xml")}catch(d){c=void 0}return c&&!c.getElementsByTagName("parsererror").length||r.error("Invalid XML: "+b),c};var wb=/\[\]$/,xb=/\r?\n/g,yb=/^(?:submit|button|image|reset|file)$/i,zb=/^(?:input|select|textarea|keygen)/i;function Ab(a,b,c,d){var e;if(Array.isArray(b))r.each(b,function(b,e){c||wb.test(a)?d(a,e):Ab(a+"["+("object"==typeof e&&null!=e?b:"")+"]",e,c,d)});else if(c||"object"!==r.type(b))d(a,b);else for(e in b)Ab(a+"["+e+"]",b[e],c,d)}r.param=function(a,b){var c,d=[],e=function(a,b){var c=r.isFunction(b)?b():b;d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(null==c?"":c)};if(Array.isArray(a)||a.jquery&&!r.isPlainObject(a))r.each(a,function(){e(this.name,this.value)});else for(c in a)Ab(c,a[c],b,e);return d.join("&")},r.fn.extend({serialize:function(){return r.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var a=r.prop(this,"elements");return a?r.makeArray(a):this}).filter(function(){var a=this.type;return this.name&&!r(this).is(":disabled")&&zb.test(this.nodeName)&&!yb.test(a)&&(this.checked||!ja.test(a))}).map(function(a,b){var c=r(this).val();return null==c?null:Array.isArray(c)?r.map(c,function(a){return{name:b.name,value:a.replace(xb,"\r\n")}}):{name:b.name,value:c.replace(xb,"\r\n")}}).get()}});var Bb=/%20/g,Cb=/#.*$/,Db=/([?&])_=[^&]*/,Eb=/^(.*?):[ \t]*([^\r\n]*)$/gm,Fb=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,Gb=/^(?:GET|HEAD)$/,Hb=/^\/\//,Ib={},Jb={},Kb="*/".concat("*"),Lb=d.createElement("a");Lb.href=tb.href;function Mb(a){return function(b,c){"string"!=typeof b&&(c=b,b="*");var d,e=0,f=b.toLowerCase().match(L)||[];if(r.isFunction(c))while(d=f[e++])"+"===d[0]?(d=d.slice(1)||"*",(a[d]=a[d]||[]).unshift(c)):(a[d]=a[d]||[]).push(c)}}function Nb(a,b,c,d){var e={},f=a===Jb;function g(h){var i;return e[h]=!0,r.each(a[h]||[],function(a,h){var j=h(b,c,d);return"string"!=typeof j||f||e[j]?f?!(i=j):void 0:(b.dataTypes.unshift(j),g(j),!1)}),i}return g(b.dataTypes[0])||!e["*"]&&g("*")}function Ob(a,b){var c,d,e=r.ajaxSettings.flatOptions||{};for(c in b)void 0!==b[c]&&((e[c]?a:d||(d={}))[c]=b[c]);return d&&r.extend(!0,a,d),a}function Pb(a,b,c){var d,e,f,g,h=a.contents,i=a.dataTypes;while("*"===i[0])i.shift(),void 0===d&&(d=a.mimeType||b.getResponseHeader("Content-Type"));if(d)for(e in h)if(h[e]&&h[e].test(d)){i.unshift(e);break}if(i[0]in c)f=i[0];else{for(e in c){if(!i[0]||a.converters[e+" "+i[0]]){f=e;break}g||(g=e)}f=f||g}if(f)return f!==i[0]&&i.unshift(f),c[f]}function Qb(a,b,c,d){var e,f,g,h,i,j={},k=a.dataTypes.slice();if(k[1])for(g in a.converters)j[g.toLowerCase()]=a.converters[g];f=k.shift();while(f)if(a.responseFields[f]&&(c[a.responseFields[f]]=b),!i&&d&&a.dataFilter&&(b=a.dataFilter(b,a.dataType)),i=f,f=k.shift())if("*"===f)f=i;else if("*"!==i&&i!==f){if(g=j[i+" "+f]||j["* "+f],!g)for(e in j)if(h=e.split(" "),h[1]===f&&(g=j[i+" "+h[0]]||j["* "+h[0]])){g===!0?g=j[e]:j[e]!==!0&&(f=h[0],k.unshift(h[1]));break}if(g!==!0)if(g&&a["throws"])b=g(b);else try{b=g(b)}catch(l){return{state:"parsererror",error:g?l:"No conversion from "+i+" to "+f}}}return{state:"success",data:b}}r.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:tb.href,type:"GET",isLocal:Fb.test(tb.protocol),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":Kb,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/\bxml\b/,html:/\bhtml/,json:/\bjson\b/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":!0,"text json":JSON.parse,"text xml":r.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(a,b){return b?Ob(Ob(a,r.ajaxSettings),b):Ob(r.ajaxSettings,a)},ajaxPrefilter:Mb(Ib),ajaxTransport:Mb(Jb),ajax:function(b,c){"object"==typeof b&&(c=b,b=void 0),c=c||{};var e,f,g,h,i,j,k,l,m,n,o=r.ajaxSetup({},c),p=o.context||o,q=o.context&&(p.nodeType||p.jquery)?r(p):r.event,s=r.Deferred(),t=r.Callbacks("once memory"),u=o.statusCode||{},v={},w={},x="canceled",y={readyState:0,getResponseHeader:function(a){var b;if(k){if(!h){h={};while(b=Eb.exec(g))h[b[1].toLowerCase()]=b[2]}b=h[a.toLowerCase()]}return null==b?null:b},getAllResponseHeaders:function(){return k?g:null},setRequestHeader:function(a,b){return null==k&&(a=w[a.toLowerCase()]=w[a.toLowerCase()]||a,v[a]=b),this},overrideMimeType:function(a){return null==k&&(o.mimeType=a),this},statusCode:function(a){var b;if(a)if(k)y.always(a[y.status]);else for(b in a)u[b]=[u[b],a[b]];return this},abort:function(a){var b=a||x;return e&&e.abort(b),A(0,b),this}};if(s.promise(y),o.url=((b||o.url||tb.href)+"").replace(Hb,tb.protocol+"//"),o.type=c.method||c.type||o.method||o.type,o.dataTypes=(o.dataType||"*").toLowerCase().match(L)||[""],null==o.crossDomain){j=d.createElement("a");try{j.href=o.url,j.href=j.href,o.crossDomain=Lb.protocol+"//"+Lb.host!=j.protocol+"//"+j.host}catch(z){o.crossDomain=!0}}if(o.data&&o.processData&&"string"!=typeof o.data&&(o.data=r.param(o.data,o.traditional)),Nb(Ib,o,c,y),k)return y;l=r.event&&o.global,l&&0===r.active++&&r.event.trigger("ajaxStart"),o.type=o.type.toUpperCase(),o.hasContent=!Gb.test(o.type),f=o.url.replace(Cb,""),o.hasContent?o.data&&o.processData&&0===(o.contentType||"").indexOf("application/x-www-form-urlencoded")&&(o.data=o.data.replace(Bb,"+")):(n=o.url.slice(f.length),o.data&&(f+=(vb.test(f)?"&":"?")+o.data,delete o.data),o.cache===!1&&(f=f.replace(Db,"$1"),n=(vb.test(f)?"&":"?")+"_="+ub++ +n),o.url=f+n),o.ifModified&&(r.lastModified[f]&&y.setRequestHeader("If-Modified-Since",r.lastModified[f]),r.etag[f]&&y.setRequestHeader("If-None-Match",r.etag[f])),(o.data&&o.hasContent&&o.contentType!==!1||c.contentType)&&y.setRequestHeader("Content-Type",o.contentType),y.setRequestHeader("Accept",o.dataTypes[0]&&o.accepts[o.dataTypes[0]]?o.accepts[o.dataTypes[0]]+("*"!==o.dataTypes[0]?", "+Kb+"; q=0.01":""):o.accepts["*"]);for(m in o.headers)y.setRequestHeader(m,o.headers[m]);if(o.beforeSend&&(o.beforeSend.call(p,y,o)===!1||k))return y.abort();if(x="abort",t.add(o.complete),y.done(o.success),y.fail(o.error),e=Nb(Jb,o,c,y)){if(y.readyState=1,l&&q.trigger("ajaxSend",[y,o]),k)return y;o.async&&o.timeout>0&&(i=a.setTimeout(function(){y.abort("timeout")},o.timeout));try{k=!1,e.send(v,A)}catch(z){if(k)throw z;A(-1,z)}}else A(-1,"No Transport");function A(b,c,d,h){var j,m,n,v,w,x=c;k||(k=!0,i&&a.clearTimeout(i),e=void 0,g=h||"",y.readyState=b>0?4:0,j=b>=200&&b<300||304===b,d&&(v=Pb(o,y,d)),v=Qb(o,v,y,j),j?(o.ifModified&&(w=y.getResponseHeader("Last-Modified"),w&&(r.lastModified[f]=w),w=y.getResponseHeader("etag"),w&&(r.etag[f]=w)),204===b||"HEAD"===o.type?x="nocontent":304===b?x="notmodified":(x=v.state,m=v.data,n=v.error,j=!n)):(n=x,!b&&x||(x="error",b<0&&(b=0))),y.status=b,y.statusText=(c||x)+"",j?s.resolveWith(p,[m,x,y]):s.rejectWith(p,[y,x,n]),y.statusCode(u),u=void 0,l&&q.trigger(j?"ajaxSuccess":"ajaxError",[y,o,j?m:n]),t.fireWith(p,[y,x]),l&&(q.trigger("ajaxComplete",[y,o]),--r.active||r.event.trigger("ajaxStop")))}return y},getJSON:function(a,b,c){return r.get(a,b,c,"json")},getScript:function(a,b){return r.get(a,void 0,b,"script")}}),r.each(["get","post"],function(a,b){r[b]=function(a,c,d,e){return r.isFunction(c)&&(e=e||d,d=c,c=void 0),r.ajax(r.extend({url:a,type:b,dataType:e,data:c,success:d},r.isPlainObject(a)&&a))}}),r._evalUrl=function(a){return r.ajax({url:a,type:"GET",dataType:"script",cache:!0,async:!1,global:!1,"throws":!0})},r.fn.extend({wrapAll:function(a){var b;return this[0]&&(r.isFunction(a)&&(a=a.call(this[0])),b=r(a,this[0].ownerDocument).eq(0).clone(!0),this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstElementChild)a=a.firstElementChild;return a}).append(this)),this},wrapInner:function(a){return r.isFunction(a)?this.each(function(b){r(this).wrapInner(a.call(this,b))}):this.each(function(){var b=r(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=r.isFunction(a);return this.each(function(c){r(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(a){return this.parent(a).not("body").each(function(){r(this).replaceWith(this.childNodes)}),this}}),r.expr.pseudos.hidden=function(a){return!r.expr.pseudos.visible(a)},r.expr.pseudos.visible=function(a){return!!(a.offsetWidth||a.offsetHeight||a.getClientRects().length)},r.ajaxSettings.xhr=function(){try{return new a.XMLHttpRequest}catch(b){}};var Rb={0:200,1223:204},Sb=r.ajaxSettings.xhr();o.cors=!!Sb&&"withCredentials"in Sb,o.ajax=Sb=!!Sb,r.ajaxTransport(function(b){var c,d;if(o.cors||Sb&&!b.crossDomain)return{send:function(e,f){var g,h=b.xhr();if(h.open(b.type,b.url,b.async,b.username,b.password),b.xhrFields)for(g in b.xhrFields)h[g]=b.xhrFields[g];b.mimeType&&h.overrideMimeType&&h.overrideMimeType(b.mimeType),b.crossDomain||e["X-Requested-With"]||(e["X-Requested-With"]="XMLHttpRequest");for(g in e)h.setRequestHeader(g,e[g]);c=function(a){return function(){c&&(c=d=h.onload=h.onerror=h.onabort=h.onreadystatechange=null,"abort"===a?h.abort():"error"===a?"number"!=typeof h.status?f(0,"error"):f(h.status,h.statusText):f(Rb[h.status]||h.status,h.statusText,"text"!==(h.responseType||"text")||"string"!=typeof h.responseText?{binary:h.response}:{text:h.responseText},h.getAllResponseHeaders()))}},h.onload=c(),d=h.onerror=c("error"),void 0!==h.onabort?h.onabort=d:h.onreadystatechange=function(){4===h.readyState&&a.setTimeout(function(){c&&d()})},c=c("abort");try{h.send(b.hasContent&&b.data||null)}catch(i){if(c)throw i}},abort:function(){c&&c()}}}),r.ajaxPrefilter(function(a){a.crossDomain&&(a.contents.script=!1)}),r.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/\b(?:java|ecma)script\b/},converters:{"text script":function(a){return r.globalEval(a),a}}}),r.ajaxPrefilter("script",function(a){void 0===a.cache&&(a.cache=!1),a.crossDomain&&(a.type="GET")}),r.ajaxTransport("script",function(a){if(a.crossDomain){var b,c;return{send:function(e,f){b=r(" -``` - -Add little JavaScript: - -```js -var menu = MenuIO({ - 'item name': function onItemNameClick() { - } -} -``` -You could use element and (or) options parameters if you need to. - -```js -var element = document.body, - - options = { - icon : true, /* add class icon-item-name */ - beforeClose : alert, - beforeShow : alert, - beforeClick : alert, - name : 'name of menu' /* if you want use a couple menu on one element */ - }, - - menu = MenuIO(element, options, { - 'item name': function onItemNameClick() { - }); -``` - -Look for `examples` directory or copy example from bottom: - -```html - - - -``` - -#License -MIT diff --git a/modules/menu/bower.json b/modules/menu/bower.json deleted file mode 100644 index d14c9adf..00000000 --- a/modules/menu/bower.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "name": "menu", - "version": "1.0.2", - "homepage": "https://github.com/coderaiser/menu-io", - "authors": [ - "coderaiser " - ], - "description": "Simple css-based multillevel context menu", - "main": "menu-io.min.js", - "moduleType": [ - "globals", - "node" - ], - "keywords": [ - "menu" - ], - "license": "MIT", - "ignore": [ - "**/.*", - "gulpfile.js", - "node_modules" - ] -} diff --git a/modules/menu/example/example.css b/modules/menu/example/example.css deleted file mode 100644 index ffaf39e5..00000000 --- a/modules/menu/example/example.css +++ /dev/null @@ -1,4 +0,0 @@ -html, body, .menu-container { - width: 99%; - height: 99%; -} \ No newline at end of file diff --git a/modules/menu/example/menu-data.js b/modules/menu/example/menu-data.js deleted file mode 100644 index 7cbf7aae..00000000 --- a/modules/menu/example/menu-data.js +++ /dev/null @@ -1,16 +0,0 @@ -var menu, MenuIO; - -(function() { - 'use strict'; - - var element = document.querySelector('#js-menu-container'), - options = { - icon: true - }; - - menu = MenuIO(element, options, { - 'help': function() { - console.log('*help'); - } - }); -})(); diff --git a/modules/menu/example/menu-min.html b/modules/menu/example/menu-min.html deleted file mode 100644 index ed653772..00000000 --- a/modules/menu/example/menu-min.html +++ /dev/null @@ -1,15 +0,0 @@ - - - - - Menu Example - - - - - - - - - - diff --git a/modules/menu/example/menu.html b/modules/menu/example/menu.html deleted file mode 100644 index e3ae64e0..00000000 --- a/modules/menu/example/menu.html +++ /dev/null @@ -1,15 +0,0 @@ - - - - - Menu Example - - - - - - - - - - diff --git a/modules/menu/menu-io.css b/modules/menu/menu-io.css deleted file mode 100644 index d1e0ed0c..00000000 --- a/modules/menu/menu-io.css +++ /dev/null @@ -1,74 +0,0 @@ -.menu-hidden { - display: none; -} - -.menu { - position : absolute; - z-index : 2; - padding : 0; - - font-size : 14px; - - list-style : none; - - color : #222; - - background : rgb(255, 255, 255); - background : rgba(255, 255, 255, 0.9); - - border-color : rgb(49, 123, 249); - border-color : rgba(49, 123, 249, .40); - border-style : solid; - border-width : 1px; - border-radius : 5px; - - -webkit-user-select : none; - -moz-user-select : none; - -ms-user-select : none; - -o-user-select : none; - user-select : none; -} - -.menu-button { - background: white; - border: 0; -} - -.menu-item { - position: relative; - padding: 3px 20px; - white-space: pre; -} - -.menu-item::after { - content: attr(data-key); - float: right; -} - -.menu-item:hover { - background-color: #e3f2ff; -} - -.menu-item > .menu { - top: 0; - left: 100%; - display: none; -} - -.menu-item:hover > .menu { - display: block; -} - -.menu-submenu > label::after { - display: block; - float: right; - width: 0; - height: 0; - margin-top: 3px; - margin-right: -10px; - border-color: transparent; - border-left-color: rgb(49, 123, 249); - border-style: solid; - border-width: 5px 0 5px 5px; - content: " "; -} diff --git a/modules/menu/menu-io.js b/modules/menu/menu-io.js deleted file mode 100644 index b433ff1a..00000000 --- a/modules/menu/menu-io.js +++ /dev/null @@ -1,434 +0,0 @@ -var MenuIO; - -(function (window) { - 'use strict'; - - MenuIO = function(element, options, menuData) { - if (!(this instanceof MenuIO)) { - return new MenuIO(element, options, menuData); - } - - var ElementMenu, - Element, - Options = {}, - ElementFuncs = new ElementFuncsProto(), - ElementHeight, - ElementWidth, - ElementEvent, - MenuFuncs = {}, - TEMPLATE = { - MAIN: '', - ITEM: '' - }; - - if (menuData) { - Element = - ElementEvent = element; - Options = options; - } else if (options) { - Element = - ElementEvent = element; - menuData = options; - } else { - Element = document.body; - ElementEvent = window; - menuData = element; - } - - function init() { - var name, - isObj = typeof menuData === 'object'; - - if (!isObj) { - name = menuData; - menuData = {}; - menuData[name] = null; - } - - ElementMenu = createMenu(menuData); - - ElementEvent.addEventListener('click', onClick); - ElementEvent.addEventListener('contextmenu', onContextMenu); - } - - function createMenu(menuData) { - var menu, - items = '', - buildItems = function(menuData, path) { - var DATA_MENU = 'data-menu="js-submenu"', - Data_KEY = 'data-key=', - items = ''; - - if (path) - path += '.'; - else - path = ''; - - Object.keys(menuData).forEach(function(name) { - var nameIcon, - key = '', - subitems = '', - className = '', - attribute = '', - pathName = path + name, - - data = menuData[name], - isObj = typeof data === 'object'; - - if (!isObj) { - MenuFuncs[pathName] = data; - } else { - subitems = rendy(TEMPLATE.MAIN, { - items: buildItems(data, pathName) - }); - - className = ' menu-submenu'; - attribute = ' ' + DATA_MENU; - } - - if (Options.icon) { - nameIcon = name - .replace(/\(|\)/g, '') - .replace(/\s/g, '-') - .toLowerCase(); - - className += ' icon icon-' + nameIcon; - } - - if (Options.keys) { - key = Options.keys[name]; - - if (key) - attribute = ' ' + Data_KEY + key; - } - - items += rendy(TEMPLATE.ITEM, { - name : name, - subitems : subitems, - className : className, - attribute : attribute, - path : pathName - }); - }); - - return items; - }; - - items = buildItems(menuData); - - menu = document.createElement('ul'); - menu.setAttribute('data-name', 'js-menu'); - menu.className = 'menu menu-hidden'; - menu.innerHTML = items; - - Element.appendChild(menu); - - return menu; - } - - this.show = showMenuElement; - this.hide = hideMenuElement; - - function checkElement(target, position) { - var is, - element = ElementFuncs.getItem(target), - isName = ElementFuncs.isName(element), - isItem = ElementFuncs.isItem(element), - isSub = ElementFuncs.isSubMenu(element); - - if (!isName || !isItem) { - element = document.elementFromPoint(position.x, position.y); - isSub = ElementFuncs.isSubMenu(element); - isName = ElementFuncs.isName(element); - isItem = ElementFuncs.isItem(element); - } - - is = { - name : isName, - item : isItem, - sub : isSub, - }; - - return is; - } - - function onClick(event, checkResult) { - var itemData, notClick, - afterClick = Options.afterClick, - beforeClick = Options.beforeClick, - name = Options.name, - - element = event.target, - is = checkResult || checkElement(element, { - x: event.clientX, - y: event.clientY - }); - - notClick = exec(beforeClick, name); - - if (is.sub) { - event.preventDefault(); - } else { - hideMenuElement(); - - if (!notClick && (is.name || is.item)) { - itemData = getMenuItemData(element); - exec(itemData); - exec(afterClick); - } - } - } - - function onContextMenu(event) { - var element = event.target, - x = event.clientX, - y = event.clientY, - is = checkElement(element, { - x: x, - y: y - }); - - if (is.name || is.item || is.sub) - onClick(event, is); - else { - hideMenuElement(); - showMenuElement(x, y); - } - - event.preventDefault(); - } - - function setMenuPosition(x, y) { - var isNumberX = typeof x === 'number', - isNumberY = typeof y === 'number', - heightMenu = getMenuHeight(), - widthMenu = getMenuWidth(), - heightInner = window.innerHeight, - widthInner = window.innerWidth; - - if (widthInner < widthMenu + x) { - x -= widthMenu; - - if (x < 0) - x = 0; - } - - if (heightInner < heightMenu + y) { - y -= heightMenu; - - if (y < 0) - y = 0; - } - - if (isNumberX) - ElementMenu.style.left = x + 'px'; - - if (isNumberY) - ElementMenu.style.top = y - 14 + 'px'; - } - - function showMenuElement(x, y) { - var beforeShow = Options.beforeShow, - name = Options.name, - params = { - x : x, - y : y, - name : name - }, - - notShow = exec(beforeShow, params); - - if (!notShow) { - ElementMenu.classList.remove('menu-hidden'); - setMenuPosition(params.x, params.y); - } - } - - function hideMenuElement() { - var notHide = exec(Options.beforeClose); - - if (!notHide) - ElementMenu.classList.add('menu-hidden'); - } - - function getMenuItemData(element) { - var path, data; - - element = ElementFuncs.getName(element); - - if (element) { - path = element.getAttribute('data-menu-path'); - } - - data = MenuFuncs[path]; - - return data; - } - - function getMenuHeight() { - var styleComputed, height; - - if (!ElementHeight) { - styleComputed = getComputedStyle(ElementMenu); - height = styleComputed.height; - - ElementHeight = parseInt(height, 10); - } - - return ElementHeight; - } - - function getMenuWidth() { - var styleComputed, width; - - if (!ElementWidth) { - styleComputed = getComputedStyle(ElementMenu); - width = styleComputed.width; - - ElementWidth = parseInt(width, 10); - } - - return ElementWidth; - } - - init(); - }; - - function ElementFuncsProto() { - this.getItem = getItem; - this.getName = getName; - this.isName = isName; - this.isItem = isItem; - this.isMenu = isMenu; - this.isSubMenu = isSubMenu; - - function getItem(element) { - var isNameElement; - - if (element) { - isNameElement = isName(element); - - if (isNameElement) - element = element.parentElement; - } - - return element; - } - - function getName(element) { - var is; - - if (element) { - is = isName(element); - - if (!is) - element = element.querySelector('[data-menu-path]'); - } - - return element; - } - - function isName(element) { - var itIs; - - if (element) - itIs = element.hasAttribute('data-menu-path'); - - return itIs; - } - - function isItem(element) { - var itIs = checkElementsName(element, 'js-menu-item'); - - return itIs; - } - - function isMenu(element) { - var itIs = checkElementsName(element, 'js-menu'); - - return itIs; - } - - function checkElementsName(element, nameElement, attribute) { - var itIs, name; - - if (!attribute) - attribute = 'data-name'; - - if (element) { - name = element.getAttribute(attribute); - - if (name === nameElement) - itIs = true; - } - - return itIs; - } - - function isSubMenu(element) { - var itIs, item, - attribute = 'data-menu', - value = 'js-submenu'; - - item = getItem(element); - itIs = checkElementsName(item, value, attribute); - - return itIs; - } - } - - function exec(callback) { - var ret, - args = [].slice.call(arguments, 1); - - if (typeof callback === 'function') - ret = callback.apply(null, args); - - return ret; - } - - /* - * rendy v1.1.0 - * https://github.com/coderaiser/rendy - */ - - /** - * render template with data - * - * @param templ - * @param data - */ - function rendy(templ, data) { - var result = templ; - - check(templ, data); - - Object - .keys(data) - .forEach(function(param) { - var name = '{{ ' + param + ' }}', - str = data[param]; - - while(~result.indexOf(name)) - result = result.replace(name, str); - }); - - if (~result.indexOf('{{')) - result = result.replace(/{{.*?}}/g, ''); - - return result; - } - - function check(templ, data) { - if (typeof templ !== 'string') - throw(Error('template should be string!')); - - if (typeof data !== 'object') - throw(Error('data should be object!')); - } -})(window); diff --git a/modules/menu/menu-io.min.css b/modules/menu/menu-io.min.css deleted file mode 100644 index 470bd045..00000000 --- a/modules/menu/menu-io.min.css +++ /dev/null @@ -1 +0,0 @@ -.menu-hidden{display:none}.menu{position:absolute;z-index:2;padding:0;font-size:14px;list-style:none;color:#222;background:#fff;background:rgba(255,255,255,.9);border-color:#317bf9;border-color:rgba(49,123,249,.4);border-style:solid;border-width:1px;border-radius:5px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;-o-user-select:none;user-select:none}.menu-button{background:#fff;border:0}.menu-item{position:relative;padding:3px 20px;white-space:pre}.menu-item::after{content:attr(data-key);float:right}.menu-item:hover{background-color:#e3f2ff}.menu-item>.menu{top:0;left:100%;display:none}.menu-item:hover>.menu{display:block}.menu-submenu>label::after{display:block;float:right;width:0;height:0;margin-top:3px;margin-right:-10px;border-color:transparent;border-left-color:#317bf9;border-style:solid;border-width:5px 0 5px 5px;content:" "} \ No newline at end of file diff --git a/modules/menu/menu-io.min.js b/modules/menu/menu-io.min.js deleted file mode 100755 index 906c7b02..00000000 --- a/modules/menu/menu-io.min.js +++ /dev/null @@ -1 +0,0 @@ -var MenuIO;!function(e){"use strict";function t(){function e(e){var t;return e&&(t=n(e),t&&(e=e.parentElement)),e}function t(e){var t;return e&&(t=n(e),t||(e=e.querySelector("[data-menu-path]"))),e}function n(e){var t;return e&&(t=e.hasAttribute("data-menu-path")),t}function a(e){var t=r(e,"js-menu-item");return t}function u(e){var t=r(e,"js-menu");return t}function r(e,t,n){var a,u;return n||(n="data-name"),e&&(u=e.getAttribute(n),u===t&&(a=!0)),a}function i(t){var n,a,u="data-menu",i="js-submenu";return a=e(t),n=r(a,i,u)}this.getItem=e,this.getName=t,this.isName=n,this.isItem=a,this.isMenu=u,this.isSubMenu=i}function n(e){var t,n=[].slice.call(arguments,1);return"function"==typeof e&&(t=e.apply(null,n)),t}function a(e,t){var n=e;return u(e,t),Object.keys(t).forEach(function(e){for(var a="{{ "+e+" }}",u=t[e];~n.indexOf(a);)n=n.replace(a,u)}),~n.indexOf("{{")&&(n=n.replace(/{{.*?}}/g,"")),n}function u(e,t){if("string"!=typeof e)throw Error("template should be string!");if("object"!=typeof t)throw Error("data should be object!")}MenuIO=function(u,r,i){function s(){var e,t="object"==typeof i;t||(e=i,i={},i[e]=null),y=o(i),M.addEventListener("click",c),M.addEventListener("contextmenu",f)}function o(e){var t,n="",u=function(e,t){var n='data-menu="js-submenu"',r="data-key=",i="";return t?t+=".":t="",Object.keys(e).forEach(function(s){var o,m="",c="",f="",l="",d=t+s,h=e[s],b="object"==typeof h;b?(c=a(N.MAIN,{items:u(h,d)}),f=" menu-submenu",l=" "+n):E[d]=h,w.icon&&(o=s.replace(/\(|\)/g,"").replace(/\s/g,"-").toLowerCase(),f+=" icon icon-"+o),w.keys&&(m=w.keys[s],m&&(l=" "+r+m)),i+=a(N.ITEM,{name:s,subitems:c,className:f,attribute:l,path:d})}),i};return n=u(e),t=document.createElement("ul"),t.setAttribute("data-name","js-menu"),t.className="menu menu-hidden",t.innerHTML=n,g.appendChild(t),t}function m(e,t){var n,a=x.getItem(e),u=x.isName(a),r=x.isItem(a),i=x.isSubMenu(a);return u&&r||(a=document.elementFromPoint(t.x,t.y),i=x.isSubMenu(a),u=x.isName(a),r=x.isItem(a)),n={name:u,item:r,sub:i}}function c(e,t){var a,u,r=w.afterClick,i=w.beforeClick,s=w.name,o=e.target,c=t||m(o,{x:e.clientX,y:e.clientY});u=n(i,s),c.sub?e.preventDefault():(h(),u||!c.name&&!c.item||(a=b(o),n(a),n(r)))}function f(e){var t=e.target,n=e.clientX,a=e.clientY,u=m(t,{x:n,y:a});u.name||u.item||u.sub?c(e,u):(h(),d(n,a)),e.preventDefault()}function l(t,n){var a="number"==typeof t,u="number"==typeof n,r=p(),i=v(),s=e.innerHeight,o=e.innerWidth;i+t>o&&(t-=i,0>t&&(t=0)),r+n>s&&(n-=r,0>n&&(n=0)),a&&(y.style.left=t+"px"),u&&(y.style.top=n-14+"px")}function d(e,t){var a=w.beforeShow,u=w.name,r={x:e,y:t,name:u},i=n(a,r);i||(y.classList.remove("menu-hidden"),l(r.x,r.y))}function h(){var e=n(w.beforeClose);e||y.classList.add("menu-hidden")}function b(e){var t,n;return e=x.getName(e),e&&(t=e.getAttribute("data-menu-path")),n=E[t]}function p(){var e,t;return I||(e=getComputedStyle(y),t=e.height,I=parseInt(t,10)),I}function v(){var e,t;return j||(e=getComputedStyle(y),t=e.width,j=parseInt(t,10)),j}if(!(this instanceof MenuIO))return new MenuIO(u,r,i);var y,g,I,j,M,w={},x=new t,E={},N={MAIN:'',ITEM:''};i?(g=M=u,w=r):r?(g=M=u,i=r):(g=document.body,M=e,i=u),this.show=d,this.hide=h,s()}}(window); \ No newline at end of file diff --git a/modules/menu/package.json b/modules/menu/package.json deleted file mode 100644 index 2af60aea..00000000 --- a/modules/menu/package.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "name": "menu", - "version": "1.0.2", - "private": true, - "branch": "gh-pages", - "author": "coderaiser (https://github.com/coderaiser)", - "description": "Simple css-based multillevel context menu", - "homepage": "http://coderaiser.github.io/menu", - "repository": { - "type": "git", - "url": "git://github.com/coderaiser/menu-io.git" - }, - "scripts": { - "test": "npm run lint:css && gulp default", - "lint:css": "stylelint menu-io.css", - "wisdom": "npm test" - }, - "devDependencies": { - "gulp": "^3.8.8", - "gulp-concat": "^2.2.0", - "gulp-jshint": "^1.5.3", - "gulp-minify-css": "^0.3.1", - "gulp-recess": "^0.3.0", - "gulp-rename": "^1.2.0", - "gulp-uglify": "^0.2.1", - "stylelint": "^4.4.0", - "stylelint-config-standard": "^3.0.0" - }, - "license": "MIT", - "engines": { - "node": ">=0.12" - } -} diff --git a/modules/olark/.bower.json b/modules/olark/.bower.json deleted file mode 100644 index af66398d..00000000 --- a/modules/olark/.bower.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "name": "olark", - "homepage": "https://github.com/cloudcmd/olark", - "authors": [ - "coderaiser " - ], - "description": "olark extension for chat", - "main": "olark.min.js", - "keywords": [ - "olark", - "chat" - ], - "license": "MIT", - "ignore": [], - "dependencies": {}, - "version": "1.0.0", - "_release": "1.0.0", - "_resolution": { - "type": "version", - "tag": "v1.0.0", - "commit": "fe00c4e0846a370aa0d5a7b73eb7c08020d18a35" - }, - "_source": "https://github.com/cloudcmd/olark.git", - "_target": "^1.0.0", - "_originalSource": "olark" -} \ No newline at end of file diff --git a/modules/olark/README.md b/modules/olark/README.md deleted file mode 100644 index 7607ccf7..00000000 --- a/modules/olark/README.md +++ /dev/null @@ -1,18 +0,0 @@ -# Olark - -Extracted instalation code for [olark](https://www.olark.com) to install via bower. - -## Install - -``` -bower i olark --save -``` - -## How to use? - -Add `olark.min.js` to your page and initialize olark with site id: - -```js -olark.identify('xxxx-xxx-xx-xxxx'); -``` - diff --git a/modules/olark/bower.json b/modules/olark/bower.json deleted file mode 100644 index 56936bba..00000000 --- a/modules/olark/bower.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "name": "olark", - "homepage": "https://github.com/cloudcmd/olark", - "authors": [ - "coderaiser " - ], - "description": "olark extension for chat", - "main": "olark.min.js", - "keywords": [ - "olark", - "chat" - ], - "license": "MIT", - "ignore": [ - ], - "dependencies": { - } -} - diff --git a/modules/olark/olark.js b/modules/olark/olark.js deleted file mode 100644 index cf51c24c..00000000 --- a/modules/olark/olark.js +++ /dev/null @@ -1,86 +0,0 @@ -window.olark || (function (c) { - var f = window, - d = document, - l = f.location.protocol == "https:" ? "https:" : "http:", - z = c.name, - r = "load"; - var nt = function () { - f[z] = function () { - (a.s = a.s || []).push(arguments); - }; - var a = f[z]._ = {}, q = c.methods.length; - while (q--) { - (function (n) { - f[z][n] = function () { - f[z]("call", n, arguments); - }; - })(c.methods[q]); - } - a.l = c.loader; - a.i = nt; - a.p = { - 0: +new Date() - }; - a.P = function (u) { - a.p[u] = new Date() - a.p[0]; - }; - - function s() { - a.P(r); - f[z](r); - } - f.addEventListener ? f.addEventListener(r, s, false) : f.attachEvent("on" + r, s); - var ld = function () { - function p(hd) { - hd = "head"; - return ["<", hd, "><", i, ' onl' + 'oad="var d=', g, ";d.getElementsByTagName('head')[0].", j, "(d.", h, "('script')).", k, "='", l, "//", a.l, "'", '"', ">"].join(""); - } - var i = "body", - m = d[i]; - if (!m) { - return setTimeout(ld, 100); - } - a.P(1); - var j = "appendChild", - h = "createElement", - k = "src", - n = d[h]("div"), - v = n[j](d[h](z)), - b = d[h]("iframe"), - g = "document", - e = "domain", - o; - n.style.display = "none"; - m.insertBefore(n, m.firstChild).id = z; - b.frameBorder = "0"; - b.id = z + "-loader"; - if (/MSIE[ ]+6/.test(navigator.userAgent)) { - b.src = "javascript:false"; - } - b.allowTransparency = "true"; - v[j](b); - try { - b.contentWindow[g].open(); - } catch (w) { - c[e] = d[e]; - o = "javascript:var d=" + g + ".open();d.domain='" + d.domain + "';"; - b[k] = o + "void(0);"; - } - try { - var t = b.contentWindow[g]; - t.write(p()); - t.close(); - } catch (x) { - b[k] = o + 'd.write("' + p().replace(/"/g, String.fromCharCode(92) + '"') + '");d.close();'; - } - a.P(2); - }; - ld(); - }; - nt(); -})({ - loader: "static.olark.com/jsclient/loader0.js", - name: "olark", - methods: ["configure", "extend", "declare", "identify"] -}); - diff --git a/modules/olark/olark.min.js b/modules/olark/olark.min.js deleted file mode 100644 index e6d5378f..00000000 --- a/modules/olark/olark.min.js +++ /dev/null @@ -1,17 +0,0 @@ -window.olark||(function(c){var f=window,d=document,l=f.location.protocol=="https:"?"https:":"http:",z=c.name,r="load";var nt=function(){ -f[z]=function(){ -(a.s=a.s||[]).push(arguments)};var a=f[z]._={ -},q=c.methods.length;while(q--){(function(n){f[z][n]=function(){ -f[z]("call",n,arguments)}})(c.methods[q])}a.l=c.loader;a.i=nt;a.p={ -0:+new Date};a.P=function(u){ -a.p[u]=new Date-a.p[0]};function s(){ -a.P(r);f[z](r)}f.addEventListener?f.addEventListener(r,s,false):f.attachEvent("on"+r,s);var ld=function(){function p(hd){ -hd="head";return["<",hd,"><",i,' onl' + 'oad="var d=',g,";d.getElementsByTagName('head')[0].",j,"(d.",h,"('script')).",k,"='",l,"//",a.l,"'",'"',">"].join("")}var i="body",m=d[i];if(!m){ -return setTimeout(ld,100)}a.P(1);var j="appendChild",h="createElement",k="src",n=d[h]("div"),v=n[j](d[h](z)),b=d[h]("iframe"),g="document",e="domain",o;n.style.display="none";m.insertBefore(n,m.firstChild).id=z;b.frameBorder="0";b.id=z+"-loader";if(/MSIE[ ]+6/.test(navigator.userAgent)){ -b.src="javascript:false"}b.allowTransparency="true";v[j](b);try{ -b.contentWindow[g].open()}catch(w){ -c[e]=d[e];o="javascript:var d="+g+".open();d.domain='"+d.domain+"';";b[k]=o+"void(0);"}try{ -var t=b.contentWindow[g];t.write(p());t.close()}catch(x){ -b[k]=o+'d.write("'+p().replace(/"/g,String.fromCharCode(92)+'"')+'");d.close();'}a.P(2)};ld()};nt()})({ -loader: "static.olark.com/jsclient/loader0.js",name:"olark",methods:["configure","extend","declare","identify"]}); - diff --git a/modules/philip/.bower.json b/modules/philip/.bower.json deleted file mode 100644 index cf8380e9..00000000 --- a/modules/philip/.bower.json +++ /dev/null @@ -1,38 +0,0 @@ -{ - "name": "philip", - "homepage": "https://github.com/coderaiser/domfs-philip", - "authors": [ - "coderaiser " - ], - "description": "Walk a directory tree in DOM File System", - "main": "lib/philip.js", - "moduleType": [ - "globals", - "node" - ], - "keywords": [ - "DOM", - "File System" - ], - "license": "MIT", - "ignore": [ - "**/.*", - "node_modules", - "modules" - ], - "dependencies": { - "execon": "~1.2.2", - "emitify": "3.0.2", - "findit": "1.1.7" - }, - "version": "1.3.6", - "_release": "1.3.6", - "_resolution": { - "type": "version", - "tag": "v1.3.6", - "commit": "7475a4547d8a8abe3f615ac983a41ef26d14509b" - }, - "_source": "https://github.com/coderaiser/domfs-philip.git", - "_target": "1.3.6", - "_originalSource": "philip" -} \ No newline at end of file diff --git a/modules/philip/ChangeLog b/modules/philip/ChangeLog deleted file mode 100644 index 845ed262..00000000 --- a/modules/philip/ChangeLog +++ /dev/null @@ -1,74 +0,0 @@ -2017.05.10, v1.3.6 - -feature: -- (bower) emitify v3.0.2 - - -2017.04.28, v1.3.5 - -feature: -- (bower) emitify v3.0.1 - - -2016.07.14, v1.3.4 - -feature: -- (bower) findit v1.1.6 -- (bower) v2.1.1 - - -2016.06.03, v1.3.3 - -feature: -- (bower) emitify v2.1.0 - - -2015.12.29, v1.3.2 - -feature: -- (bower) findit v1.1.4 -- (bower) emitify v2.0.0 - - -2015.09.30, v1.3.1 - -feature: -- (bower) findit v1.1.3 -- (philip) emitify v1.3.0 - - -2015.07.20, v1.3.0 - -feature: -- (philip) add optional parameters to processingFn: i, n - - -2015.07.19, v1.2.1 - -fix: -- (philip) _getFiles: to fast callback call - - -2015.07.18, v1.2.0 - -fix: -- (philip) not all files was processed - - -2015.07.17, v1.1.2 - -feature: -- (philip) emit progress only when value changed - - -2015.07.16, v1.1.1 - -feature: -- (philip) inherit from Emitify - - -2015.07.16, v1.1.0 - -feature: -- (philip) add abort, pause, continue - diff --git a/modules/philip/LICENSE b/modules/philip/LICENSE deleted file mode 100644 index a103b669..00000000 --- a/modules/philip/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2015 coderaiser - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/modules/philip/README.md b/modules/philip/README.md deleted file mode 100644 index be394cd8..00000000 --- a/modules/philip/README.md +++ /dev/null @@ -1,77 +0,0 @@ -# Philip - -[Dom File System](https://developer.mozilla.org/en-US/docs/Web/API/FileSystem "Dom File System") processing library - -## Install - -``` -bower i philip --save -``` - -## How to use? - -Add `philip.js` [findit](https://github.com/coderaiser/domfs-findit "Find It"), [execon](https://github.com/coderaiser/execon "Patterns of function calls")(or [async](https://github.com/caolan/async "Async utilities for node and the browser" with `window.exec = window.async`) and [emitify](https://github.com/coderaiser/emitify "Emitify"). - -Or any other node-compitable [EventEmitter](https://iojs.org/api/events.html "Events") (set `window.Emitify = your_emitter` before using `findit`). - -```html - - - -``` - -```js -(function() { - 'use strict'; - - var node = window; - - node.addEventListener('drop', function (e) { - var upload, - entry, - finder, - item = e.dataTransfer.items[0]; - - e.preventDefault(); - - entry = item.webkitGetAsEntry(); - - upload = philip(entry, function(type, name, data/*, i, n,*/, callback) { - var error = null; - - switch(type) { - case 'file': - console.log('file', name, data); - break; - - case 'directory': - console.log('directory', name); - break; - } - - callback(error); - }); - - upload.on('error', function(error) { - upload.abort(); - console.error(error); - }); - - upload.on('progress', function(count) { - console.log(count); - }); - - upload.on('end', function() { - console.log('done'); - }); - }); - - node.addEventListener('dragover', function (e) { - e.preventDefault(); - }); -})(); -``` - -## License - -MIT diff --git a/modules/philip/bower.json b/modules/philip/bower.json deleted file mode 100644 index c029d28e..00000000 --- a/modules/philip/bower.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "name": "philip", - "homepage": "https://github.com/coderaiser/domfs-philip", - "authors": [ - "coderaiser " - ], - "description": "Walk a directory tree in DOM File System", - "main": "lib/philip.js", - "moduleType": [ - "globals", - "node" - ], - "keywords": [ - "DOM", - "File System" - ], - "license": "MIT", - "ignore": [ - "**/.*", - "node_modules", - "modules" - ], - "dependencies": { - "execon": "~1.2.2", - "emitify": "3.0.2", - "findit": "1.1.7" - } -} diff --git a/modules/philip/example/index.html b/modules/philip/example/index.html deleted file mode 100644 index 956e7730..00000000 --- a/modules/philip/example/index.html +++ /dev/null @@ -1,55 +0,0 @@ - - - - - - diff --git a/modules/philip/lib/philip.js b/modules/philip/lib/philip.js deleted file mode 100644 index 99e3c44f..00000000 --- a/modules/philip/lib/philip.js +++ /dev/null @@ -1,172 +0,0 @@ -/* global Emitify */ -/* global findit */ -/* global exec */ - -(function(global) { - 'use strict'; - - if (typeof module !== 'undefined' && module.exports) - module.exports = Philip; - else - global.philip = Philip; - - Philip.prototype = Object.create(Emitify.prototype); - - function Philip(entries, processingFn) { - var array, - self; - - if (!(this instanceof Philip)) - return new Philip(entries, processingFn); - - if (typeof processingFn !== 'function') - throw Error('processingFn should be function!'); - - Emitify.call(this); - - if (Array.isArray(entries)) - array = entries; - else - array = [entries]; - - self = this; - - this._i = 0; - this._n = 0; - this._processingFn = processingFn; - this._pause = false; - this._prev = 0; - - this._find(array, function(files, dirs) { - self._files = files; - self._dirs = dirs; - self._n = files.length + dirs.length; - self._data = {}; - - self._getFiles(files, self._data, function() { - self._process(); - }); - }); - } - - Philip.prototype._process = function() { - var args, - argsLength = this._processingFn.length, - el, - data, - self = this, - name = self._dirs.shift(), - type = 'directory', - fn = function(error) { - ++self._i; - - if (error) { - self.emit('error', error); - self.pause(); - } - - self._process(); - self._progress(); - }; - - if (!name) { - type = 'file'; - el = self._files.shift(); - - if (el) { - name = el.fullPath; - data = self._data[name]; - } - } - - if (!name) { - self.emit('end'); - } else if (!this._pause) { - switch(argsLength) { - default: - args = [type, name, data]; - break; - - case 6: - args = [type, name, data, this._i, this._n]; - break; - } - - args.push(fn); - - self._processingFn.apply(null, args); - } - }; - - Philip.prototype.pause = function() { - this._pause = true; - }; - - Philip.prototype.continue = function() { - if (this._pause) { - this._pause = false; - this._process(); - } - }; - - Philip.prototype.abort = function() { - this._files = []; - this._dirs = []; - - this._process(); - }; - - Philip.prototype._progress = function() { - var value = Math.round(this._i * 100 / this._n); - - if (value !== this._prev) { - this._prev = value; - this.emit('progress', value); - } - }; - - Philip.prototype._getFiles = function(files, obj, callback) { - var current, - self = this; - - files = files.slice(); - current = files.shift(); - - if (!obj) - obj = {}; - - if (!current) - callback(null, obj); - else - current.file(function(file) { - var name = current.fullPath; - - obj[name] = file; - - self._getFiles(files, obj, callback); - }); - }; - - Philip.prototype._find = function(entries, fn) { - var files = [], - dirs = []; - - exec.each(entries, function(entry, callback) { - var finder = findit(entry); - - finder.on('directory', function(name) { - dirs.push(name); - }); - - finder.on('file', function(name, current) { - files.push(current); - }); - - finder.on('end', function() { - callback(); - }); - }, function() { - fn(files, dirs); - }); - }; -})(this); diff --git a/modules/philip/package.json b/modules/philip/package.json deleted file mode 100644 index 2df5c320..00000000 --- a/modules/philip/package.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "name": "philip", - "private": true, - "version": "1.3.6", - "description": "Process files and directories in DOM File System", - "main": "lib/philip.js", - "dependencies": {}, - "devDependencies": {}, - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" - }, - "repository": { - "type": "git", - "url": "git://github.com/coderaiser/domfs-philip.git" - }, - "keywords": [ - "philip", - "DOM", - "File System" - ], - "author": "coderaiser (http://coderaiser.github.io/)", - "license": "MIT", - "bugs": { - "url": "https://github.com/coderaiser/domfs-philip/issues" - }, - "homepage": "https://github.com/coderaiser/domfs-philip" -} diff --git a/modules/smalltalk/.bower.json b/modules/smalltalk/.bower.json deleted file mode 100644 index 19194f8b..00000000 --- a/modules/smalltalk/.bower.json +++ /dev/null @@ -1,39 +0,0 @@ -{ - "name": "smalltalk", - "homepage": "https://github.com/coderaiser/smalltalk", - "authors": [ - "coderaiser " - ], - "description": "Promise-based Alert, Confirm and Prompt replacement", - "main": "dist/smalltalk.min.js", - "moduleType": [ - "globals", - "node" - ], - "keywords": [ - "modal", - "alert", - "prompt", - "confirm" - ], - "license": "MIT", - "ignore": [ - "**/.*", - "screen", - "example", - "test", - "webpack.config.js" - ], - "dependencies": {}, - "version": "2.3.1", - "_release": "2.3.1", - "_resolution": { - "type": "version", - "tag": "v2.3.1", - "commit": "fffdfc6c567ae774f6fbf033b74788aa366317dc" - }, - "_source": "https://github.com/coderaiser/smalltalk.git", - "_target": "^2.3.1", - "_originalSource": "smalltalk", - "_direct": true -} \ No newline at end of file diff --git a/modules/smalltalk/ChangeLog b/modules/smalltalk/ChangeLog deleted file mode 100644 index c05b1ffa..00000000 --- a/modules/smalltalk/ChangeLog +++ /dev/null @@ -1,294 +0,0 @@ -2017.05.17, v2.3.1 - -feature: -- (bower) ignore: add webpack.config.js - - -2017.05.17, v2.3.0 - -feature: -- (package) browserify -> webpack: add sourcemaps - - -2017.05.16, v2.2.2 - -fix: -- (smalltalk) prompt value is a number - - -2017.05.10, v2.2.1 - -fix: -- feature(package) autoprefixer v7.0.1 - -feature: -- (package) postcss-cli v4.0.0 -- (package) autoprefixer v7.0.1 -- (package) postcss-cli v3.0.0 -- (package) sinon v2.0.0 - - -2017.02.24, v2.2.0 - -fix: -- test(smalltalk) fixture: confirm, prompt -- test(smalltalk) alert: fixture - -feature: -- (smalltalk) add currify - - -2017.02.23, v2.1.4 - -fix: -- (smalltalk) double quotes (#2) - -feature: -- (package) stylelint-config-standard v16.0.0 -- (package) browserify v14.0.0 -- (package) systemjs v0.20.2 -- (package) nyc v10.0.0 -- (package) stylelint-config-standard v15.0.0 -- (package) nyc v9.0.1 -- (package) stylelint-config-standard v14.0.0 - - -2016.10.04, v2.1.3 - -feature: -- (smalltalk) showDialog: if -> ternary -- (package) stylelint-config-standard v13.0.0 -- (package) nyc v8.1.0 - - -2016.08.08, v2.1.2 - -fix: -- (smalltalk) get back old way of hiding all but first - -feature: -- (package) stylelint-config-standard v12.0.0 - - -2016.07.25, v2.1.1 - -fix: -- (smalltalk.native) confirm options: noCancel -> cancel - -feature: -- (package) promise-polyfill v6.0.0 - - -2016.07.20, v2.1.0 - -fix: -- feature(package) add postcss, autoprefixer - -feature: -- (smalltalk) hide all windows but first, no matter where they located in DOM -- (travis) node v6 -- (package) add postcss, autoprefixer -- (package) stylelint-config-standard v11.0.0 -- (package) stylelint v7.0.2 - - -2016.07.15, v2.0.0 - -feature: -- (npmignore) add -- (package) add legacy:index -- (smalltalk) hide all bu first -- (bower) ignore: clean -- (smalltalk) alert: rm options -- (package) lint: add eslint -- (smalltalk) src -> lib -- (gitignore) legacy -- (package) add bundle -- (example) add legacy -- (smalltalk) IIFE -> commonjs -- (jshint) esversion: 6 -- (package) redrun v5.0.0 -- (package) add lint -- (package) redrun v5.0.0 -- (package) stylelint-config-standard v10.0.0 -- (package) redrun v4.0.0 -- (package) watch v0.19.1 -- (package) stylelint-config-standard v9.0.0 -- (package) stylelint-config-standard v8.0.0 - - -2016.05.10, v1.6.8 - -feature: -- (package) v0.18.0 -- (package) stylelint-config-standard v7.0.0 -- (package) promise-polyfill v5.1.0 -- (package) redrun v3.0.0 -- (package) stylelint v6.2.2 -- (package) jscs v3.0.3 -- (package) stylelint-config-standard v5.0.0 -- (package) stylelint v5.1.0, stylelint-config-standard v4.0.1 - - -2016.03.21, v1.6.7 - -feature: -- (package) promise-poyfill v4.0.1 -- (travis) notifications: default - - -2016.03.01, v1.6.6 - -feature: -- (package) add stylelint -- (smalltalk) .button: rm outline - - -2016.01.10, v1.6.5 - -feature: -- (package) promise-polyfill v3.0.0 -- (travis) node v5 -- (package) watch v0.17.1 - - -2015.12.09, v1.6.4 - -feature: -- (smalltalk) bind: slice -> rest - - -2015.12.05, v1.6.3 - -fix: -- (package) minify-css -> minify:css - - -2015.12.05, v1.6.2 - -feature: -- (smalltalk) add z-index -- (package) babel v6 -- (package) add npm-run-all - - -2015.11.02, v1.6.1 - -fix: -- (smalltalk) .content-area: rm nowrap - - -2015.11.02, v1.6.0 - -feature: -- (smalltalk) cut content when it is to large - - -2015.10.29, v1.5.6 - -feature: -- (package) 6to5: --blacklist strict -- (package) devDependencies: ~ -> ^ -- (package) minify v2.0.0 - - -2015.10.26, v1.5.5 - -fix: -- (package) build-native-full - -feature: -- (gitignore) npm-debug.log -> npm-debug.log* - - -2015.10.26, v1.5.4 - -feature: -- (smalltalk) addListenerAll: fn(event) -> fn - - -2015.10.14, v1.5.3 - -fix: -- (smalltalk) prompt: focus on ok -> focus on input - - -2015.09.30, v1.5.2 - -fix: -- (smalltalk) changeButtons: when input active - - -2015.09.29, v1.5.1 - -feature: -- (smalltalk) add es6 native - - -2015.09.28, v1.5.0 - -feature: -- (smalltalk) add native - - -2015.09.26, v1.4.1 - -feature: -- (bower) rm promise-polyfill - - -2015.09.26, v1.4.0 - -feature: -- (smalltalk) Cancel, OK -> OK, Cancel - - -2015.09.26, v1.3.4 - -fix: -- (smalltalk) keyDown enter: prevent pass next - -feature: -- (package) add jscs -- (package) add jshint support - - -2015.09.24, v1.3.3 - -feature: -- (smalltalk) header: add font-weight - - -2015.09.24, v1.3.2 - -feature: -- (smalltalk) h1 -> header -- (smalltalk) .content-area: add max-width - - -2015.09.23, v1.3.1 - -fix: -- (smalltalk) changeButtonFocus: left, right, up, down do not work with confirm - - -2015.09.23, v1.3.0 - -feature: -- (smalltalk) add handling of keys: left, right, up, down - - -2015.09.23, v1.2.0 - -feature: -- (smalltalk) keyDown: add stopPropogation -- (smalltalk) .smalltalk: rm background-color - - -2015.09.22, v1.1.0 - -feature: -- (package) scripts build: add build-poly -- (smalltalk) add options {cancel} -- (screen) add - diff --git a/modules/smalltalk/LICENSE b/modules/smalltalk/LICENSE deleted file mode 100644 index a103b669..00000000 --- a/modules/smalltalk/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2015 coderaiser - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/modules/smalltalk/README.md b/modules/smalltalk/README.md deleted file mode 100644 index 5a5a1df6..00000000 --- a/modules/smalltalk/README.md +++ /dev/null @@ -1,85 +0,0 @@ -# Smalltalk [![License][LicenseIMGURL]][LicenseURL] [![NPM version][NPMIMGURL]][NPMURL] [![Dependency Status][DependencyStatusIMGURL]][DependencyStatusURL] [![Build Status][BuildStatusIMGURL]][BuildStatusURL] [![Coverage][CoverageIMGURL]][CoverageURL] - -Simple [Promise](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Promise)-based replacement of native Alert, Confirm and Prompt. - -# Install -With help of [bower](http://bower.io "Bower"). - -``` -bower install smalltalk -``` - -Or npm: - -``` -npm i smalltalk -``` - -# API - -In every method of `smalltalk` last parameter *options* is optional and could be used -for preventing of handling cancel event. - -```js -{ - cancel: true /* default */ -} -``` - -## smalltalk.alert(title, message) - -![Alert](https://raw.githubusercontent.com/coderaiser/smalltalk/master/screen/alert.png "Alert") - -```js -smalltalk.alert('Error', 'There was an error!').then(function() { - console.log('ok'); -}); -``` - -## smalltalk.confirm(title, message [, options]) - -![Confirm](https://raw.githubusercontent.com/coderaiser/smalltalk/master/screen/confirm.png "Confirm") - -```js -smalltalk.confirm('Question', 'Are you sure?').then(function() { - console.log('yes'); -}, function() { - console.log('no'); -}); -``` - -## smalltalk.prompt(title, message, value [, options]) - -![Prompt](https://raw.githubusercontent.com/coderaiser/smalltalk/master/screen/prompt.png "Prompt") - -```js -smalltalk.prompt('Question', 'How old are you?', '10').then(function(value) { - console.log(value); -}, function() { - console.log('cancel'); -}); -``` - -## Bundlers - -When `webpack` `rollup` or `browserify` used, you can import `es5` version with: - -```js -import smalltalk from 'smalltalk/legacy'; -``` - -# License -MIT - -[NPMIMGURL]: https://img.shields.io/npm/v/smalltalk.svg?style=flat -[BuildStatusIMGURL]: https://img.shields.io/travis/coderaiser/smalltalk/master.svg?style=flat -[DependencyStatusIMGURL]: https://img.shields.io/gemnasium/coderaiser/smalltalk.svg?style=flat -[LicenseIMGURL]: https://img.shields.io/badge/license-MIT-317BF9.svg?style=flat -[NPMURL]: https://npmjs.org/package/smalltalk "npm" -[BuildStatusURL]: https://travis-ci.org/coderaiser/smalltalk "Build Status" -[DependencyStatusURL]: https://gemnasium.com/coderaiser/smalltalk "Dependency Status" -[LicenseURL]: https://tldrlegal.com/license/mit-license "MIT License" - -[CoverageURL]: https://coveralls.io/github/coderaiser/smalltalk?branch=master -[CoverageIMGURL]: https://coveralls.io/repos/coderaiser/smalltalk/badge.svg?branch=master&service=github - diff --git a/modules/smalltalk/bower.json b/modules/smalltalk/bower.json deleted file mode 100644 index e2d28370..00000000 --- a/modules/smalltalk/bower.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "name": "smalltalk", - "homepage": "https://github.com/coderaiser/smalltalk", - "authors": [ - "coderaiser " - ], - "description": "Promise-based Alert, Confirm and Prompt replacement", - "main": "dist/smalltalk.min.js", - "moduleType": [ - "globals", - "node" - ], - "keywords": [ - "modal", - "alert", - "prompt", - "confirm" - ], - "license": "MIT", - "ignore": [ - "**/.*", - "screen", - "example", - "test", - "webpack.config.js" - ], - "dependencies": {} -} diff --git a/modules/smalltalk/css/smalltalk.css b/modules/smalltalk/css/smalltalk.css deleted file mode 100644 index 7f5adc35..00000000 --- a/modules/smalltalk/css/smalltalk.css +++ /dev/null @@ -1,154 +0,0 @@ -.smalltalk { - display: flex; - - align-items: center; - flex-direction: column; - justify-content: center; - - transition: 200ms opacity; - - bottom: 0; - left: 0; - overflow: auto; - padding: 20px; - position: fixed; - right: 0; - top: 0; - - z-index: 100; -} - -.smalltalk + .smalltalk { - transition: ease 1s; - display: none; -} - -.smalltalk .page { - border-radius: 3px; - background: white; - box-shadow: 0 4px 23px 5px rgba(0, 0, 0, .2), 0 2px 6px rgba(0, 0, 0, .15); - color: #333; - min-width: 400px; - padding: 0; - position: relative; - z-index: 0; -} - -@media only screen and (max-width: 500px) { - .smalltalk .page { - min-width: 0; - } -} - -.smalltalk .page > .close-button { - background-image: url(../img/IDR_CLOSE_DIALOG.png); - background-position: center; - background-repeat: no-repeat; - height: 14px; - position: absolute; - right: 7px; - top: 7px; - width: 14px; - z-index: 1; -} - -.smalltalk .page > .close-button:hover { - background-image: url(../img/IDR_CLOSE_DIALOG_H.png); -} - -.smalltalk .page header { - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - max-width: 500px; - - user-select: none; - color: #333; - font-size: 120%; - font-weight: bold; - margin: 0; - padding: 14px 17px; - text-shadow: white 0 1px 2px; -} - -.smalltalk .page .content-area { - overflow: hidden; - text-overflow: ellipsis; - - padding: 6px 17px; - position: relative; - max-width: 500px; -} - -.smalltalk .page .action-area { - padding: 14px 17px; -} - -.smalltalk .page .button-strip { - display: flex; - - flex-direction: row; - justify-content: flex-end; -} - -.smalltalk .page .button-strip > button { - margin-left: 10px; -} - -.smalltalk button:enabled:focus, .smalltalk input:enabled:focus { - transition: border-color 200ms; - border-color: rgb(77, 144, 254); - outline: none; -} - -.smalltalk button:enabled:active { - background-image: linear-gradient(#e7e7e7, #e7e7e7 38%, #d7d7d7); - box-shadow: none; - text-shadow: none; -} - -.smalltalk button, .smalltalk .smalltalk { - min-height: 2em; - min-width: 4em; -} - -.smalltalk button::-moz-focus-inner { - border: 0; -} - -.smalltalk button { - appearance: none; - user-select: none; - background-image: linear-gradient(#ededed, #ededed 38%, #dedede); - - border: 1px solid rgba(0, 0, 0, 0.25); - border-radius: 2px; - box-shadow: 0 1px 0 rgba(0, 0, 0, 0.08), inset 0 1px 2px rgba(255, 255, 255, 0.75); - color: #444; - font: inherit; - margin: 0 1px 0 0; - text-shadow: 0 1px 0 rgb(240, 240, 240); -} - -.smalltalk button:enabled:focus, .smalltalk input:enabled:focus { - transition: border-color 200ms; - border-color: rgb(77, 144, 254); - outline: none; -} - -.smalltalk input { - width: 100%; - border: 1px solid #bfbfbf; - border-radius: 2px; - box-sizing: border-box; - color: #444; - font: inherit; - margin: 0; - min-height: 2em; - padding: 3px; - outline: none; -} - -button { - font-family: Ubuntu, Arial, sans-serif; -} diff --git a/modules/smalltalk/dist/smalltalk.min.css b/modules/smalltalk/dist/smalltalk.min.css deleted file mode 100644 index f52dbba9..00000000 --- a/modules/smalltalk/dist/smalltalk.min.css +++ /dev/null @@ -1,2 +0,0 @@ -.smalltalk{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;-webkit-transition:.2s opacity;transition:.2s opacity;bottom:0;left:0;overflow:auto;padding:20px;position:fixed;right:0;top:0;z-index:100}.smalltalk .page .content-area,.smalltalk .page header{overflow:hidden;text-overflow:ellipsis;max-width:500px}.smalltalk+.smalltalk{-webkit-transition:ease 1s;transition:ease 1s;display:none}.smalltalk .page{border-radius:3px;background:#fff;-webkit-box-shadow:0 4px 23px 5px rgba(0,0,0,.2),0 2px 6px rgba(0,0,0,.15);box-shadow:0 4px 23px 5px rgba(0,0,0,.2),0 2px 6px rgba(0,0,0,.15);color:#333;min-width:400px;padding:0;position:relative;z-index:0}@media only screen and (max-width:500px){.smalltalk .page{min-width:0}}.smalltalk .page>.close-button{background-image:url(../img/IDR_CLOSE_DIALOG.png);background-position:center;background-repeat:no-repeat;height:14px;position:absolute;right:7px;top:7px;width:14px;z-index:1}.smalltalk .page>.close-button:hover{background-image:url(../img/IDR_CLOSE_DIALOG_H.png)}.smalltalk .page header{white-space:nowrap;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;color:#333;font-size:120%;font-weight:700;margin:0;padding:14px 17px;text-shadow:#fff 0 1px 2px}.smalltalk .page .content-area{padding:6px 17px;position:relative}.smalltalk .page .action-area{padding:14px 17px}.smalltalk .page .button-strip{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row;-webkit-box-pack:end;-ms-flex-pack:end;justify-content:flex-end}.smalltalk .page .button-strip>button{margin-left:10px}.smalltalk button:enabled:active{background-image:-webkit-gradient(linear,left top,left bottom,from(#e7e7e7),color-stop(38%,#e7e7e7),to(#d7d7d7));background-image:linear-gradient(#e7e7e7,#e7e7e7 38%,#d7d7d7);-webkit-box-shadow:none;box-shadow:none;text-shadow:none}.smalltalk .smalltalk,.smalltalk button{min-height:2em;min-width:4em}.smalltalk button::-moz-focus-inner{border:0}.smalltalk button{-webkit-appearance:none;-moz-appearance:none;appearance:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background-image:-webkit-gradient(linear,left top,left bottom,from(#ededed),color-stop(38%,#ededed),to(#dedede));background-image:linear-gradient(#ededed,#ededed 38%,#dedede);border:1px solid rgba(0,0,0,.25);border-radius:2px;-webkit-box-shadow:0 1px 0 rgba(0,0,0,.08),inset 0 1px 2px rgba(255,255,255,.75);box-shadow:0 1px 0 rgba(0,0,0,.08),inset 0 1px 2px rgba(255,255,255,.75);color:#444;font:inherit;margin:0 1px 0 0;text-shadow:0 1px 0 #f0f0f0}.smalltalk button:enabled:focus,.smalltalk input:enabled:focus{-webkit-transition:border-color .2s;transition:border-color .2s;border-color:#4d90fe;outline:0}.smalltalk input{width:100%;border:1px solid #bfbfbf;border-radius:2px;-webkit-box-sizing:border-box;box-sizing:border-box;color:#444;font:inherit;margin:0;min-height:2em;padding:3px;outline:0}button{font-family:Ubuntu,Arial,sans-serif} -/*# sourceMappingURL=smalltalk.min.css.map */ \ No newline at end of file diff --git a/modules/smalltalk/dist/smalltalk.min.js b/modules/smalltalk/dist/smalltalk.min.js deleted file mode 100644 index fb8ac210..00000000 --- a/modules/smalltalk/dist/smalltalk.min.js +++ /dev/null @@ -1,2 +0,0 @@ -var smalltalk=function(n){function t(r){if(e[r])return e[r].exports;var o=e[r]={i:r,l:!1,exports:{}};return n[r].call(o.exports,o,o.exports,t),o.l=!0,o.exports}var e={};return t.m=n,t.c=e,t.i=function(n){return n},t.d=function(n,e,r){t.o(n,e)||Object.defineProperty(n,e,{configurable:!1,enumerable:!0,get:r})},t.n=function(n){var e=n&&n.__esModule?function(){return n.default}:function(){return n};return t.d(e,"a",e),e},t.o=function(n,t){return Object.prototype.hasOwnProperty.call(n,t)},t.p="",t(t.s=2)}([function(n,t){n.exports=es6-promise},function(n,t,e){n.exports=e(4)},function(n,t,e){"use strict";function r(n,t,e,r){return'
    \n
    \n
    '+n+'
    \n
    \n '+t+"\n "+e+'\n
    \n
    \n
    '+r.map(function(n,t){return""}).join("")+"\n
    \n
    \n
    "}function o(n,t,e,o,u){var c=g(),i=g(),a=document.createElement("div"),p=["cancel","close","ok"],d=new Promise(function(n,t){var e=u&&!u.cancel,r=function(){};c(n),i(e?r:t)}),m=r(n,t,e,o);return a.innerHTML=m,a.className="smalltalk",document.body.appendChild(a),l(a,["ok","input"]).forEach(function(n){return n.focus()}),l(a,["input"]).forEach(function(n){n.setSelectionRange(0,e.length)}),s("click",a,p,function(n){return f(n.target,a,c(),i())}),["click","contextmenu"].forEach(function(n){return a.addEventListener(n,function(){return l(a,["ok","input"]).forEach(function(n){return n.focus()})})}),a.addEventListener("keydown",v(a,c(),i())),d}function u(n,t,e,r){var o={ENTER:13,ESC:27,TAB:9,LEFT:37,UP:38,RIGHT:39,DOWN:40},u=r.keyCode,s=r.target,p=["ok","cancel","input"],d=l(n,p).map(c);switch(u){case o.ENTER:f(s,n,t,e),r.preventDefault();break;case o.ESC:m(),e();break;case o.TAB:r.shiftKey&&a(n,d),a(n,d),r.preventDefault();break;default:["left","right","up","down"].filter(function(n){return u===o[n.toUpperCase()]}).forEach(function(){i(n,d)})}r.stopPropagation()}function c(n){return n.getAttribute("data-name").replace("js-","")}function i(n,t){var e=document.activeElement,r=c(e),o=/ok|cancel/.test(r),u=t.length-1;if("input"!==r&&u&&o){l(n,[function(n){return"cancel"===n?"ok":"cancel"}(r)]).forEach(function(n){n.focus()})}}function a(n,t){var e=document.activeElement,r=c(e),o=t.length-1,u=t.indexOf(r);l(n,[t[E(o,u)]]).forEach(function(n){return n.focus()})}function f(n,t,e,r){if(/close|cancel/.test(n.getAttribute("data-name").replace("js-","")))return r(),void m();e(l(t,["input"]).reduce(function(n,t){return t.value},null)),m()}function l(n,t){var e=function(n){return n};return t.map(function(t){return n.querySelector('[data-name="js-'+t+'"]')}).filter(e)}function s(n,t,e,r){l(t,e).forEach(function(t){return t.addEventListener(n,r)})}function p(n){var t=document.querySelector(n);t.parentElement.removeChild(t)}window.Promise=window.Promise||e(0);var d=e(1),v=d(u),m=function(n){for(var t=arguments.length,e=Array(t>1?t-1:0),r=1;r2&&void 0!==arguments[2]?arguments[2]:"",r=arguments[3];return o(n,t,'',y,r)},t.confirm=function(n,t,e){return o(n,t,"",y,e)};var g=function(){var n=void 0;return function(){for(var t=arguments.length,e=Array(t),r=0;r=t.length)return t.apply(void 0,r(e));var i=function(){return n.apply(void 0,[t].concat(r(e),Array.prototype.slice.call(arguments)))},a=t.length-arguments.length;return c(i)[a]||i}}]); -//# sourceMappingURL=smalltalk.min.js.map \ No newline at end of file diff --git a/modules/smalltalk/dist/smalltalk.native.min.js b/modules/smalltalk/dist/smalltalk.native.min.js deleted file mode 100644 index c5979cd0..00000000 --- a/modules/smalltalk/dist/smalltalk.native.min.js +++ /dev/null @@ -1,2 +0,0 @@ -var smalltalk=function(n){function r(e){if(t[e])return t[e].exports;var o=t[e]={i:e,l:!1,exports:{}};return n[e].call(o.exports,o,o.exports,r),o.l=!0,o.exports}var t={};return r.m=n,r.c=t,r.i=function(n){return n},r.d=function(n,t,e){r.o(n,t)||Object.defineProperty(n,t,{configurable:!1,enumerable:!0,get:e})},r.n=function(n){var t=n&&n.__esModule?function(){return n.default}:function(){return n};return r.d(t,"a",t),t},r.o=function(n,r){return Object.prototype.hasOwnProperty.call(n,r)},r.p="",r(r.s=3)}([function(n,r){n.exports=es6-promise},,,function(n,r,t){"use strict";window.Promise=window.Promise||t(0),r.alert=function(n,r){return new Promise(function(n){alert(r),n()})},r.prompt=function(n,r,t,e){var o=e;return new Promise(function(n,e){var u=o&&!o.cancel,i=prompt(r,t);if(null!==i)return n(i);u||e()})},r.confirm=function(n,r,t){var e=t,o=e&&!e.cancel;return new Promise(function(n,t){if(confirm(r)||o)return n();t()})}}]); -//# sourceMappingURL=smalltalk.native.min.js.map \ No newline at end of file diff --git a/modules/smalltalk/dist/smalltalk.native.poly.min.js b/modules/smalltalk/dist/smalltalk.native.poly.min.js deleted file mode 100644 index 1997383e..00000000 --- a/modules/smalltalk/dist/smalltalk.native.poly.min.js +++ /dev/null @@ -1,2 +0,0 @@ -var smalltalk=function(t){function n(e){if(r[e])return r[e].exports;var o=r[e]={i:e,l:!1,exports:{}};return t[e].call(o.exports,o,o.exports,n),o.l=!0,o.exports}var r={};return n.m=t,n.c=r,n.i=function(t){return t},n.d=function(t,r,e){n.o(t,r)||Object.defineProperty(t,r,{configurable:!1,enumerable:!0,get:e})},n.n=function(t){var r=t&&t.__esModule?function(){return t.default}:function(){return t};return n.d(r,"a",r),r},n.o=function(t,n){return Object.prototype.hasOwnProperty.call(t,n)},n.p="",n(n.s=6)}([function(t,n,r){(function(n,e){!function(n,r){t.exports=r()}(0,function(){"use strict";function t(t){return"function"==typeof t||"object"==typeof t&&null!==t}function o(t){return"function"==typeof t}function i(t){H=t}function u(t){I=t}function s(){return void 0!==G?function(){G(a)}:c()}function c(){var t=setTimeout;return function(){return t(a,1)}}function a(){for(var t=0;t1)for(var r=1;r1)for(var e=1;e\n
    \n
    '+t+'
    \n
    \n '+n+"\n "+e+'\n
    \n
    \n
    '+r.map(function(t,n){return""}).join("")+"\n
    \n
    \n
    "}function o(t,n,e,o,i){var u=_(),c=_(),a=document.createElement("div"),h=["cancel","close","ok"],p=new Promise(function(t,n){var e=i&&!i.cancel,r=function(){};u(t),c(e?r:n)}),d=r(t,n,e,o);return a.innerHTML=d,a.className="smalltalk",document.body.appendChild(a),f(a,["ok","input"]).forEach(function(t){return t.focus()}),f(a,["input"]).forEach(function(t){t.setSelectionRange(0,e.length)}),l("click",a,h,function(t){return s(t.target,a,u(),c())}),["click","contextmenu"].forEach(function(t){return a.addEventListener(t,function(){return f(a,["ok","input"]).forEach(function(t){return t.focus()})})}),a.addEventListener("keydown",v(a,u(),c())),p}function i(t,n,e,r){var o={ENTER:13,ESC:27,TAB:9,LEFT:37,UP:38,RIGHT:39,DOWN:40},i=r.keyCode,l=r.target,h=["ok","cancel","input"],p=f(t,h).map(u);switch(i){case o.ENTER:s(l,t,n,e),r.preventDefault();break;case o.ESC:d(),e();break;case o.TAB:r.shiftKey&&a(t,p),a(t,p),r.preventDefault();break;default:["left","right","up","down"].filter(function(t){return i===o[t.toUpperCase()]}).forEach(function(){c(t,p)})}r.stopPropagation()}function u(t){return t.getAttribute("data-name").replace("js-","")}function c(t,n){var e=document.activeElement,r=u(e),o=/ok|cancel/.test(r),i=n.length-1;if("input"!==r&&i&&o){f(t,[function(t){return"cancel"===t?"ok":"cancel"}(r)]).forEach(function(t){t.focus()})}}function a(t,n){var e=document.activeElement,r=u(e),o=n.length-1,i=n.indexOf(r);f(t,[n[g(o,i)]]).forEach(function(t){return t.focus()})}function s(t,n,e,r){if(/close|cancel/.test(t.getAttribute("data-name").replace("js-","")))return r(),void d();e(f(n,["input"]).reduce(function(t,n){return n.value},null)),d()}function f(t,n){var e=function(t){return t};return n.map(function(n){return t.querySelector('[data-name="js-'+n+'"]')}).filter(e)}function l(t,n,e,r){f(n,e).forEach(function(n){return n.addEventListener(t,r)})}function h(t){var n=document.querySelector(t);n.parentElement.removeChild(n)}window.Promise=window.Promise||e(0);var p=e(4),v=p(i),d=function(t){for(var n=arguments.length,e=Array(n>1?n-1:0),r=1;r2&&void 0!==arguments[2]?arguments[2]:"",r=arguments[3];return o(t,n,'',y,r)},n.confirm=function(t,n,e){return o(t,n,"",y,e)};var _=function(){var t=void 0;return function(){for(var n=arguments.length,e=Array(n),r=0;r=n.length)return n.apply(void 0,r(e));var c=function(){return t.apply(void 0,[n].concat(r(e),Array.prototype.slice.call(arguments)))},a=n.length-arguments.length;return u(c)[a]||c}}]); -//# sourceMappingURL=smalltalk.poly.min.js.map \ No newline at end of file diff --git a/modules/smalltalk/img/IDR_CLOSE_DIALOG.png b/modules/smalltalk/img/IDR_CLOSE_DIALOG.png deleted file mode 100644 index 9e2956d9..00000000 Binary files a/modules/smalltalk/img/IDR_CLOSE_DIALOG.png and /dev/null differ diff --git a/modules/smalltalk/img/IDR_CLOSE_DIALOG_H.png b/modules/smalltalk/img/IDR_CLOSE_DIALOG_H.png deleted file mode 100644 index aeafd962..00000000 Binary files a/modules/smalltalk/img/IDR_CLOSE_DIALOG_H.png and /dev/null differ diff --git a/modules/smalltalk/lib/smalltalk.js b/modules/smalltalk/lib/smalltalk.js deleted file mode 100644 index ead08640..00000000 --- a/modules/smalltalk/lib/smalltalk.js +++ /dev/null @@ -1,252 +0,0 @@ -'use strict'; - -window.Promise = window.Promise || require('es6-promise'); - -const currify = require('currify/legacy'); -const keyDown = currify(keyDown_); - -const remove = bind(removeEl, '.smalltalk'); - -const BUTTON_OK = ['OK']; -const BUTTON_OK_CANCEL = ['OK', 'Cancel']; - -exports.alert = (title, msg) => { - return showDialog(title, msg, '', BUTTON_OK, {cancel: false}); -}; - -exports.prompt = (title, msg, value = '', options) => { - const val = String(value).replace(/\"/g, '"'); - const valueStr = ``; - - return showDialog(title, msg, valueStr, BUTTON_OK_CANCEL, options); -}; - -exports.confirm = (title, msg, options) => { - return showDialog(title, msg, '', BUTTON_OK_CANCEL, options); -}; - -function getTemplate(title, msg, value, buttons) { - return `
    -
    -
    ${ title }
    -
    - ${ msg } - ${ value } -
    -
    -
    ${ - buttons.map((name, i) => - `` - ).join('') - } -
    -
    -
    `; -} - -const store = () => { - let a; - return (...b) => { - if (b.length) - a = b.pop(); - - return a; - }; -}; - -function showDialog(title, msg, value, buttons, options) { - const ok = store(); - const cancel = store(); - - const dialog = document.createElement('div'); - const closeButtons = [ - 'cancel', - 'close', - 'ok' - ]; - - const promise = new Promise((resolve, reject) => { - const noCancel = options && !options.cancel; - const empty = () => {}; - - ok(resolve); - cancel(noCancel ? empty : reject); - }); - - const tmpl = getTemplate(title, msg, value, buttons); - - dialog.innerHTML = tmpl; - dialog.className = 'smalltalk'; - - document.body.appendChild(dialog); - - find(dialog, ['ok', 'input']).forEach((el) => - el.focus() - ); - - find(dialog, ['input']).forEach((el) => { - el.setSelectionRange(0, value.length); - }); - - addListenerAll('click', dialog, closeButtons, (event) => - closeDialog(event.target, dialog, ok(), cancel()) - ); - - ['click', 'contextmenu'].forEach((event) => - dialog.addEventListener(event, () => - find(dialog, ['ok', 'input']).forEach((el) => - el.focus() - ) - ) - ); - - dialog.addEventListener('keydown', keyDown(dialog, ok(), cancel())); - - return promise; -} - -function keyDown_(dialog, ok, cancel, event) { - const KEY = { - ENTER : 13, - ESC : 27, - TAB : 9, - LEFT : 37, - UP : 38, - RIGHT : 39, - DOWN : 40 - }; - - const keyCode = event.keyCode; - const el = event.target; - - const namesAll = ['ok', 'cancel', 'input']; - const names = find(dialog, namesAll) - .map(getDataName); - - switch(keyCode) { - case KEY.ENTER: - closeDialog(el, dialog, ok, cancel); - event.preventDefault(); - break; - - case KEY.ESC: - remove(); - cancel(); - break; - - case KEY.TAB: - if (event.shiftKey) - tab(dialog, names); - - tab(dialog, names); - event.preventDefault(); - break; - - default: - ['left', 'right', 'up', 'down'].filter((name) => { - return keyCode === KEY[name.toUpperCase()]; - }).forEach(() => { - changeButtonFocus(dialog, names); - }); - - break; - } - - event.stopPropagation(); -} - -function getDataName(el) { - return el - .getAttribute('data-name') - .replace('js-', ''); -} - -function changeButtonFocus(dialog, names) { - const active = document.activeElement; - const activeName = getDataName(active); - const isButton = /ok|cancel/.test(activeName); - const count = names.length - 1; - const getName = (activeName) => { - if (activeName === 'cancel') - return 'ok'; - - return 'cancel'; - }; - - if (activeName === 'input' || !count || !isButton) - return; - - const name = getName(activeName); - - find(dialog, [name]).forEach((el) => { - el.focus(); - }); -} - -const getIndex = (count, index) => { - if (index === count) - return 0; - - if (index < count) - return index + 1; -}; - -function tab(dialog, names) { - const active = document.activeElement; - const activeName = getDataName(active); - const count = names.length - 1; - - const activeIndex = names.indexOf(activeName); - const index = getIndex(count, activeIndex); - - const name = names[index]; - - find(dialog, [name]).forEach((el) => - el.focus() - ); -} - -function closeDialog(el, dialog, ok, cancel) { - const name = el - .getAttribute('data-name') - .replace('js-', ''); - - if (/close|cancel/.test(name)) { - cancel(); - remove(); - return; - } - - const value = find(dialog, ['input']) - .reduce((value, el) => el.value, null); - - ok(value); - remove(); -} - -function find(element, names) { - const notEmpty = (a) => a; - const elements = names.map((name) => - element.querySelector(`[data-name="js-${ name }"]`) - ).filter(notEmpty); - - return elements; -} - -function addListenerAll(event, parent, elements, fn) { - find(parent, elements) - .forEach((el) => - el.addEventListener(event, fn) - ); -} - -function removeEl(name) { - const el = document.querySelector(name); - - el.parentElement.removeChild(el); -} - -function bind(fn, ...args) { - return () => fn(...args); -} - diff --git a/modules/smalltalk/lib/smalltalk.native.js b/modules/smalltalk/lib/smalltalk.native.js deleted file mode 100644 index 0003e5b4..00000000 --- a/modules/smalltalk/lib/smalltalk.native.js +++ /dev/null @@ -1,44 +0,0 @@ -'use strict'; - -window.Promise = window.Promise || require('es6-promise'); - -exports.alert = (title, message) => { - const promise = new Promise((resolve) => { - alert(message); - resolve(); - }); - - return promise; -}; - -exports.prompt = (title, message, value, options) => { - const o = options; - const promise = new Promise((resolve, reject) => { - const noCancel = o && !o.cancel; - const result = prompt(message, value); - - if (result !== null) - return resolve(result); - - if (!noCancel) - reject(); - }); - - return promise; -}; - -exports.confirm = (title, message, options) => { - const o = options; - const noCancel = o && !o.cancel; - const promise = new Promise((resolve, reject) => { - const is = confirm(message); - - if (is || noCancel) - return resolve(); - - reject(); - }); - - return promise; -}; - diff --git a/modules/smalltalk/package.json b/modules/smalltalk/package.json deleted file mode 100644 index bf3fb165..00000000 --- a/modules/smalltalk/package.json +++ /dev/null @@ -1,77 +0,0 @@ -{ - "name": "smalltalk", - "version": "2.3.1", - "description": "Promise-based Alert, Confirm and Prompt replacement", - "homepage": "http://github.com/coderaiser/smalltalk", - "repository": { - "type": "git", - "url": "git://github.com/coderaiser/smalltalk.git" - }, - "main": "lib/smalltalk.js", - "babel": { - "presets": [ - "es2015" - ] - }, - "scripts": { - "watch": "nodemon --watch lib --watch test --exec", - "watch:client": "redrun compile:client -- --watch", - "watch:test": "npm run watch -- npm test", - "watch:lint": "npm run watch -- 'npm run lint'", - "watch:lint:js": "npm run watch -- \"run lint:js\"", - "watch:coverage": "redrun watch -- redrun coverage", - "coverage": "nyc npm test", - "report": "nyc report --reporter=text-lcov | coveralls", - "compile:server": "babel -d legacy lib", - "compile:client": "webpack --progress", - "compile:client:poly": "BUILD_TYPE=poly webpack --progress", - "build": "redrun clean build:js build:css", - "build:js": "redrun compile:* legacy:index", - "build:css": "postcss css/*.css -o dist/smalltalk.min.css -m --use autoprefixer postcss-clean", - "legacy:index": "echo \"module.exports = require('./smalltalk');\" > legacy/index.js", - "clean": "rimraf dist", - "wisdom": "npm run build", - "lint:css": "stylelint css/*.css", - "lint:js": "jshint lib test && jscs lib test && eslint lib test", - "lint": "redrun lint:*", - "test": "tape 'test/**/*.js'" - }, - "keywords": [ - "modal", - "alert", - "confirm", - "prompt" - ], - "author": "coderaiser (http://coderaiser.github.io/)", - "license": "MIT", - "bugs": { - "url": "https://github.com/coderaiser/smalltalk/issues" - }, - "devDependencies": { - "autoprefixer": "^7.0.1", - "babel-cli": "^6.1.1", - "babel-loader": "^7.0.0", - "babel-preset-es2015": "^6.0.15", - "coveralls": "^2.11.11", - "eslint": "^3.0.1", - "glob": "^7.1.1", - "jscs": "^3.0.3", - "jshint": "^2.8.0", - "nodemon": "^1.9.2", - "nyc": "^10.0.0", - "postcss-clean": "^1.0.2", - "postcss-cli": "^4.0.0", - "redrun": "^5.0.1", - "rimraf": "^2.5.3", - "sinon": "^2.0.0", - "stylelint": "^7.0.2", - "stylelint-config-standard": "^16.0.0", - "systemjs": "^0.20.2", - "tape": "^4.6.0", - "webpack": "^2.5.1" - }, - "dependencies": { - "currify": "^2.0.3", - "es6-promise": "^4.1.0" - } -} diff --git a/package.json b/package.json index 270ce0fb..f680e519 100644 --- a/package.json +++ b/package.json @@ -1,15 +1,19 @@ { "name": "cloudcmd", - "version": "6.14.0", + "version": "19.19.1", + "type": "module", "author": "coderaiser (https://github.com/coderaiser)", - "description": "Orthodox web file manager with console and editor", + "description": "File manager for the web with console and editor", "homepage": "http://cloudcmd.io", + "funding": "https://opencollective.com/cloudcmd", "repository": { "type": "git", - "url": "git://github.com/coderaiser/cloudcmd.git" + "url": "git+https://github.com/coderaiser/cloudcmd.git" }, + "main": "server/cloudcmd.js", "keywords": [ "console", + "terminal", "edit", "editor", "file", @@ -35,167 +39,206 @@ "server" ], "bin": { - "cloudcmd": "legacy/bin/cloudcmd.js", - "cloudcmd+": "bin/cloudcmd.js" - }, - "config": { - "dirs": "bin server test webpack.config.js" + "cloudcmd": "bin/cloudcmd.js" }, "scripts": { - "start": "node bin/cloudcmd.js", - "start:dev": "NODE_ENV=development node bin/cloudcmd.js", - "build:start": "redrun build:client start", - "build:start:dev": "redrun build:client:dev start:dev", - "security": "nsp check", - "codestyle": "redrun lint spell", - "lint": "redrun lint:*", - "lint:css": "stylelint css/*.css", - "lint:js": "redrun lint:js:*", - "lint:js:eslint:server": "eslint --rule 'no-console:0' $npm_package_config_dirs", - "lint:js:jshint": "jshint bin client server", - "lint:js:jscs": "jscs --esnext $npm_package_config_dirs", - "lint:js:eslint:client": "eslint --rule 'no-console:0' --env browser client", - "fix:js:eslint:client": "redrun eslint:client -- --fix", - "fix:js:eslint:server": "redrun eslint:server -- --fix", - "test": "tape 'test/**/*.js'", - "spell": "yaspeller .", - "wisdom": "npm run build; npm run docker:rm-old; bin/release.js", - "postpublish": "redrun docker", - "docker:pull:node": "docker pull node", - "docker:pull:alpine": "docker pull mhart/alpine-node", - "docker:push": "docker push coderaiser/cloudcmd:`version`", - "docker:push:alpine": "docker push coderaiser/cloudcmd:`version`-alpine", - "docker:push:alpine:latest": "docker push coderaiser/cloudcmd:latest-alpine", - "docker:build": "docker build -t coderaiser/cloudcmd:`version` .", - "docker:build:alpine": "docker build -f Dockerfile.alpine -t coderaiser/cloudcmd:`version`-alpine .", - "docker": "redrun docker:pull* docker:build* docker:tag* docker:push*", - "docker:alpine": "redrun docker:pull:alpine docker:build:alpine docker:tag:alpine docker:push:alpine docker:push:alpine:latest", - "docker:tag:alpine": "docker tag coderaiser/cloudcmd:`version`-alpine coderaiser/cloudcmd:latest-alpine", - "docker:rm:version": "docker rmi coderaiser/cloudcmd:`version`", - "docker:rm:latest": "docker rmi coderaiser/cloudcmd:latest", - "docker:rm:alpine": "docker rmi coderaiser/cloudcmd:`version`-alpine", - "docker:rm:latest-alpine": "docker rmi coderaiser/cloudcmd:latest-alpine", - "docker:rm-old": "redrun --parallel docker:rm:*", - "coverage": "nyc npm test", - "report": "nyc report --reporter=text-lcov | coveralls", - "6to5:bin": "babel bin -d legacy/bin", - "6to5:server": "babel server -d server_", - "6to5:client": "webpack --progress", - "6to5:client:dev": "NODE_ENV=development redrun 6to5:client", - "watch:client": "redrun 6to5:client -- --watch", - "watch:server": "nodemon bin/cloudcmd.js", - "watch:lint": "nodemon -w client -w server -w webpack.config.js -x 'redrun lint:js'", - "watch:lint:client": "nodemon -w client -w webpack.config.js -x 'redrun lint:js:eslint:client'", - "watch:test": "nodemon -w server -w test -w common -x \"npm run test\"", - "watch:coverage": "nodemon -w server -w test -w common -x \"npm run coverage\"", - "w:c": "redrun watch:client", - "watch:client:dev": "redrun 6to5:client:dev -- --watch", - "w:c:d": "redrun watch:client:dev", - "build": "redrun rm:* 6to5:* mkdir:* legacy:*", - "build:client": "redrun 6to5:client", - "build:client:dev": "redrun 6to5:client:dev", - "legacy:package": "echo \"module.exports = require('../package');\" > legacy/package.js", - "mkdir:server": "mkdirp legacy/server", - "mkdir:json": "mkdirp legacy/json", - "legacy:server": "bin/legacy.js", - "legacy:help": "cp json/help.json legacy/json/", - "rm:server": "rimraf server_ legacy", - "rm:client": "rimraf dist dist-dev", - "heroku-postbuild": "redrun 6to5:client -- --progress && npm i gritty" + "start": "madrun start", + "start:dev": "madrun start:dev", + "build:start": "madrun build:start", + "build:start:dev": "madrun build:start:dev", + "lint:all": "madrun lint:all", + "lint": "madrun lint", + "lint:progress": "madrun lint:progress", + "watch:lint": "madrun watch:lint", + "fresh:lint": "madrun fresh:lint", + "lint:fresh": "madrun lint:fresh", + "fix:lint": "madrun fix:lint", + "lint:stream": "madrun lint:stream", + "test": "madrun test", + "test:e2e": "madrun test:e2e", + "test:client": "madrun test:client", + "test:server": "madrun test:server", + "wisdom": "madrun wisdom", + "wisdom:type": "madrun wisdom:type", + "coverage": "madrun coverage", + "coverage:report": "madrun coverage:report", + "report": "madrun report", + "6to5": "madrun 6to5", + "6to5:client": "madrun 6to5:client", + "6to5:client:dev": "madrun 6to5:client:dev", + "watch:client": "madrun watch:client", + "watch:client:dev": "madrun watch:client:dev", + "watch:server": "madrun watch:server", + "watch:test": "madrun watch:test", + "watch:test:client": "madrun watch:test:client", + "watch:test:server": "madrun watch:test:server", + "watch:coverage": "madrun watch:coverage", + "watch:fix:lint": "madrun watch:fix:lint", + "build": "madrun build", + "build:dev": "madrun build:dev", + "build:client": "madrun build:client", + "build:client:dev": "madrun build:client:dev", + "heroku-postbuild": "madrun heroku-postbuild" }, "directories": { "man": "man" }, "subdomain": "cloudcmd", "dependencies": { - "apart": "^1.0.1", - "chalk": "^1.1.0", - "checkup": "^1.3.0", - "console-io": "^3.0.0", - "copymitter": "^2.0.0", - "criton": "^1.0.0", - "currify": "^2.0.3", - "deepmerge": "^1.3.2", - "deepword": "^1.3.0", - "dword": "^4.1.0", - "edward": "^4.2.0", + "@cloudcmd/dropbox": "^5.0.1", + "@cloudcmd/fileop": "^9.0.7", + "@cloudcmd/move-files": "^8.0.0", + "@cloudcmd/read-files-sync": "^2.0.0", + "@putout/cli-validate-args": "^2.0.0", + "@putout/plugin-cloudcmd": "^5.2.0", + "aleman": "^2.0.1", + "apart": "^2.0.0", + "chalk": "^5.3.0", + "compression": "^1.7.4", + "console-io": "^15.0.1", + "copymitter": "^10.3.0", + "criton": "^2.0.0", + "currify": "^4.0.0", + "deepmerge": "^4.0.0", + "deepword": "^11.0.0", + "dword": "^16.0.0", + "edward": "^16.0.0", + "es6-promisify": "^7.0.0", "execon": "^1.2.0", - "express": "^4.13.0", - "files-io": "^1.2.0", - "flop": "^2.0.0", - "format-io": "^0.9.6", - "http-auth": "^2.3.1", - "inly": "^1.0.2", - "ishtar": "^1.5.0", - "jaguar": "^3.0.0", + "express": "^5.1.0", + "express-rate-limit": "^8.5.2", + "files-io": "^4.0.0", + "find-up": "^8.0.0", + "for-each-key": "^2.0.0", + "format-io": "^2.0.0", + "fullstore": "^4.0.0", + "http-auth": "^4.2.1", + "inly": "^5.0.0", + "jaguar": "^6.0.0", "jju": "^1.3.0", - "join-io": "^1.4.0", - "jonny": "^1.0.0", - "markdown-it": "^8.0.0", - "mellow": "^2.0.0", - "minify": "^2.0.0", - "minimist": "^1.2.0", - "mollify": "^1.0.0", - "nomine": "^1.0.1", - "omnes": "^1.0.3", - "onezip": "^1.0.5", - "opn": "^4.0.1", - "os-homedir": "^1.0.0", - "package-json": "^2.3.0", - "ponse": "^1.4.0", - "pullout": "^1.0.1", - "remedy": "^1.5.0", - "rendy": "^1.1.0", - "restafary": "^2.0.0", - "salam": "^1.0.0", - "socket.io": "^2.0.1", - "spero": "^1.5.0", - "squad": "^1.1.3", - "try-catch": "^1.0.0", - "tryrequire": "^1.1.5", - "writejson": "^1.1.0" + "jonny": "^3.0.0", + "just-snake-case": "^3.2.0", + "markdown-it": "^14.0.0", + "mellow": "^3.0.0", + "mime-types": "^3.0.1", + "montag": "^2.0.1", + "nano-memoize": "^3.0.16", + "nomine": "^4.0.0", + "once": "^1.4.0", + "onezip": "^7.0.0", + "open": "^11.0.0", + "package-json": "^10.0.0", + "pipe-io": "^4.0.1", + "ponse": "^8.0.0", + "pullout": "^5.0.0", + "putout": "^42.0.5", + "qword": "^1.0.0", + "redzip": "^4.6.1", + "rendy": "^5.0.0", + "restafary": "^13.0.1", + "restbox": "^4.0.0", + "shortdate": "^2.0.0", + "socket.io": "^4.0.0", + "socket.io-client": "^4.0.1", + "squad": "^3.0.0", + "table": "^6.0.1", + "try-catch": "^4.0.4", + "try-to-catch": "^4.0.0", + "tryrequire": "^3.0.0", + "win32": "^8.0.0", + "wraptile": "^3.0.0", + "writejson": "^3.0.0", + "yargs-parser": "^22.0.0" }, "devDependencies": { - "babel-cli": "^6.18.0", - "babel-loader": "^7.0.0", - "babel-plugin-transform-object-assign": "^6.22.0", - "babel-preset-es2015": "^6.18.0", - "coveralls": "^2.11.6", - "emitify": "^3.0.2", - "es6-promise": "^4.0.5", - "es6-promisify": "^5.0.0", - "eslint": "^3.1.1", + "@babel/code-frame": "^8.0.0", + "@babel/core": "^8.0.1", + "@babel/plugin-transform-optional-chaining": "^8.0.1", + "@babel/preset-env": "^8.0.2", + "@cloudcmd/clipboard": "^2.0.0", + "@cloudcmd/create-element": "^2.0.0", + "@cloudcmd/modal": "^4.0.0", + "@cloudcmd/olark": "^3.0.2", + "@cloudcmd/stub": "^5.0.0", + "@iocmd/wait": "^2.1.0", + "@putout/eslint-flat": "^4.0.0", + "@rspack/cli": "^2.1.4", + "@rspack/core": "^2.1.4", + "@supertape/loader-css": "^1.0.0", + "@types/node-fetch": "^2.6.11", + "auto-globals": "^4.0.0", + "babel-loader": "^10.0.0", + "babel-plugin-macros": "^3.0.0", + "cheerio": "^1.0.0-rc.5", + "clean-css-loader": "^4.2.1", + "codegen.macro": "^4.0.0", + "css-loader": "^7.1.2", + "css-modules-require-hook": "^4.2.3", + "cssnano-preset-default": "^8.0.1", + "domtokenlist-shim": "^1.2.0", + "emitify": "^4.0.1", + "eslint": "^10.0.0", + "eslint-plugin-putout": "^31.0.0", + "globals": "^17.0.0", + "gritty": "^10.2.0", "gunzip-maybe": "^1.3.1", - "html-looks-like": "^1.0.2", - "jscs": "^3.0.1", - "jshint": "^2.8.0", + "html-webpack-plugin": "^5.6.3", + "inherits": "^2.0.3", + "itype": "^3.0.1", + "just-capitalize": "^3.2.0", + "just-pascal-case": "^3.2.0", + "limier": "^3.0.0", + "load.js": "^3.0.0", + "madrun": "^13.0.0", + "memfs": "^4.2.0", "minor": "^1.2.2", - "mkdirp": "^0.5.1", "morgan": "^1.6.1", - "nodemon": "^1.9.1", - "nsp": "^2.2.1", - "nyc": "^10.1.2", + "multi-rename": "^3.0.0", + "nodemon": "^3.0.1", + "path-browserify": "^1.0.1", + "philip": "^3.0.0", "place": "^1.1.4", - "readjson": "^1.1.3", - "redrun": "^5.0.0", + "postcss": "^8.5.3", + "process": "^0.11.10", + "readjson": "^2.0.1", + "redlint": "^6.0.0", "request": "^2.76.0", - "rimraf": "^2.5.4", - "shortdate": "^1.0.1", - "sinon": "^2.1.0", - "sinon-called-with-diff": "^1.0.0", - "socket.io-client": "^2.0.1", - "stylelint": "^7.0.2", - "stylelint-config-standard": "^16.0.0", - "tape": "^4.4.0", - "tar-stream": "^1.5.2", - "version-io": "^1.2.5", - "webpack": "^2.2.1", - "wraptile": "^1.0.0", - "yaspeller": "^3.0.0" + "rimraf": "^6.0.1", + "scroll-into-view-if-needed": "^3.0.4", + "serve-once": "^4.0.1", + "smalltalk": "^5.0.0", + "style-loader": "^4.0.0", + "superc8": "^12.6.0", + "supermenu": "^5.0.0", + "supertape": "^13.0.0", + "tar-stream": "^3.0.0", + "unionfs": "^4.0.0", + "url-loader": "^4.0.0", + "util": "^0.12.5", + "webpack-merge": "^6.0.1" + }, + "imports": { + "#css/": "./css/", + "#dom": "./client/dom/index.js", + "#dom/events": "./client/dom/events/index.js", + "#dom/load": "./client/dom/load.js", + "#dom/dialog": "./client/dom/dialog.js", + "#dom/images": "./client/dom/images.js", + "#dom/files": "./client/dom/files.js", + "#dom/upload-files": "./client/dom/upload-files.js", + "#dom/storage": "./client/dom/storage.js", + "#dom/rest": "./client/dom/rest.js", + "#common/util": "./common/util.js", + "#common/omit": "./common/omit.js", + "#common/cloudfunc": "./common/cloudfunc.js", + "#common/entity": "./common/entity.js", + "#server/cloudcmd": "./server/cloudcmd.js" }, "engines": { - "node": ">=0.10" + "node": ">=22" }, "license": "MIT", - "main": "legacy/server/cloudcmd.js" + "publishConfig": { + "access": "public" + } } diff --git a/robots.txt b/robots.txt new file mode 100644 index 00000000..1f53798b --- /dev/null +++ b/robots.txt @@ -0,0 +1,2 @@ +User-agent: * +Disallow: / diff --git a/rspack.config.js b/rspack.config.js new file mode 100644 index 00000000..5dcb033d --- /dev/null +++ b/rspack.config.js @@ -0,0 +1,10 @@ +import {merge} from 'webpack-merge'; +import * as htmlConfig from './.rspack/html.js'; +import cssConfig from './.rspack/css.js'; +import jsConfig from './.rspack/js.js'; + +export default merge([ + jsConfig, + htmlConfig, + cssConfig, +]); diff --git a/rules/split-autoglobals-with-tape.js b/rules/split-autoglobals-with-tape.js new file mode 100644 index 00000000..5c3c3eb2 --- /dev/null +++ b/rules/split-autoglobals-with-tape.js @@ -0,0 +1,8 @@ +export const report = () => `Use 'if condition' instead of 'ternary expression'`; + +export const replace = () => ({ + 'const test = autoGlobals(require("supertape"))': `{ + const {test: tape} = require('supertape'); + const test = autoGlobals(tape); + }`, +}); diff --git a/server/auth.js b/server/auth.js index 18943e92..09da0c2a 100644 --- a/server/auth.js +++ b/server/auth.js @@ -1,31 +1,31 @@ -'use strict'; +import httpAuth from 'http-auth'; +import criton from 'criton'; +import currify from 'currify'; -const httpAuth = require('http-auth'); -const criton = require('criton'); +const middle = currify(_middle); +const check = currify(_check); -const config = require('./config'); - -module.exports = () => { +export default (config) => { const auth = httpAuth.basic({ - realm: 'Cloud Commander' - }, check); + realm: 'Cloud Commander', + }, check(config)); - return middle(auth); + return middle(config, auth); }; -function middle(authentication) { - return (req, res, next) => { - const is = config('auth'); - - if (!is) - return next(); - - const success = () => next(/* success */); - authentication.check(req, res, success); - }; +function _middle(config, authentication, req, res, next) { + const is = config('auth'); + const {originalUrl} = req; + + if (!is || originalUrl.startsWith('/public/')) + return next(); + + const success = () => next(); + + return authentication.check(success)(req, res); } -function check(username, password, callback) { +function _check(config, username, password, callback) { const BAD_CREDENTIALS = false; const name = config('username'); const pass = config('password'); @@ -39,4 +39,3 @@ function check(username, password, callback) { callback(sameName && samePass); } - diff --git a/server/cloudcmd.js b/server/cloudcmd.js index 64fc4389..2e751520 100644 --- a/server/cloudcmd.js +++ b/server/cloudcmd.js @@ -1,296 +1,274 @@ -'use strict'; +import path, {dirname, join} from 'node:path'; +import {fileURLToPath} from 'node:url'; +import process from 'node:process'; +import fs from 'node:fs'; +import {fullstore} from 'fullstore'; +import currify from 'currify'; +import apart from 'apart'; +import * as ponse from 'ponse'; +import {restafary} from 'restafary'; +import restbox from 'restbox'; +import {konsole} from 'console-io'; +import {edward} from 'edward'; +import {dword} from 'dword'; +import {deepword} from 'deepword'; +import {qword} from 'qword'; +import nomine from 'nomine'; +import {fileop} from '@cloudcmd/fileop'; +import * as cloudfunc from '#common/cloudfunc'; +import authentication from './auth.js'; +import {createConfig, configPath} from './config.js'; +import modulas from './modulas.js'; +import {userMenu} from './user-menu.js'; +import rest from './rest/index.js'; +import route from './route.js'; +import * as validate from './validate.js'; +import prefixer from './prefixer.js'; +import terminal from './terminal.js'; +import {distributeExport} from './distribute/export.js'; +import {createDepStore} from './depstore.js'; -const DIR = __dirname + '/'; -const DIR_ROOT = DIR + '../'; +const __filename = fileURLToPath(import.meta.url); +const __dirname = dirname(__filename); +const {assign} = Object; +const DIR = `${__dirname}/`; +const DIR_ROOT = join(DIR, '..'); +const getDist = (isDev) => isDev ? 'dist-dev' : 'dist'; -const cloudfunc = require(DIR + 'cloudfunc'); -const auth = require(DIR + 'auth'); -const config = require(DIR + 'config'); -const modulas = require(DIR + 'modulas'); -const rest = require(DIR + 'rest'); -const route = require(DIR + 'route'); -const validate = require(DIR + 'validate'); -const prefixer = require(DIR + 'prefixer'); -const pluginer = require(DIR + 'plugins'); -const terminal = require(DIR + 'terminal'); +const isDev = fullstore(process.env.NODE_ENV === 'development'); -const apart = require('apart'); -const join = require('join-io'); -const ponse = require('ponse'); -const mollify = require('mollify'); -const restafary = require('restafary/legacy'); -const konsole = require('console-io/legacy'); -const edward = require('edward/legacy'); -const dword = require('dword/legacy'); -const deepword = require('deepword/legacy'); -const nomine = require('nomine/legacy'); -const spero = require('spero'); -const remedy = require('remedy'); -const ishtar = require('ishtar'); -const salam = require('salam/legacy'); -const omnes = require('omnes/legacy'); -const criton = require('criton'); - -const root = () => config('root'); +const getIndexPath = (isDev) => path.join(DIR, '..', `${getDist(isDev)}/index.html`); +const html = fs.readFileSync(getIndexPath(isDev()), 'utf8'); +const initAuth = currify(_initAuth); const notEmpty = (a) => a; const clean = (a) => a.filter(notEmpty); -const isDev = process.env.NODE_ENV === 'development'; +const isUndefined = (a) => typeof a === 'undefined'; +const isFn = (a) => typeof a === 'function'; -function getPrefix(prefix) { - if (typeof prefix === 'function') - return prefix() || ''; - - return prefix || ''; -} +export default cloudcmd; -module.exports = (params) => { +export function cloudcmd(params) { const p = params || {}; const options = p.config || {}; - const plugins = p.plugins; - const modules = p.modules; - const keys = Object.keys(options); - - let prefix; - - checkPlugins(plugins); - - keys.forEach((name) => { - let value = options[name]; - - switch(name) { - case 'root': - validate.root(value); - break; - case 'editor': - validate.editor(value); - break; - case 'packer': - validate.packer(value); - break; - case 'password': - /* could be useful when used as middleware */ - value = criton(value, config('algo')); - break; - case 'prefix': - prefix = prefixer(value); - break; - } - - config(name, value); + const config = p.configManager || createConfig({ + configPath, }); - config('console', defaultValue('console', options)); - config('configDialog', defaultValue('configDialog', options)); + const {modules} = p; + const keys = Object.keys(options); + + for (const name of keys) { + let value = options[name]; + + if (/root/.test(name)) + validate.root(value, config); + + if (/editor|packer|themes|menu/.test(name)) + validate[name](value); + + if (/prefix/.test(name)) + value = prefixer(value); + + config(name, value); + } + + config('console', defaultValue(config, 'console', options)); + config('configDialog', defaultValue(config, 'configDialog', options)); + + const prefixSocket = prefixer(options.prefixSocket); if (p.socket) - listen(prefix, p.socket); + listen({ + prefixSocket, + config, + socket: p.socket, + }); - return cloudcmd(prefix, plugins, modules); + return cloudcmdMiddle({ + modules, + config, + }); +} + +const depStore = createDepStore(); + +export const createConfigManager = createConfig; +export { + configPath, }; -function defaultValue(name, options) { +export const _getIndexPath = getIndexPath; + +function defaultValue(config, name, options) { const value = options[name]; const previous = config(name); - if (typeof value === 'undefined') + if (isUndefined(value)) return previous; return value; } -function authCheck(socket, success) { - if (!config('auth')) - return success(); +export const _getPrefix = getPrefix; + +function getPrefix(prefix) { + if (isFn(prefix)) + return prefix() || ''; - socket.on('auth', (name, pass) => { - const isName = name === config('username'); - const isPass = pass === config('password'); - - if (!isName || !isPass) - return socket.emit('reject'); - - success(); - socket.emit('accept'); - }); + return prefix || ''; } -function listen(prefix, socket) { - const size = cloudfunc.MAX_SIZE; +export function _initAuth(config, accept, reject, username, password) { + if (!config('auth')) + return accept(); - prefix = getPrefix(prefix); + const isName = username === config('username'); + const isPass = password === config('password'); - config.listen(socket, authCheck); + if (isName && isPass) + return accept(); + + reject(); +} + +function listen({prefixSocket, socket, config}) { + const root = apart(config, 'root'); + const auth = initAuth(config); + + prefixSocket = getPrefix(prefixSocket); + config.listen(socket, auth); edward.listen(socket, { - size, root, - authCheck, - prefix: prefix + '/edward', + auth, + prefixSocket: `${prefixSocket}/edward`, }); dword.listen(socket, { - size, root, - authCheck, - prefix: prefix + '/dword', + auth, + prefixSocket: `${prefixSocket}/dword`, + }); + + qword.listen(socket, { + root, + auth, + prefixSocket: `${prefixSocket}/qword`, }); deepword.listen(socket, { - size, root, - authCheck, - prefix: prefix + '/deepword', - }); - - spero.listen(socket, { - root, - authCheck, - prefix: prefix + '/spero', - }); - - remedy.listen(socket, { - root, - authCheck, - prefix: prefix + '/remedy', - }); - - ishtar.listen(socket, { - root, - authCheck, - prefix: prefix + '/ishtar', - }); - - salam.listen(socket, { - root, - authCheck, - prefix: prefix + '/salam', - }); - - omnes.listen(socket, { - root, - authCheck, - prefix: prefix + '/omnes', + auth, + prefixSocket: `${prefixSocket}/deepword`, }); config('console') && konsole.listen(socket, { - authCheck, - prefix: prefix + '/console', + auth, + prefixSocket: `${prefixSocket}/console`, }); - config('terminal') && terminal().listen(socket, { - authCheck, - prefix: prefix + '/gritty', + fileop.listen(socket, { + root, + auth, + prefix: `${prefixSocket}/fileop`, }); + + config('terminal') && terminal(config).listen(socket, { + auth, + prefix: `${prefixSocket}/gritty`, + command: config('terminalCommand'), + autoRestart: config('terminalAutoRestart'), + }); + + distributeExport(config, socket); } -function cloudcmd(prefix, plugins, modules) { - const isOption = (name) => { - return config(name); - }; +function cloudcmdMiddle({modules, config}) { + const online = apart(config, 'online'); + const cache = false; + const diff = apart(config, 'diff'); + const zip = apart(config, 'zip'); + const root = apart(config, 'root'); - const minify = apart(isOption, 'minify'); - const online = apart(isOption, 'online'); - const cache = apart(isOption, 'cache'); - const diff = apart(isOption, 'diff'); - const zip = apart(isOption, 'zip'); + const ponseStatic = ponse.createStatic({ + cache, + root: DIR_ROOT, + }); + + const dropbox = config('dropbox'); + const dropboxToken = config('dropboxToken'); - const ponseStatic = ponse.static(DIR_ROOT, {cache}); - const funcs = clean([ config('console') && konsole({ - prefix: prefix + '/console', - minify, online, }), - - config('terminal') && terminal({ - prefix: prefix + '/gritty', - }), - + config('terminal') && terminal(config, {}), edward({ - prefix : prefix + '/edward', - minify, + root, online, diff, zip, + dropbox, + dropboxToken, }), - dword({ - prefix : prefix + '/dword', - minify, + root, online, diff, zip, + dropbox, + dropboxToken, + }), + qword({ + root, + online, + diff, + zip, + dropbox, + dropboxToken, }), - deepword({ - prefix : prefix + '/deepword', - minify, + root, online, diff, zip, + dropbox, + dropboxToken, }), - - spero({ - prefix : prefix + '/spero', - minify, - online, - }), - - remedy({ - prefix : prefix + '/remedy', - minify, - online, - }), - - ishtar({ - prefix : prefix + '/ishtar', - minify, - online, - }), - - salam({ - prefix: prefix + '/salam', - }), - - omnes({ - prefix: prefix + '/omnes', - }), - - nomine({ - prefix: prefix + '/rename', - }), - - setUrl(prefix), + fileop(), + nomine(), + setUrl, + setSW, logout, - auth(), + authentication(config), config.middle, - modules && modulas(modules), - + config('dropbox') && restbox({ + prefix: cloudfunc.apiURL, + root, + token: dropboxToken, + }), restafary({ prefix: cloudfunc.apiURL + '/fs', - root + root, }), - - rest, - route, - - join({ - dir : DIR_ROOT, - minify, + userMenu({ + menuName: '.cloudcmd.menu.js', + config, }), - - mollify({ - dir : DIR_ROOT, - is : minify, + rest({ + config, + fs: depStore('fs'), + moveFiles: depStore('moveFiles'), }), - - pluginer(plugins), - ponseStatic + route(config, { + html, + win32: depStore('win32'), + }), + ponseStatic, ]); return funcs; @@ -303,31 +281,38 @@ function logout(req, res, next) { res.sendStatus(401); } -function setUrl(pref) { - return (req, res, next) => { - const prefix = getPrefix(pref); - const is = !req.url.indexOf(prefix); - - if (!is) - return next(); - - req.url = req.url.replace(prefix, '') || '/'; - - if (/^\/cloudcmd\.js(\.map)?$/.test(req.url)) - req.url = `/dist${req.url}`; - - if (isDev) - req.url = req.url.replace(/^\/dist\//, '/dist-dev/'); - - next(); - }; -} +export const _isDev = isDev; +export const _replaceDist = replaceDist; -function checkPlugins(plugins) { - if (typeof plugins === 'undefined') - return; +function replaceDist(url) { + if (!isDev()) + return url; - if (!Array.isArray(plugins)) - throw Error('plugins should be an array!'); + return url.replace(/^\/dist\//, '/dist-dev/'); } +function setUrl(req, res, next) { + if (/^\/cloudcmd\.js(\.map)?$/.test(req.url)) + req.url = `/dist${req.url}`; + + req.url = replaceDist(req.url); + + next(); +} + +function setSW(req, res, next) { + const {url} = req; + const isSW = /^\/sw\.[mc]?js(\.map)?$/.test(url); + + if (isSW) { + const url = req.url.replace(/[cm]js/, 'js'); + req.url = replaceDist(`/dist${url}`); + } + + next(); +} + +assign(cloudcmd, { + depStore, + createConfigManager, +}); diff --git a/server/cloudcmd.spec.js b/server/cloudcmd.spec.js new file mode 100644 index 00000000..d79aa4c1 --- /dev/null +++ b/server/cloudcmd.spec.js @@ -0,0 +1,247 @@ +import path, {dirname} from 'node:path'; +import {fileURLToPath} from 'node:url'; +import {serveOnce} from 'serve-once'; +import {test, stub} from 'supertape'; +import cloudcmd, { + _isDev, + _replaceDist, + createConfigManager, + _getPrefix, + _initAuth, + _getIndexPath, +} from '#server/cloudcmd'; +import {connect} from '../test/before.js'; + +const noop = () => {}; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = dirname(__filename); + +const {request} = serveOnce(cloudcmd, { + config: { + auth: false, + dropbox: false, + }, +}); + +test('cloudcmd: defaults: config', (t) => { + const configManager = createConfigManager(); + + configManager('configDialog', false); + + cloudcmd({ + configManager, + }); + + t.notOk(configManager('configDialog'), 'should not override config with defaults'); + t.end(); +}); + +test('cloudcmd: defaults: console', (t) => { + const configManager = createConfigManager(); + configManager('console', false); + + cloudcmd({ + configManager, + }); + + t.notOk(configManager('console'), 'should not override config with defaults'); + t.end(); +}); + +test('cloudcmd: getPrefix', (t) => { + const value = 'hello'; + const result = _getPrefix(value); + + t.equal(result, value); + t.end(); +}); + +test('cloudcmd: getPrefix: function', (t) => { + const value = 'hello'; + const fn = () => value; + const result = _getPrefix(fn); + + t.equal(result, value); + t.end(); +}); + +test('cloudcmd: getPrefix: function: empty', (t) => { + const value = null; + const fn = () => value; + const result = _getPrefix(fn); + + t.equal(result, ''); + t.end(); +}); + +test('cloudcmd: replaceDist', (t) => { + const currentIsDev = _isDev(); + + _isDev(true); + const url = '/dist/hello'; + const result = _replaceDist(url); + const expected = '/dist-dev/hello'; + + _isDev(currentIsDev); + + t.equal(result, expected); + t.end(); +}); + +test('cloudcmd: replaceDist: !isDev', (t) => { + const url = '/dist/hello'; + + const currentIsDev = _isDev(); + _isDev(false); + const result = _replaceDist(url); + + _isDev(currentIsDev); + + t.equal(result, url); + t.end(); +}); + +test('cloudcmd: auth: reject', (t) => { + const accept = stub(); + const reject = stub(); + + const config = createConfigManager(); + + const username = 'root'; + const password = 'toor'; + + config('auth', true); + config('username', username); + config('password', password); + + _initAuth(config, accept, reject, username, 'abc'); + + t.ok(reject.called, 'should reject'); + t.end(); +}); + +test('cloudcmd: auth: accept', (t) => { + const accept = stub(); + const reject = stub(); + + const username = 'root'; + const password = 'toor'; + const auth = true; + + const config = createConfigManager(); + config('username', username); + config('password', password); + config('auth', auth); + + _initAuth(config, accept, reject, username, password); + + t.ok(accept.called, 'should accept'); + t.end(); +}); + +test('cloudcmd: auth: accept: no auth', (t) => { + const accept = stub(); + const reject = stub(); + + const auth = false; + const username = 'root'; + const password = 'toor'; + + const config = createConfigManager(); + config('username', username); + config('password', password); + config('auth', auth); + + _initAuth(config, accept, reject, username, password); + + t.ok(accept.called, 'should accept'); + t.end(); +}); + +test('cloudcmd: getIndexPath: production', (t) => { + const isDev = false; + + const result = _getIndexPath(isDev); + const expected = path.join(__dirname, '..', 'dist', 'index.html'); + + t.equal(result, expected); + t.end(); +}); + +test('cloudcmd: getIndexPath: development', (t) => { + const isDev = true; + const result = _getIndexPath(isDev); + const expected = path.join(__dirname, '..', 'dist-dev', 'index.html'); + + t.equal(result, expected); + t.end(); +}); + +test('cloudcmd: sw', async (t) => { + const {status} = await request.get('/sw.mjs'); + + t.equal(status, 200, 'should return sw'); + t.end(); +}); + +test('cloudcmd: no params', (t) => { + const middle = cloudcmd(); + + t.ok(Array.isArray(middle), 'should return middleware list when no params passed'); + t.end(); +}); + +test('cloudcmd: listen: terminal', async (t) => { + const {done} = await connect({ + config: { + terminal: true, + }, + }); + + await done(); + + t.pass('should listen with terminal enabled'); + t.end(); +}); + +test('cloudcmd: middle: dropbox', async (t) => { + const {port, done} = await connect({ + config: { + dropbox: true, + dropboxToken: 'hello', + }, + }); + + const response = await fetch(`http://localhost:${port}/api/v1/dropbox/nonexistent`); + + await done(); + + t.ok(response.status, 'should mount dropbox route'); + t.end(); +}); + +test('cloudcmd: logout', async (t) => { + const {status} = await request.get('/logout'); + + t.equal(status, 401, 'should return 401 for /logout'); + t.end(); +}); + +test('cloudcmd: modules', (t) => { + const middle = cloudcmd({ + modules: { + hello: noop, + }, + }); + + t.ok(Array.isArray(middle), 'should return middleware list with modules'); + t.end(); +}); + +test('cloudcmd: setUrl: cloudcmd.js', async (t) => { + const {status} = await request.get('/cloudcmd.js'); + + t.equal(status, 200, 'should serve cloudcmd.js'); + t.end(); +}); diff --git a/server/cloudfunc.js b/server/cloudfunc.js deleted file mode 100644 index 1231a745..00000000 --- a/server/cloudfunc.js +++ /dev/null @@ -1,231 +0,0 @@ -'use strict'; - -const rendy = require('rendy'); -const Entity = require('./common/entity'); -const store = require('./common/store'); - -/* КОНСТАНТЫ (общие для клиента и сервера)*/ - -/* название программы */ -const NAME = 'Cloud Commander'; -const FS = '/fs'; - -const Path = store(); - -Path('/'); - -module.exports.FS = FS; -module.exports.apiURL = '/api/v1'; -module.exports.MAX_FILE_SIZE = 500 * 1024; -module.exports.Entity = Entity; - -module.exports.formatMsg = (msg, name, status) => { - status = status || 'ok'; - - if (name) - name = '("' + name + '")'; - else - name = ''; - - return msg + ': ' + status + name; -}; - -/** - * Функция возвращает заголовок веб страницы - * @path - */ -module.exports.getTitle = (path) => { - return NAME + ' - ' + (path || Path()); -}; - -/** Функция получает адреса каждого каталога в пути - * возвращаеться массив каталогов - * @param url - адрес каталога - */ -function getPathLink(url, prefix, template) { - if (!url) - throw Error('url could not be empty!'); - - if (!template) - throw Error('template could not be empty!'); - - const names = url - .split('/') - .slice(1, -1); - - const allNames = ['/', ...names]; - const length = allNames.length - 1; - - let path = '/'; - - const pathHTML = allNames.map((name, index) => { - const isLast = index === length; - - if (index) - path += name + '/'; - - if (index && isLast) - return name + '/'; - - const slash = index ? '/' : ''; - - return rendy(template, { - path, - name, - slash, - prefix, - }); - }).join(''); - - return pathHTML; -} - -/** - * Функция строит таблицу файлв из JSON-информации о файлах - * @param params - информация о файлах - * - */ -module.exports.buildFromJSON = (params) => { - const prefix = params.prefix; - const template = params.template; - const templateFile = template.file; - const templateLink = template.link; - const json = params.data; - - const {path, files} = json; - - const sort = params.sort || 'name'; - const order = params.order || 'asc'; - - /* - * Строим путь каталога в котором мы находимся - * со всеми подкаталогами - */ - const htmlPath = getPathLink(path, prefix, template.pathLink); - - let fileTable = rendy(template.path, { - link : prefix + FS + path, - fullPath : path, - path : htmlPath - }); - - let name = 'name'; - let size = 'size'; - let date = 'date'; - const owner = 'owner'; - const mode = 'mode'; - const arrow = order === 'asc' ? '↑' : '↓'; - - if (sort === 'name' && order !== 'asc') - name += arrow; - else if (sort === 'size') - size += arrow; - else if (sort === 'date') - date += arrow; - - const header = rendy(templateFile, { - tag : 'div', - attribute : 'data-name="js-fm-header" ', - className : 'fm-header', - type : '', - name, - size, - date, - owner, - mode, - }); - - /* сохраняем путь */ - Path(path); - - fileTable += header + '
      '; - /* Если мы не в корне */ - if (path !== '/') { - /* убираем последний слеш и каталог в котором мы сейчас находимся*/ - const lastSlash = path.substr(path, path.lastIndexOf('/')); - const dotDot = lastSlash.substr(lastSlash, lastSlash.lastIndexOf('/')); - - const link = prefix + FS + (dotDot || '/'); - - const linkResult = rendy(template.link, { - link, - title : '..', - name : '..' - }); - - const dataName = 'data-name="js-file-.." '; - const attribute = 'draggable="true" ' + dataName; - - /* Сохраняем путь к каталогу верхнего уровня*/ - fileTable += rendy(template.file, { - tag : 'li', - attribute, - className : '', - type : 'directory', - name : linkResult, - size : '<dir>', - date : '--.--.----', - owner : '.', - mode : '--- --- ---' - }); - } - - fileTable += files.map((file) => { - const link = prefix + FS + path + file.name; - - const type = getType(file.size); - const size = getSize(file.size); - - const date = file.date || '--.--.----'; - const owner = file.owner || 'root'; - const mode = file.mode; - - const linkResult = rendy(templateLink, { - link, - title: file.name, - name: Entity.encode(file.name), - attribute: getAttribute(file.size) - }); - - const dataName = 'data-name="js-file-' + file.name + '" '; - const attribute = 'draggable="true" ' + dataName; - - return rendy(templateFile, { - tag: 'li', - attribute, - className: '', - type, - name: linkResult, - size, - date, - owner, - mode, - }); - }).join(''); - - fileTable += '
    '; - - return fileTable; -}; - -function getType(size) { - if (size === 'dir') - return 'directory'; - - return 'text-file'; -} - -function getAttribute(size) { - if (size === 'dir') - return ''; - - return 'target="_blank" '; -} - -function getSize(size) { - if (size === 'dir') - return '<dir>'; - - return size; -} - diff --git a/server/columns.js b/server/columns.js new file mode 100644 index 00000000..eff63957 --- /dev/null +++ b/server/columns.js @@ -0,0 +1,44 @@ +import path, {dirname} from 'node:path'; +import {fileURLToPath} from 'node:url'; +import process from 'node:process'; +import fs from 'node:fs'; +import {fullstore} from 'fullstore'; +import * as nanomemoizeDefault from 'nano-memoize'; +import readFilesSync from '@cloudcmd/read-files-sync'; + +const nanomemoize = nanomemoizeDefault.default.nanomemoize || nanomemoizeDefault.default; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = dirname(__filename); +const isMap = (a) => /\.(map|js)$/.test(a); +const not = (fn) => (a) => !fn(a); + +const defaultColumns = { + '': '', + 'name-size-date-owner-mode': '', +}; + +const _isDev = fullstore(process.env.NODE_ENV === 'development'); +const getDist = (isDev) => isDev ? 'dist-dev' : 'dist'; + +export const isDev = _isDev; + +export const getColumns = ({isDev = _isDev()} = {}) => { + const columns = readFilesSyncMemo(isDev); + + return { + ...columns, + ...defaultColumns, + }; +}; + +const readFilesSyncMemo = nanomemoize((isDev) => { + const dist = getDist(isDev); + const columnsDir = path.join(__dirname, '..', dist, 'columns'); + + const names = fs + .readdirSync(columnsDir) + .filter(not(isMap)); + + return readFilesSync(columnsDir, names, 'utf8'); +}); diff --git a/server/columns.spec.js b/server/columns.spec.js new file mode 100644 index 00000000..533cfe75 --- /dev/null +++ b/server/columns.spec.js @@ -0,0 +1,40 @@ +import {dirname} from 'node:path'; +import {fileURLToPath} from 'node:url'; +import fs from 'node:fs'; +import test from 'supertape'; +import {getColumns, isDev} from './columns.js'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = dirname(__filename); + +test('columns: prod', (t) => { + const columns = getColumns({ + isDev: false, + }); + + t.equal(columns[''], ''); + t.end(); +}); + +test('columns: dev', (t) => { + const columns = getColumns({ + isDev: true, + }); + + const css = fs.readFileSync(`${__dirname}/../css/columns/name-size-date.css`, 'utf8'); + + t.match(columns['name-size-date'], css); + t.end(); +}); + +test('columns: no args', (t) => { + const currentIsDev = isDev(); + isDev(true); + const columns = getColumns(); + + const css = fs.readFileSync(`${__dirname}/../css/columns/name-size-date.css`, 'utf8'); + isDev(currentIsDev); + + t.match(columns['name-size-date'], css); + t.end(); +}); diff --git a/server/common/entity.js b/server/common/entity.js deleted file mode 100644 index 8472a1bd..00000000 --- a/server/common/entity.js +++ /dev/null @@ -1,32 +0,0 @@ -'use strict'; - -const Entities = { - ' ': ' ', - '<': '<', - '>': '>', -}; - -const keys = Object.keys(Entities); - -module.exports.encode = (str) => { - keys.forEach((code) => { - const char = Entities[code]; - const reg = RegExp(char, 'g'); - - str = str.replace(reg, code); - }); - - return str; -}; - -module.exports.decode = (str) => { - keys.forEach((code) => { - const char = Entities[code]; - const reg = RegExp(code, 'g'); - - str = str.replace(reg, char); - }); - - return str; -}; - diff --git a/server/common/store.js b/server/common/store.js deleted file mode 100644 index 7a94054f..00000000 --- a/server/common/store.js +++ /dev/null @@ -1,13 +0,0 @@ -'use strict'; - -module.exports = () => { - const data = {}; - - return (value) => { - if (typeof value !== 'undefined') - data.value = value; - - return data.value; - }; -}; - diff --git a/server/config.fixture.json b/server/config.fixture.json new file mode 100644 index 00000000..530ec120 --- /dev/null +++ b/server/config.fixture.json @@ -0,0 +1,3 @@ +{ + "password": "9b71d224bd62f3785d96d46ad3ea3d73319bfbc2890caadae2dff72519673ca72323c3d99ba5c11d7c7acc6e14b8c5da0c4663475c2e5c3adef46f73bcdec043" +} diff --git a/server/config.js b/server/config.js index e085419f..77c4a6af 100644 --- a/server/config.js +++ b/server/config.js @@ -1,125 +1,170 @@ -'use strict'; +import path from 'node:path'; +import fs from 'node:fs'; +import Emitter from 'node:events'; +import {homedir} from 'node:os'; +import currify from 'currify'; +import wraptile from 'wraptile'; +import {tryToCatch} from 'try-to-catch'; +import pullout from 'pullout'; +import * as ponse from 'ponse'; +import jonny from 'jonny'; +import jju from 'jju'; +import writejson from 'writejson'; +import {tryCatch} from 'try-catch'; +import criton from 'criton'; +import * as CloudFunc from '#common/cloudfunc'; +import exit from './exit.js'; +import rootConfig from '../json/config.json' with { + type: 'json', +}; -const DIR_SERVER = __dirname + '/'; -const DIR = DIR_SERVER + '../'; +const isUndefined = (a) => typeof a === 'undefined'; -const path = require('path'); -const fs = require('fs'); +const HOME = homedir(); -const exit = require(DIR_SERVER + 'exit'); -const CloudFunc = require(DIR_SERVER + 'cloudfunc'); +const resolve = Promise.resolve.bind(Promise); -const pullout = require('pullout/legacy'); -const ponse = require('ponse'); -const jonny = require('jonny'); -const jju = require('jju'); -const writejson = require('writejson'); -const tryCatch = require('try-catch'); -const exec = require('execon'); -const criton = require('criton'); -const HOME = require('os-homedir')(); +const formatMsg = currify((a, b) => CloudFunc.formatMsg(a, b)); -const apiURL = CloudFunc.apiURL; +const {apiURL} = CloudFunc; -const ConfigPath = path.join(DIR, 'json/config.json'); -const ConfigHome = path.join(HOME, '.cloudcmd.json'); +const key = (a) => Object + .keys(a) + .pop(); + +const connection = currify(_connection); + +const connectionWrapped = wraptile(_connection); + +const middle = currify(_middle); const readjsonSync = (name) => { return jju.parse(fs.readFileSync(name, 'utf8'), { - mode: 'json' + mode: 'json', }); }; -const rootConfig = readjsonSync(ConfigPath); - -const key = (a) => Object.keys(a).pop(); - -let configHome; -let error = tryCatch(() => { - configHome = readjsonSync(ConfigHome); -}); - -if (error && error.code !== 'ENOENT') - exit(`cloudcmd --config ${ConfigHome}: ${error.message}`); - -const config = Object.assign({}, rootConfig, configHome); - -module.exports = manage; -module.exports.save = save; -module.exports.middle = middle; -module.exports.listen = (socket, authCheck) => { - check(socket, authCheck); +function read(filename) { + if (!filename) + return rootConfig; + const [error, configHome] = tryCatch(readjsonSync, filename); + + if (error && error.code !== 'ENOENT') + exit(`cloudcmd --config ${filename}: ${error.message}`); + + return { + ...rootConfig, + ...configHome, + }; +} + +export const configPath = path.join(HOME, '.cloudcmd.json'); + +const manageListen = currify((manage, socket, auth) => { if (!manage('configDialog')) return middle; - listen(socket, authCheck); + listen(manage, socket, auth); return middle; +}); + +function initWrite(filename, configManager) { + if (filename) + return write.bind(null, filename, configManager); + + return resolve; +} + +export function createConfig({configPath} = {}) { + const config = {}; + const changeEmitter = new Emitter(); + + const configManager = (key, value) => { + if (key === '*') + return config; + + if (isUndefined(value)) + return config[key]; + + config[key] = value; + changeEmitter.emit('change', key, value); + + return `${key} = ${value}`; + }; + + Object.assign(config, read(configPath)); + + configManager.middle = middle(configManager); + configManager.listen = manageListen(configManager); + configManager.write = initWrite(configPath, configManager); + configManager.subscribe = (fn) => { + changeEmitter.on('change', fn); + }; + + configManager.unsubscribe = (fn) => { + changeEmitter.off('change', fn); + }; + + return configManager; +} + +const write = (filename, config) => { + return writejson(filename, config('*'), { + mode: 0o600, + }); }; -function manage(key, value) { - if (!key) - return; +function _connection(manage, socket) { + socket.emit('config', manage('*')); - if (key === '*') - return config; - - if (value === undefined) - return config[key]; - - config[key] = value; -} - -function save(callback) { - writejson(ConfigHome, config, callback); -} - -function listen(sock, authCheck) { - const prefix = manage('prefix'); - - sock.of(prefix + '/config') - .on('connection', (socket) => { - const connect = exec.with(connection, socket); - - exec.if(!manage('auth'), connect, (fn) => { - authCheck(socket, fn); - }); - }); -} - -function connection(socket) { - socket.emit('config', config); + const emit = currify((socket, name, e) => { + return socket.emit(name, e.message); + }); socket.on('message', (json) => { if (typeof json !== 'object') return socket.emit('err', 'Error: Wrong data type!'); - - cryptoPass(json); - traverse(json); - save((error) => { - if (error) - return socket.emit('err', error.message); - + traverse(cryptoPass(manage, json)); + + const send = () => { const data = CloudFunc.formatMsg('config', key(json)); - - socket.broadcast.send(json); socket.send(json); socket.emit('log', data); - }); + }; + + manage + .write() + .then(send) + .catch(emit(socket, 'err')); }); } -function middle(req, res, next) { +function listen(manage, sock, auth) { + const prefix = manage('prefixSocket'); + + sock + .of(`${prefix}/config`) + .on('connection', (socket) => { + if (!manage('auth')) + return connection(manage, socket); + + const reject = () => socket.emit('reject'); + socket.on('auth', auth(connectionWrapped(manage, socket), reject)); + }); +} + +async function _middle(manage, req, res, next) { const noConfigDialog = !manage('configDialog'); - if (req.url !== apiURL + '/config') + if (req.url !== `${apiURL}/config`) return next(); - + switch(req.method) { case 'GET': - get(req, res, next); + get(manage, req, res); break; case 'PATCH': @@ -127,8 +172,8 @@ function middle(req, res, next) { return res .status(404) .send('Config is disabled'); - - patch(req, res, next); + + await patch(manage, req, res); break; default: @@ -136,63 +181,70 @@ function middle(req, res, next) { } } -function get(req, res) { - const data = jonny.stringify(config); +function get(manage, request, response) { + const data = jonny.stringify(manage('*')); ponse.send(data, { - name : 'config.json', - request : req, - response: res, - cache : false + name: 'config.json', + request, + response, + cache: false, }); } -function patch(req, res, callback) { +async function patch(manage, request, response) { + const name = 'config.json'; + const cache = false; + const options = { - name : 'config.json', - request : req, - response: res, - cache : false + name, + request, + response, + cache, }; - pullout(req, 'string', (error, body) => { - const json = jonny.parse(body) || {}; - - if (error) - return callback(error); - - cryptoPass(json); - traverse(json); - - save((error) => { - if (error) - return ponse.sendError(error, options); - - const data = CloudFunc.formatMsg('config', key(json)); - - ponse.send(data, options); - }); + const [e] = await tryToCatch(patchConfig, manage, options); + + if (e) + ponse.sendError(e, options); +} + +async function patchConfig(manage, {name, request, response, cache}) { + const str = await pullout(request); + const json = jonny.parse(str); + + traverse(cryptoPass(manage, json)); + await manage.write(); + + const msg = formatMsg('config', key(json)); + ponse.send(msg, { + name, + request, + response, + cache, }); } -function traverse(json) { - Object.keys(json).forEach((name) => { +function traverse([manage, json]) { + for (const name of Object.keys(json)) { manage(name, json[name]); - }); + } } -function cryptoPass(json) { +export const _cryptoPass = cryptoPass; + +function cryptoPass(manage, json) { const algo = manage('algo'); - if (json && json.password) - json.password = criton(json.password, algo); -} - -function check(socket, authCheck) { - if (!socket) - throw Error('socket could not be empty!'); + if (!json.password) + return [manage, json]; - if (authCheck && typeof authCheck !== 'function') - throw Error('authCheck should be function!'); + const password = criton(json.password, algo); + + return [ + manage, { + ...json, + password, + }, + ]; } - diff --git a/server/config.spec.js b/server/config.spec.js new file mode 100644 index 00000000..92b0646c --- /dev/null +++ b/server/config.spec.js @@ -0,0 +1,105 @@ +import {createRequire} from 'node:module'; +import {test, stub} from 'supertape'; +import {apiURL} from '#common/cloudfunc'; +import {createConfig, _cryptoPass} from './config.js'; +import {connect} from '../test/before.js'; + +const require = createRequire(import.meta.url); +const fixture = require('./config.fixture.json'); + +const config = createConfig(); + +test('config: manage', (t) => { + t.equal(undefined, config(), 'should return "undefined"'); + t.end(); +}); + +test('config: manage: get', async (t) => { + const editor = 'deepword'; + const configManager = createConfig(); + + const {done} = await connect({ + config: { + editor, + }, + configManager, + }); + + done(); + + t.equal(configManager('editor'), editor, 'should get config'); + t.end(); +}); + +test('config: manage: get: config', async (t) => { + const editor = 'deepword'; + const conf = { + editor, + }; + + const {done} = await connect({ + config: conf, + }); + + config('editor', 'dword'); + done(); + + t.equal('dword', config('editor'), 'should set config'); + t.end(); +}); + +test('config: manage: get: *', (t) => { + const data = config('*'); + const keys = Object.keys(data); + + t.ok(keys.length > 1, 'should return config data'); + t.end(); +}); + +test('config: cryptoPass: no password', (t) => { + const json = { + hello: 'world', + }; + + const config = createConfig(); + const result = _cryptoPass(config, json); + + t.deepEqual(result, [config, json], 'should not change json'); + t.end(); +}); + +test('config: cryptoPass', (t) => { + const json = { + password: 'hello', + }; + + const {password} = fixture; + + const expected = { + password, + }; + + const config = createConfig(); + const result = _cryptoPass(config, json); + + t.deepEqual(result, [config, expected], 'should crypt password'); + t.end(); +}); + +test('config: middle: no', (t) => { + const {middle} = config; + const next = stub(); + const res = null; + const url = `${apiURL}/config`; + const method = 'POST'; + + const req = { + url, + method, + }; + + middle(req, res, next); + + t.calledWithNoArgs(next, 'should call next'); + t.end(); +}); diff --git a/server/depstore.js b/server/depstore.js new file mode 100644 index 00000000..c5fefaa9 --- /dev/null +++ b/server/depstore.js @@ -0,0 +1,13 @@ +export const createDepStore = () => { + const deps = {}; + + return (name, value) => { + if (!name) + return false; + + if (!value) + return deps[name]; + + deps[name] = value; + }; +}; diff --git a/server/distribute/export.js b/server/distribute/export.js new file mode 100644 index 00000000..5e1b54d4 --- /dev/null +++ b/server/distribute/export.js @@ -0,0 +1,124 @@ +import currify from 'currify'; +import wraptile from 'wraptile'; +import squad from 'squad'; +import {omit} from '#common/omit'; +import log, { + exportStr, + connectedStr, + disconnectedStr, + authTryStr, + makeColor, + getMessage, + getDescription, + logWrapped, +} from './log.js'; + +const omitList = [ + 'auth', + 'username', + 'password', + 'algo', + 'name', + 'ip', + 'port', + 'root', + 'import', + 'importUrl', + 'importToken', + 'export', + 'exportToken', + 'log', + 'configDialog', +]; + +const omitConfig = (config) => omit(config, omitList); + +export const distributeExport = (config, socket) => { + if (!config('export')) + return; + + const prefix = config('prefix'); + const distributePrefix = `${prefix}/distribute`; + const isLog = config('log'); + + const onError = squad(logWrapped(isLog, exportStr), getMessage); + + const onConnectError = squad(logWrapped(isLog, exportStr), getDescription); + + socket + .of(distributePrefix) + .on('connection', onConnection(push, config)) + .on('error', onError) + .on('connect_error', onConnectError); +}; + +const push = currify((socket, key, value) => { + if (omitList.includes(key)) + return; + + socket.emit('change', key, value); +}); + +function getHost(socket) { + const {remoteAddress} = socket.request.connection; + + const { + name, + port, + color, + } = socket.handshake.query; + + if (!name) + return `${remoteAddress}:${port}`; + + const colorName = makeColor(name, color); + + return `${colorName} [${remoteAddress}:${port}]`; +} + +const connectPush = wraptile((push, config, socket) => { + socket.emit('accept'); + + const isLog = config('log'); + const host = getHost(socket); + const subscription = push(socket); + + socket.on('disconnect', onDisconnect( + subscription, + config, + host, + )); + + log(isLog, exportStr, `${connectedStr} to ${host}`); + socket.emit('config', omitConfig(config('*'))); + log(isLog, exportStr, `config send to ${host}`); + + config.subscribe(subscription); +}); + +const onConnection = currify((push, config, socket) => { + const host = getHost(socket); + const reject = () => { + socket.emit('reject'); + socket.disconnect(); + }; + + const isLog = config('log'); + + log(isLog, exportStr, `${authTryStr} from ${host}`); + socket.on('auth', auth(config, reject, connectPush(push, config, socket))); +}); + +const auth = currify((config, reject, fn, token) => { + if (token === config('exportToken')) + return fn(); + + reject(); +}); + +const onDisconnect = wraptile((subscription, config, host) => { + const isLog = config('log'); + + config.unsubscribe(subscription); + log(isLog, exportStr, `${disconnectedStr} from ${host}`); +}); diff --git a/server/distribute/export.spec.js b/server/distribute/export.spec.js new file mode 100644 index 00000000..ca6155a8 --- /dev/null +++ b/server/distribute/export.spec.js @@ -0,0 +1,68 @@ +import {once} from 'node:events'; +import test from 'supertape'; +import io from 'socket.io-client'; +import * as Config from '../config.js'; +import {connect} from '../../test/before.js'; + +const config = Config.createConfig(); + +test('distribute: export', async (t) => { + const defaultConfig = { + export: true, + exportToken: 'a', + vim: true, + log: false, + prefix: '', + }; + + const {port, done} = await connect({ + config: defaultConfig, + configManager: config, + }); + + const url = `http://localhost:${port}/distribute?port=1111`; + const socket = io.connect(url); + + await once(socket, 'connect'); + socket.emit('auth', 'a'); + + await once(socket, 'accept'); + config('vim', false); + config('auth', true); + + await once(socket, 'change'); + + socket.close(); + await done(); + + t.pass('should emit change'); + t.end(); +}); + +test('distribute: export: config', async (t) => { + const defaultConfig = { + export: true, + exportToken: 'a', + vim: true, + log: false, + }; + + const {port, done} = await connect({ + config: defaultConfig, + }); + + const url = `http://localhost:${port}/distribute?port=1111`; + const socket = io.connect(url); + + socket.once('connect', () => { + socket.emit('auth', 'a'); + }); + + const data = await once(socket, 'config'); + + socket.close(); + await done(); + + t.equal(typeof data, 'object', 'should emit object'); + t.end(); +}); diff --git a/server/distribute/import.js b/server/distribute/import.js new file mode 100644 index 00000000..f6cbe614 --- /dev/null +++ b/server/distribute/import.js @@ -0,0 +1,160 @@ +import currify from 'currify'; +import wraptile from 'wraptile'; +import squad from 'squad'; +import {fullstore} from 'fullstore'; +import io from 'socket.io-client'; +import _forEachKey from 'for-each-key'; +import log from './log.js'; +import * as env from '../env.js'; + +const isUndefined = (a) => typeof a === 'undefined'; + +const noop = () => {}; +const forEachKey = currify(_forEachKey); + +const { + importStr, + connectedStr, + disconnectedStr, + tokenRejectedStr, + authTryStr, + getMessage, + getDescription, + logWrapped, +} = log; + +const {entries} = Object; + +const equal = (a, b) => `${a}=${b}`; +const append = currify((obj, a, b) => obj.value += b && equal(a, b) + '&'); + +const wrapApply = (f, disconnect) => (status) => () => f(null, { + status, + disconnect, +}); + +const closeIfNot = wraptile((socket, is) => !is && socket.close()); +const addUrl = currify((url, a) => `${url}: ${a}`); + +const rmListeners = wraptile((socket, listeners) => { + socket.removeListener('connect', listeners.onConnect); + socket.removeListener('accept', listeners.onAccept); + socket.removeListener('config', listeners.onConfig); + socket.removeListener('error', listeners.onError); + socket.removeListener('connect_error', listeners.onConnectError); + socket.removeListener('reject', listeners.onReject); + + if (listeners.onChange) + socket.removeListener('change', listeners.onChange); +}); + +const canceled = (f) => f(null, { + status: 'canceled', + disconnect: noop, +}); + +const done = wraptile((fn, store) => fn(null, { + status: store(), +})); + +const emitAuth = wraptile((importUrl, config, socket) => { + const isLog = config('log'); + log(isLog, importStr, `${authTryStr} to ${importUrl}`); + socket.emit('auth', config('importToken')); +}); + +const updateConfig = currify((config, data) => { + for (const [key, value] of entries(data)) { + if (!isUndefined(env.parse(key))) + continue; + + config(key, value); + } +}); + +export const distributeImport = (config, options, fn) => { + fn = fn || options; + + if (!config('import')) + return canceled(fn); + + const importUrl = config('importUrl'); + const importListen = config('importListen'); + const name = config('name'); + const port = config('port'); + const isLog = config('log'); + + const query = toLine({ + name, + port, + }); + + const url = `${importUrl}/distribute?${query}`; + + const socket = io.connect(url, { + ...options, + rejectUnauthorized: false, + }); + + const superFn = wrapApply(fn, socket.close.bind(socket)); + const colorUrl = importUrl; + const close = closeIfNot(socket, importListen); + + const statusStore = fullstore(); + const statusStoreWrapped = wraptile(statusStore); + + const onConfig = squad(close, logWrapped(isLog, importStr, `config received from ${colorUrl}`), statusStoreWrapped('received'), updateConfig(config)); + + const onError = squad(superFn('error'), logWrapped(isLog, config, importStr), addUrl(colorUrl), getMessage); + + const onConnectError = squad(superFn('connect_error'), logWrapped(isLog, importStr), addUrl(colorUrl), getDescription); + + const onConnect = emitAuth(importUrl, config, socket); + const onAccept = logWrapped(isLog, importStr, `${connectedStr} to ${colorUrl}`); + const onChange = squad(logWrapped(isLog, importStr), config); + + const onReject = squad(superFn('reject'), logWrapped( + isLog, + importStr, + tokenRejectedStr, + )); + + const onDisconnect = squad(...[ + done(fn, statusStore), + logWrapped(isLog, importStr, `${disconnectedStr} from ${colorUrl}`), + rmListeners(socket, { + onConnect, + onAccept, + onConfig, + onError, + onConnectError, + onReject, + onChange, + }), + ]); + + socket.on('connect', onConnect); + socket.on('accept', onAccept); + socket.on('disconnect', onDisconnect); + socket.on('config', onConfig); + socket.on('error', onError); + socket.on('connect_error', onConnectError); + socket.on('reject', onReject); + + if (config('importListen')) + socket.on('change', onChange); +}; + +function toLine(obj) { + const result = { + value: '', + }; + + forEachKey(append(result), obj); + + const start = 0; + const end = 1; + const backward = -1; + + return result.value.slice(start, backward * end); +} diff --git a/server/distribute/import.spec.js b/server/distribute/import.spec.js new file mode 100644 index 00000000..10e246be --- /dev/null +++ b/server/distribute/import.spec.js @@ -0,0 +1,285 @@ +import process from 'node:process'; +import {promisify} from 'node:util'; +import test from 'supertape'; +import {tryToCatch} from 'try-to-catch'; +import {createConfigManager} from '#server/cloudcmd'; +import {connect} from '../../test/before.js'; +import {distributeImport} from './import.js'; + +const distribute = { + import: promisify(distributeImport), +}; + +const config = createConfigManager(); + +process.on('unhandledRejection', console.log); + +test('distribute: import: canceled', async (t) => { + const {done} = await connect({ + config: { + export: false, + import: false, + importListen: false, + log: false, + }, + }); + + const {status} = await distribute.import(config); + + await done(); + + t.equal(status, 'canceled'); + t.end(); +}); + +test('distribute: import: received: no error', async (t) => { + const {done, port} = await connect({ + config: { + import: true, + importListen: false, + export: true, + log: false, + }, + }); + + config('importUrl', `http://localhost:${port}`); + + const [e] = await tryToCatch(distribute.import, config); + + await done(); + + t.notOk(e, 'should not be error'); + t.end(); +}); + +test('distribute: import: received', async (t) => { + const configManager = createConfigManager(); + const {done, port} = await connect({ + configManager, + config: { + name: 'bill', + import: true, + importToken: 'a', + exportToken: 'a', + export: true, + importListen: false, + log: false, + }, + }); + + configManager('importUrl', `http://localhost:${port}`); + + const {status} = await distribute.import(configManager); + await done(); + + t.equal(status, 'received'); + t.end(); +}); + +test('distribute: import: received: auth: reject', async (t) => { + const configManager = createConfigManager(); + const {done, port} = await connect({ + configManager, + config: { + name: 'bill', + import: true, + importToken: 'xxxxx', + exportToken: 'bbbbb', + export: true, + importListen: false, + log: false, + }, + }); + + configManager('importUrl', `http://localhost:${port}`); + + const {status} = await distribute.import(configManager); + await done(); + + t.equal(status, 'reject'); + t.end(); +}); + +test('distribute: import: received: auth: accept', async (t) => { + const configManager = createConfigManager(); + const {done, port} = await connect({ + configManager, + config: { + name: 'bill', + import: true, + importToken: 'xxxxx', + exportToken: 'xxxxx', + export: true, + importListen: false, + log: false, + }, + }); + + configManager('importUrl', `http://localhost:${port}`); + + const {status} = await distribute.import(configManager); + await done(); + + t.equal(status, 'received'); + t.end(); +}); + +test('distribute: import: received: no name', async (t) => { + const configManager = createConfigManager(); + const {done, port} = await connect({ + configManager, + config: { + name: '', + import: true, + export: true, + importListen: false, + log: false, + }, + }); + + configManager('importUrl', `http://localhost:${port}`); + + const {status} = await distribute.import(configManager); + await done(); + + t.equal(status, 'received'); + t.end(); +}); + +test('distribute: import: error', async (t) => { + const configManager = createConfigManager(); + const {done} = await connect({ + configManager, + config: { + import: true, + export: false, + importListen: false, + log: false, + }, + }); + + configManager('importUrl', `http://localhost:0`); + + const {status} = await distribute.import(configManager, { + reconnection: false, + }); + + await done(); + + t.equal(status, 'connect_error'); + t.end(); +}); + +test('distribute: import: config:change: no export', async (t) => { + const configManager = createConfigManager(); + const {done} = await connect({ + configManager, + config: { + import: true, + export: false, + importListen: true, + log: false, + }, + }); + + const {status} = await distribute.import(configManager, { + reconnection: false, + }); + + await done(); + + t.equal(status, 'connect_error'); + t.end(); +}); + +test('distribute: import: env', async (t) => { + const configManager = createConfigManager(); + const configManagerImport = createConfigManager(); + + const exporter = await connect({ + configManager, + config: { + name: 'bill', + import: false, + importListen: false, + export: true, + exportToken: 'a', + log: false, + editor: 'edward', + }, + }); + + const importer = await connect({ + configManager: configManagerImport, + config: { + name: 'jack', + import: true, + importToken: 'a', + export: false, + importListen: false, + log: false, + editor: 'deepword', + }, + }); + + process.env.cloudcmd_editor = 'some editor'; + + configManagerImport('importUrl', `http://localhost:${exporter.port}`); + + await distribute.import(configManagerImport); + + await importer.done(); + await exporter.done(); + + delete process.env.cloudcmd_editor; + + const result = configManagerImport('editor'); + const expected = 'deepword'; + + t.equal(result, expected); + t.end(); +}); + +test('distribute: import: no env', async (t) => { + const configManager = createConfigManager(); + const configManagerImport = createConfigManager(); + + const exporter = await connect({ + configManager, + config: { + name: 'bill', + import: false, + importListen: false, + export: true, + exportToken: 'a', + log: false, + editor: 'edward', + }, + }); + + const importer = await connect({ + configManager: configManagerImport, + config: { + name: 'jack', + import: true, + importToken: 'a', + export: false, + importListen: false, + log: false, + editor: 'deepword', + }, + }); + + configManagerImport('importUrl', `http://localhost:${exporter.port}`); + + await distribute.import(configManagerImport); + + await importer.done(); + await exporter.done(); + + const result = configManagerImport('editor'); + const expected = 'edward'; + + t.equal(result, expected); + t.end(); +}); diff --git a/server/distribute/log.js b/server/distribute/log.js new file mode 100644 index 00000000..acea5759 --- /dev/null +++ b/server/distribute/log.js @@ -0,0 +1,52 @@ +import wraptile from 'wraptile'; +import chalk from 'chalk'; +import datetime from '../../common/datetime.js'; + +const {assign} = Object; + +const log = (isLog, name, msg) => isLog && console.log(`${datetime()} -> ${name}: ${msg}`); + +export const makeColor = (a) => chalk.blue(a); +export const getMessage = (e) => e.message || e; +export const getDescription = (e) => e.message; + +export default log; + +export const logWrapped = wraptile(log); + +export const importStr = 'import'; +export const exportStr = 'export'; +export const connectedStr = chalk.green('connected'); +export const disconnectedStr = chalk.red('disconnected'); +export const tokenRejectedStr = chalk.red('token rejected'); +export const authTryStr = chalk.yellow('try to auth'); + +export function stringToRGB(a) { + return [ + a.charCodeAt(0), + a.length, + crc(a), + ]; +} + +const add = (a, b) => a + b.charCodeAt(0); + +function crc(a) { + return a + .split('') + .reduce(add, 0); +} + +assign(log, { + getMessage, + makeColor, + getDescription, + authTryStr, + stringToRGB, + logWrapped, + importStr, + exportStr, + connectedStr, + disconnectedStr, + tokenRejectedStr, +}); diff --git a/server/distribute/log.spec.js b/server/distribute/log.spec.js new file mode 100644 index 00000000..1c6d1aa3 --- /dev/null +++ b/server/distribute/log.spec.js @@ -0,0 +1,63 @@ +import test from 'supertape'; +import log from './log.js'; +import {createConfig} from '../config.js'; + +test('distribute: log: getMessage', (t) => { + const e = 'hello'; + const result = log.getMessage(e); + + t.equal(e, result); + t.end(); +}); + +test('distribute: log: getMessage: message', (t) => { + const message = 'hello'; + const result = log.getMessage({ + message, + }); + + t.equal(result, message); + t.end(); +}); + +test('distribute: log: config', (t) => { + const config = createConfig(); + const logOriginal = config('log'); + + config('log', true); + log('log', 'test message'); + config('log', logOriginal); + + t.end(); +}, { + checkAssertionsCount: false, +}); + +test('distribute: log: stringToRGB', (t) => { + const result = log.stringToRGB('abc'); + + t.deepEqual(result, [97, 3, 294], 'should return [charCode, length, crc]'); + t.end(); +}); + +test('distribute: log: makeColor', (t) => { + const result = log.makeColor('hello'); + + t.match(result, 'hello', 'should return colored string containing the input'); + t.end(); +}); + +test('distribute: log: getDescription', (t) => { + const message = 'some error'; + const result = log.getDescription({ + message, + }); + + t.equal(result, message, 'should return message from error object'); + t.end(); +}); + +test('distribute: log: connectedStr', (t) => { + t.ok(log.connectedStr, 'should have connectedStr'); + t.end(); +}); diff --git a/server/env.js b/server/env.js index bc6d5eff..86865307 100644 --- a/server/env.js +++ b/server/env.js @@ -1,22 +1,27 @@ -'use strict'; +import {env} from 'node:process'; +import snake from 'just-snake-case'; -const env = process.env; const up = (a) => a.toUpperCase(); -module.exports = parse; -module.exports.bool = (name) => { +export const bool = (name) => { const value = parse(name); + if (value === 'true') + return true; + + if (value === '1') + return true; + if (value === 'false') return false; - return value; + if (value === '0') + return false; }; -function parse(name) { - const small = `cloudcmd_${name}`; +export const parse = (name) => { + const small = `cloudcmd_${snake(name)}`; const big = up(small); - return env[small] || env[big]; -} - + return env[big] || env[small]; +}; diff --git a/server/env.spec.js b/server/env.spec.js new file mode 100644 index 00000000..5a8765f4 --- /dev/null +++ b/server/env.spec.js @@ -0,0 +1,69 @@ +import process from 'node:process'; +import {test} from 'supertape'; +import * as env from './env.js'; + +test('cloudcmd: server: env: bool: upper case first', (t) => { + const { + CLOUDCMD_TERMINAL, + cloudcmd_terminal, + } = process.env; + + process.env.cloudcmd_terminal = 'true'; + process.env.CLOUDCMD_TERMINAL = 'false'; + + const result = env.bool('terminal'); + + process.env.cloudcmd_terminal = cloudcmd_terminal; + process.env.CLOUDCMD_TERMINAL = CLOUDCMD_TERMINAL; + + t.notOk(result); + t.end(); +}); + +test('cloudcmd: server: env: bool: snake_case', (t) => { + process.env.cloudcmd_config_auth = 'true'; + + const result = env.bool('configAuth'); + + t.ok(result); + t.end(); +}); + +test('cloudcmd: server: env: bool: number', (t) => { + const {cloudcmd_terminal} = process.env; + + process.env.CLOUDCMD_TERMINAL = '1'; + + const result = env.bool('terminal'); + + process.env.CLOUDCMD_TERMINAL = cloudcmd_terminal; + + t.ok(result); + t.end(); +}); + +test('cloudcmd: server: env: bool: number: 0', (t) => { + const {cloudcmd_terminal} = process.env; + + process.env.cloudcmd_terminal = '0'; + + const result = env.bool('terminal'); + + process.env.cloudcmd_terminal = cloudcmd_terminal; + + t.notOk(result); + t.end(); +}); + +test('cloudcmd: server: env: bool: zero uppercase', (t) => { + const {CLOUDCMD_TERMINAL} = process.env; + + process.env.CLOUDCMD_TERMINAL = '0'; + + const result = env.bool('terminal'); + + process.env.CLOUDCMD_TERMINAL = CLOUDCMD_TERMINAL; + + t.notOk(result); + t.end(); +}); diff --git a/server/exit.js b/server/exit.js index 75a4fe20..ebe5ad8f 100644 --- a/server/exit.js +++ b/server/exit.js @@ -1,7 +1,10 @@ -'use strict'; +import process from 'node:process'; -module.exports = function() { - console.error.apply(console, arguments); +const getMessage = (a) => a?.message || a; + +export default (...args) => { + const messages = args.map(getMessage); + + console.error(...messages); process.exit(1); }; - diff --git a/server/exit.spec.js b/server/exit.spec.js new file mode 100644 index 00000000..94d627ac --- /dev/null +++ b/server/exit.spec.js @@ -0,0 +1,49 @@ +import process from 'node:process'; +import {test, stub} from 'supertape'; +import exit from './exit.js'; + +test('cloudcmd: exit: process.exit', (t) => { + const {exit: exitOriginal} = process; + const exitStub = stub(); + + process.exit = exitStub; + + exit(); + process.exit = exitOriginal; + + t.calledWith(exitStub, [1], 'should call process.exit'); + t.end(); +}); + +test('cloudcmd: exit: console.error', (t) => { + const {exit: exitOriginal} = process; + const {error} = console; + const errorStub = stub(); + + console.error = errorStub; + process.exit = stub(); + + exit('hello world'); + + process.exit = exitOriginal; + console.error = error; + + t.calledWith(errorStub, ['hello world'], 'should call console.error'); + t.end(); +}); + +test('cloudcmd: exit.error: console.error: error', (t) => { + const {exit: exitOriginal} = process; + const {error} = console; + const errorStub = stub(); + + console.error = errorStub; + process.exit = stub(); + + exit(Error('hello world')); + process.exit = exitOriginal; + console.error = error; + + t.calledWith(errorStub, ['hello world'], 'should call console.error'); + t.end(); +}); diff --git a/server/fixture-user-menu/io-cp-fix.js b/server/fixture-user-menu/io-cp-fix.js new file mode 100644 index 00000000..52f9c0b0 --- /dev/null +++ b/server/fixture-user-menu/io-cp-fix.js @@ -0,0 +1,3 @@ +async function copy() { + await IO.copy(dirPath, mp3Dir, mp3Names); +} diff --git a/server/fixture-user-menu/io-cp.js b/server/fixture-user-menu/io-cp.js new file mode 100644 index 00000000..0547933c --- /dev/null +++ b/server/fixture-user-menu/io-cp.js @@ -0,0 +1,7 @@ +async function copy() { + await IO.cp({ + from: dirPath, + to: mp3Dir, + names: mp3Names, + }); +} diff --git a/server/fixture-user-menu/io-mv-fix.js b/server/fixture-user-menu/io-mv-fix.js new file mode 100644 index 00000000..d95ccf3f --- /dev/null +++ b/server/fixture-user-menu/io-mv-fix.js @@ -0,0 +1,3 @@ +async function move() { + await IO.move(dirPath, mp3Dir, mp3Names); +} diff --git a/server/fixture-user-menu/io-mv.js b/server/fixture-user-menu/io-mv.js new file mode 100644 index 00000000..56884891 --- /dev/null +++ b/server/fixture-user-menu/io-mv.js @@ -0,0 +1,7 @@ +async function move() { + await IO.mv({ + from: dirPath, + to: mp3Dir, + names: mp3Names, + }); +} diff --git a/server/fixture/route.js b/server/fixture/route.js new file mode 100644 index 00000000..ce013625 --- /dev/null +++ b/server/fixture/route.js @@ -0,0 +1 @@ +hello diff --git a/server/markdown.js b/server/markdown.js deleted file mode 100644 index 8e6538c3..00000000 --- a/server/markdown.js +++ /dev/null @@ -1,64 +0,0 @@ -'use strict'; - -const DIR_ROOT = __dirname + '/../'; -const fs = require('fs'); - -const pullout = require('pullout/legacy'); -const ponse = require('ponse'); -const markdown = require('markdown-it')(); - -const root = require('./root'); - -module.exports = (name, request, callback) => { - const method = request.method; - const query = ponse.getQuery(request); - - check(name, request, callback); - - switch(method) { - case 'GET': - name = name.replace('/markdown', ''); - - if (query === 'relative') - name = DIR_ROOT + name; - else - name = root(name); - - fs.readFile(name, 'utf8', (error, data) => { - if (error) - return callback(error); - - parse(data, callback); - }); - break; - - case 'PUT': - pullout(request, 'string', (error, data) => { - if (error) - return callback(error); - - parse(data, callback); - }); - break; - } -}; - -function parse(data, callback) { - process.nextTick(() => { - const md = markdown.render(data); - - callback(null, md); - }); -} - -function check(name, request, callback) { - if (typeof name !== 'string') - throw Error('name should be string!'); - - if (!request) - throw Error('request could not be empty!'); - - if (typeof callback !== 'function') - throw Error('callback should be function!'); -} - diff --git a/server/markdown/fixture/markdown.html b/server/markdown/fixture/markdown.html new file mode 100644 index 00000000..6e7c1e6a --- /dev/null +++ b/server/markdown/fixture/markdown.html @@ -0,0 +1 @@ +

    hello

    diff --git a/server/markdown/fixture/markdown.md b/server/markdown/fixture/markdown.md new file mode 100644 index 00000000..8954bb97 --- /dev/null +++ b/server/markdown/fixture/markdown.md @@ -0,0 +1 @@ +# hello diff --git a/server/markdown/fixture/markdown.zip b/server/markdown/fixture/markdown.zip new file mode 100644 index 00000000..41e0b976 Binary files /dev/null and b/server/markdown/fixture/markdown.zip differ diff --git a/server/markdown/index.js b/server/markdown/index.js new file mode 100644 index 00000000..3f80ff03 --- /dev/null +++ b/server/markdown/index.js @@ -0,0 +1,62 @@ +import {callbackify} from 'node:util'; +import {fileURLToPath} from 'node:url'; +import {dirname} from 'node:path'; +import pullout from 'pullout'; +import {getQuery} from 'ponse'; +import {read} from 'redzip'; +import root from '../root.js'; +import parse from './worker.js'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = dirname(__filename); +const isString = (a) => typeof a === 'string'; + +// warm up +parse(''); + +const DIR_ROOT = `${__dirname}/../../`; + +export default callbackify(async (name, rootDir, request) => { + check(name, request); + + const {method} = request; + + switch(method) { + case 'GET': + return await onGET(request, name, rootDir); + + case 'PUT': + return await onPUT(request); + } +}); + +function parseName(query, name, rootDir) { + const shortName = name.replace('/markdown', ''); + + if (query === 'relative') + return DIR_ROOT + shortName; + + return root(shortName, rootDir); +} + +async function onGET(request, name, root) { + const query = getQuery(request); + const fileName = parseName(query, name, root); + const stream = await read(fileName); + const data = await pullout(stream); + + return parse(data); +} + +async function onPUT(request) { + const data = await pullout(request); + return parse(data); +} + +function check(name, request) { + if (!isString(name)) + throw Error('name should be string!'); + + if (!request) + throw Error('request could not be empty!'); +} diff --git a/server/markdown/index.spec.js b/server/markdown/index.spec.js new file mode 100644 index 00000000..f705915e --- /dev/null +++ b/server/markdown/index.spec.js @@ -0,0 +1,128 @@ +import fs from 'node:fs'; +import {join} from 'node:path'; +import {promisify} from 'node:util'; +import {tryToCatch} from 'try-to-catch'; +import test from 'supertape'; +import {serveOnce} from 'serve-once'; +import {cloudcmd} from '#server/cloudcmd'; +import markdown from './index.js'; + +const config = { + auth: false, +}; + +const configManager = cloudcmd.createConfigManager(); + +const {request} = serveOnce(cloudcmd, { + config, + configManager, +}); + +const fixtureDir = new URL('fixture', import.meta.url).pathname; + +const _markdown = promisify(markdown); + +test('cloudcmd: markdown: error', async (t) => { + const {body} = await request.get('/api/v1/markdown/not-found'); + + t.match(body, 'ENOENT', 'should not found'); + t.end(); +}); + +test('cloudcmd: markdown: relative: error', async (t) => { + const {body} = await request.get('/api/v1/markdown/not-found?relative'); + + t.match(body, 'ENOENT', 'should not found'); + t.end(); +}); + +test('cloudcmd: markdown: relative', async (t) => { + const {body} = await request.get('/api/v1/markdown/HELP.md?relative'); + + t.notOk(/ENOENT/.test(body), 'should not return error'); + t.end(); +}); + +test('cloudcmd: markdown: put', async (t) => { + const md = join(fixtureDir, 'markdown.md'); + const html = join(fixtureDir, 'markdown.html'); + + const mdStream = fs.createReadStream(md); + const htmlFile = fs.readFileSync(html, 'utf8'); + + const {body} = await request.put('/api/v1/markdown', { + body: mdStream, + }); + + t.equal(body, htmlFile, 'should render markdown input to html'); + t.end(); +}); + +test('cloudcmd: markdown: put: error', async (t) => { + const md = join(fixtureDir, 'markdown-not-exist.md'); + + const name = 'hello'; + const mdStream = fs.createReadStream(md); + + mdStream.url = 'http://hello.world'; + mdStream.method = 'PUT'; + + const [e] = await tryToCatch(_markdown, name, '/', mdStream); + + t.match(e.message, 'ENOENT: no such file or directory', 'should emit error'); + t.end(); +}); + +test('cloudcmd: markdown: no name', async (t) => { + const [e] = await tryToCatch(_markdown); + + t.equal(e.message, 'name should be string!', 'should throw when no name'); + t.end(); +}); + +test('cloudcmd: markdown: no request', async (t) => { + const [e] = await tryToCatch(_markdown, 'hello'); + + t.equal(e.message, 'request could not be empty!', 'should throw when no request'); + t.end(); +}); + +test('cloudcmd: markdown', async (t) => { + const configManager = cloudcmd.createConfigManager(); + const fixtureDir = new URL('fixture', import.meta.url).pathname; + + const config = { + auth: false, + root: fixtureDir, + }; + + const {request} = serveOnce(cloudcmd, { + config, + configManager, + }); + + const {body} = await request.get('/api/v1/markdown/markdown.md'); + + t.equal(body, '

    hello

    \n'); + t.end(); +}); + +test('cloudcmd: markdown: zip', async (t) => { + const configManager = cloudcmd.createConfigManager(); + const fixtureDir = new URL('fixture', import.meta.url).pathname; + + const config = { + auth: false, + root: fixtureDir, + }; + + const {request} = serveOnce(cloudcmd, { + config, + configManager, + }); + + const {body} = await request.get('/api/v1/markdown/markdown.zip/markdown.md'); + + t.equal(body, '

    hello

    \n'); + t.end(); +}); diff --git a/server/markdown/worker.js b/server/markdown/worker.js new file mode 100644 index 00000000..ccac2aee --- /dev/null +++ b/server/markdown/worker.js @@ -0,0 +1,5 @@ +import createMarkdownIt from 'markdown-it'; + +const markdownIt = createMarkdownIt(); + +export default (a) => markdownIt.render(a); diff --git a/server/modulas.js b/server/modulas.js index 1b32dffa..7d38df99 100644 --- a/server/modulas.js +++ b/server/modulas.js @@ -1,9 +1,9 @@ -'use strict'; +import deepmerge from 'deepmerge'; +import originalModules from '../json/modules.json' with { + type: 'json', +}; -const deepmerge = require('deepmerge'); -const originalModules = require('../json/modules'); - -module.exports = (modules) => { +export default (modules) => { const result = deepmerge(originalModules, modules || {}); return (req, res, next) => { @@ -13,4 +13,3 @@ module.exports = (modules) => { res.send(result); }; }; - diff --git a/server/plugins.js b/server/plugins.js deleted file mode 100644 index 8b2c1105..00000000 --- a/server/plugins.js +++ /dev/null @@ -1,20 +0,0 @@ -'use strict'; - -const currify = require('currify/legacy'); -const files = require('files-io'); - -module.exports = currify((plugins, req, res, next) => { - if (req.url !== '/plugins.js') - return next(); - - if (!plugins || !plugins.length) - return res.send(''); - - files.readPipe(plugins, res, (e) => { - if (!e) - return; - - res.end(e.message); - }); -}); - diff --git a/server/prefixer.js b/server/prefixer.js index 3b5f3a95..87a83411 100644 --- a/server/prefixer.js +++ b/server/prefixer.js @@ -1,15 +1,14 @@ -'use strict'; +const isString = (a) => typeof a === 'string'; -module.exports = (value) => { - if (typeof value !== 'string') +export default (value) => { + if (!isString(value)) return ''; if (value.length === 1) return ''; - if (value && !~value.indexOf('/')) - return '/' + value; + if (value && !value.includes('/')) + return `/${value}`; return value; }; - diff --git a/test/server/prefixer.js b/server/prefixer.spec.js similarity index 79% rename from test/server/prefixer.js rename to server/prefixer.spec.js index a7c7e824..3ea77dfb 100644 --- a/test/server/prefixer.js +++ b/server/prefixer.spec.js @@ -1,9 +1,5 @@ -'use strict'; - -const test = require('tape'); - -const dir = '../../server/'; -const prefixer = require(dir + 'prefixer'); +import {test} from 'supertape'; +import prefixer from './prefixer.js'; test('prefixer: prefix without a slash', (t) => { t.equal(prefixer('hello'), '/hello', 'should add slash'); diff --git a/server/repl.js b/server/repl.js index a24c7d0b..46d58a15 100644 --- a/server/repl.js +++ b/server/repl.js @@ -1,25 +1,25 @@ -'use strict'; - -const net = require('net'); -const repl = require('repl'); - -module.exports = net.createServer((socket) => { - const pid = process.pid; - const addr = socket.remoteAddress; - const port = socket.remotePort; - - const r = repl.start({ - prompt: `[${pid} ${addr}:${port}>`, - input: socket, - output: socket, - terminal: true, - useGlobal: false - }); - - r.on('exit', () => { - socket.end(); - }); - - r.context.socket = socket; -}).listen(1337); +import process from 'node:process'; +import net from 'node:net'; +import repl from 'node:repl'; +export default net + .createServer((socket) => { + const {pid} = process; + const addr = socket.remoteAddress; + const port = socket.remotePort; + + const r = repl.start({ + prompt: `[${pid} ${addr}:${port}>`, + input: socket, + output: socket, + terminal: true, + useGlobal: false, + }); + + r.on('exit', () => { + socket.end(); + }); + + r.context.socket = socket; + }) + .listen(1337); diff --git a/server/rest.js b/server/rest.js deleted file mode 100644 index fe8370e5..00000000 --- a/server/rest.js +++ /dev/null @@ -1,376 +0,0 @@ -'use strict'; - -const DIR = './'; -const path = require('path'); - -const root = require(DIR + 'root'); -const config = require(DIR + 'config'); -const CloudFunc = require(DIR + 'cloudfunc'); -const markdown = require(DIR + 'markdown'); - -const jaguar = require('jaguar/legacy'); -const onezip = require('onezip/legacy'); -const inly = require('inly/legacy'); -const flop = require('flop/legacy'); -const pullout = require('pullout/legacy'); -const ponse = require('ponse'); -const copymitter = require('copymitter/legacy'); -const json = require('jonny'); -const check = require('checkup'); - -const isWin32 = process.platform === 'win32'; - -/** - * rest interface - * - * @param request - * @param response - * @param callback - */ -module.exports = (request, response, next) => { - check - .type('next', next, 'function') - .check({ - request, - response, - }); - - const apiURL = CloudFunc.apiURL; - const name = ponse.getPathName(request); - const regExp = RegExp('^' + apiURL); - const is = regExp.test(name); - - if (!is) - return next(); - - const params = { - request, - response, - name: name.replace(apiURL, '') || '/', - }; - - sendData(params, (error, options, data) => { - params.gzip = !error; - - if (!data) { - data = options; - options = {}; - } - - if (options.name) - params.name = options.name; - - if (options.gzip !== undefined) - params.gzip = options.gzip; - - if (options.query) - params.query = options.query; - - if (error) - return ponse.sendError(error, params); - - ponse.send(data, params); - }); -}; - -/** - * getting data on method and command - * - * @param params {name, method, body, requrest, response} - */ -function sendData(params, callback) { - const p = params; - const isMD = RegExp('^/markdown').test(p.name); - - if (isMD) - return markdown(p.name, p.request, (error, data) => { - callback(error, data); - }); - - switch(p.request.method) { - case 'GET': - onGET(params, callback); - break; - - case 'PUT': - pullout(p.request, 'string', (error, body) => { - if (error) - return callback(error); - - onPUT(p.name, body, callback); - }); - break; - } -} - -function onGET(params, callback) { - let cmd; - const p = params; - - if (p.name[0] === '/') - cmd = p.name.replace('/', ''); - - if (/^pack/.test(cmd)) { - cmd = cmd.replace(/^pack/, ''); - streamPack(root(cmd), p.response); - return; - } - - switch(cmd) { - case '': - p.data = json.stringify({ - info: 'Cloud Commander API v1' - }); - - callback(null, {name: 'api.json'}, p.data); - break; - - default: - callback({ - message: 'Not Found' - }); - break; - } -} - -function getPackReg() { - if (config('packer') === 'zip') - return /\.zip$/; - - return /\.tar\.gz$/; -} - -function streamPack(cmd, response) { - const noop = () => {}; - const filename = cmd.replace(getPackReg(), ''); - const dir = path.dirname(filename); - const names = [ - path.basename(filename) - ]; - - operation('pack', dir, response, names, noop); -} - -function getCMD(cmd) { - if (cmd[0] === '/') - return cmd.slice(1); - - return cmd; -} - -function onPUT(name, body, callback) { - check - .type('callback', callback, 'function') - .check({ - name, - body, - }); - - const cmd = getCMD(name); - const files = json.parse(body); - - switch(cmd) { - case 'mv': - if (!files.from || !files.to) - return callback(body); - - if (isRootAll([files.to, files.from])) - return callback(getWin32RootMsg()); - - files.from = root(files.from); - files.to = root(files.to); - - copyFiles(files, flop.move, (error) => { - const data = !files.names ? files : files.names.slice(); - const msg = formatMsg('move', data); - - callback(error, msg); - }); - - break; - - case 'cp': - if (!files.from || !files.names || !files.to) - return callback(body); - - if (isRootAll([files.to, files.from])) - return callback(getWin32RootMsg()); - - files.from = root(files.from); - files.to = root(files.to); - - copy(files.from, files.to, files.names, (error) => { - const msg = formatMsg('copy', files.names); - callback(error, msg); - }); - break; - - case 'pack': - if (!files.from) - return callback(body); - - pack(files.from, files.to, files.names, callback); - break; - - case 'extract': - if (!files.from) - return callback(body); - - extract(files.from, files.to, callback); - - break; - - default: - callback(); - break; - } -} - -function pack(from, to, names, fn) { - from = root(from); - to = root(to); - - if (!names) { - names = [ - path.basename(from) - ]; - - from = path.dirname(from); - } - - operation('pack', from, to, names, fn); -} - -function extract(from, to, fn) { - from = root(from); - - if (to) - to = root(to); - else - to = from.replace(/\.tar\.gz$/, ''); - - operation('extract', from, to, fn); -} - -function getPacker(operation) { - if (operation === 'extract') - return inly; - - if (config('packer') === 'zip') - return onezip.pack; - - return jaguar.pack; -} - -function operation(op, from, to, names, fn) { - if (!fn) { - fn = names; - names = [ - path.basename(from) - ]; - } - - const packer = getPacker(op); - const pack = packer(from, to, names); - - pack.on('error', fn); - - const name = names[0]; - pack.on('progress', (count) => { - process.stdout.write(`\r${ op } "${ name }": ${ count }%`); - }); - - pack.on('end', () => { - process.stdout.write('\n'); - - const name = path.basename(from); - const msg = formatMsg(op, name); - - fn(null, msg); - }); -} - -function copy(from, to, names, fn) { - copymitter(from, to, names) - .on('error', fn) - .on('progress', (count) => { - process.stdout.write(`\r copy ${from} ${to} ${count}%`); - }) - .on('end', () => { - process.stdout.write('\n'); - fn(); - }); -} - -function copyFiles(files, processFunc, callback) { - let names = files.names; - - const copy = () => { - let isLast; - let name; - let from = files.from; - let to = files.to; - - if (names) { - isLast = !names.length; - name = names.shift(); - from += name; - to += name; - } else { - isLast = false; - names = []; - } - - if (isLast) - return callback(); - - processFunc(from, to, error => { - if (error) - return callback(error); - - copy(); - }); - }; - - check - .type('callback', callback, 'function') - .type('processFunc', processFunc, 'function') - .check({ - files: files - }); - - copy(); -} - -function isRootWin32(path) { - const isRoot = path === '/'; - const isConfig = config('root') === '/'; - - return isWin32 && isRoot && isConfig; -} - -function isRootAll(names) { - return names.some((name) => { - return isRootWin32(name); - }); -} - -function getWin32RootMsg() { - const message = 'Could not copy from/to root on windows!'; - const error = Error(message); - - return error; -} - -function formatMsg(msgParam, dataParam, status) { - let data; - const isObj = typeof dataParam === 'object'; - - if (isObj) - data = json.stringify(dataParam); - else - data = dataParam; - - return CloudFunc.formatMsg(msgParam, data, status); -} - diff --git a/server/rest/index.js b/server/rest/index.js new file mode 100644 index 00000000..c3a3eda0 --- /dev/null +++ b/server/rest/index.js @@ -0,0 +1,419 @@ +import path from 'node:path'; +import _fs from 'node:fs'; +import process from 'node:process'; +import jaguar from 'jaguar'; +import {onezip} from 'onezip'; +import inly from 'inly'; +import wraptile from 'wraptile'; +import currify from 'currify'; +import pullout from 'pullout'; +import json from 'jonny'; +import * as ponse from 'ponse'; +import {copymitter} from 'copymitter'; +import _moveFiles from '@cloudcmd/move-files'; +import * as CloudFunc from '#common/cloudfunc'; +import root from '../root.js'; +import markdown from '../markdown/index.js'; +import info from './info.js'; + +const isUndefined = (a) => typeof a === 'undefined'; +const isRootAll = (root, names) => names.some(isRootWin32(root)); +const isString = (a) => typeof a === 'string'; +const isFn = (a) => typeof a === 'function'; +const swap = wraptile((fn, a, b) => fn(b, a)); +const isWin32 = process.platform === 'win32'; +const {apiURL} = CloudFunc; + +const UserError = (msg) => { + const error = Error(msg); + + error.code = 'EUSER'; + + return error; +}; + +export const _UserError = UserError; + +export default currify(({config, fs = _fs, moveFiles = _moveFiles}, request, response, next) => { + const name = ponse.getPathName(request); + const regExp = RegExp(`^${apiURL}`); + const is = regExp.test(name); + + if (!is) + return next(); + + rest({fs, config, moveFiles}, request, response); +}); + +function rest({fs, config, moveFiles}, request, response) { + const name = ponse.getPathName(request); + const params = { + request, + response, + name: name.replace(apiURL, '') || '/', + }; + + sendData(params, {fs, config, moveFiles}, (error, options, data) => { + params.gzip = !error; + + if (!data) { + data = options; + options = {}; + } + + if (options.name) + params.name = options.name; + + if (!isUndefined(options.gzip)) + params.gzip = options.gzip; + + if (options.query) + params.query = options.query; + + if (error?.code) + return ponse.sendError(error, params); + + if (error) + return ponse.sendError(error, params); + + ponse.send(data, params); + }); +} + +/** + * getting data on method and command + * + * @param params {name, method, body, request, response} + * @param config {} + * @param callback + */ +function sendData(params, {fs, config, moveFiles}, callback) { + const p = params; + const isMD = p.name.startsWith('/markdown'); + const rootDir = config('root'); + + if (isMD) + return markdown(p.name, rootDir, p.request, callback); + + const {method} = p.request; + + switch(method) { + case 'GET': + return onGET(params, config, callback); + + case 'PUT': + return pullout(p.request) + .then((body) => { + onPUT({ + name: p.name, + fs, + moveFiles, + config, + body, + }, callback); + }) + .catch(callback); + } +} + +function onGET(params, config, callback) { + let cmd; + const p = params; + const packer = config('packer'); + const prefix = config('prefix'); + const rootDir = config('root'); + + if (p.name[0] === '/') + cmd = p.name.replace('/', ''); + + if (cmd.startsWith('pack')) { + cmd = cmd.replace(/^pack/, ''); + streamPack(root(cmd, rootDir), p.response, packer); + + return; + } + + switch(cmd) { + case '': + p.data = json.stringify(info(prefix)); + + callback(null, {name: 'api.json'}, p.data); + break; + + default: + callback({ + message: 'Not Found', + }); + break; + } +} + +function getPackReg(packer) { + if (packer === 'zip') + return /\.zip$/; + + return /\.tar\.gz$/; +} + +export const _getPackReg = getPackReg; + +function streamPack(cmd, response, packer) { + const noop = () => {}; + const filename = cmd.replace(getPackReg(packer), ''); + const dir = path.dirname(filename); + + const names = [ + path.basename(filename), + ]; + + operation('pack', packer, dir, response, names, noop); +} + +function getCMD(cmd) { + if (cmd[0] === '/') + return cmd.slice(1); + + return cmd; +} + +export const _getCMD = getCMD; + +const getMoveMsg = (names) => formatMsg('move', names); + +const getRenameMsg = (from, to) => { + const msg = formatMsg('rename', { + from, + to, + }); + + return msg; +}; + +export const _onPUT = onPUT; + +function onPUT({name, fs, moveFiles, config, body}, callback) { + checkPut(name, body, callback); + + const cmd = getCMD(name); + const files = json.parse(body); + const rootDir = config('root'); + + switch(cmd) { + case 'move': { + const { + from, + to, + names, + } = files; + + if (!from) + return callback(UserError('"from" should be filled')); + + if (!to) + return callback(UserError('"to" should be filled')); + + if (isRootAll(rootDir, [to, from])) + return callback(getWin32RootMsg()); + + const msg = getMoveMsg(names); + const fn = swap(callback, msg); + + const fromRooted = root(from, rootDir); + const toRooted = root(to, rootDir); + + return moveFiles(fromRooted, toRooted, names) + .on('error', fn) + .on('end', fn); + } + + case 'rename': + return rename(rootDir, files.from, files.to, fs, callback); + + case 'copy': + if (!files.from || !files.names || !files.to) + return callback(body); + + if (isRootAll(rootDir, [files.to, files.from])) + return callback(getWin32RootMsg()); + + files.from = root(files.from, rootDir); + files.to = root(files.to, rootDir); + + copy(files.from, files.to, files.names, (error) => { + const msg = formatMsg('copy', files.names); + callback(error, msg); + }); + break; + + case 'pack': + if (!files.from) + return callback(body); + + pack(files.from, files.to, files.names, config, callback); + break; + + case 'extract': + if (!files.from) + return callback(body); + + extract(files.from, files.to, config, callback); + + break; + + default: + callback(); + break; + } +} + +function rename(rootDir, from, to, fs, callback) { + if (!from) + return callback(UserError('"from" should be filled')); + + if (!to) + return callback(UserError('"to" should be filled')); + + const msg = getRenameMsg(from, to); + const fn = swap(callback, msg); + + const fromRooted = root(from, rootDir); + const toRooted = root(to, rootDir); + + return fs.rename(fromRooted, toRooted, fn); +} + +export const _rename = rename; + +function pack(from, to, names, config, fn) { + const rootDir = config('root'); + const packer = config('packer'); + + from = root(from, rootDir); + to = root(to, rootDir); + + if (!names) { + names = [ + path.basename(from), + ]; + + from = path.dirname(from); + } + + operation('pack', packer, from, to, names, fn); +} + +export const _pack = pack; + +function extract(from, to, config, fn) { + const rootDir = config('root'); + + from = root(from, rootDir); + + if (to) + to = root(to, rootDir); + else + to = from.replace(/\.tar\.gz$/, ''); + + operation('extract', config('packer'), from, to, fn); +} + +export const _extract = extract; + +function getPacker(operation, packer) { + if (operation === 'extract') + return inly; + + if (packer === 'zip') + return onezip.pack; + + return jaguar.pack; +} + +export const _getPacker = getPacker; + +function operation(op, packer, from, to, names, fn) { + if (!fn) { + fn = names; + names = [ + path.basename(from), + ]; + } + + const packerFn = getPacker(op, packer); + const pack = packerFn(from, to, names); + + pack.on('error', fn); + + const [name] = names; + pack.on('progress', (count) => { + process.stdout.write(`\r${op} "${name}": ${count}%`); + }); + + pack.on('end', () => { + process.stdout.write('\n'); + + const name = path.basename(from); + const msg = formatMsg(op, name); + + fn(null, msg); + }); +} + +export const _operation = operation; + +function copy(from, to, names, fn) { + copymitter(from, to, names) + .on('error', fn) + .on('progress', (count) => { + process.stdout.write(`\r copy ${from} ${to} ${count}%`); + }) + .on('end', () => { + process.stdout.write('\n'); + fn(); + }); +} + +const isRootWin32 = currify((root, path) => { + const isRoot = path === '/'; + const isConfig = root === '/'; + + return isWin32 && isRoot && isConfig; +}); + +export const _isRootWin32 = isRootWin32; +export const _isRootAll = isRootAll; + +export const _getWin32RootMsg = getWin32RootMsg; + +function getWin32RootMsg() { + const message = 'Could not copy from/to root on windows!'; + + return Error(message); +} + +function parseData(data) { + const isObj = typeof data === 'object'; + + if (!isObj) + return data; + + return json.stringify(data); +} + +export const _formatMsg = formatMsg; + +function formatMsg(msg, data, status) { + const value = parseData(data); + return CloudFunc.formatMsg(msg, value, status); +} + +function checkPut(name, body, callback) { + if (!isString(name)) + throw Error('name should be a string!'); + + if (!isString(body)) + throw Error('body should be a string!'); + + if (!isFn(callback)) + throw Error('callback should be a function!'); +} diff --git a/server/rest/index.spec.js b/server/rest/index.spec.js new file mode 100644 index 00000000..9c672095 --- /dev/null +++ b/server/rest/index.spec.js @@ -0,0 +1,178 @@ +import {test, stub} from 'supertape'; +import {tryToCatch} from 'try-to-catch'; +import { + _formatMsg, + _getWin32RootMsg, + _isRootWin32, + _isRootAll, + _onPUT, + _UserError, + _getPackReg, + _getCMD, + _rename, + _getPacker, +} from './index.js'; + +test('rest: formatMsg', (t) => { + const result = _formatMsg('hello', 'world'); + + t.equal(result, 'hello: ok("world")', 'should be equal'); + t.end(); +}); + +test('rest: formatMsg: json', (t) => { + const result = _formatMsg('hello', { + name: 'world', + }); + + t.equal(result, 'hello: ok("{"name":"world"}")', 'should parse json'); + t.end(); +}); + +test('rest: getWin32RootMsg', (t) => { + const {message} = _getWin32RootMsg(); + + t.equal(message, 'Could not copy from/to root on windows!', 'should return error'); + t.end(); +}); + +test('rest: isRootWin32', (t) => { + const result = _isRootWin32('/', '/'); + + t.notOk(result, 'should equal'); + t.end(); +}); + +test('rest: isRootAll', (t) => { + const result = _isRootAll('/', ['/', '/h']); + + t.notOk(result, 'should equal'); + t.end(); +}); + +test('rest: onPUT: no args', async (t) => { + const [e] = await tryToCatch(_onPUT, {}); + + t.equal(e.message, 'name should be a string!', 'should throw when no args'); + t.end(); +}); + +test('rest: onPUT: no body', async (t) => { + const [e] = await tryToCatch(_onPUT, { + name: 'hello', + }); + + t.equal(e.message, 'body should be a string!', 'should throw when no body'); + t.end(); +}); + +test('rest: onPUT: no callback', async (t) => { + const [e] = await tryToCatch(_onPUT, { + name: 'hello', + body: 'world', + }); + + t.equal(e.message, 'callback should be a function!', 'should throw when no callback'); + t.end(); +}); + +test('rest: UserError: message', (t) => { + const result = _UserError('hello'); + + t.equal(result.message, 'hello', 'should set message'); + t.end(); +}); + +test('rest: UserError: code', (t) => { + const result = _UserError('hello'); + + t.equal(result.code, 'EUSER', 'should set code'); + t.end(); +}); + +test('rest: getPackReg: zip', (t) => { + const result = _getPackReg('zip'); + + t.match('file.zip', result, 'should match .zip'); + t.end(); +}); + +test('rest: getPackReg: tar', (t) => { + const result = _getPackReg('tar'); + + t.match('file.tar.gz', result, 'should match .tar.gz'); + t.end(); +}); + +test('rest: getCMD: with slash', (t) => { + const result = _getCMD('/move'); + + t.equal(result, 'move', 'should strip leading slash'); + t.end(); +}); + +test('rest: getCMD: no slash', (t) => { + const result = _getCMD('move'); + + t.equal(result, 'move', 'should return as is'); + t.end(); +}); + +test('rest: rename: no from', (t) => { + const callback = stub(); + + _rename('/', null, 'to', null, callback); + + const msg = '"from" should be filled'; + + t.calledWith(callback, [ + _UserError(msg), + ], 'should return UserError'); + t.end(); +}); + +test('rest: rename: no to', (t) => { + const callback = stub(); + + _rename('/', 'from', null, null, callback); + + const msg = '"to" should be filled'; + + t.calledWith(callback, [ + _UserError(msg), + ], 'should return UserError'); + t.end(); +}); + +test('rest: rename: success', (t) => { + const callback = stub(); + const fs = { + rename: stub(), + }; + + _rename('/root', 'from', 'to', fs, callback); + + t.calledWith(fs.rename, ['/root/from', '/root/to', callback], 'should call fs.rename'); + t.end(); +}); + +test('rest: getPacker: extract', (t) => { + const result = _getPacker('extract', 'zip'); + + t.equal(typeof result, 'function', 'should return function'); + t.end(); +}); + +test('rest: getPacker: pack zip', (t) => { + const result = _getPacker('pack', 'zip'); + + t.equal(typeof result, 'function', 'should return function'); + t.end(); +}); + +test('rest: getPacker: pack tar', (t) => { + const result = _getPacker('pack', 'tar'); + + t.equal(typeof result, 'function', 'should return function'); + t.end(); +}); diff --git a/server/rest/info.js b/server/rest/info.js new file mode 100644 index 00000000..8cf0e1d7 --- /dev/null +++ b/server/rest/info.js @@ -0,0 +1,18 @@ +import process from 'node:process'; +import format from 'format-io'; +import info from '../../package.json' with { + type: 'json', +}; + +const {version} = info; + +const getMemory = () => { + const {rss} = process.memoryUsage(); + return format.size(rss); +}; + +export default (prefix) => ({ + version, + prefix, + memory: getMemory(), +}); diff --git a/server/rest/info.spec.js b/server/rest/info.spec.js new file mode 100644 index 00000000..cac19e53 --- /dev/null +++ b/server/rest/info.spec.js @@ -0,0 +1,18 @@ +import process from 'node:process'; +import {test, stub} from 'supertape'; +import info from './info.js'; + +test('cloudcmd: rest: info', (t) => { + const {memoryUsage} = process; + + const _memoryUsage = stub().returns({}); + + process.memoryUsage = _memoryUsage; + + info(); + + process.memoryUsage = memoryUsage; + + t.calledWithNoArgs(_memoryUsage, 'should call memoryUsage'); + t.end(); +}); diff --git a/server/root.js b/server/root.js index 5c3ea26b..b563d77d 100644 --- a/server/root.js +++ b/server/root.js @@ -1,11 +1,5 @@ -'use strict'; +import mellow from 'mellow'; -const config = require('./config'); -const mellow = require('mellow'); - -module.exports = (dir) => { - const root = config('root') || '/'; - - return mellow.pathToWin(dir, root); +export default (dir, root, {webToWin = mellow.webToWin} = {}) => { + return webToWin(dir, root || '/'); }; - diff --git a/server/root.spec.js b/server/root.spec.js new file mode 100644 index 00000000..2d9dd768 --- /dev/null +++ b/server/root.spec.js @@ -0,0 +1,16 @@ +import {test, stub} from 'supertape'; +import root from './root.js'; + +test('cloudcmd: root: mellow', (t) => { + const webToWin = stub(); + + const dir = 'hello'; + const dirRoot = '/'; + + root(dir, '', { + webToWin, + }); + + t.calledWith(webToWin, [dir, dirRoot], 'should call mellow'); + t.end(); +}); diff --git a/server/route.js b/server/route.js index 4177b392..7844ce09 100644 --- a/server/route.js +++ b/server/route.js @@ -1,252 +1,208 @@ -'use strict'; +import {createRequire} from 'node:module'; +import {extname} from 'node:path'; +import * as _win32 from 'win32'; +import * as ponse from 'ponse'; +import {rendy} from 'rendy'; +import format from 'format-io'; +import currify from 'currify'; +import wraptile from 'wraptile'; +import {tryToCatch} from 'try-to-catch'; +import once from 'once'; +import pipe from 'pipe-io'; +import {contentType} from 'mime-types'; +import * as CloudFunc from '#common/cloudfunc'; +import root from './root.js'; +import prefixer from './prefixer.js'; +import Template from './template.js'; +import {getColumns} from './columns.js'; +import {getThemes} from './theme.js'; -const DIR = __dirname + '/../'; -const DIR_TMPL = DIR + 'tmpl/'; -const DIR_HTML = DIR + 'html/'; -const DIR_JSON = DIR + 'json/'; -const DIR_SERVER = './'; -const DIR_FS = DIR_TMPL + 'fs/'; +const require = createRequire(import.meta.url); +const {stringify} = JSON; +const {FS} = CloudFunc; -const fs = require('fs'); - -const flop = require('flop/legacy'); -const ponse = require('ponse'); -const files = require('files-io'); -const rendy = require('rendy'); -const exec = require('execon'); -const minify = require('minify'); -const format = require('format-io'); -const squad = require('squad'); -const apart = require('apart'); - -const config = require(DIR_SERVER + 'config'); -const root = require(DIR_SERVER + 'root'); -const prefixer = require(DIR_SERVER + 'prefixer'); -const CloudFunc = require(DIR_SERVER + 'cloudfunc'); -const prefix = squad(prefixer, apart(config, 'prefix')); - -const PATH_INDEX = DIR_HTML + 'index.html'; - -const TMPL_PATH = [ - 'file', - 'panel', - 'path', - 'pathLink', - 'link' -]; - -const Template = {}; -const FS = CloudFunc.FS; - -const CSS_URL = require(DIR_JSON + 'css.json') - .map((name) => { - return 'css/' + name + '.css'; - }).join(':'); - -module.exports = (req, res, next) => { - check(req, res, next); +const sendIndex = (params, data) => { + const ponseParams = { + ...params, + name: 'index.html', + }; - readFiles(() => { - route(req, res, next); - }); + ponse.send(data, ponseParams); }; +const onceRequire = once(require); +const getPrefix = (config) => prefixer(config('prefix')); + +const getReadDir = (config, {win32 = _win32} = {}) => { + if (!config('dropbox')) + return win32.read; + + const {readDir} = onceRequire('@cloudcmd/dropbox'); + + return wraptile(readDir, config('dropboxToken')); +}; + +/** + * routing of server queries + */ +export default currify((config, options, request, response, next) => { + const name = ponse.getPathName(request); + const isFS = RegExp(`^/$|^${FS}`).test(name); + + if (!isFS) + return next(); + + route({ + config, + options, + request, + response, + }).catch(next); +}); + +export const _getReadDir = getReadDir; + +async function route({config, options, request, response}) { + const name = ponse.getPathName(request); + const gzip = true; + + const p = { + request, + response, + gzip, + name, + }; + + config('prefix', prefixer(request.baseUrl)); + + const rootName = name.replace(CloudFunc.FS, '') || '/'; + const fullPath = root(rootName, config('root')); + + if (fullPath.indexOf(config('root'))) + return ponse.sendError(Error(`Path '${fullPath}' beyond root '${config('root')}'`), p); + + const {html, win32} = options; + + const read = getReadDir(config, { + win32, + }); + + const [error, stream] = await tryToCatch(read, fullPath, { + root: config('root'), + }); + + if (error) + return ponse.sendError(error, p); + + if (stream.type === 'directory') { + const {files} = stream; + + return sendIndex(p, buildIndex(config, html, { + files, + path: format.addSlashToEnd(rootName), + })); + } + + const {contentLength} = stream; + + response.setHeader('Content-Length', contentLength); + response.setHeader('Content-Type', contentType(extname(fullPath))); + + await pipe([stream, response]); +} + /** * additional processing of index file */ -function indexProcessing(options) { - const keysPanel = '
    { - if (dir) - dir.path = format.addSlashToEnd(name); - - if (!error) - return buildIndex(dir, (error, data) => { - p.name = PATH_INDEX; - - if (error) - return ponse.sendError(error, p); - - ponse.send(data, p); - }); - - if (error.code !== 'ENOTDIR') - return ponse.sendError(error, p); - - fs.realpath(fullPath, (error, pathReal) => { - if (!error) - p.name = pathReal; - else - p.name = name; - - p.gzip = false; - ponse.sendFile(p); - }); + const from = rendy(keysPanelRegExp, { + className: 'keyspanel', }); -} - -function buildIndex(json, callback) { - const isMinify = config('minify'); - exec.if(!isMinify, (error, name) => { - fs.readFile(name || PATH_INDEX, 'utf8', (error, template) => { - if (error) - return; - - const panel = CloudFunc.buildFromJSON({ - data : json, - prefix : prefix(), - template : Template - }); - - const data = indexProcessing({ - panel : panel, - data : template - }); - - callback(error, data); - }); - }, (callback) => { - minify(PATH_INDEX, 'name', callback); + const to = rendy(keysPanel, { + className: 'keyspanel hidden', }); -} - -function check(req, res, next) { - if (!req) - throw Error('req could not be empty!'); - if (!res) - throw Error('res could not be empty!'); - - if (typeof next !== 'function') - throw Error('next should be function!'); + return html.replace(RegExp(from), to); } - diff --git a/server/route.spec.js b/server/route.spec.js new file mode 100644 index 00000000..ed19fdc6 --- /dev/null +++ b/server/route.spec.js @@ -0,0 +1,460 @@ +import path, {dirname} from 'node:path'; +import {fileURLToPath} from 'node:url'; +import {Readable} from 'node:stream'; +import fs from 'node:fs'; +import {tryToCatch} from 'try-to-catch'; +import {test, stub} from 'supertape'; +import {serveOnce} from 'serve-once'; +import {cloudcmd} from '#server/cloudcmd'; +import {_getReadDir} from './route.js'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = dirname(__filename); +const fixtureDir = path.join(__dirname, '..', 'test', 'fixture'); +const {createConfigManager} = cloudcmd; + +const defaultConfig = { + auth: false, + dropbox: false, +}; + +const {request} = serveOnce(cloudcmd, { + config: defaultConfig, +}); + +const {stringify} = JSON; +const {assign} = Object; + +test('cloudcmd: route: buttons: no console', async (t) => { + const options = { + config: { + console: false, + }, + }; + + const {body} = await request.get('/', { + options, + }); + + t.match(body, 'icon-console none', 'should hide console'); + t.end(); +}); + +test('cloudcmd: route: buttons: console', async (t) => { + const config = { + console: true, + }; + + const options = { + config, + }; + + const {body} = await request.get('/', { + options, + }); + + t.notOk(/icon-console none/.test(body), 'should not hide console'); + t.end(); +}); + +test('cloudcmd: route: buttons: no config', async (t) => { + const config = { + configDialog: false, + }; + + const options = { + config, + }; + + const {body} = await request.get('/', { + options, + }); + + t.match(body, 'icon-config none', 'should hide config'); + t.end(); +}); + +test('cloudcmd: route: buttons: no contact', async (t) => { + const config = { + contact: false, + }; + + const options = { + config, + }; + + const {body} = await request.get('/', { + options, + }); + + t.match(body, 'icon-contact none', 'should hide contact'); + t.end(); +}); + +test('cloudcmd: route: buttons: one file panel: move', async (t) => { + const config = { + oneFilePanel: true, + }; + + const options = { + config, + }; + + const {body} = await request.get('/', { + options, + }); + + t.match(body, 'icon-move none', 'should hide move button'); + t.end(); +}); + +test('cloudcmd: route: buttons: one file panel: copy', async (t) => { + const config = { + oneFilePanel: true, + }; + + const options = { + config, + }; + + const {body} = await request.get('/', { + options, + }); + + t.match(body, 'icon-copy none', 'should hide copy button'); + t.end(); +}); + +test('cloudcmd: route: keys panel: hide', async (t) => { + const config = { + keysPanel: false, + }; + + const options = { + config, + }; + + const {body} = await request.get('/', { + options, + }); + + t.match(body, 'keyspanel hidden', 'should hide keyspanel'); + t.end(); +}); + +test('cloudcmd: route: keys panel', async (t) => { + const config = { + keysPanel: true, + }; + + const options = { + config, + }; + + const {body} = await request.get('/', { + options, + }); + + t.notOk(/keyspanel hidden/.test(body), 'should show keyspanel'); + t.end(); +}); + +test('cloudcmd: route: symlink', async (t) => { + const emptyDir = path.join(fixtureDir, 'empty-dir'); + const root = fixtureDir; + const symlink = path.join(root, 'symlink-dir'); + + const config = { + root, + }; + + const options = { + config, + }; + + fs.symlinkSync(emptyDir, symlink); + + const {body} = await request.get('/fs/symlink-dir', { + options, + }); + + fs.unlinkSync(symlink); + + t.ok(body.length, 'should return html document'); + t.end(); +}); + +test('cloudcmd: route: not found', async (t) => { + const root = fixtureDir; + const config = { + root, + }; + + const options = { + config, + }; + + const {body} = await request.get('/fs/file-not-found', { + options, + }); + + t.match(body, 'ENOENT: no such file or directory', 'should return error'); + t.end(); +}); + +test('cloudcmd: route: sendIndex: encode', async (t) => { + const name = '">'; + const nameEncoded = '"><svg onload=alert(3);>'; + const path = '/'; + + const files = [{ + name, + }]; + + const stream = Readable.from(stringify({ + path, + files, + })); + + assign(stream, { + path, + files, + type: 'directory', + }); + + const read = stub().resolves(stream); + + cloudcmd.depStore('win32', { + read, + }); + + const {request} = serveOnce(cloudcmd, { + configManager: createConfigManager(), + }); + + const {body} = await request.get('/'); + + cloudcmd.depStore(); + + t.match(body, nameEncoded, 'should encode name'); + t.end(); +}); + +test('cloudcmd: route: sendIndex: encode: not encoded', async (t) => { + const name = '">'; + const path = '/'; + + const files = [{ + name, + }]; + + const stream = Readable.from(stringify({ + path, + files, + })); + + assign(stream, { + path, + files, + type: 'directory', + }); + + const read = stub().resolves(stream); + + cloudcmd.depStore('win32', { + read, + }); + + const {request} = serveOnce(cloudcmd); + const {body} = await request.get('/'); + + cloudcmd.depStore(); + + t.notOk(body.includes(name), 'should not put not encoded name'); + t.end(); +}); + +test('cloudcmd: route: sendIndex: ddos: render', async (t) => { + const name = `$$$'"`; + const path = '/'; + + const files = [{ + name, + }]; + + const stream = Readable.from(stringify({ + path, + files, + })); + + assign(stream, { + path, + files, + type: 'directory', + }); + + const read = stub().resolves(stream); + + cloudcmd.depStore('win32', { + read, + }); + const {request} = serveOnce(cloudcmd, { + config: defaultConfig, + }); + + const {status} = await request.get('/'); + + cloudcmd.depStore(); + + t.equal(status, 200, 'should not hang up'); + t.end(); +}); + +test('cloudcmd: route: buttons: no terminal', async (t) => { + const config = { + terminal: false, + }; + + const options = { + config, + }; + + const {body} = await request.get('/', { + options, + }); + + t.match(body, 'icon-terminal none', 'should hide terminal'); + t.end(); +}); + +test('cloudcmd: route: no terminal: /fs', async (t) => { + const config = { + terminal: false, + }; + + const options = { + config, + configManager: createConfigManager(), + }; + + const {request} = serveOnce(cloudcmd); + + const {body} = await request.get('/fs', { + options, + }); + + t.match(body, 'icon-terminal none', 'should hide terminal'); + t.end(); +}); + +test('cloudcmd: route: buttons: terminal: can not load', async (t) => { + const config = { + terminal: true, + terminalPath: 'xxxxxxxxxxxx', + }; + + const options = { + config, + }; + + const {body} = await request.get('/', { + options, + }); + + t.match(body, 'icon-terminal none', 'should not enable terminal'); + t.end(); +}); + +test('cloudcmd: route: buttons: terminal', async (t) => { + const config = { + terminal: true, + terminalPath: 'gritty', + }; + + const options = { + config, + }; + + const {body} = await request.get('/', { + options, + }); + + t.notOk(/icon-terminal none/.test(body), 'should not enable terminal'); + t.end(); +}); + +test('cloudcmd: route: buttons: contact', async (t) => { + const config = { + contact: true, + }; + + const options = { + config, + }; + + const {request} = serveOnce(cloudcmd); + + const {body} = await request.get('/', { + options, + }); + + t.notOk(/icon-contact none/.test(body), 'should enable terminal'); + t.end(); +}); + +test('cloudcmd: route: dropbox', async (t) => { + const config = createConfigManager(); + config('dropbox', true); + config('dropboxToken', ''); + + const readdir = _getReadDir(config); + const [e] = await tryToCatch(readdir, '/root'); + + t.match(e.message, 'API', 'should contain word token in message'); + t.end(); +}); + +test('cloudcmd: route: content length', async (t) => { + const options = { + root: fixtureDir, + }; + + const {headers} = await request.get('/route.js', { + options, + }); + + const result = headers.get('content-length'); + + t.ok(result); + t.end(); +}); + +test('cloudcmd: route: read: root', async (t) => { + const stream = Readable.from('hello'); + + stream.contentLength = 5; + + const read = stub().returns(stream); + cloudcmd.depStore('win32', { + read, + }); + + const configManager = createConfigManager(); + const root = '/hello'; + + configManager('root', root); + + const {request} = serveOnce(cloudcmd, { + configManager, + }); + + await request.get('/fs/route.js'); + cloudcmd.depStore(); + + const expected = ['/hello/route.js', { + root, + }]; + + t.calledWith(read, expected); + t.end(); +}); diff --git a/server/server.js b/server/server.js index 5fa7f31c..06b6464a 100644 --- a/server/server.js +++ b/server/server.js @@ -1,64 +1,100 @@ -'use strict'; +import http from 'node:http'; +import {promisify} from 'node:util'; +import process from 'node:process'; +import {rateLimit} from 'express-rate-limit'; +import currify from 'currify'; +import squad from 'squad'; +import {tryToCatch} from 'try-to-catch'; +import opn from 'open'; +import express from 'express'; +import {Server} from 'socket.io'; +import wraptile from 'wraptile'; +import compression from 'compression'; +import tryRequire from 'tryrequire'; +import {cloudcmd} from '#server/cloudcmd'; +import exit from './exit.js'; -const DIR_SERVER = './'; -const cloudcmd = require(DIR_SERVER + 'cloudcmd'); +const RATE_LIMIT = 1000; +const RATE_WINDOW = 15 * 60 * 1000; -const exit = require(DIR_SERVER + 'exit'); -const config = require(DIR_SERVER + 'config'); -const prefixer = require(DIR_SERVER + 'prefixer'); +const bind = (f, self) => f.bind(self); -const http = require('http'); -const opn = require('opn'); -const express = require('express'); -const io = require('socket.io'); -const squad = require('squad'); -const apart = require('apart'); +const two = currify((f, a, b) => f(a, b)); +const shutdown = wraptile(async (config, promises) => { + if (config('log')) + console.log('closing cloudcmd...'); + + await Promise.all(promises); + process.exit(0); +}); + +const promisifySelf = squad(promisify, bind); + +const exitPort = two(exit, 'cloudcmd --port: %s'); -const tryRequire = require('tryrequire'); const logger = tryRequire('morgan'); -const prefix = squad(prefixer, apart(config, 'prefix')); - -module.exports = (options) => { - const port = process.env.PORT || /* c9 */ - process.env.VCAP_APP_PORT || /* cloudfoundry */ - config('port'); +export default async (options, config) => { + const prefix = config('prefix'); + const port = process.env.PORT /* c9 */ || config('port'); - const ip = process.env.IP || /* c9 */ - config('ip') || - '0.0.0.0'; + const ip = process.env.IP /* c9 */ || config('ip') || '0.0.0.0'; const app = express(); const server = http.createServer(app); - if (logger) + if (config('log') && logger) app.use(logger('dev')); - app.use(cloudcmd({ + if (prefix) + app.get('/', (req, res) => res.redirect(`${prefix}/`)); + + const socketServer = new Server(server, { + path: `${prefix}/socket.io`, + }); + + const limiter = rateLimit({ + windowMs: RATE_WINDOW, + limit: RATE_LIMIT, + }); + + app.set('trust proxy', 1); + + app.use(compression()); + app.use(limiter); + app.use(prefix, cloudcmd({ config: options, - socket: io(server, { - path: prefix() + '/socket.io' - }), + socket: socketServer, + configManager: config, })); - if (port < 0 || port > 65535) - exit('cloudcmd --port: %s', 'port number could be 1..65535, 0 means any available port'); + if (port < 0 || port > 65_535) + return exitPort('port number could be 1..65535, 0 means any available port'); - server.listen(port, ip, () => { - const host = config('ip') || 'localhost'; - const port0 = port || server.address().port; - const url = `http://${host}:${port0}${prefix()}/`; - - console.log('url:', url); - - if (!config('open')) - return; - - opn(url); - }); + const listen = promisifySelf(server.listen, server); + const closeServer = promisifySelf(server.close, server); + const closeSocket = promisifySelf(socketServer.close, socketServer); - server.on('error', error => { - exit('cloudcmd --port: %s', error.message); - }); + server.on('error', exitPort); + await listen(port, ip); + + const close = shutdown(config, [closeServer, closeSocket]); + + process.on('SIGINT', close); + process.on('SIGUSR1', close); + + const host = config('ip') || 'localhost'; + const port0 = port || server.address().port; + const url = `http://${host}:${port0}${prefix}/`; + + if (config('log')) + console.log(`url: ${url}`); + + if (!config('open')) + return; + + const [openError] = await tryToCatch(opn, url); + + if (openError) + console.error('cloudcmd --open:', openError.message); }; - diff --git a/server/show-config.js b/server/show-config.js new file mode 100644 index 00000000..f151dd10 --- /dev/null +++ b/server/show-config.js @@ -0,0 +1,36 @@ +import { + table, + getBorderCharacters, +} from 'table'; + +export const showConfig = (config) => { + check(config); + + const data = Object + .keys(config) + .map((name) => [ + name, + config[name], + ]); + + if (!data.length) + return ''; + + return table(data, { + columns: { + 1: { + width: 30, + truncate: 30, + }, + }, + border: getBorderCharacters('ramac'), + }); +}; + +function check(config) { + if (!config) + throw Error('config could not be empty!'); + + if (typeof config !== 'object') + throw Error('config should be an object!'); +} diff --git a/server/show-config.spec.js b/server/show-config.spec.js new file mode 100644 index 00000000..b25e56a2 --- /dev/null +++ b/server/show-config.spec.js @@ -0,0 +1,37 @@ +import {test} from 'supertape'; +import {tryCatch} from 'try-catch'; +import {showConfig} from './show-config.js'; + +test('cloudcmd: show-config: no arguments', (t) => { + const [error] = tryCatch(showConfig); + + t.equal(error.message, 'config could not be empty!', 'should throw when no config'); + t.end(); +}); + +test('cloudcmd: show-config: bad arguments', (t) => { + const [error] = tryCatch(showConfig, 'hello'); + + t.equal(error.message, 'config should be an object!', 'should throw when config not object'); + t.end(); +}); + +test('cloudcmd: show-config: empty: return', (t) => { + t.equal(showConfig({}), '', 'should return string'); + t.end(); +}); + +test('cloudcmd: show-config: return', (t) => { + const config = { + hello: 'world', + }; + + const result = [ + '+-------+--------------------------------+\n', + '| hello | world |\n', + '+-------+--------------------------------+\n', + ].join(''); + + t.equal(showConfig(config), result, 'should return table'); + t.end(); +}); diff --git a/server/template.js b/server/template.js new file mode 100644 index 00000000..0e705e79 --- /dev/null +++ b/server/template.js @@ -0,0 +1,9 @@ +import path, {dirname} from 'node:path'; +import {fileURLToPath} from 'node:url'; +import readFilesSync from '@cloudcmd/read-files-sync'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = dirname(__filename); +const templatePath = path.join(__dirname, '..', 'tmpl/fs'); + +export default readFilesSync(templatePath, 'utf8'); diff --git a/server/terminal.js b/server/terminal.js index 04689966..c6d80df9 100644 --- a/server/terminal.js +++ b/server/terminal.js @@ -1,34 +1,35 @@ -'use strict'; +import {createRequire} from 'node:module'; +import {tryCatch} from 'try-catch'; -const tryCatch = require('try-catch'); -const config = require('./config'); +const require = createRequire(import.meta.url); -const noop = () => {}; -noop.listen = noop; - -module.exports = (arg) => { - return getTerminal(config('terminal'), arg); +const noop = (req, res, next) => { + next && next(); }; -function getTerminal(term, arg) { - if (!term) +noop.listen = noop; + +const parseDefault = (a) => a.default || a; +const _getModule = (a) => parseDefault(require(a)); + +export default (config, arg, overrides = {}) => { + const { + getModule = _getModule, + } = overrides; + + if (!config('terminal')) return noop; - let result; - - const e = tryCatch(() => { - result = require(config('terminalPath')); - }); + const [e, terminalModule] = tryCatch(getModule, config('terminalPath')); if (!e && !arg) - return result; + return terminalModule; if (!e) - return result(arg); + return terminalModule(arg); config('terminal', false); console.log(`cloudcmd --terminal: ${e.message}`); return noop; -} - +}; diff --git a/server/terminal.spec.js b/server/terminal.spec.js new file mode 100644 index 00000000..22f20282 --- /dev/null +++ b/server/terminal.spec.js @@ -0,0 +1,73 @@ +import {test, stub} from 'supertape'; +import {createConfigManager} from '#server/cloudcmd'; +import terminal from './terminal.js'; + +test('cloudcmd: terminal: disabled', (t) => { + const config = createConfigManager(); + config('terminal', false); + + const fn = terminal(config); + + t.notOk(fn(), 'should return noop'); + t.end(); +}); + +test('cloudcmd: terminal: disabled: listen', (t) => { + const config = createConfigManager(); + config('terminal', false); + + const fn = terminal(config).listen(); + + t.notOk(fn, 'should return noop'); + t.end(); +}); + +test('cloudcmd: terminal: enabled', (t) => { + const term = stub(); + const arg = 'hello'; + const config = stub().returns(true); + const getModule = stub().returns(term); + + terminal(config, arg, { + getModule, + }); + + t.calledWith(term, [arg], 'should call terminal'); + t.end(); +}); + +test('cloudcmd: terminal: enabled: no string', (t) => { + const {log: originalLog} = console; + const log = stub(); + + console.log = log; + const config = createConfigManager(); + + config('terminal', true); + config('terminalPath', 'hello'); + terminal(config); + + console.log = originalLog; + + const msg = `cloudcmd --terminal: Cannot find module 'hello'`; + const [arg] = log.args[0]; + + t.match(arg, RegExp(msg), 'should call with msg'); + t.end(); +}); + +test('cloudcmd: terminal: no arg', (t) => { + const gritty = {}; + const getModule = stub().returns(gritty); + const config = createConfigManager(); + + config('terminal', true); + config('terminalPath', 'gritty'); + + const result = terminal(config, '', { + getModule, + }); + + t.equal(result, gritty); + t.end(); +}); diff --git a/server/theme.js b/server/theme.js new file mode 100644 index 00000000..d66623b5 --- /dev/null +++ b/server/theme.js @@ -0,0 +1,33 @@ +import path, {dirname} from 'node:path'; +import {fileURLToPath} from 'node:url'; +import process from 'node:process'; +import fs from 'node:fs'; +import {fullstore} from 'fullstore'; +import * as nanomemoizeDefault from 'nano-memoize'; +import readFilesSync from '@cloudcmd/read-files-sync'; + +const nanomemoize = nanomemoizeDefault.default.nanomemoize || nanomemoizeDefault.default; +const __filename = fileURLToPath(import.meta.url); +const __dirname = dirname(__filename); +const isMap = (a) => /\.(map|js)$/.test(a); +const not = (fn) => (a) => !fn(a); + +const _isDev = fullstore(process.env.NODE_ENV === 'development'); +const getDist = (isDev) => isDev ? 'dist-dev' : 'dist'; + +export const isDev = _isDev; + +export const getThemes = ({isDev = _isDev()} = {}) => { + return readFilesSyncMemo(isDev); +}; + +const readFilesSyncMemo = nanomemoize((isDev) => { + const dist = getDist(isDev); + const themesDir = path.join(__dirname, '..', dist, 'themes'); + + const names = fs + .readdirSync(themesDir) + .filter(not(isMap)); + + return readFilesSync(themesDir, names, 'utf8'); +}); diff --git a/server/themes.spec.js b/server/themes.spec.js new file mode 100644 index 00000000..709896e8 --- /dev/null +++ b/server/themes.spec.js @@ -0,0 +1,50 @@ +import {dirname} from 'node:path'; +import {fileURLToPath} from 'node:url'; +import fs from 'node:fs'; +import test from 'supertape'; +import {getThemes, isDev} from './theme.js'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = dirname(__filename); + +test('themes: dev', (t) => { + const themes = getThemes({ + isDev: true, + }); + + const css = fs.readFileSync(`${__dirname}/../css/themes/dark.css`, 'utf8'); + const result = themes.dark.includes(css); + + t.ok(result); + t.end(); +}); + +test('themes: no args', (t) => { + const currentIsDev = isDev(); + isDev(true); + const themes = getThemes(); + + const css = fs.readFileSync(`${__dirname}/../css/themes/light.css`, 'utf8'); + isDev(currentIsDev); + + t.match(themes.light, css); + t.end(); +}); + +test('themes: production', (t) => { + const themes = getThemes({ + isDev: false, + }); + + t.ok(themes.dark, 'should have dark theme'); + t.end(); +}); + +test('themes: production: light', (t) => { + const themes = getThemes({ + isDev: false, + }); + + t.ok(themes.light, 'should have light theme'); + t.end(); +}); diff --git a/server/user-menu.js b/server/user-menu.js new file mode 100644 index 00000000..53599553 --- /dev/null +++ b/server/user-menu.js @@ -0,0 +1,125 @@ +import {homedir} from 'node:os'; +import {readFile as _readFile} from 'node:fs/promises'; +import {join} from 'node:path'; +// warm up worker cache +import {montag} from 'montag'; +import {tryToCatch} from 'try-to-catch'; +import currify from 'currify'; +import {putout, codeframe} from 'putout'; + +// warm up worker cache +transpile(''); + +const PREFIX = '/api/v1/user-menu'; + +export const userMenu = currify(async ({menuName, readFile = _readFile, config}, req, res, next) => { + if (!req.url.startsWith(PREFIX)) + return next(); + + const {method} = req; + + if (method === 'GET') + return await onGET({ + req, + res, + menuName, + readFile, + config, + }); + + next(); +}); + +async function onGET({req, res, menuName, readFile, config}) { + const {dir} = req.query; + const url = req.url.replace(PREFIX, ''); + + if (url === '/default') + return await sendDefaultMenu(res, { + readFile, + }); + + const {findUp} = await import('find-up'); + + const cwd = join(config('root'), dir); + const [errorFind, currentMenuPath] = await tryToCatch(findUp, [menuName], { + cwd, + }); + + if (errorFind && errorFind.code !== 'ENOENT') + return res + .status(404) + .send(errorFind.message); + + const homeMenuPath = join(homedir(), menuName); + const menuPath = currentMenuPath || homeMenuPath; + const [e, source] = await tryToCatch(readFile, menuPath, 'utf8'); + + if (e && e.code !== 'ENOENT') + return res + .status(404) + .send(e.message); + + if (e) + return await sendDefaultMenu(res, { + readFile, + }); + + const [parseError, result] = await transpile(source); + + if (parseError) + return res + .type('js') + .send(getError(parseError, source)); + + res + .type('js') + .send(result.code); +} + +function getError(error, source) { + return montag` + const e = Error(\`
    ${codeframe({
    +            error,
    +            source,
    +            highlightCode: false,
    +        })}
    \`); + + e.code = 'frame'; + + throw e; + `; +} + +async function sendDefaultMenu(res, {readFile}) { + const menu = await getDefaultMenu({ + readFile, + }); + + res + .type('js') + .send(menu); +} + +async function transpile(source) { + return await tryToCatch(putout, source, { + rules: { + 'nodejs/convert-esm-to-commonjs': 'on', + }, + plugins: [ + 'nodejs', + 'cloudcmd', + ], + }); +} + +async function getDefaultMenu({readFile}) { + const DEFAULT_MENU_PATH = new URL('../static/user-menu.js', import.meta.url).pathname; + const menu = await readFile(DEFAULT_MENU_PATH, 'utf8'); + const [error, result] = await transpile(menu); + + if (error) + return String(error); + + return result.code; +} diff --git a/server/user-menu.spec.js b/server/user-menu.spec.js new file mode 100644 index 00000000..7c5fcf2c --- /dev/null +++ b/server/user-menu.spec.js @@ -0,0 +1,129 @@ +import {dirname, join} from 'node:path'; +import {fileURLToPath} from 'node:url'; +import {readFileSync} from 'node:fs'; +import {test, stub} from 'supertape'; +import {serveOnce} from 'serve-once'; +import {putout} from 'putout'; +import {userMenu} from './user-menu.js'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = dirname(__filename); + +const {request} = serveOnce(userMenu); +const userMenuPath = join(__dirname, '..', '.cloudcmd.menu.js'); + +const fixtureDir = new URL('fixture-user-menu', import.meta.url).pathname; +const fixtureMoveName = join(fixtureDir, 'io-mv.js'); +const fixtureMoveFixName = join(fixtureDir, 'io-mv-fix.js'); +const fixtureCopyName = join(fixtureDir, 'io-cp.js'); +const fixtureCopyFixName = join(fixtureDir, 'io-cp-fix.js'); + +const fixtureMove = readFileSync(fixtureMoveName, 'utf8'); +const fixtureMoveFix = readFileSync(fixtureMoveFixName, 'utf8'); +const fixtureCopy = readFileSync(fixtureCopyName, 'utf8'); +const fixtureCopyFix = readFileSync(fixtureCopyFixName, 'utf8'); + +test('cloudcmd: user menu', async (t) => { + const config = stub().returns(''); + const userMenuFile = getUserMenuFile(); + + const options = { + config, + menuName: '.cloudcmd.menu.js', + }; + + const {body} = await request.get(`/api/v1/user-menu?dir=${__dirname}`, { + options, + }); + + t.equal(userMenuFile, body); + t.end(); +}); + +test('cloudcmd: user menu: io.mv', async (t) => { + const config = stub().returns(''); + const readFile = stub().returns(fixtureMove); + + const options = { + menuName: '.cloudcmd.menu.js', + readFile, + config, + }; + + const {request} = serveOnce(userMenu); + + const {body} = await request.get(`/api/v1/user-menu?dir=${__dirname}`, { + options, + }); + + t.equal(body, fixtureMoveFix); + t.end(); +}); + +test('cloudcmd: user menu: default menu', async (t) => { + const config = stub().returns(''); + const options = { + menuName: '111.cloudcmd.menu.js', + config, + }; + + const {request} = serveOnce(userMenu); + + const {body} = await request.get(`/api/v1/user-menu?dir=abcd`, { + options, + }); + + t.match(body, 'module.exports'); + t.end(); +}); + +test('cloudcmd: user menu: io.cp', async (t) => { + const config = stub().returns(''); + const readFile = stub().returns(fixtureCopy); + + const options = { + menuName: '.cloudcmd.menu.js', + readFile, + config, + }; + + const {request} = serveOnce(userMenu); + + const {body} = await request.get(`/api/v1/user-menu?dir=${__dirname}`, { + options, + }); + + t.equal(body, fixtureCopyFix); + t.end(); +}); + +test('cloudcmd: user menu: broken file', async (t) => { + const readFile = stub().returns('sdfsdf /; s'); + const options = { + menuName: '.cloudcmd.menu.js', + readFile, + }; + + const {request} = serveOnce(userMenu); + + const {body} = await request.get(`/api/v1/user-menu/default`, { + options, + }); + + const expected = 'SyntaxError: Unexpected token (1:8)'; + + t.equal(body, expected); + t.end(); +}); + +function getUserMenuFile() { + const userMenuFile = readFileSync(userMenuPath, 'utf8'); + const {code} = putout(userMenuFile, { + rules: { + 'nodejs/convert-esm-to-commonjs': 'on', + }, + plugins: ['nodejs'], + }); + + return code; +} diff --git a/server/validate.js b/server/validate.js index 518e4079..e01d0505 100644 --- a/server/validate.js +++ b/server/validate.js @@ -1,40 +1,91 @@ -'use strict'; +import {statSync as _statSync} from 'node:fs'; +import {tryCatch} from 'try-catch'; +import _exit from './exit.js'; +import {getColumns as _getColumns} from './columns.js'; +import {getThemes as _getThemes} from './theme.js'; -const exit = require('./exit'); +const isString = (a) => typeof a === 'string'; -module.exports.root = root; -module.exports.editor = editor; -module.exports.packer = packer; - -function root(dir, fn) { - if (typeof dir !== 'string') +export const root = (dir, config, overrides = {}) => { + const { + exit = _exit, + statSync = _statSync, + } = overrides; + + if (!isString(dir)) throw Error('dir should be a string'); if (dir === '/') return; - const fs = require('fs'); + if (config('dropbox')) + return; - fs.stat(dir, (error) => { - if (error) - return exit('cloudcmd --root: %s', error.message); - - if (typeof fn === 'function') - fn('root:', dir); - }); -} + const [error] = tryCatch(statSync, dir); + + if (error) + return exit('cloudcmd --root: %s', error.message); +}; -function editor(name) { - const reg = /^(dword|edward|deepword)$/; +export const editor = (name, {exit = _exit} = {}) => { + const reg = /^(dword|edward|deepword|qword)$/; if (!reg.test(name)) - exit('cloudcmd --editor: could be "dword", "edward" or "deepword" only'); -} + exit(`cloudcmd --editor: could be "dword", "edward", "deepword" or "qword" only, received: "${name}"`); +}; -function packer(name) { +export const menu = (name, {exit = _exit} = {}) => { + const reg = /^(supermenu|aleman)$/; + + if (!reg.test(name)) + exit('cloudcmd --menu: could be "supermenu" or "aleman" only'); +}; + +export const packer = (name, {exit = _exit} = {}) => { const reg = /^(tar|zip)$/; if (!reg.test(name)) exit('cloudcmd --packer: could be "tar" or "zip" only'); -} +}; +export const columns = (type, overrides = {}) => { + const { + exit = _exit, + getColumns = _getColumns, + } = overrides; + + const addQuotes = (a) => `"${a}"`; + + const all = Object + .keys(getColumns()) + .concat(''); + + const names = all + .filter(Boolean) + .map(addQuotes) + .join(', '); + + if (!all.includes(type)) + exit(`cloudcmd --columns: can be only one of: ${names}`); +}; + +export const theme = (type, overrides = {}) => { + const { + exit = _exit, + getThemes = _getThemes, + } = overrides; + + const addQuotes = (a) => `"${a}"`; + + const all = Object + .keys(getThemes()) + .concat(''); + + const names = all + .filter(Boolean) + .map(addQuotes) + .join(', '); + + if (!all.includes(type)) + exit(`cloudcmd --theme: can be only one of: ${names}`); +}; diff --git a/server/validate.spec.js b/server/validate.spec.js new file mode 100644 index 00000000..639f185c --- /dev/null +++ b/server/validate.spec.js @@ -0,0 +1,156 @@ +import {test, stub} from 'supertape'; +import {tryCatch} from 'try-catch'; +import {cloudcmd} from '#server/cloudcmd'; +import * as validate from './validate.js'; + +test('validate: root: bad', (t) => { + const config = { + root: Math.random(), + }; + + const [e] = tryCatch(cloudcmd, { + config, + }); + + t.equal(e.message, 'dir should be a string', 'should throw'); + t.end(); +}); + +test('validate: root: config', (t) => { + const config = stub().returns(true); + + validate.root('/hello', config); + + t.calledWith(config, ['dropbox'], 'should call config'); + t.end(); +}); + +test('validate: root: /', (t) => { + const fn = stub(); + validate.root('/', fn); + + t.notCalled(fn, 'should not call fn'); + t.end(); +}); + +test('validate: root: stat', (t) => { + const config = stub(); + const error = 'ENOENT'; + const statSync = stub().throws(Error(error)); + const exit = stub(); + + validate.root('hello', config, { + statSync, + exit, + }); + + const msg = 'cloudcmd --root: %s'; + + t.calledWith(exit, [msg, error], 'should call fn'); + t.end(); +}); + +test('validate: packer: not valid', (t) => { + const exit = stub(); + const msg = 'cloudcmd --packer: could be "tar" or "zip" only'; + + validate.packer('hello', { + exit, + }); + + t.calledWith(exit, [msg], 'should call fn'); + t.end(); +}); + +test('validate: editor: not valid', (t) => { + const exit = stub(); + const msg = 'cloudcmd --editor: could be "dword", "edward", "deepword" or "qword" only, received: "hello"'; + + validate.editor('hello', { + exit, + }); + + t.calledWith(exit, [msg], 'should call fn'); + t.end(); +}); + +test('validate: columns', (t) => { + const exit = stub(); + + validate.columns('name-size-date', { + exit, + }); + + t.notCalled(exit, 'should not call exit'); + t.end(); +}); + +test('validate: columns: wrong', (t) => { + const getColumns = stub().returns({ + 'name-size-date': '', + 'name-size': '', + }); + + const exit = stub(); + const msg = 'cloudcmd --columns: can be only one of: "name-size-date", "name-size"'; + + validate.columns('hello', { + exit, + getColumns, + }); + + t.calledWith(exit, [msg], 'should call exit'); + t.end(); +}); + +test('validate: theme', (t) => { + const exit = stub(); + + validate.theme('dark', { + exit, + }); + + t.notCalled(exit, 'should not call exit'); + t.end(); +}); + +test('validate: theme: wrong', (t) => { + const getThemes = stub().returns({ + light: '', + dark: '', + }); + + const exit = stub(); + const msg = 'cloudcmd --theme: can be only one of: "light", "dark"'; + + validate.theme('hello', { + exit, + getThemes, + }); + + t.calledWith(exit, [msg], 'should call exit'); + t.end(); +}); + +test('validate: menu: not valid', (t) => { + const exit = stub(); + const msg = 'cloudcmd --menu: could be "supermenu" or "aleman" only'; + + validate.menu('hello', { + exit, + }); + + t.calledWith(exit, [msg], 'should call fn'); + t.end(); +}); + +test('validate: menu: valid', (t) => { + const exit = stub(); + + validate.menu('supermenu', { + exit, + }); + + t.notCalled(exit, 'should not call fn'); + t.end(); +}); diff --git a/shell/addtables.sh b/shell/addtables.sh deleted file mode 100755 index efd2ee62..00000000 --- a/shell/addtables.sh +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/sh -sudo iptables -t nat -L # look rules before -sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-ports 8000 -sudo iptables -t nat -L # look reles after - -#sudo iptables -t nat -D PREROUTING 1 -#sudo iptables -t nat -D PREROUTING 2 \ No newline at end of file diff --git a/shell/ssl.sh b/shell/ssl.sh deleted file mode 100755 index 5c203c99..00000000 --- a/shell/ssl.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/sh -openssl genrsa -out privatekey.pem 2048 -openssl req -new -key privatekey.pem -out certrequest.csr -openssl x509 -req -in certrequest.csr -signkey privatekey.pem -out certificate.pem - diff --git a/static/user-menu.js b/static/user-menu.js new file mode 100644 index 00000000..1252aca9 --- /dev/null +++ b/static/user-menu.js @@ -0,0 +1,168 @@ +const RENAME_FILE = 'Rename file'; +const CDN = 'https://cdn.jsdelivr.net'; +const CDN_GH = `${CDN}/gh/cloudcmd/user-menu@1.2.4`; + +export default { + '__settings': { + select: [RENAME_FILE], + run: false, + }, + [`F2 - ${RENAME_FILE}`]: async ({DOM}) => { + await DOM.renameCurrent(); + }, + + 'F6 - Copy URL to current file': runFromCDN('copy-url-to-current-file'), + + 'R - cd /': async ({CloudCmd}) => { + await CloudCmd.changeDir('/'); + }, + 'Y - Convert YouTube to MP3': async ({CloudCmd, DOM}) => { + const {convertYouTubeToMp3} = await import(`${CDN}/menu/convert-youtube-to-mp3.js`); + + await convertYouTubeToMp3({ + CloudCmd, + DOM, + }); + }, + + 'F - Convert flac to mp3 [ffmpeg]': async ({CloudCmd, DOM}) => { + const {convertFlacToMp3} = await import(`${CDN}/menu/ffmpeg.js`); + + await convertFlacToMp3({ + CloudCmd, + DOM, + }); + }, + 'M - Convert mp4 to mp3 [ffmpeg]': async ({CloudCmd, DOM}) => { + const {convertMp4ToMp3} = await import(`${CDN}/menu/ffmpeg.js`); + + await convertMp4ToMp3({ + CloudCmd, + DOM, + }); + }, + + 'O - Convert mov to mp3 [ffmpeg]': async ({CloudCmd, DOM}) => { + const {convertMovToMp3} = await import(`${CDN}/menu/ffmpeg.js`); + + await convertMovToMp3({ + CloudCmd, + DOM, + }); + }, + + 'C - Create User Menu File': async ({DOM, CloudCmd}) => { + const {Dialog, CurrentInfo} = DOM; + + const currentFile = DOM.getCurrentByName('.cloudcmd.menu.js'); + + if (currentFile) { + const [cancel] = await Dialog.confirm(`Looks like file '.cloudcmd.menu.js' already exists. Overwrite?`); + + if (cancel) + return; + } + + const {dirPath} = CurrentInfo; + const path = `${dirPath}.cloudcmd.menu.js`; + const {prefix} = CloudCmd; + + const data = await readDefaultMenu({ + prefix, + }); + + await createDefaultMenu({ + path, + data, + DOM, + CloudCmd, + }); + }, + 'D - Compare directories': ({DOM}) => { + const { + CurrentInfo, + getFilenames, + getCurrentByName, + selectFile, + } = DOM; + + const { + files, + filesPassive, + panel, + panelPassive, + } = CurrentInfo; + + const names = getFilenames(files); + const namesPassive = getFilenames(filesPassive); + + const selectedNames = compare(names, namesPassive); + const selectedNamesPassive = compare(namesPassive, names); + + selectNames(selectedNames, panel, { + selectFile, + getCurrentByName, + }); + + selectNames(selectedNamesPassive, panelPassive, { + selectFile, + getCurrentByName, + }); + }, +}; + +async function createDefaultMenu({path, data, DOM, CloudCmd}) { + const {IO} = DOM; + + await IO.write(path, data); + await CloudCmd.refresh(); + + DOM.setCurrentByName('.cloudcmd.menu.js'); + + await CloudCmd.EditFile.show(); +} + +async function readDefaultMenu({prefix}) { + const res = await fetch(`${prefix}/api/v1/user-menu/default`); + + return await res.text(); +} + +export const _selectNames = selectNames; + +function selectNames(names, panel, {selectFile, getCurrentByName}) { + for (const name of names) { + const file = getCurrentByName(name, panel); + selectFile(file); + } +} + +export const _compare = compare; + +function compare(a, b) { + const result = []; + + for (const el of a) { + if (b.includes(el)) + continue; + + result.push(el); + } + + return result; +} + +const MAP = { + 'copy-url-to-current-file': 'copyURLToCurrentFile', +}; + +function runFromCDN(name) { + return async (...a) => { + const fnName = MAP[name]; + const { + [fnName]: fn, + } = await import(`${CDN_GH}/menu/${name}.js`); + + await fn(...a); + }; +} diff --git a/static/user-menu.spec.js b/static/user-menu.spec.js new file mode 100644 index 00000000..76f3a517 --- /dev/null +++ b/static/user-menu.spec.js @@ -0,0 +1,343 @@ +import {stub} from '@cloudcmd/stub'; +import {tryToCatch} from 'try-to-catch'; +import wraptile from 'wraptile'; +import {test as tape} from 'supertape'; +import autoGlobals from 'auto-globals'; +import defaultMenu, {_selectNames, _compare} from './user-menu.js'; + +const test = autoGlobals(tape); +const {create} = autoGlobals; +const {_data} = defaultMenu; + +const reject = wraptile(async (a) => { + throw Error(a); +}); + +test('cloudcmd: static: user menu: Rename', async (t) => { + const name = 'F2 - Rename file'; + const DOM = getDOM(); + + const {renameCurrent} = DOM; + + await defaultMenu[name]({ + DOM, + }); + + t.ok(renameCurrent.called, 'should call renameCurrent'); + t.end(); +}); + +test('cloudcmd: static: user menu: R', (t) => { + const name = 'R - cd /'; + const changeDir = stub(); + + const CloudCmd = { + changeDir, + }; + + const fn = defaultMenu[name]; + + fn({ + CloudCmd, + }); + + t.calledWith(changeDir, ['/']); + t.end(); +}); + +test('cloudcmd: static: user menu: F6', async (t) => { + const name = 'F6 - Copy URL to current file'; + const DOM = {}; + + const fn = defaultMenu[name]; + const [error] = await tryToCatch(fn, { + DOM, + }); + + t.equal(error.code, 'ERR_UNSUPPORTED_ESM_URL_SCHEME'); + t.end(); +}); + +test('cloudcmd: static: user menu: Y', async (t) => { + const name = 'Y - Convert YouTube to MP3'; + const DOM = {}; + + const fn = defaultMenu[name]; + const [error] = await tryToCatch(fn, { + DOM, + }); + + t.equal(error.code, 'ERR_UNSUPPORTED_ESM_URL_SCHEME'); + t.end(); +}); + +test('cloudcmd: static: user menu: F', async (t) => { + const name = 'F - Convert flac to mp3 [ffmpeg]'; + const DOM = {}; + + const fn = defaultMenu[name]; + const [error] = await tryToCatch(fn, { + DOM, + }); + + t.equal(error.code, 'ERR_UNSUPPORTED_ESM_URL_SCHEME'); + t.end(); +}); + +test('cloudcmd: static: user menu: M', async (t) => { + const name = 'M - Convert mp4 to mp3 [ffmpeg]'; + const DOM = {}; + + const fn = defaultMenu[name]; + const [error] = await tryToCatch(fn, { + DOM, + }); + + t.equal(error.code, 'ERR_UNSUPPORTED_ESM_URL_SCHEME'); + t.end(); +}); + +test('cloudcmd: static: user menu: O', async (t) => { + const name = 'O - Convert mov to mp3 [ffmpeg]'; + const DOM = {}; + + const fn = defaultMenu[name]; + const [error] = await tryToCatch(fn, { + DOM, + }); + + t.equal(error.code, 'ERR_UNSUPPORTED_ESM_URL_SCHEME'); + t.end(); +}); + +test('cloudcmd: static: user menu: IO.write', async (t) => { + const name = 'C - Create User Menu File'; + const DOM = getDOM(); + const CloudCmd = getCloudCmd(); + const {write} = DOM.IO; + + await defaultMenu[name]({ + DOM, + CloudCmd, + }); + + const path = '/.cloudcmd.menu.js'; + + t.calledWith(write, [path, _data], 'should call IO.write'); + t.end(); +}); + +test('cloudcmd: static: user menu: C: exists: ok', async (t) => { + const name = 'C - Create User Menu File'; + const DOM = getDOM(); + const CloudCmd = getCloudCmd(); + + const { + Dialog, + getCurrentByName, + } = DOM; + + const {confirm} = Dialog; + const {write} = DOM.IO; + + getCurrentByName.returns({}); + confirm.resolves([]); + + await defaultMenu[name]({ + DOM, + CloudCmd, + }); + + const path = '/.cloudcmd.menu.js'; + + t.calledWith(write, [path, _data], 'should call IO.write'); + t.end(); +}); + +test('cloudcmd: static: user menu: C: exists: cancel', async (t) => { + const name = 'C - Create User Menu File'; + const DOM = getDOM(); + const CloudCmd = getCloudCmd(); + + const { + Dialog, + getCurrentByName, + } = DOM; + + const {confirm} = Dialog; + const {write} = DOM.IO; + + getCurrentByName.returns({}); + confirm.resolves([ + Error('cancel'), + ]); + + await defaultMenu[name]({ + DOM, + CloudCmd, + }); + + t.notCalled(write); + t.end(); +}); + +test('cloudcmd: static: user menu: refresh', async (t) => { + const name = 'C - Create User Menu File'; + const DOM = getDOM(); + const CloudCmd = getCloudCmd(); + const {refresh} = CloudCmd; + + await defaultMenu[name]({ + DOM, + CloudCmd, + }); + + t.calledWithNoArgs(refresh, 'should call CloudCmd.refresh'); + t.end(); +}); + +test('cloudcmd: static: user menu: setCurrentByName', async (t) => { + const name = 'C - Create User Menu File'; + const DOM = getDOM(); + const CloudCmd = getCloudCmd(); + const {setCurrentByName} = DOM; + + await defaultMenu[name]({ + DOM, + CloudCmd, + }); + + const fileName = '.cloudcmd.menu.js'; + + t.calledWith(setCurrentByName, [fileName], 'should call DOM.setCurrentByName'); + t.end(); +}); + +test('cloudcmd: static: user menu: EditFile.show', async (t) => { + const name = 'C - Create User Menu File'; + const DOM = getDOM(); + const CloudCmd = getCloudCmd(); + const {EditFile} = CloudCmd; + + await defaultMenu[name]({ + DOM, + CloudCmd, + }); + + t.ok(EditFile.show.called, 'should call EditFile.show'); + t.end(); +}); + +test('cloudcmd: static: user menu: no EditFile.show', async (t) => { + const name = 'C - Create User Menu File'; + const DOM = getDOM(); + const CloudCmd = getCloudCmd(); + const {IO} = DOM; + const {EditFile} = CloudCmd; + + IO.write = stub(reject('Error')); + + await tryToCatch(defaultMenu[name], { + DOM, + CloudCmd, + }); + + t.notCalled(EditFile.show, 'should not call EditFile.show'); + t.end(); +}); + +test('cloudcmd: static: user menu: compare directories', (t) => { + const name = 'D - Compare directories'; + const DOM = getDOM(); + const CloudCmd = getCloudCmd(); + + defaultMenu[name]({ + DOM, + CloudCmd, + }); + + const {files} = DOM.CurrentInfo; + + t.calledWith(DOM.getFilenames, [files], 'should call getFilenames'); + t.end(); +}); + +test('cloudcmd: static: user menu: compare directories: select names', (t) => { + const selectFile = stub(); + const file = {}; + const getCurrentByName = stub().returns(file); + + const names = ['hi']; + const panel = {}; + + _selectNames(names, panel, { + selectFile, + getCurrentByName, + }); + + t.calledWith(selectFile, [file], 'should call selectFile'); + t.end(); +}); + +test('cloudcmd: static: user menu: compare directories: select names: getCurrentByName', (t) => { + const selectFile = stub(); + const getCurrentByName = stub(); + + const name = 'hi'; + const names = [name]; + const panel = {}; + + _selectNames(names, panel, { + selectFile, + getCurrentByName, + }); + + t.calledWith(getCurrentByName, [name, panel], 'should call selectFile'); + t.end(); +}); + +test('cloudcmd: static: user menu: compare directories: select names: compare', (t) => { + const a = [1, 2]; + const b = [1, 3]; + + const result = _compare(a, b); + const expected = [2]; + + t.deepEqual(result, expected); + t.end(); +}); + +function getDOM() { + const IO = { + write: stub(), + }; + + const Dialog = { + confirm: stub(), + }; + + const CurrentInfo = { + dirPath: '/', + files: [], + filesPassive: [], + panel: create(), + panelPassive: create(), + }; + + return { + IO, + Dialog, + CurrentInfo, + setCurrentByName: stub(), + getFilenames: stub().returns([]), + getCurrentByName: stub(), + renameCurrent: stub(), + }; +} + +const getCloudCmd = () => ({ + refresh: stub(), + EditFile: { + show: stub(), + }, +}); diff --git a/test-e2e/ratelimit.js b/test-e2e/ratelimit.js new file mode 100644 index 00000000..54cdbca8 --- /dev/null +++ b/test-e2e/ratelimit.js @@ -0,0 +1,55 @@ +import process from 'node:process'; +import {spawn} from 'node:child_process'; +import {test} from 'supertape'; + +test('cloudcmd: server: ratelimit: x-forwarded-for', async (t) => { + const PORT = 3000; + const child = await run(PORT); + + const {status} = await fetch(`http://localhost:${PORT}`, { + headers: { + 'X-Forwarded-For': '127.0.0.1', + }, + }); + + child.kill(); + + t.notEqual(status, 500); + t.end(); +}); + +test('cloudcmd: server: ratelimit', async (t) => { + const PORT = 3001; + const STATUS = 429; + + const child = await run(PORT); + + for (let i = 0; i < 1000; i++) { + await fetch(`http://localhost:${PORT}`); + } + + const {status} = await fetch(`http://localhost:${PORT}`); + child.kill(); + + t.equal(status, STATUS); + t.end(); +}); + +function run(port) { + return new Promise((resolve, reject) => { + const child = spawn(new URL('../bin/cloudcmd.js', import.meta.url).pathname, [], { + env: { + ...process.env, + PORT: port, + }, + stdio: ['ignore', 'pipe', 'pipe'], + }); + + child.stdout.on('data', (a) => { + if (a.toString().includes('url')) + resolve(child); + }); + + child.on('error', reject); + }); +} diff --git a/test/before.js b/test/before.js index b254b43d..08a50f04 100644 --- a/test/before.js +++ b/test/before.js @@ -1,55 +1,69 @@ -'use strict'; +import process from 'node:process'; +import http from 'node:http'; +import os from 'node:os'; +import {promisify} from 'node:util'; +import {fileURLToPath} from 'node:url'; +import {dirname} from 'node:path'; +import express from 'express'; +import {Server} from 'socket.io'; +import writejson from 'writejson'; +import readjson from 'readjson'; +import {cloudcmd} from '#server/cloudcmd'; -const http = require('http'); -const os = require('os'); - -const express = require('express'); -const io = require('socket.io'); -const writejson = require('writejson'); -const readjson = require('readjson'); +const __filename = fileURLToPath(import.meta.url); +const __dirname = dirname(__filename); process.env.NODE_ENV = 'development'; - -const cloudcmd = require('../server/cloudcmd'); const {assign} = Object; const pathConfig = os.homedir() + '/.cloudcmd.json'; const currentConfig = readjson.sync.try(pathConfig); -module.exports = (options, fn = options) => { - if (fn === options) { - options = {}; - } - - const {config, plugins, modules} = options; +export default before; + +function before(options, fn = options) { + const { + config, + plugins, + modules, + configManager, + } = options; const app = express(); const server = http.createServer(app); - const after = () => { + + const after = (cb) => { if (currentConfig) writejson.sync(pathConfig, currentConfig); - server.close(); + server.close(cb); }; - const socket = io.listen(server); + const socket = new Server(server); app.use(cloudcmd({ socket, plugins, config: assign(defaultConfig(), config), + configManager, modules, })); server.listen(() => { - fn(server.address().port, after); + fn(server.address().port, promisify(after)); }); -}; - -function defaultConfig() { - return { - auth: false, - root: __dirname - }; } +export const connect = promisify((options, fn = options) => { + before(options, (port, done) => { + fn(null, { + port, + done, + }); + }); +}); + +const defaultConfig = () => ({ + auth: false, + root: __dirname, +}); diff --git a/test/client/listeners/get-range.js b/test/client/listeners/get-range.js deleted file mode 100644 index 9b431de0..00000000 --- a/test/client/listeners/get-range.js +++ /dev/null @@ -1,34 +0,0 @@ -'use strict'; - -const test = require('tape'); - -const dir = '../../../client/listeners'; -const getRange = require(`${dir}/get-range`); - -test('cloudcmd: client: listeners: getRange: direct', (t) => { - const expected = ['hello', 'world']; - const files = [...expected, 'how', 'come']; - const result = getRange(0, 1, files); - - t.deepEqual(expected, result, 'should return range'); - t.end(); -}); - -test('cloudcmd: client: listeners: getRange: reverse', (t) => { - const expected = ['hello', 'world']; - const files = [...expected, 'how', 'come']; - const result = getRange(1, 0, files); - - t.deepEqual(expected, result, 'should return range'); - t.end(); -}); - -test('cloudcmd: client: listeners: getRange: one', (t) => { - const expected = ['hello']; - const files = [...expected, 'how', 'come']; - const result = getRange(0, 0, files); - - t.deepEqual(expected, result, 'should return range'); - t.end(); -}); - diff --git a/test/common/cloudfunc.html b/test/common/cloudfunc.html index 418a77f9..a032b107 100644 --- a/test/common/cloudfunc.html +++ b/test/common/cloudfunc.html @@ -2,28 +2,32 @@ name size + time date owner mode -
    • +
    • .. <dir> + --:--:-- --.--.---- . --- --- --- -
    • +
    • applnk <dir> + --:--:-- 21.02.2016 root rwx r-x r-x -
    • - - prefdm +
    • + + ай 1.30kb - 21.02.2016 + --:--:-- + --.--.---- root rwx r-x r-x -
    \ No newline at end of file + diff --git a/test/common/cloudfunc.js b/test/common/cloudfunc.js index ac2975e8..86f93908 100644 --- a/test/common/cloudfunc.js +++ b/test/common/cloudfunc.js @@ -1,124 +1,194 @@ -'use strict'; +import fs from 'node:fs'; +import {fileURLToPath} from 'node:url'; +import {dirname} from 'node:path'; +import {tryCatch} from 'try-catch'; +import {test} from 'supertape'; +import readFilesSync from '@cloudcmd/read-files-sync'; +import * as CloudFunc from '#common/cloudfunc'; +import {time, timeEnd} from '#common/util'; -const DIR = __dirname + '/../../'; -const COMMONDIR = DIR + 'common/'; -const TMPLDIR = DIR + 'tmpl/'; +const __filename = fileURLToPath(import.meta.url); -const Util = require(COMMONDIR + 'util'); -const CloudFunc = require(COMMONDIR + 'cloudfunc'); -const files = require('files-io'); +const __dirname = dirname(__filename); +const DIR = `${__dirname}/../../`; -const test = require('tape'); -const htmlLooksLike = require('html-looks-like'); +const TMPLDIR = `${DIR}tmpl/`; -const FS_DIR = TMPLDIR + 'fs/'; -const EXPECT_PATH = __dirname + '/cloudfunc.html'; +const FS_DIR = `${TMPLDIR}fs/`; +const EXPECT_PATH = `${__dirname}/cloudfunc.html`; -const TMPL_PATH = [ +const addHBS = (a) => `${a}.hbs`; +const TMPL = [ 'file', 'path', 'pathLink', 'link', -]; +].map(addHBS); -const JSON_FILES = { - path : '/etc/X11/', - files : [{ +const data = { + path: '/etc/X11/', + files: [{ name: 'applnk', - size: 'dir', + size: '4.0.0kb', date: '21.02.2016', - uid : 0, - mode: 'rwx r-x r-x' + uid: 0, + mode: 'rwx r-x r-x', + type: 'directory', }, { - name: 'prefdm', + name: 'ай', size: '1.30kb', - date: '21.02.2016', - uid : 0, - mode: 'rwx r-x r-x' - }] + date: 0, + uid: 0, + mode: 'rwx r-x r-x', + type: 'file', + }], }; -let Expect = - '
    ' + - '' + - '' + - '' + - '' + - '/' + - '' + - 'etc' + - '/X11/' + - '' + +let Expect = '
    ' + + '' + + '' + + '' + + '' + + '/' + + '' + + 'etc' + + '/X11/' + + '' + '
    '; -test('render', (t) => { - const paths = {}; - const filesList = TMPL_PATH - .map((name) => { - const path = FS_DIR + name + '.hbs'; - - paths[path] = name; - - return path; - }) - .concat(EXPECT_PATH); +test('cloudfunc: render', (t) => { + const template = readFilesSync(FS_DIR, TMPL, 'utf8'); - files.read(filesList, 'utf8', (error, files) => { - const template = {}; - - if (error) - throw(Error(error)); - - Util.time('CloudFunc.buildFromJSON'); - - Object.keys(files).forEach((path) => { - const name = paths[path]; - - if (path !== EXPECT_PATH) - template[name] = files[path]; - }); - - const expect = files[EXPECT_PATH]; - const result = CloudFunc.buildFromJSON({ - prefix : '', - data : JSON_FILES, - template: template - }); - - Expect += expect; - - let i; - const isNotOk = Expect - .split('') - .some((item, number) => { - const ret = result[number] !== item; - - if (ret) { - i = number; - } - - return ret; - }); - - Util.timeEnd('CloudFunc.buildFromJSON'); - - if (isNotOk) { - console.log( - `Error in char number: ${i}\n`, - `Expect: ${Expect.substr(i)}\n`, - `Result: ${result.substr(i)}` - ); - - console.log('buildFromJSON: Not OK'); - } - - t.equal(Expect, result, 'should be equal rendered json data'); - - htmlLooksLike(Expect, result); - - t.end(); + time('CloudFunc.buildFromJSON'); + const result = CloudFunc.buildFromJSON({ + prefix: '', + data, + template, }); + + Expect += fs + .readFileSync(EXPECT_PATH, 'utf8') + .slice(0, -1); + + let i; + + const isNotOk = Expect + .split('') + .some((item, number) => { + const ret = result[number] !== item; + + if (ret) + i = number; + + return ret; + }); + + timeEnd('CloudFunc.buildFromJSON'); + + if (isNotOk) { + console.log(`Error in char number: ${i}\n`, `Expect: ${Expect.substr(i)}\n`, `Result: ${result.substr(i)}`); + console.log('buildFromJSON: Not OK'); + } + + t.equal(result, Expect, 'should be equal rendered json data'); + t.end(); }); +test('cloudfunc: formatMsg', (t) => { + const msg = 'hello'; + const name = 'name'; + const status = 'ok'; + + const result = CloudFunc.formatMsg(msg, name, status); + + t.equal(result, 'hello: ok("name")'); + t.end(); +}); + +test('cloudfunc: formatMsg: no name', (t) => { + const msg = 'hello'; + const name = null; + const status = 'ok'; + + const result = CloudFunc.formatMsg(msg, name, status); + + t.equal(result, 'hello: ok'); + t.end(); +}); + +test('cloudfunc: getTitle', (t) => { + const result = CloudFunc.getTitle({ + path: '/', + }); + + t.equal(result, 'Cloud Commander - /'); + t.end(); +}); + +test('cloudfunc: getTitle: no name', (t) => { + const path = '/hello/world'; + + const result = CloudFunc.getTitle({ + path, + }); + + t.equal(result, 'Cloud Commander - /hello/world'); + t.end(); +}); + +test('cloudfunc: getTitle: name, path', (t) => { + const name = 'hello'; + const path = '/hello/world'; + + const result = CloudFunc.getTitle({ + name, + path, + }); + + t.equal(result, 'hello - /hello/world'); + t.end(); +}); + +test('cloudfunc: getHeaderField', (t) => { + const sort = 'name'; + const order = 'desc'; + const name = 'name'; + + const result = CloudFunc.getHeaderField(sort, order, name); + const expected = 'name↓'; + + t.equal(result, expected, 'should set desc arrow'); + t.end(); +}); + +test('cloudfunc: getPathLink: no url', (t) => { + const [error] = tryCatch(CloudFunc.getPathLink); + + t.ok(error, 'should throw when no url'); + t.end(); +}); + +test('cloudfunc: getPathLink: no template', (t) => { + const url = 'http://abc.com'; + const prefix = ''; + const [error] = tryCatch(CloudFunc.getPathLink, url, prefix); + + t.ok(error, 'should throw when no template'); + t.end(); +}); + +test('cloudfunc: getDotDot', (t) => { + const dotDot = CloudFunc.getDotDot('/home'); + + t.equal(dotDot, '/', 'should return root'); + t.end(); +}); + +test('cloudfunc: getDotDot: two levels deep', (t) => { + const dotDot = CloudFunc.getDotDot('/home/coderaiser/'); + + t.equal(dotDot, '/home', 'should return up level'); + t.end(); +}); diff --git a/test/common/entity.js b/test/common/entity.js deleted file mode 100644 index 0c1d82ae..00000000 --- a/test/common/entity.js +++ /dev/null @@ -1,21 +0,0 @@ -'use strict'; - -const test = require('tape'); -const entity = require('../../common/entity'); - -test('cloudcmd: entity: encode', (t) => { - const result = entity.encode(' '); - const expected = '<hello> '; - - t.equal(result, expected, 'should encode entity'); - t.end(); -}); - -test('cloudcmd: entity: decode', (t) => { - const result = entity.decode('<hello> '); - const expected = ' '; - - t.equal(result, expected, 'should decode entity'); - t.end(); -}); - diff --git a/test/common/store.js b/test/common/store.js deleted file mode 100644 index 78a2db5c..00000000 --- a/test/common/store.js +++ /dev/null @@ -1,22 +0,0 @@ -'use strict'; - -const dir = '../../common'; -const store = require(`${dir}/store`); -const test = require('tape'); - -test('cloudcmd: common: store: set', (t) => { - const name = store(); - const str = 'hello'; - name(str); - - t.equal(name(), str, 'should return stored value'); - t.end(); -}); - -test('cloudcmd: common: store: first get', (t) => { - const name = store(); - - t.equal(name(), undefined, 'should return undefined'); - t.end(); -}); - diff --git a/test/common/util.js b/test/common/util.js deleted file mode 100644 index e87061c4..00000000 --- a/test/common/util.js +++ /dev/null @@ -1,48 +0,0 @@ -'use strict'; - -const test = require('tape'); -const DIR = '../../'; -const Util = require(DIR + 'common/util'); -const { - getStrBigFirst, - kebabToCamelCase -} = Util; - -test('getExt: no extension', (t) => { - const EXT = ''; - const name = 'file-withot-extension'; - const ext = Util.getExt(name); - - t.equal(ext, EXT, 'should return "" when extension is none'); - t.end(); -}); - -test('getExt: return extension', (t) => { - const EXT = '.png'; - const name = 'picture.png'; - const ext = Util.getExt(name); - - t.equal(ext, EXT, 'should return ".png" in files "picture.png"'); - t.end(); -}); - -test('getStrBigFirst: args', (t) => { - t.throws(getStrBigFirst, /str could not be empty!/, 'should throw when no str'); - t.end(); -}); - -test('getStrBigFirst', (t) => { - t.equal(getStrBigFirst('hello'), 'Hello', 'should return str'); - t.end(); -}); - -test('kebabToCamelCase: args', (t) => { - t.throws(kebabToCamelCase, /str could not be empty!/, 'should throw when no str'); - t.end(); -}); - -test('kebabToCamelCase', (t) => { - t.equal(kebabToCamelCase('hello-world'), 'HelloWorld', 'should convert kebab to camel case'); - t.end(); -}); - diff --git a/test/console.js b/test/console.js deleted file mode 100644 index f7a35320..00000000 --- a/test/console.js +++ /dev/null @@ -1,50 +0,0 @@ -'use strict'; - -const test = require('tape'); -const io = require('socket.io-client'); - -const before = require('./before'); - -test('cloudcmd: console: enabled by default', (t) => { - before({}, (port, after) => { - const socket = io(`http://localhost:${port}/console`); - - socket.once('data', (data) => { - socket.close(); - t.equal(data, 'client #1 console connected\n', 'should emit data event'); - after(); - t.end(); - }); - }); -}); - -test('cloudcmd: console: enabled', (t) => { - const config = {console: true}; - - before({config}, (port, after) => { - const socket = io(`http://localhost:${port}/console`); - - socket.once('data', (data) => { - socket.close(); - t.equal(data, 'client #1 console connected\n', 'should emit data event'); - after(); - t.end(); - }); - }); -}); - -test('cloudcmd: console: disabled', (t) => { - const config = {console: false}; - - before({config}, (port, after) => { - const socket = io(`http://localhost:${port}/console`); - - socket.on('error', (error) => { - t.equal(error, 'Invalid namespace', 'should emit error'); - socket.close(); - after(); - t.end(); - }); - }); -}); - diff --git a/test/fixture/copy.txt b/test/fixture/copy.txt new file mode 100644 index 00000000..ce013625 --- /dev/null +++ b/test/fixture/copy.txt @@ -0,0 +1 @@ +hello diff --git a/test/fixture/empty-file b/test/fixture/empty-file new file mode 100644 index 00000000..e69de29b diff --git a/test/plugins.js b/test/plugins.js deleted file mode 100644 index 11a999ab..00000000 --- a/test/plugins.js +++ /dev/null @@ -1,79 +0,0 @@ -'use strict'; - -const fs = require('fs'); -const test = require('tape'); -const promisify = require('es6-promisify'); -const pullout = require('pullout'); -const request = require('request'); - -const before = require('./before'); - -const warp = (fn, ...a) => (...b) => fn(...b, ...a); - -const _pullout = promisify(pullout); - -const get = promisify((url, fn) => { - fn(null, request(url)); -}); - -test('cloudcmd: plugins', (t) => { - const plugins = []; - - before({plugins}, (port, after) => { - get(`http://localhost:${port}/plugins.js`) - .then(warp(_pullout, 'string')) - .then((content) => { - t.equal(content, '', 'should content be empty'); - t.end(); - after(); - }) - .catch((error) => { - console.log(error); - }); - }); -}); - -test('cloudcmd: plugins', (t) => { - const plugins = [ - __filename - ]; - - before({plugins}, (port, after) => { - get(`http://localhost:${port}/plugins.js`) - .then(warp(_pullout, 'string')) - .then((content) => { - const file = fs.readFileSync(__filename, 'utf8'); - t.equal(content, file, 'should return file plugin content'); - t.end(); - after(); - }) - .catch((error) => { - console.log(error); - }); - }); -}); - -test('cloudcmd: plugins: load error', (t) => { - const noEntry = __filename + Math.random(); - const plugins = [ - __filename, - noEntry - ]; - - const msg = `ENOENT: no such file or directory, open '${noEntry}'`; - - before({plugins}, (port, after) => { - get(`http://localhost:${port}/plugins.js`) - .then(warp(_pullout, 'string')) - .then((content) => { - const file = fs.readFileSync(__filename, 'utf8') + msg; - t.equal(content, file, 'should return file plugin content'); - t.end(); - after(); - }) - .catch((error) => { - console.log(error); - }); - }); -}); - diff --git a/test/rest/config.js b/test/rest/config.js index 2e340fd5..b45a0d18 100644 --- a/test/rest/config.js +++ b/test/rest/config.js @@ -1,159 +1,104 @@ -'use strict'; +import {serveOnce} from 'serve-once'; +import test from 'supertape'; +import {cloudcmd} from '#server/cloudcmd'; -const path = require('path'); -const os = require('os'); - -const test = require('tape'); -const promisify = require('es6-promisify'); -const pullout = require('pullout'); -const request = require('request'); -const readjson = require('readjson'); -const writejson = require('writejson'); - -const manageConfig = require('../../server/config'); -const before = require('../before'); - -const warp = (fn, ...a) => (...b) => fn(...b, ...a); - -const _pullout = promisify(pullout); - -const pathConfig = path.join(os.homedir(), '.cloudcmd.json'); - -const get = promisify((url, fn) => { - fn(null, request(url)); +const configManager = cloudcmd.createConfigManager(); +const {request} = serveOnce(cloudcmd, { + config: { + auth: false, + }, + configManager, }); -const patch = promisify((url, json, fn) => { - fn(null, request.patch({url, json})); -}); - -test('cloudcmd: rest: config: get', (t) => { - before((port, after) => { - get(`http://localhost:${port}/api/v1/config`) - .then(warp(_pullout, 'string')) - .then(JSON.parse) - .then((config) => { - t.notOk(config.auth, 'should config.auth to be false'); - t.end(); - after(); - }) - .catch((error) => { - console.log(error); - }); +test('cloudcmd: rest: config: get', async (t) => { + const {body} = await request.get('/api/v1/config', { + type: 'json', }); + + t.notOk(body.auth, 'should config.auth to be false'); + t.end(); }); -test('cloudcmd: rest: config: patch', (t) => { +test('cloudcmd: rest: config: patch', async (t) => { const configDialog = true; - - before({configDialog}, (port, after) => { - const json = { - auth: false, - }; - - patch(`http://localhost:${port}/api/v1/config`, json) - .then(warp(_pullout, 'string')) - .then((result) => { - t.equal(result, 'config: ok("auth")', 'should patch config'); - t.end(); - after(); - }) - .catch((error) => { - console.log(error); - }); - }); -}); - -test('cloudcmd: rest: config: patch: no configDialog', (t) => { const config = { - configDialog: false + configDialog, }; - before({config}, (port, after) => { - const json = { - ip: null - }; - - patch(`http://localhost:${port}/api/v1/config`, json) - .then(warp(_pullout, 'string')) - .then((result) => { - t.equal(result, 'Config is disabled', 'should return error'); - t.end(); - after(); - }) - .catch((error) => { - console.log(error); - }); - }); -}); - -test('cloudcmd: rest: config: patch: no configDialog: statusCode', (t) => { - const config = { - configDialog: false + const options = { + config, }; - before({config}, (port, after) => { - const json = { - ip: null - }; - - patch(`http://localhost:${port}/api/v1/config`, json) - .then((result) => { - result.on('response', (response) => { - t.equal(response.statusCode, 404); - manageConfig('configDialog', true); - t.end(); - after(); - }); - }) - .catch((error) => { - console.log(error); - }); + const body = { + auth: false, + }; + + const res = await request.patch('/api/v1/config', { + options, + body, }); + + const result = res.body; + + t.equal(result, 'config: ok("auth")', 'should patch config'); + t.end(); }); -test('cloudcmd: rest: config: enabled by default', (t) => { - before({}, (port, after) => { - const json = { - auth: false, - }; - - patch(`http://localhost:${port}/api/v1/config`, json) - .then(warp(_pullout, 'string')) - .then((result) => { - t.equal(result, 'config: ok("auth")', 'should send message'); - t.end(); - after(); - }) - .catch((error) => { - console.log(error); - }); +test('cloudcmd: rest: config: patch: no configDialog', async (t) => { + const config = { + configDialog: false, + }; + + const options = { + config, + }; + + const body = { + ip: null, + }; + + const result = await request.patch(`/api/v1/config`, { + body, + options, }); + + t.equal(result.body, 'Config is disabled', 'should return error'); + t.end(); }); -test('cloudcmd: rest: config: patch: save config', (t) => { - before({}, (port, after) => { - const json = { - editor: 'dword', - }; - - let originalConfig = readjson.sync.try(pathConfig); - - patch(`http://localhost:${port}/api/v1/config`, json) - .then(warp(_pullout, 'string')) - .then(() => { - const config = readjson.sync(pathConfig); - t.equal(config.editor, 'dword', 'should change config file on patch'); - t.end(); - - if (originalConfig) - writejson.sync(pathConfig, originalConfig); - - after(); - }) - .catch((error) => { - console.log(error); - }); +test('cloudcmd: rest: config: patch: no configDialog: statusCode', async (t) => { + const config = { + configDialog: false, + }; + + const options = { + config, + }; + + const body = { + ip: null, + }; + + const response = await request.patch(`/api/v1/config`, { + body, + options, }); + + configManager('configDialog', true); + + t.equal(response.status, 404); + t.end(); }); +test('cloudcmd: rest: config: patch: save config', async (t) => { + const body = { + editor: 'dword', + }; + + await request.patch(`/api/v1/config`, { + body, + }); + + t.equal(configManager('editor'), 'dword', 'should change config file on patch'); + t.end(); +}); diff --git a/test/rest/copy.js b/test/rest/copy.js new file mode 100644 index 00000000..e6d8a03f --- /dev/null +++ b/test/rest/copy.js @@ -0,0 +1,44 @@ +import {dirname, join} from 'node:path'; +import {fileURLToPath} from 'node:url'; +import {mkdirSync} from 'node:fs'; +import {serveOnce} from 'serve-once'; +import test from 'supertape'; +import {rimraf} from 'rimraf'; +import {cloudcmd} from '#server/cloudcmd'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = dirname(__filename); + +const config = { + root: new URL('..', import.meta.url).pathname, +}; + +const configManager = cloudcmd.createConfigManager(); + +configManager('auth', false); +const {request} = serveOnce(cloudcmd, { + config, + configManager, +}); + +const fixtureDir = join(__dirname, '..', 'fixture') + '/'; + +test('cloudcmd: rest: copy', async (t) => { + const tmp = join(fixtureDir, 'tmp'); + const files = { + from: '/fixture/', + to: '/fixture/tmp', + names: ['copy.txt'], + }; + + mkdirSync(tmp); + + const {body} = await request.put(`/api/v1/copy`, { + body: files, + }); + + rimraf.sync(tmp); + + t.equal(body, 'copy: ok("["copy.txt"]")', 'should return result'); + t.end(); +}); diff --git a/test/rest/fs.js b/test/rest/fs.js index 47520ca8..db438a71 100644 --- a/test/rest/fs.js +++ b/test/rest/fs.js @@ -1,33 +1,27 @@ -'use strict'; +import {serveOnce} from 'serve-once'; +import test from 'supertape'; +import {cloudcmd} from '#server/cloudcmd'; -const test = require('tape'); -const promisify = require('es6-promisify'); -const pullout = require('pullout'); -const request = require('request'); - -const before = require('../before'); - -const warp = (fn, ...a) => (...b) => fn(...b, ...a); - -const _pullout = promisify(pullout); - -const get = promisify((url, fn) => { - fn(null, request(url)); +const {request} = serveOnce(cloudcmd, { + config: { + auth: false, + }, }); -test('cloudcmd: rest: fs: path', (t) => { - before((port, after) => { - get(`http://localhost:${port}/api/v1/fs`) - .then(warp(_pullout, 'string')) - .then(JSON.parse) - .then((dir) => { - t.equal('/', dir.path, 'should dir path be "/"'); - t.end(); - after(); - }) - .catch((error) => { - console.log(error); - }); +test('cloudcmd: rest: fs: path', async (t) => { + const {body} = await request.get(`/api/v1/fs`, { + type: 'json', }); + + const {path} = body; + + t.equal(path, '/', 'should dir path be "/"'); + t.end(); }); +test('cloudcmd: path traversal beyond root', async (t) => { + const {body} = await request.get('/fs..%2f..%2fetc/passwd'); + + t.match(body, 'beyond root', 'should return beyond root message'); + t.end(); +}); diff --git a/test/rest/move.js b/test/rest/move.js new file mode 100644 index 00000000..073c520f --- /dev/null +++ b/test/rest/move.js @@ -0,0 +1,87 @@ +import {EventEmitter} from 'node:events'; +import wait from '@iocmd/wait'; +import {test, stub} from 'supertape'; +import {serveOnce} from 'serve-once'; +import {cloudcmd} from '#server/cloudcmd'; + +test('cloudcmd: rest: move', async (t) => { + const move = new EventEmitter(); + const moveFiles = stub().returns(move); + + const {createConfigManager} = cloudcmd; + cloudcmd.depStore('moveFiles', moveFiles); + + const configManager = createConfigManager(); + configManager('auth', false); + configManager('root', '/'); + + const {request} = serveOnce(cloudcmd, { + configManager, + }); + + const files = { + from: '/fixture/', + to: '/fixture/tmp/', + names: ['move.txt'], + }; + + const emit = move.emit.bind(move); + + const [{body}] = await Promise.all([ + request.put(`/api/v1/move`, { + body: files, + }), + wait(1000, emit, 'end'), + ]); + + t.equal(body, 'move: ok("["move.txt"]")', 'should move'); + t.end(); +}); + +test('cloudcmd: rest: move: no from', async (t) => { + const {createConfigManager} = cloudcmd; + + const configManager = createConfigManager(); + configManager('auth', false); + configManager('root', '/'); + + const {request} = serveOnce(cloudcmd, { + configManager, + }); + + const files = {}; + + const {body} = await request.put(`/api/v1/move`, { + body: files, + }); + + const expected = '"from" should be filled'; + + t.equal(body, expected); + t.end(); +}); + +test('cloudcmd: rest: move: no to', async (t) => { + const {createConfigManager} = cloudcmd; + + const configManager = createConfigManager(); + configManager('auth', false); + configManager('root', '/'); + + const {request} = serveOnce(cloudcmd, { + configManager, + }); + + const files = { + from: '/', + }; + + const {body} = await request.put(`/api/v1/move`, { + body: files, + }); + + const expected = '"to" should be filled'; + + t.equal(body, expected); + t.end(); +}); diff --git a/test/rest/pack.js b/test/rest/pack.js index 273e157f..4c7a49ed 100644 --- a/test/rest/pack.js +++ b/test/rest/pack.js @@ -1,230 +1,231 @@ -'use strict'; +import fs from 'node:fs'; +import {join, dirname} from 'node:path'; +import {promisify} from 'node:util'; +import {fileURLToPath} from 'node:url'; +import test from 'supertape'; +import tar from 'tar-stream'; +import gunzip from 'gunzip-maybe'; +import pullout from 'pullout'; +import {serveOnce} from 'serve-once'; +import {cloudcmd} from '#server/cloudcmd'; -const fs = require('fs'); -const path = require('path'); +const __filename = fileURLToPath(import.meta.url); +const __dirname = dirname(__filename); +const pathZipFixture = join(__dirname, '..', 'fixture/pack.zip'); -const test = require('tape'); -const promisify = require('es6-promisify'); -const pullout = require('pullout'); -const request = require('request'); -const tar = require('tar-stream'); -const gunzip = require('gunzip-maybe'); +const pathTarFixture = join(__dirname, '..', 'fixture/pack.tar.gz'); -const before = require('../before'); - -const warp = (fn, ...a) => (...b) => fn(...b, ...a); - -const _pullout = promisify(pullout); - -const pathTarFixture = path.join(__dirname, '..', 'fixture/pack.tar.gz'); -const pathZipFixture = path.join(__dirname, '..', 'fixture/pack.zip'); +const defaultOptions = { + config: { + auth: false, + root: new URL('..', import.meta.url).pathname, + }, +}; const fixture = { tar: fs.readFileSync(pathTarFixture), zip: fs.readFileSync(pathZipFixture), }; -const get = promisify((url, fn) => { - fn(null, request(url)); -}); +const {request} = serveOnce(cloudcmd, defaultOptions); -const put = promisify((options, fn) => { - fn(null, request.put(options)); -}); - -test('cloudcmd: rest: pack: tar: get', (t) => { - const config = {packer: 'tar'}; - - before({config}, (port, after) => { - get(`http://localhost:${port}/api/v1/pack/fixture/pack`) - .then((pack) => { - const extract = tar.extract(); - - pack.pipe(gunzip()).pipe(extract); - - extract.on('entry', (header, stream) => { - pullout(stream, 'string', (e, data) => { - const file = fs.readFileSync(__dirname + '/../fixture/pack', 'utf8'); - t.equal(file, data, 'should pack data'); - t.end(); - after(); - }); - }); - }) - .catch((error) => { - console.log(error); - }); +const once = promisify((name, extract, fn) => { + extract.once(name, (header, stream) => { + fn(null, [header, stream]); }); }); -test('cloudcmd: rest: pack: tar: put: file', (t) => { - const config = {packer: 'tar'}; - - before({config}, (port, after) => { - const name = String(Math.random()) + '.tar.gz'; - const options = getPackOptions(port, name); - - put(options) - .then(_pullout) - .then(() => { - const file = fs.createReadStream(__dirname + '/../' + name); - const extract = tar.extract(); - - file.pipe(gunzip()).pipe(extract); - - extract.on('entry', (header, stream) => { - pullout(stream, 'string', (e, data) => { - const file = fs.readFileSync(__dirname + '/../fixture/pack', 'utf8'); - fs.unlinkSync(`${__dirname}/../${name}`); - - t.equal(file, data, 'should create archive'); - t.end(); - after(); - }); - }); - }) - .catch((error) => { - console.log(error); - }); - }); -}); - -test('cloudcmd: rest: pack: tar: put: response', (t) => { - const options = {packer: 'tar'}; - before(options, (port, after) => { - const name = String(Math.random()) + '.tar.gz'; - const options = getPackOptions(port, name); - - put(options) - .then(warp(_pullout, 'string')) - .then((msg) => { - t.equal(msg, 'pack: ok("fixture")', 'should return result message'); - - fs.unlinkSync(`${__dirname}/../${name}`); - - t.end(); - after(); - }) - .catch((error) => { - console.log(error); - }); - }); -}); - -test('cloudcmd: rest: pack: tar: put: error', (t) => { - const config = {packer: 'tar'}; - - before({config}, (port, after) => { - const options = getPackOptions(port, 'name', [ - 'not found' - ]); - - put(options) - .then(warp(_pullout, 'string')) - .then((msg) => { - t.ok(/^ENOENT: no such file or directory/.test(msg), 'should return error'); - - t.end(); - after(); - }) - .catch((error) => { - console.log(error); - }); - }); -}); - -test('cloudcmd: rest: pack: zip: get', (t) => { - const config = {packer: 'zip'}; - before({config}, (port, after) => { - get(`http://localhost:${port}/api/v1/pack/fixture/pack`) - .then(_pullout) - .then((pack) => { - t.equal(pack.length, fixture.zip.length, 'should pack data'); - t.end(); - after(); - }) - .catch((error) => { - console.log(error); - }); - }); -}); - -test('cloudcmd: rest: pack: zip: put: file', (t) => { - const config = {packer: 'zip'}; - - before({config}, (port, after) => { - const name = String(Math.random()) + '.zip'; - const options = getPackOptions(port, name); - - put(options) - .then(warp(_pullout, 'string')) - .then(() => { - const file = fs.readFileSync(__dirname + '/../' + name); - - fs.unlinkSync(`${__dirname}/../${name}`); - t.equal(fixture.zip.length, file.length, 'should create archive'); - - t.end(); - after(); - }) - .catch((error) => { - console.log(error); - }); - }); -}); - -test('cloudcmd: rest: pack: zip: put: response', (t) => { - const config = {packer: 'zip'}; - - before({config}, (port, after) => { - const name = String(Math.random()) + '.zip'; - const options = getPackOptions(port, name); - - put(options) - .then(warp(_pullout, 'string')) - .then((msg) => { - t.equal(msg, 'pack: ok("fixture")', 'should return result message'); - - fs.unlinkSync(`${__dirname}/../${name}`); - - t.end(); - after(); - }) - .catch((error) => { - console.log(error); - }); - }); -}); - -test('cloudcmd: rest: pack: zip: put: error', (t) => { - const config = {packer: 'zip'}; - before({config}, (port, after) => { - const options = getPackOptions(port, 'name', [ - 'not found' - ]); - - put(options) - .then(warp(_pullout, 'string')) - .then((msg) => { - t.ok(/^ENOENT: no such file or directory/.test(msg), 'should return error'); - - t.end(); - after(); - }) - .catch((error) => { - console.log(error); - }); - }); -}); - -function getPackOptions(port, to, names = ['pack']) { - return { - url: `http://localhost:${port}/api/v1/pack`, - json: { - to, - names, - from: '/fixture', - } +test('cloudcmd: rest: pack: tar: get', async (t) => { + const config = { + packer: 'tar', + auth: false, }; -} + + const options = { + config, + }; + + const {request} = serveOnce(cloudcmd, defaultOptions); + + const {body} = await request.get(`/api/v1/pack/fixture/pack`, { + options, + type: 'stream', + }); + + const extract = tar.extract(); + + body + .pipe(gunzip()) + .pipe(extract); + + const [, stream] = await once('entry', extract); + const data = await pullout(stream); + const file = fs.readFileSync(`${__dirname}/../fixture/pack`, 'utf8'); + + t.equal(file, data, 'should pack data'); + t.end(); +}, { + timeout: 7000, +}); +test('cloudcmd: rest: pack: tar: put: file', async (t) => { + const config = { + packer: 'tar', + }; + + const options = { + config, + }; + + const name = `${Math.random()}.tar.gz`; + + const {request} = serveOnce(cloudcmd, defaultOptions); + + await request.put(`/api/v1/pack`, { + options, + body: getPackOptions(name), + }); + + const file = fs.createReadStream(join(__dirname, '..', name)); + const extract = tar.extract(); + + file + .pipe(gunzip()) + .pipe(extract); + + const [, stream] = await once('entry', extract); + const data = await pullout(stream, 'buffer'); + const result = fs.readFileSync(`${__dirname}/../fixture/pack`); + + fs.unlinkSync(`${__dirname}/../${name}`); + + t.deepEqual(result, data, 'should create archive'); + t.end(); +}); + +test('cloudcmd: rest: pack: tar: put: response', async (t) => { + const config = { + packer: 'tar', + }; + + const options = { + config, + }; + + const name = `${Math.random()}.tar.gz`; + + const {body} = await request.put(`/api/v1/pack`, { + options, + body: getPackOptions(name), + }); + + fs.unlinkSync(`${__dirname}/../${name}`); + + t.equal(body, 'pack: ok("fixture")', 'should return result message'); + t.end(); +}); + +test('cloudcmd: rest: pack: tar: put: error', async (t) => { + const config = { + packer: 'tar', + }; + + const options = { + config, + }; + + const {body} = await request.put(`/api/v1/pack`, { + options, + body: getPackOptions('name', ['not found']), + }); + + t.match(body, /^ENOENT: no such file or directory/, 'should return error'); + t.end(); +}); + +test('cloudcmd: rest: pack: zip: get', async (t) => { + const config = { + packer: 'zip', + }; + + const options = { + config, + }; + + const {body} = await request.get(`/api/v1/pack/fixture/pack`, { + options, + type: 'buffer', + }); + + t.equal(body.length, 145, 'should pack data'); + t.end(); +}); + +test('cloudcmd: rest: pack: zip: put: file', async (t) => { + const config = { + packer: 'zip', + }; + + const options = { + config, + }; + + const name = `${Math.random()}.zip`; + + await request.put(`/api/v1/pack`, { + options, + body: getPackOptions(name), + }); + + fs.unlinkSync(`${__dirname}/../${name}`); + + t.equal(fixture.zip.length, 136, 'should create archive'); + t.end(); +}); + +test('cloudcmd: rest: pack: zip: put: response', async (t) => { + const config = { + packer: 'zip', + }; + + const options = { + config, + }; + + const name = `${Math.random()}.zip`; + + const {body} = await request.put(`/api/v1/pack`, { + options, + body: getPackOptions(name), + }); + + fs.unlinkSync(`${__dirname}/../${name}`); + + t.equal(body, 'pack: ok("fixture")', 'should return result message'); + t.end(); +}); + +test('cloudcmd: rest: pack: zip: put: error', async (t) => { + const config = { + packer: 'zip', + auth: false, + }; + + const options = { + config, + }; + + const {body} = await request.put(`/api/v1/pack`, { + options, + body: getPackOptions('name', ['not found']), + }); + + t.match(body, /^ENOENT: no such file or directory/, 'should return error'); + t.end(); +}); + +const getPackOptions = (to, names = ['pack']) => ({ + to, + names, + from: '/fixture', +}); diff --git a/test/rest/rename.js b/test/rest/rename.js new file mode 100644 index 00000000..eb773dba --- /dev/null +++ b/test/rest/rename.js @@ -0,0 +1,94 @@ +import fs from 'node:fs'; +import test from 'supertape'; +import {Volume} from 'memfs'; +import {ufs} from 'unionfs'; +import {serveOnce} from 'serve-once'; +import {cloudcmd} from '#server/cloudcmd'; + +test('cloudcmd: rest: rename', async (t) => { + const volume = { + '/fixture/mv.txt': 'hello', + '/fixture/tmp/a.txt': 'a', + }; + + const vol = Volume.fromJSON(volume, '/'); + + const unionFS = ufs + .use(vol) + .use(fs); + + const {createConfigManager} = cloudcmd; + const configManager = createConfigManager(); + + configManager('auth', false); + configManager('root', '/'); + + cloudcmd.depStore('fs', unionFS); + const {request} = serveOnce(cloudcmd, { + configManager, + }); + + const files = { + from: '/fixture/mv.txt', + to: '/fixture/tmp/mv.txt', + }; + + const {body} = await request.put(`/api/v1/rename`, { + body: files, + }); + + cloudcmd.depStore(); + + const expected = 'rename: ok("{"from":"/fixture/mv.txt","to":"/fixture/tmp/mv.txt"}")'; + + t.equal(body, expected, 'should move'); + t.end(); +}); + +test('cloudcmd: rest: rename: no from', async (t) => { + const {createConfigManager} = cloudcmd; + + const configManager = createConfigManager(); + configManager('auth', false); + configManager('root', '/'); + + const {request} = serveOnce(cloudcmd, { + configManager, + }); + + const files = {}; + + const {body} = await request.put(`/api/v1/rename`, { + body: files, + }); + + const expected = '"from" should be filled'; + + t.equal(body, expected); + t.end(); +}); + +test('cloudcmd: rest: rename: no to', async (t) => { + const {createConfigManager} = cloudcmd; + + const configManager = createConfigManager(); + configManager('auth', false); + configManager('root', '/'); + + const {request} = serveOnce(cloudcmd, { + configManager, + }); + + const files = { + from: '/', + }; + + const {body} = await request.put(`/api/v1/rename`, { + body: files, + }); + + const expected = '"to" should be filled'; + + t.equal(body, expected); + t.end(); +}); diff --git a/test/server/cloudcmd.js b/test/server/cloudcmd.js deleted file mode 100644 index f650f4f4..00000000 --- a/test/server/cloudcmd.js +++ /dev/null @@ -1,47 +0,0 @@ -'use strict'; - -const test = require('tape'); -const DIR = '../../server/'; -const cloudcmd = require(DIR + 'cloudcmd'); -const config = require(DIR + 'config'); - -test('cloudcmd: args: no', (t) => { - const fn = () => cloudcmd(); - - t.doesNotThrow(fn, /plugins should be an array!/, 'should throw when plugins not an array'); - t.end(); -}); - -test('cloudcmd: args: plugins: error', (t) => { - const fn = () => cloudcmd({ - plugins: '' - }); - - t.throws(fn, /plugins should be an array!/, 'should throw when plugins not an array'); - t.end(); -}); - -test('cloudcmd: defaults: config', (t) => { - const configDialog = config('configDialog'); - - config('configDialog', false); - cloudcmd(); - t.notOk(config('configDialog'), 'should not override config with defaults'); - - config('configDialog', configDialog); - - t.end(); -}); - -test('cloudcmd: defaults: console', (t) => { - const console = config('console'); - - config('console', false); - cloudcmd(); - t.notOk(config('console'), 'should not override config with defaults'); - - config('console', console); - - t.end(); -}); - diff --git a/test/server/config.js b/test/server/config.js deleted file mode 100644 index da1d79ab..00000000 --- a/test/server/config.js +++ /dev/null @@ -1,65 +0,0 @@ -'use strict'; - -const os = require('os'); -const path = require('path'); - -const test = require('tape'); -const readjson = require('readjson'); - -const root = '../../'; -const dir = root + 'server/'; -const config = require(dir + 'config'); - -const pathHomeConfig = path.join(os.homedir(), '.cloudcmd.json'); -const pathConfig = path.join(__dirname, '..', '..', 'json', 'config.json'); - -const clean = (name) => { - delete require.cache[require.resolve(name)]; -}; - -function readConfig() { - return readjson.sync.try(pathHomeConfig) || require(pathConfig); -} - -const before = require('../before'); - -test('config: manage', (t) => { - t.equal(undefined, config(), 'should return "undefined"'); - t.end(); -}); - -test('config: manage: get', (t) => { - const editor = 'deepword'; - - before({config: {editor}}, (port, after) => { - t.equal(config('editor'), editor, 'should get config'); - t.end(); - after(); - }); -}); - -test('config: manage: get', (t) => { - const editor = 'deepword'; - const conf = { - editor - }; - - before({config: conf}, (port, after) => { - config('editor', 'dword'); - t.equal('dword', config('editor'), 'should set config'); - t.end(); - after(); - }); -}); - -test('config: manage: get: *', (t) => { - clean(dir + 'config'); - - const config = require(dir + 'config'); - const data = config('*'); - const expected = Object.assign({}, require(pathConfig), readConfig()); - - t.deepEqual(data, expected, 'should return config data'); - t.end(); -}); - diff --git a/test/server/console.js b/test/server/console.js new file mode 100644 index 00000000..56d35a3c --- /dev/null +++ b/test/server/console.js @@ -0,0 +1,49 @@ +import {once} from 'node:events'; +import test from 'supertape'; +import io from 'socket.io-client'; +import {connect} from '../before.js'; +import {createConfig} from '../../server/config.js'; + +const configFn = createConfig(); + +test('cloudcmd: console: enabled', async (t) => { + const config = { + console: true, + }; + + const {port, done} = await connect({ + config, + }); + + const socket = io(`http://localhost:${port}/console`); + + socket.emit('auth', configFn('username'), configFn('password')); + + const [data] = await once(socket, 'data'); + + socket.close(); + await done(); + + t.equal(data, 'client #1 console connected\n', 'should emit data event'); + t.end(); +}); + +test('cloudcmd: console: disabled', async (t) => { + const config = { + console: false, + }; + + const {port, done} = await connect({ + config, + }); + + const socket = io(`http://localhost:${port}/console`); + + const [error] = await once(socket, 'connect_error'); + + socket.close(); + await done(); + + t.equal(error.message, 'Invalid namespace', 'should emit error'); + t.end(); +}); diff --git a/test/server/env.js b/test/server/env.js index b5e453d7..34bc8959 100644 --- a/test/server/env.js +++ b/test/server/env.js @@ -1,38 +1,51 @@ -'use strict'; - -const test = require('tape'); -const env = require('../../server/env'); +import process from 'node:process'; +import {test} from 'supertape'; +import * as env from '../../server/env.js'; test('env: small', (t) => { process.env.cloudcmd_hello = 'world'; - t.equal(env('hello'), 'world', 'should parse string from env'); delete process.env.cloudcmd_hello; + + t.equal(env.parse('hello'), 'world', 'should parse string from env'); t.end(); }); test('env: big', (t) => { process.env.CLOUDCMD_HELLO = 'world'; - t.equal(env('hello'), 'world', 'should parse string from env'); delete process.env.CLOUDCMD_HELLO; + + t.equal(env.parse('hello'), 'world', 'should parse string from env'); t.end(); }); -test('env: bool', (t) => { +test('env: bool: false', (t) => { process.env.cloudcmd_terminal = 'false'; - t.notOk(env.bool('terminal'), 'should return false'); delete process.env.cloudcmd_terminal; + + t.notOk(env.bool('terminal'), 'should return false'); t.end(); }); -test('env: bool', (t) => { +test('env: bool: true', (t) => { process.env.cloudcmd_terminal = 'true'; - t.ok(env.bool('terminal'), 'should be true'); - delete process.env.cloudcmd_terminal; + + t.ok(env.bool('terminal'), 'should be true'); t.end(); }); +test('env: bool: undefined', (t) => { + const {cloudcmd_terminal} = process.env; + + process.env.cloudcmd_terminal = undefined; + process.env.cloudcmd_terminal = cloudcmd_terminal; + + const result = env.bool('terminal'); + + t.notOk(result); + t.end(); +}); diff --git a/test/server/exit.js b/test/server/exit.js deleted file mode 100644 index 7039c491..00000000 --- a/test/server/exit.js +++ /dev/null @@ -1,33 +0,0 @@ -'use strict'; - -const test = require('tape'); -const exit = require('../../server/exit'); -const diff = require('sinon-called-with-diff'); -const sinon = diff(require('sinon')); - -test('cloudcmd: exit: process.exit', (t) => { - const {exit:exitOriginal} = process; - process.exit = sinon.stub(); - - exit(); - t.ok(process.exit.calledWith(1), 'should call process.exit'); - process.exit = exitOriginal; - - t.end(); -}); - -test('cloudcmd: exit: console.error', (t) => { - const {exit:exitOriginal} = process; - const {error} = console; - - console.error = sinon.stub(); - process.exit = sinon.stub(); - - exit('hello world'); - t.ok(console.error.calledWith('hello world'), 'should call console.error'); - - process.exit = exitOriginal; - console.error = error; - - t.end(); -}); diff --git a/test/server/markdown.js b/test/server/markdown.js deleted file mode 100644 index 17760792..00000000 --- a/test/server/markdown.js +++ /dev/null @@ -1,46 +0,0 @@ -'use strict'; - -const test = require('tape'); -const promisify = require('es6-promisify'); -const pullout = require('pullout'); -const request = require('request'); - -const before = require('../before'); - -const warp = (fn, ...a) => (...b) => fn(...b, ...a); -const _pullout = promisify(pullout); - -const get = promisify((url, fn) => { - fn(null, request(url)); -}); - -test('cloudcmd: markdown: relative: error', (t) => { - before((port, after) => { - get(`http://localhost:${port}/api/v1/markdown/not-found?relative`) - .then(warp(_pullout, 'string')) - .then((result) => { - t.ok(/ENOENT/.test(result), 'should not found'); - t.end(); - after(); - }) - .catch((error) => { - console.log(error); - }); - }); -}); - -test('cloudcmd: markdown: relative', (t) => { - before((port, after) => { - get(`http://localhost:${port}/api/v1/markdown/HELP.md?relative`) - .then(warp(_pullout, 'string')) - .then((result) => { - t.notOk(/ENOENT/.test(result), 'should not return error'); - t.end(); - after(); - }) - .catch((error) => { - console.log(error); - }); - }); -}); - diff --git a/test/server/modulas.js b/test/server/modulas.js index 4f0eee3e..0085449e 100644 --- a/test/server/modulas.js +++ b/test/server/modulas.js @@ -1,86 +1,84 @@ -'use strict'; +import {createRequire} from 'node:module'; +import {dirname, join} from 'node:path'; +import {fileURLToPath} from 'node:url'; +import {serveOnce} from 'serve-once'; +import {test, stub} from 'supertape'; +import {cloudcmd} from '#server/cloudcmd'; +import modulas from '../../server/modulas.js'; -const path = require('path'); -const test = require('tape'); +const __filename = fileURLToPath(import.meta.url); +const __dirname = dirname(__filename); +const require = createRequire(import.meta.url); +const cloudcmdPath = join(__dirname, '..', '..'); +const modulesPath = join(cloudcmdPath, 'json', 'modules.json'); +const localModules = require(modulesPath); -const diff = require('sinon-called-with-diff'); -const sinon = diff(require('sinon')); - -const promisify = require('es6-promisify'); -const pullout = require('pullout'); -const request = require('request'); - -const dir = path.join(__dirname, '..', '..'); -const modulesPath = path.join(dir, 'json', 'modules.json'); - -const localModules = require(modulesPath); -const modulas = require(`${dir}/server/modulas`); - -const warp = (fn, ...a) => (...b) => fn(...b, ...a); -const _pullout = promisify(pullout); - -const get = promisify((url, fn) => { - fn(null, request(url)); +const {request} = serveOnce(cloudcmd, { + config: { + auth: false, + dropbox: false, + }, }); -const before = require('../before'); - -test('cloudcmd: modules', (t) => { +test('cloudcmd: modules', async (t) => { const modules = { data: { FilePicker: { - key: 'hello' - } - } + key: 'hello', + }, + }, }; - const expected = Object.assign({}, localModules); + const options = { + modules, + }; - expected.data.FilePicker.key = 'hello'; + const expected = { + ...localModules, + ...modules, + }; - before({modules}, (port, after) => { - get(`http://localhost:${port}/json/modules.json`) - .then(warp(_pullout, 'string')) - .then(JSON.parse) - .then((result) => { - t.deepEqual(result, expected, 'should equal'); - t.end(); - after(); - }) - .catch(console.error); + const {body} = await request.get(`/json/modules.json`, { + type: 'json', + options, }); + + t.deepEqual(body, expected); + t.end(); }); -test('cloudcmd: modules: wrong route', (t) => { +test('cloudcmd: modules: wrong route', async (t) => { const modules = { - hello: 'world' + hello: 'world', }; - const expected = Object.assign({}, localModules, modules); + const options = { + modules, + }; - before({modules}, (port, after) => { - get(`http://localhost:${port}/package.json`) - .then(warp(_pullout, 'string')) - .then(JSON.parse) - .then((result) => { - t.notDeepEqual(result, expected, 'should not be equal'); - t.end(); - after(); - }) - .catch(console.error); + const expected = { + ...localModules, + ...modules, + }; + + const {body} = await request.get(`/package.json`, { + type: 'json', + options, }); + + t.notDeepEqual(body, expected, 'should not be equal'); + t.end(); }); test('cloudcmd: modules: no', (t) => { const fn = modulas(); const url = '/json/modules.json'; - const send = sinon.stub(); + const send = stub(); fn({url}, { - send + send, }); - t.ok(send.calledWith(localModules), 'should have been called with modules'); + t.calledWith(send, [localModules], 'should have been called with modules'); t.end(); }); - diff --git a/test/server/root.js b/test/server/root.js deleted file mode 100644 index 5230b0ed..00000000 --- a/test/server/root.js +++ /dev/null @@ -1,68 +0,0 @@ -'use strict'; - -const path = require('path'); - -const test = require('tape'); - -const diff = require('sinon-called-with-diff'); -const sinon = diff(require('sinon')); - -const dir = path.join(__dirname, '..', '..', 'server'); -const pathConfig = path.join(dir, 'config'); -const pathRoot = `${dir}/root`; - -const clean = (name) => { - delete require.cache[require.resolve(name)]; -}; - -test('cloudcmd: root: config', (t) => { - clean(pathRoot); - - const config = sinon.stub().returns(false); - const originalConfig = stub(pathConfig, config); - const root = require(pathRoot); - - root('hello'); - - t.ok(config.calledWith('root'), 'should call config'); - - stub(pathConfig, originalConfig); - t.end(); -}); - -test('cloudcmd: root: mellow', (t) => { - clean(pathRoot); - - const config = sinon.stub().returns(''); - const pathToWin = sinon.stub(); - - const mellow = { - pathToWin - }; - - const originalMellow = stub('mellow', mellow); - const originalConfig = stub(pathConfig, config); - - const root = require(pathRoot); - const dir = 'hello'; - const dirRoot = '/'; - - root(dir); - - t.ok(pathToWin.calledWith(dir, dirRoot), 'should call mellow'); - - stub('mellow', originalMellow); - stub(pathConfig, originalConfig); - - t.end(); -}); - -function stub(name, data) { - const resolved = require.resolve(name); - const {exports} = require.cache[resolved]; - - require.cache[resolved].exports = data; - - return exports; -} - diff --git a/test/server/route.js b/test/server/route.js deleted file mode 100644 index ab780f40..00000000 --- a/test/server/route.js +++ /dev/null @@ -1,87 +0,0 @@ -'use strict'; - -const test = require('tape'); -const promisify = require('es6-promisify'); -const pullout = require('pullout'); -const request = require('request'); - -const route = require('../../server/route'); -const before = require('../before'); - -const warp = (fn, ...a) => (...b) => fn(...b, ...a); -const _pullout = promisify(pullout); - -const get = promisify((url, fn) => { - fn(null, request(url)); -}); - -const getStr = (url) => { - return get(url) - .then(warp(_pullout, 'string')) - .catch(console.log); -}; - - -test('cloudcmd: route: no args', (t) => { - t.throws(route, /req could not be empty!/, 'should throw when no args'); - t.end(); -}); - -test('cloudcmd: route: no res', (t) => { - const fn = () => route({}); - - t.throws(fn, /res could not be empty!/, 'should throw when no res'); - t.end(); -}); - -test('cloudcmd: route: no next', (t) => { - const fn = () => route({}, {}); - - t.throws(fn, /next should be function!/, 'should throw when no next'); - t.end(); -}); - -test('cloudcmd: route: buttons: no console', (t) => { - const config = { - console: false - }; - - before({config}, (port, after) => { - getStr(`http://localhost:${port}/`) - .then((result) => { - t.ok(/icon-console none/.test(result), 'should hide console'); - t.end(); - after(); - }); - }); -}); - -test('cloudcmd: route: buttons: no terminal', (t) => { - const config = { - terminal: false - }; - - before({config}, (port, after) => { - getStr(`http://localhost:${port}/`) - .then((result) => { - t.ok(/icon-terminal none/.test(result), 'should hide terminal'); - t.end(); - after(); - }); - }); -}); - -test('cloudcmd: route: buttons: no config', (t) => { - const config = { - configDialog: false - }; - - before({config}, (port, after) => { - getStr(`http://localhost:${port}/`) - .then((result) => { - t.ok(/icon-config none/.test(result), 'should hide config'); - t.end(); - after(); - }); - }); -}); diff --git a/test/server/terminal.js b/test/server/terminal.js deleted file mode 100644 index 42813006..00000000 --- a/test/server/terminal.js +++ /dev/null @@ -1,73 +0,0 @@ -'use strict'; - -const test = require('tape'); -const diff = require('sinon-called-with-diff'); -const sinon = diff(require('sinon')); - -const configPath = '../../server/config'; -const terminalPath = '../../server/terminal'; - - -test('cloudcmd: terminal: disabled', (t) => { - clean(terminalPath); - stub(configPath, () => { - return false; - }); - - const terminal = require('../../server/terminal'); - - const fn = terminal(); - - t.notOk(fn(), 'should return noop'); - - clean(configPath); - require(configPath); - - t.end(); -}); - -test('cloudcmd: terminal: disabled: listen', (t) => { - clean(terminalPath); - stub(configPath, () => false); - - const terminal = require(terminalPath); - - const fn = terminal().listen(); - - t.notOk(fn, 'should return noop'); - - clean(configPath); - require(configPath); - - t.end(); -}); - -test('cloudcmd: terminal: enabled', (t) => { - const {log} = console; - console.log = sinon.stub(); - - clean(terminalPath); - stub(configPath, () => true); - - const terminal = require(terminalPath); - terminal(); - - const msg = 'cloudcmd --terminal: path must be a string'; - - t.ok(console.log.calledWith(msg), 'should call exit'); - - console.log = log; - - clean(configPath); - - t.end(); -}); - -function clean(path) { - delete require.cache[require.resolve(path)]; -} - -function stub(name, fn) { - require.cache[require.resolve(name)].exports = fn; -} - diff --git a/test/server/validate.js b/test/server/validate.js deleted file mode 100644 index 676588aa..00000000 --- a/test/server/validate.js +++ /dev/null @@ -1,116 +0,0 @@ -'use strict'; - -const fs = require('fs'); - -const test = require('tape'); -const diff = require('sinon-called-with-diff'); -const sinon = diff(require('sinon')); - -const before = require('../before'); -const dir = '../..'; - -const validatePath = `${dir}/server/validate`; -const exitPath = `${dir}/server/exit`; - -const validate = require(validatePath); - -test('validate: root: bad', (t) => { - const config = { - root: Math.random() - }; - const fn = () => { - before({config}, (port, after) => { - t.fail('should not create server'); - after(); - t.end(); - }); - }; - - t.throws(fn, /dir should be a string/, 'should throw'); - t.end(); -}); - -test('validate: root: /', (t) => { - const fn = sinon.stub(); - validate.root('/', fn); - - t.notOk(fn.called, 'should not call fn'); - t.end(); -}); - -test('validate: root: /home', (t) => { - const fn = sinon.stub(); - - validate.root('/home', (...args) => { - fn(...args); - - t.ok(fn.calledWith('root:', '/home'), 'should not call fn'); - t.end(); - }); -}); - -test('validate: root: stat', (t) => { - const fn = sinon.stub(); - const {stat} = fs; - - const error = 'ENOENT'; - fs.stat = (dir, fn) => fn(Error(error)); - - clean(); - require(exitPath); - stub(exitPath, fn); - - const {root} = require(validatePath); - - root('hello', fn); - - const msg = 'cloudcmd --root: %s'; - t.ok(fn.calledWith(msg, error), 'should call fn'); - - fs.stat = stat; - t.end(); -}); - -test('validate: packer: not valid', (t) => { - const fn = sinon.stub(); - - clean(); - require(exitPath); - stub(exitPath, fn); - - const {packer} = require(validatePath); - const msg = 'cloudcmd --packer: could be "tar" or "zip" only'; - - packer('hello'); - - t.ok(fn.calledWith(msg), 'should call fn'); - - t.end(); -}); - -test('validate: editor: not valid', (t) => { - const fn = sinon.stub(); - - clean(); - require(exitPath); - stub(exitPath, fn); - - const {editor} = require(validatePath); - const msg = 'cloudcmd --editor: could be "dword", "edward" or "deepword" only'; - - editor('hello'); - - t.ok(fn.calledWith(msg), 'should call fn'); - - t.end(); -}); - -function clean() { - delete require.cache[require.resolve(validatePath)]; - delete require.cache[require.resolve(exitPath)]; -} - -function stub(name, fn) { - require.cache[require.resolve(name)].exports = fn; -} - diff --git a/test/static.js b/test/static.js index b012cd46..0f0da5cb 100644 --- a/test/static.js +++ b/test/static.js @@ -1,111 +1,152 @@ -'use strict'; +import {Buffer} from 'node:buffer'; +import {serveOnce} from 'serve-once'; +import test from 'supertape'; +import criton from 'criton'; +import {cloudcmd} from '#server/cloudcmd'; -const test = require('tape'); -const promisify = require('es6-promisify'); -const pullout = require('pullout'); -const request = require('request'); +const config = { + auth: false, +}; -const before = require('./before'); - -const warp = (fn, ...a) => (...b) => fn(...b, ...a); - -const _pullout = promisify(pullout); - -const get = promisify((url, fn) => { - fn(null, request(url)); +const {request} = serveOnce(cloudcmd, { + config, }); -test('cloudcmd: static', (t) => { - before({}, (port, after) => { - const name = 'package.json'; - - get(`http://localhost:${port}/${name}`) - .then(warp(_pullout, 'string')) - .then(JSON.parse) - .then((json) => { - t.equal(json.name, 'cloudcmd', 'should download file'); - t.end(); - after(); - }) - .catch((error) => { - console.log(error); - }); +const configFn = cloudcmd.createConfigManager(); + +test('cloudcmd: static', async (t) => { + const name = 'package.json'; + const {body} = await request.get(`/${name}`, { + type: 'json', }); -}); - -test('cloudcmd: static: not found', (t) => { - before({}, (port, after) => { - const name = Math.random(); - get(`http://localhost:${port}/${name}`) - .then((res) => { - res.on('response', (res) => { - t.equal(res.statusCode, 404, 'should return 404'); - }); - res.on('end', () => { - t.end(); - after(); - }); - }) - .catch((error) => { - console.log(error); - }); - }); -}); - -test('cloudcmd: prefix: wrong', (t) => { - const prefix = '/hello'; - const config = {prefix}; - before({config}, (port, after) => { - const name = Math.random(); - - get(`http://localhost:${port}/${name}`) - .then((res) => { - res.on('response', ({statusCode}) => { - t.equal(statusCode, 404, 'should return 404'); - }); - res.on('end', () => { - t.end(); - after(); - }); - }) - .catch(console.error); - }); + t.equal(body.name, 'cloudcmd', 'should download file'); + t.end(); }); -test('cloudcmd: /cloudcmd.js', (t) => { - before({}, (port, after) => { - const name = 'cloudcmd.js'; - - get(`http://localhost:${port}/${name}`) - .then((res) => { - res.on('response', ({statusCode}) => { - t.equal(statusCode, 200, 'should return OK'); - }); - res.on('end', () => { - t.end(); - after(); - }); - }) - .catch(console.error); - }); +test('cloudcmd: static: not found', async (t) => { + const name = Math.random(); + const {status} = await request.get(`/${name}`); + + t.equal(status, 404, 'should return 404'); + t.end(); }); -test('cloudcmd: /logout', (t) => { - before({}, (port, after) => { - const name = 'logout'; - - get(`http://localhost:${port}/${name}`) - .then((res) => { - res.on('response', ({statusCode}) => { - t.equal(statusCode, 401, 'should return 401'); - }); - res.on('end', () => { - t.end(); - after(); - }); - }) - .catch(console.error); +test('cloudcmd: prefix: wrong', async (t) => { + const originalPrefix = configFn('prefix'); + const config = { + prefix: '/hello', + }; + + const options = { + config, + }; + + const name = Math.random(); + + const {status} = await request.get(`/${name}`, { + options, }); + + configFn('prefix', originalPrefix); + + t.equal(status, 404, 'should return 404'); + t.end(); }); +test('cloudcmd: /cloudcmd.js', async (t) => { + const name = 'cloudcmd.js'; + const {status} = await request.get(`/${name}`); + + t.equal(status, 200, 'should return OK'); + t.end(); +}); + +test('cloudcmd: /cloudcmd.js: auth: access denied', async (t) => { + const name = 'cloudcmd.js'; + const config = { + auth: true, + }; + + const options = { + config, + }; + + const {status} = await request.get(`/${name}`, { + options, + }); + + t.equal(status, 401, 'should return auth'); + t.end(); +}); + +test('cloudcmd: /cloudcmd.js: auth: no password', async (t) => { + const name = 'cloudcmd.js'; + const username = 'hello'; + + const config = { + auth: true, + username, + }; + + const options = { + config, + }; + + const encoded = Buffer + .from(`${username}:`) + .toString('base64'); + + const authorization = `Basic ${encoded}`; + + const {status} = await request.get(`/${name}`, { + headers: { + authorization, + }, + options, + }); + + t.equal(status, 401, 'should return auth'); + t.end(); +}); + +test('cloudcmd: /cloudcmd.js: auth: access granted', async (t) => { + const name = 'cloudcmd.js'; + const username = 'hello'; + const password = 'world'; + const algo = configFn('algo'); + + const config = { + auth: true, + username, + password: criton(password, algo), + }; + + const options = { + config, + }; + + const encoded = Buffer + .from(`${username}:${password}`) + .toString('base64'); + + const authorization = `Basic ${encoded}`; + + const {status} = await request.get(`/${name}`, { + headers: { + authorization, + }, + options, + }); + + t.equal(status, 200, 'should return auth'); + t.end(); +}); + +test('cloudcmd: /logout', async (t) => { + const name = 'logout'; + const {status} = await request.get(`/${name}`); + + t.equal(status, 401, 'should return 401'); + t.end(); +}); diff --git a/tmpl/config.hbs b/tmpl/config.hbs index 05824506..6002cd8b 100644 --- a/tmpl/config.hbs +++ b/tmpl/config.hbs @@ -1,29 +1,31 @@ -
      -
    • +
        +
      • -
      • +
      • + title="Username" + autocomplete="username">
      • -
      • +
      • + title="Password" + autocomplete="current-password">
      • -
      • +
      • -
      • +
      • -
      • +
      • + +
      • +
      • + +
      • +
      • -
      • +
      • -
      • - +
      • + +
      • +
      • -
      • +
      • -
      • - -
      • -
      • +
      • -
      • +
      • -
      • +
      • -
      • +
      • -
      • +
      • + +
      • +
      • -
      • - +
      • -
      • +
      • -
      • +
      • -
      • +
      • -
      +
    • + +
    • +
    • + +
    • +
    \ No newline at end of file diff --git a/tmpl/fs/file.hbs b/tmpl/fs/file.hbs index 0eaa6887..8b50494f 100644 --- a/tmpl/fs/file.hbs +++ b/tmpl/fs/file.hbs @@ -2,6 +2,7 @@ {{ name }} {{ size }} + {{ time }} {{ date }} {{ owner }} {{ mode }} diff --git a/tmpl/fs/path.hbs b/tmpl/fs/path.hbs index a985a7ef..b1a5e148 100644 --- a/tmpl/fs/path.hbs +++ b/tmpl/fs/path.hbs @@ -1 +1 @@ -
    {{ path }}
    \ No newline at end of file +
    {{ path }}
    \ No newline at end of file diff --git a/webpack.config.js b/webpack.config.js index c86cc703..5d684391 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -1,95 +1,10 @@ -'use strict'; +import {merge} from 'webpack-merge'; +import * as htmlConfig from './.webpack/html.js'; +import cssConfig from './.webpack/css.js'; +import jsConfig from './.webpack/js.js'; -const path = require('path'); -const webpack = require('webpack'); -const {optimize} = webpack; -const {UglifyJsPlugin} = optimize; - -const dir = './client'; -const dirModules = './client/modules'; -const modules = './modules'; - -const {env} = process; -const isDev = env.NODE_ENV === 'development'; - -const dist = path.resolve(__dirname, 'dist'); -const distDev = path.resolve(__dirname, 'dist-dev'); -const devtool = isDev ? 'eval' : 'source-map'; -const notEmpty = (a) => a; -const clean = (array) => array.filter(notEmpty); - -const plugins = clean([ - !isDev && new UglifyJsPlugin({ - sourceMap: true, - comments: false, - }), - new webpack.optimize.CommonsChunkPlugin({ - name: 'cloudcmd', - filename: 'cloudcmd.js', - }), +export default merge([ + jsConfig, + htmlConfig, + cssConfig, ]); - -const loaders = clean([ - !isDev && { - test: /\.js$/, - exclude: /node_modules/, - loader: 'babel-loader', - } -]); - -module.exports = { - devtool, - entry: { - cloudcmd: `${dir}/cloudcmd.js`, - [modules + '/edit']: `${dirModules}/edit.js`, - [modules + '/edit-file']: `${dirModules}/edit-file.js`, - [modules + '/edit-file-vim']: `${dirModules}/edit-file-vim.js`, - [modules + '/edit-names']: `${dirModules}/edit-names.js`, - [modules + '/menu']: `${dirModules}/menu.js`, - [modules + '/view']: `${dirModules}/view.js`, - [modules + '/help']: `${dirModules}/help.js`, - [modules + '/markdown']: `${dirModules}/markdown.js`, - [modules + '/config']: `${dirModules}/config.js`, - [modules + '/contact']: `${dirModules}/contact.js`, - [modules + '/upload']: `${dirModules}/upload.js`, - [modules + '/operation']: `${dirModules}/operation/index.js`, - [modules + '/konsole']: `${dirModules}/konsole.js`, - [modules + '/terminal']: `${dirModules}/terminal.js`, - [modules + '/cloud']: `${dirModules}/cloud.js`, - [modules + '/polyfill']: `${dirModules}/polyfill.js`, - }, - output: { - filename: '[name].js', - path: isDev ? distDev : dist, - pathinfo: isDev, - libraryTarget: 'var', - devtoolModuleFilenameTemplate, - }, - plugins, - externals: [ - externals - ], - module: { - loaders, - }, -}; - -function externals(context, request, fn) { - if (!isDev) - return fn(); - - const list = [ - 'es6-promise', - ]; - - if (list.includes(request)) - return fn(null, request); - - fn(); -} - -function devtoolModuleFilenameTemplate(info) { - const resource = info.absoluteResourcePath.replace(__dirname + path.sep, ''); - return `file://cloudcmd/${resource}`; -} -