diff --git a/.dockerignore b/.dockerignore index 9f0b60f1..d1f98f1b 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,3 +1,4 @@ * !docker/* +!docker_config.json !filebrowser \ No newline at end of file diff --git a/.github/workflows/main.yaml b/.github/workflows/main.yaml index 42ae7c60..b2a59f77 100644 --- a/.github/workflows/main.yaml +++ b/.github/workflows/main.yaml @@ -24,7 +24,7 @@ jobs: - uses: actions/checkout@v2 - uses: actions/setup-go@v2 with: - go-version: 1.20.1 + go-version: 1.20.6 - run: make lint-backend lint-commits: runs-on: ubuntu-latest @@ -57,7 +57,7 @@ jobs: - uses: actions/checkout@v2 - uses: actions/setup-go@v2 with: - go-version: 1.20.1 + go-version: 1.20.6 - run: make test-backend test: runs-on: ubuntu-latest @@ -76,7 +76,7 @@ jobs: fetch-depth: 0 - uses: actions/setup-go@v2 with: - go-version: 1.20.1 + go-version: 1.20.6 - uses: actions/setup-node@v2 with: node-version: '16' diff --git a/.golangci.yml b/.golangci.yml index c946c73a..832114fd 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -54,7 +54,6 @@ linters: enable: - bodyclose - deadcode - - depguard - dogsled - dupl - errcheck diff --git a/.goreleaser.yml b/.goreleaser.yml index a697179f..9ca03ac4 100644 --- a/.goreleaser.yml +++ b/.goreleaser.yml @@ -57,6 +57,7 @@ dockers: - "filebrowser/filebrowser:v{{ .Major }}-amd64" extra_files: - docker_config.json + - healthcheck.sh - dockerfile: Dockerfile use: buildx @@ -75,6 +76,7 @@ dockers: - "filebrowser/filebrowser:v{{ .Major }}-arm64" extra_files: - docker_config.json + - healthcheck.sh - dockerfile: Dockerfile use: buildx @@ -94,6 +96,7 @@ dockers: - "filebrowser/filebrowser:v{{ .Major }}-armv6" extra_files: - docker_config.json + - healthcheck.sh - dockerfile: Dockerfile use: buildx @@ -113,6 +116,7 @@ dockers: - "filebrowser/filebrowser:v{{ .Major }}-armv7" extra_files: - docker_config.json + - healthcheck.sh ## s6 based docker images - dockerfile: Dockerfile.s6 @@ -150,82 +154,35 @@ dockers: - "filebrowser/filebrowser:v{{ .Major }}-arm64-s6" extra_files: - docker/root - - - dockerfile: Dockerfile.s6.armhf - use: buildx - build_flag_templates: - - "--pull" - - "--label=org.opencontainers.image.created={{.Date}}" - - "--label=org.opencontainers.image.name={{.ProjectName}}" - - "--label=org.opencontainers.image.revision={{.FullCommit}}" - - "--label=org.opencontainers.image.version={{.Version}}" - - "--label=org.opencontainers.image.source={{.GitURL}}" - - "--platform=linux/arm/v6" - goos: linux - goarch: arm - goarm: '6' - image_templates: - - "filebrowser/filebrowser:{{ .Tag }}-armv6-s6" - - "filebrowser/filebrowser:v{{ .Major }}-armv6-s6" - extra_files: - - docker/root - - - dockerfile: Dockerfile.s6.armhf - use: buildx - build_flag_templates: - - "--pull" - - "--label=org.opencontainers.image.created={{.Date}}" - - "--label=org.opencontainers.image.name={{.ProjectName}}" - - "--label=org.opencontainers.image.revision={{.FullCommit}}" - - "--label=org.opencontainers.image.version={{.Version}}" - - "--label=org.opencontainers.image.source={{.GitURL}}" - - "--platform=linux/arm/v7" - goos: linux - goarch: arm - goarm: '7' - image_templates: - - "filebrowser/filebrowser:{{ .Tag }}-armv7-s6" - - "filebrowser/filebrowser:v{{ .Major }}-armv7-s6" - extra_files: - - docker/root docker_manifests: - name_template: "filebrowser/filebrowser:latest" image_templates: - "filebrowser/filebrowser:{{ .Tag }}-amd64" - "filebrowser/filebrowser:{{ .Tag }}-arm64" - - "filebrowser/filebrowser:{{ .Tag }}-armv6" - "filebrowser/filebrowser:{{ .Tag }}-armv7" - name_template: "filebrowser/filebrowser:{{ .Tag }}" image_templates: - "filebrowser/filebrowser:{{ .Tag }}-amd64" - "filebrowser/filebrowser:{{ .Tag }}-arm64" - - "filebrowser/filebrowser:{{ .Tag }}-armv6" - "filebrowser/filebrowser:{{ .Tag }}-armv7" - name_template: "filebrowser/filebrowser:v{{ .Major }}" image_templates: - "filebrowser/filebrowser:v{{ .Major }}-amd64" - "filebrowser/filebrowser:v{{ .Major }}-arm64" - - "filebrowser/filebrowser:v{{ .Major }}-armv6" - "filebrowser/filebrowser:v{{ .Major }}-armv7" ## s6 image manifests - name_template: "filebrowser/filebrowser:s6" image_templates: - "filebrowser/filebrowser:{{ .Tag }}-amd64-s6" - "filebrowser/filebrowser:{{ .Tag }}-arm64-s6" - - "filebrowser/filebrowser:{{ .Tag }}-armv6-s6" - - "filebrowser/filebrowser:{{ .Tag }}-armv7-s6" - name_template: "filebrowser/filebrowser:{{ .Tag }}-s6" image_templates: - "filebrowser/filebrowser:{{ .Tag }}-amd64-s6" - "filebrowser/filebrowser:{{ .Tag }}-arm64-s6" - - "filebrowser/filebrowser:{{ .Tag }}-armv6-s6" - - "filebrowser/filebrowser:{{ .Tag }}-armv7-s6" - name_template: "filebrowser/filebrowser:v{{ .Major }}-s6" image_templates: - "filebrowser/filebrowser:v{{ .Major }}-amd64-s6" - "filebrowser/filebrowser:v{{ .Major }}-arm64-s6" - - "filebrowser/filebrowser:v{{ .Major }}-armv6-s6" - - "filebrowser/filebrowser:v{{ .Major }}-armv7-s6" brews: - name: filebrowser tap: diff --git a/CHANGELOG.md b/CHANGELOG.md index ca897439..3bb2d07e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,58 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +### [2.24.1](https://github.com/filebrowser/filebrowser/compare/v2.24.0...v2.24.1) (2023-07-31) + + +### Bug Fixes + +* add directory creation code to partial upload handler ([#2575](https://github.com/filebrowser/filebrowser/issues/2575)) ([#2580](https://github.com/filebrowser/filebrowser/issues/2580)) ([912f27a](https://github.com/filebrowser/filebrowser/commit/912f27a9e3286ee4bf2a27b366a1d35b3b55799c)) +* resolved CSS rendering issue in Chrome browser ([#2582](https://github.com/filebrowser/filebrowser/issues/2582)) ([2a4a46c](https://github.com/filebrowser/filebrowser/commit/2a4a46c61a5d5376bea65b28d0eb6a7ec2fdf4e5)) + + +### Build + +* **backend:** upgrade golangci-lint to v1.53.3 ([efd41cc](https://github.com/filebrowser/filebrowser/commit/efd41cc4c147b8d2d5e61fb2642df8d934f49362)) + +## [2.24.0](https://github.com/filebrowser/filebrowser/compare/v2.23.0...v2.24.0) (2023-07-29) + + +### Features + +* add a healthcheck script that works with a dynamic port ([#2510](https://github.com/filebrowser/filebrowser/issues/2510)) ([ff4375c](https://github.com/filebrowser/filebrowser/commit/ff4375cf6ce849459889f892dd91304703c52dcd)) +* add a new setting that disables the display of the disk usage ([#2136](https://github.com/filebrowser/filebrowser/issues/2136)) ([428c1c6](https://github.com/filebrowser/filebrowser/commit/428c1c606d1b858ed0eb58b7c31f570bc6a9b792)) +* add Hungarian translation ([#2232](https://github.com/filebrowser/filebrowser/issues/2232)) ([11e9202](https://github.com/filebrowser/filebrowser/commit/11e92021607e12efff9fb2d5c8728483eee31199)) +* add option to copy download links from shares ([#2442](https://github.com/filebrowser/filebrowser/issues/2442)) ([a4ef02a](https://github.com/filebrowser/filebrowser/commit/a4ef02a47b53742a0ac1f639563b0c67116619c8)) +* integrate tus.io for resumable and chunked uploads ([#2145](https://github.com/filebrowser/filebrowser/issues/2145)) ([7b35815](https://github.com/filebrowser/filebrowser/commit/7b35815754690540f76e3ffe114eedb47cfd5c7e)) + + +### Bug Fixes + +* added an early return on non-existent items ([#2571](https://github.com/filebrowser/filebrowser/issues/2571)) ([2744f7d](https://github.com/filebrowser/filebrowser/commit/2744f7d5b9106c7c2eec69010e550e0939c23d80)) +* build on FreeBSD and non-Linux platforms ([#2332](https://github.com/filebrowser/filebrowser/issues/2332)) ([60d1e2d](https://github.com/filebrowser/filebrowser/commit/60d1e2d2913cce591fbee97337bd58310480269f)) +* error while using fallback of dir move ([#2349](https://github.com/filebrowser/filebrowser/issues/2349)) ([853ec90](https://github.com/filebrowser/filebrowser/commit/853ec906efbdee9013c5d34ed1d9b8fee88a6b29)) +* filter ANSI color for shell ([#2529](https://github.com/filebrowser/filebrowser/issues/2529)) ([9bcfa90](https://github.com/filebrowser/filebrowser/commit/9bcfa900f904fe683c8d9085947f57932bfe22a0)) +* goreleaser docker build ([051104b](https://github.com/filebrowser/filebrowser/commit/051104bfa061720d4402c612e61bb0fc80a946bf)) +* solve broken Docker build with alpine image ([#2486](https://github.com/filebrowser/filebrowser/issues/2486)) ([b8ee340](https://github.com/filebrowser/filebrowser/commit/b8ee3404ee480ef1fd439543ab6d46f318ff3647)) +* video preview click next or prev button subtitles not update ([#2423](https://github.com/filebrowser/filebrowser/issues/2423)) ([6744cd4](https://github.com/filebrowser/filebrowser/commit/6744cd47cef87e3a76a2190bdf123b6c2197fe6f)) +* xss vulnerability in /api/raw ([#2570](https://github.com/filebrowser/filebrowser/issues/2570)) ([#2572](https://github.com/filebrowser/filebrowser/issues/2572)) ([b508ac3](https://github.com/filebrowser/filebrowser/commit/b508ac3d4f7f0f75d6b49c99bdc661a6d2173f30)) + + +### Refactorings + +* replace username old focus logic with the autofocus attribute ([#2223](https://github.com/filebrowser/filebrowser/issues/2223)) ([2b2c108](https://github.com/filebrowser/filebrowser/commit/2b2c1085fb50ad68612ad438e527fd316d8aafee)) + + +### Build + +* **backend:** bump go version to 1.20.1 ([fa95299](https://github.com/filebrowser/filebrowser/commit/fa95299df4aa7e4c54d872e786a91ded5bdb01c1)) +* **backend:** bump go version to 1.20.6 ([9bf6b85](https://github.com/filebrowser/filebrowser/commit/9bf6b856e5411e635ba9102ff53dfe927183848e)) +* **deps-dev:** bump word-wrap from 1.2.3 to 1.2.4 in /frontend ([#2556](https://github.com/filebrowser/filebrowser/issues/2556)) ([bb34862](https://github.com/filebrowser/filebrowser/commit/bb3486286c0da112ad97456ad258ddcdfe17c154)) +* **deps:** bump minimatch from 3.0.4 to 3.1.2 in /tools ([#2561](https://github.com/filebrowser/filebrowser/issues/2561)) ([a664ba1](https://github.com/filebrowser/filebrowser/commit/a664ba1f9df45c7f6d03492c85466c5aa07c740e)) +* **deps:** bump semver from 5.7.1 to 5.7.2 in /tools ([#2546](https://github.com/filebrowser/filebrowser/issues/2546)) ([c2f1423](https://github.com/filebrowser/filebrowser/commit/c2f1423c02e4736f4c243c3164dc671879e065f3)) +* remove armv6-s6 docker target ([66dfbb3](https://github.com/filebrowser/filebrowser/commit/66dfbb303cf792b7b01650d0125d948ab8d81ddd)) +* remove armv7-s6 docker target ([4d77ce0](https://github.com/filebrowser/filebrowser/commit/4d77ce0955644551f891af3e4098c37e9cc37e40)) + ## [2.23.0](https://github.com/filebrowser/filebrowser/compare/v2.22.4...v2.23.0) (2022-11-05) diff --git a/Dockerfile b/Dockerfile index ab826705..40a91a06 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,10 +1,14 @@ FROM alpine:latest RUN apk --update add ca-certificates \ mailcap \ - curl + curl \ + jq + +COPY healthcheck.sh /healthcheck.sh +RUN chmod +x /healthcheck.sh # Make the script executable HEALTHCHECK --start-period=2s --interval=5s --timeout=3s \ - CMD curl -f http://localhost/health || exit 1 + CMD /healthcheck.sh || exit 1 VOLUME /srv EXPOSE 80 diff --git a/Dockerfile.s6 b/Dockerfile.s6 index 3208b057..233feb22 100644 --- a/Dockerfile.s6 +++ b/Dockerfile.s6 @@ -1,4 +1,4 @@ -FROM ghcr.io/linuxserver/baseimage-alpine:3.14 +FROM ghcr.io/linuxserver/baseimage-alpine:3.17 RUN apk --update add ca-certificates \ mailcap \ diff --git a/Dockerfile.s6.aarch64 b/Dockerfile.s6.aarch64 index 84319607..d7f3dcee 100644 --- a/Dockerfile.s6.aarch64 +++ b/Dockerfile.s6.aarch64 @@ -1,4 +1,4 @@ -FROM ghcr.io/linuxserver/baseimage-alpine:arm64v8-3.14 +FROM ghcr.io/linuxserver/baseimage-alpine:arm64v8-3.17 RUN apk --update add ca-certificates \ mailcap \ diff --git a/Dockerfile.s6.armhf b/Dockerfile.s6.armhf index 5aa9af16..17bd1def 100644 --- a/Dockerfile.s6.armhf +++ b/Dockerfile.s6.armhf @@ -1,4 +1,4 @@ -FROM ghcr.io/linuxserver/baseimage-alpine:arm32v7-3.14 +FROM ghcr.io/linuxserver/baseimage-alpine:arm32v7-3.17 RUN apk --update add ca-certificates \ mailcap \ diff --git a/cmd/docs.go b/cmd/docs.go index 9ebb9573..ff104b1e 100644 --- a/cmd/docs.go +++ b/cmd/docs.go @@ -98,12 +98,12 @@ func generateMarkdown(cmd *cobra.Command, w io.Writer) { buf.WriteString(long + "\n\n") if cmd.Runnable() { - buf.WriteString(fmt.Sprintf("```\n%s\n```\n\n", cmd.UseLine())) + _, _ = fmt.Fprintf(buf, "```\n%s\n```\n\n", cmd.UseLine()) } if len(cmd.Example) > 0 { buf.WriteString("## Examples\n\n") - buf.WriteString(fmt.Sprintf("```\n%s\n```\n\n", cmd.Example)) + _, _ = fmt.Fprintf(buf, "```\n%s\n```\n\n", cmd.Example) } printOptions(buf, cmd) diff --git a/cmd/root.go b/cmd/root.go index 4674d168..dc8b57e8 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -334,9 +334,13 @@ func quickSetup(flags *pflag.FlagSet, d pythonData) { }, AuthMethod: "", Branding: settings.Branding{}, - Commands: nil, - Shell: nil, - Rules: nil, + Tus: settings.Tus{ + ChunkSize: settings.DefaultTusChunkSize, + RetryCount: settings.DefaultTusRetryCount, + }, + Commands: nil, + Shell: nil, + Rules: nil, } var err error diff --git a/files/file.go b/files/file.go index 3e3214dd..ce157abb 100644 --- a/files/file.go +++ b/files/file.go @@ -25,6 +25,9 @@ import ( "github.com/filebrowser/filebrowser/v2/rules" ) +const PermFile = 0664 +const PermDir = 0755 + // FileInfo describes a file. type FileInfo struct { *Listing diff --git a/fileutils/file.go b/fileutils/file.go index 0f782cf5..81aeffeb 100644 --- a/fileutils/file.go +++ b/fileutils/file.go @@ -17,12 +17,12 @@ func MoveFile(fs afero.Fs, src, dst string) error { return nil } // fallback - err := CopyFile(fs, src, dst) + err := Copy(fs, src, dst) if err != nil { _ = fs.Remove(dst) return err } - if err := fs.Remove(src); err != nil { + if err := fs.RemoveAll(src); err != nil { return err } return nil diff --git a/frontend/package-lock.json b/frontend/package-lock.json index cbf1136b..295a369e 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -21,6 +21,7 @@ "noty": "^3.2.0-beta", "pretty-bytes": "^6.0.0", "qrcode.vue": "^1.7.0", + "tus-js-client": "^3.1.0", "utif": "^3.1.0", "vue": "^2.6.10", "vue-async-computed": "^3.9.0", @@ -3315,10 +3316,9 @@ } }, "node_modules/buffer-from": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", - "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", - "dev": true + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" }, "node_modules/buffer-indexof": { "version": "1.1.1", @@ -4088,6 +4088,15 @@ "integrity": "sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w==", "dev": true }, + "node_modules/combine-errors": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/combine-errors/-/combine-errors-3.0.3.tgz", + "integrity": "sha512-C8ikRNRMygCwaTx+Ek3Yr+OuZzgZjduCOfSQBjbM8V3MfgcjSTeto/GXP6PAwKvJz/v15b7GHZvx5rOlczFw/Q==", + "dependencies": { + "custom-error-instance": "2.1.1", + "lodash.uniqby": "4.5.0" + } + }, "node_modules/combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", @@ -5042,6 +5051,11 @@ "node": ">=0.10.0" } }, + "node_modules/custom-error-instance": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/custom-error-instance/-/custom-error-instance-2.1.1.tgz", + "integrity": "sha512-p6JFxJc3M4OTD2li2qaHkDCw9SfMw82Ldr6OC9Je1aXiGfhx2W8p3GaoeaGrPJTUN9NirTM/KTxHWMUdR1rsUg==" + }, "node_modules/cyclist": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-1.0.1.tgz", @@ -7065,8 +7079,7 @@ "node_modules/graceful-fs": { "version": "4.2.6", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz", - "integrity": "sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==", - "dev": true + "integrity": "sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==" }, "node_modules/gzip-size": { "version": "5.1.1", @@ -8847,6 +8860,46 @@ "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", "dev": true }, + "node_modules/lodash._baseiteratee": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/lodash._baseiteratee/-/lodash._baseiteratee-4.7.0.tgz", + "integrity": "sha512-nqB9M+wITz0BX/Q2xg6fQ8mLkyfF7MU7eE+MNBNjTHFKeKaZAPEzEg+E8LWxKWf1DQVflNEn9N49yAuqKh2mWQ==", + "dependencies": { + "lodash._stringtopath": "~4.8.0" + } + }, + "node_modules/lodash._basetostring": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/lodash._basetostring/-/lodash._basetostring-4.12.0.tgz", + "integrity": "sha512-SwcRIbyxnN6CFEEK4K1y+zuApvWdpQdBHM/swxP962s8HIxPO3alBH5t3m/dl+f4CMUug6sJb7Pww8d13/9WSw==" + }, + "node_modules/lodash._baseuniq": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash._baseuniq/-/lodash._baseuniq-4.6.0.tgz", + "integrity": "sha512-Ja1YevpHZctlI5beLA7oc5KNDhGcPixFhcqSiORHNsp/1QTv7amAXzw+gu4YOvErqVlMVyIJGgtzeepCnnur0A==", + "dependencies": { + "lodash._createset": "~4.0.0", + "lodash._root": "~3.0.0" + } + }, + "node_modules/lodash._createset": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/lodash._createset/-/lodash._createset-4.0.3.tgz", + "integrity": "sha512-GTkC6YMprrJZCYU3zcqZj+jkXkrXzq3IPBcF/fIPpNEAB4hZEtXU8zp/RwKOvZl43NUmwDbyRk3+ZTbeRdEBXA==" + }, + "node_modules/lodash._root": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._root/-/lodash._root-3.0.1.tgz", + "integrity": "sha512-O0pWuFSK6x4EXhM1dhZ8gchNtG7JMqBtrHdoUFUWXD7dJnNSUze1GuyQr5sOs0aCvgGeI3o/OJW8f4ca7FDxmQ==" + }, + "node_modules/lodash._stringtopath": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/lodash._stringtopath/-/lodash._stringtopath-4.8.0.tgz", + "integrity": "sha512-SXL66C731p0xPDC5LZg4wI5H+dJo/EO4KTqOMwLYCH3+FmmfAKJEZCm6ohGpI+T1xwsDsJCfL4OnhorllvlTPQ==", + "dependencies": { + "lodash._basetostring": "~4.12.0" + } + }, "node_modules/lodash.clonedeep": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", @@ -8899,6 +8952,15 @@ "integrity": "sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=", "dev": true }, + "node_modules/lodash.uniqby": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.uniqby/-/lodash.uniqby-4.5.0.tgz", + "integrity": "sha512-IRt7cfTtHy6f1aRVA5n7kT8rgN3N1nH6MOWLcHfpWG2SH19E3JksLK38MktLxZDhlAjCP9jpIXkOnRXlu6oByQ==", + "dependencies": { + "lodash._baseiteratee": "~4.7.0", + "lodash._baseuniq": "~4.6.0" + } + }, "node_modules/log-symbols": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", @@ -11181,6 +11243,16 @@ "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=", "dev": true }, + "node_modules/proper-lockfile": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/proper-lockfile/-/proper-lockfile-4.1.2.tgz", + "integrity": "sha512-TjNPblN4BwAWMXU8s9AEz4JmQxnD1NNL7bNOY/AKUzyamc379FWASUhc/K1pL2noVb+XmZKLL68cjzLsiOAMaA==", + "dependencies": { + "graceful-fs": "^4.2.4", + "retry": "^0.12.0", + "signal-exit": "^3.0.2" + } + }, "node_modules/proxy-addr": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz", @@ -11333,8 +11405,7 @@ "node_modules/querystringify": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", - "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", - "dev": true + "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==" }, "node_modules/randombytes": { "version": "2.1.0", @@ -11681,8 +11752,7 @@ "node_modules/requires-port": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", - "dev": true + "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=" }, "node_modules/resolve": { "version": "1.20.0", @@ -11751,7 +11821,6 @@ "version": "0.12.0", "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", "integrity": "sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs=", - "dev": true, "engines": { "node": ">= 4" } @@ -12132,8 +12201,7 @@ "node_modules/signal-exit": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", - "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", - "dev": true + "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==" }, "node_modules/simple-swizzle": { "version": "0.2.2", @@ -13382,6 +13450,36 @@ "node": "*" } }, + "node_modules/tus-js-client": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/tus-js-client/-/tus-js-client-3.1.0.tgz", + "integrity": "sha512-Hfpc8ho4C9Lhs/OflPUA/nHUHZJUrKD5upoPBq7dYJJ9DQhWocsjJU2RZYfN16Y5n19j9dFDszwCvVZ5sfcogw==", + "dependencies": { + "buffer-from": "^1.1.2", + "combine-errors": "^3.0.3", + "is-stream": "^2.0.0", + "js-base64": "^3.7.2", + "lodash.throttle": "^4.1.1", + "proper-lockfile": "^4.1.2", + "url-parse": "^1.5.7" + } + }, + "node_modules/tus-js-client/node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/tus-js-client/node_modules/js-base64": { + "version": "3.7.5", + "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-3.7.5.tgz", + "integrity": "sha512-3MEt5DTINKqfScXKfJFrRbxkrnk2AxPWGBL/ycjz4dK8iqiSJ06UxD8jh8xuh6p10TX4t2+7FsBYVxxQbMg+qA==" + }, "node_modules/tweetnacl": { "version": "0.14.5", "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", @@ -13709,7 +13807,6 @@ "version": "1.5.10", "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", - "dev": true, "dependencies": { "querystringify": "^2.1.1", "requires-port": "^1.0.0" @@ -15049,9 +15146,9 @@ "dev": true }, "node_modules/word-wrap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.4.tgz", + "integrity": "sha512-2V81OA4ugVo5pRo46hAoD2ivUJx8jXmWXfUkY4KFNw0hEptvN0QfH3K4nHiwzGeKl5rFKedV48QVoqYavy4YpA==", "dev": true, "engines": { "node": ">=0.10.0" @@ -18142,10 +18239,9 @@ } }, "buffer-from": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", - "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", - "dev": true + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" }, "buffer-indexof": { "version": "1.1.1", @@ -18771,6 +18867,15 @@ "integrity": "sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w==", "dev": true }, + "combine-errors": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/combine-errors/-/combine-errors-3.0.3.tgz", + "integrity": "sha512-C8ikRNRMygCwaTx+Ek3Yr+OuZzgZjduCOfSQBjbM8V3MfgcjSTeto/GXP6PAwKvJz/v15b7GHZvx5rOlczFw/Q==", + "requires": { + "custom-error-instance": "2.1.1", + "lodash.uniqby": "4.5.0" + } + }, "combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", @@ -19531,6 +19636,11 @@ } } }, + "custom-error-instance": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/custom-error-instance/-/custom-error-instance-2.1.1.tgz", + "integrity": "sha512-p6JFxJc3M4OTD2li2qaHkDCw9SfMw82Ldr6OC9Je1aXiGfhx2W8p3GaoeaGrPJTUN9NirTM/KTxHWMUdR1rsUg==" + }, "cyclist": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-1.0.1.tgz", @@ -21146,8 +21256,7 @@ "graceful-fs": { "version": "4.2.6", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz", - "integrity": "sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==", - "dev": true + "integrity": "sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==" }, "gzip-size": { "version": "5.1.1", @@ -22521,6 +22630,46 @@ "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", "dev": true }, + "lodash._baseiteratee": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/lodash._baseiteratee/-/lodash._baseiteratee-4.7.0.tgz", + "integrity": "sha512-nqB9M+wITz0BX/Q2xg6fQ8mLkyfF7MU7eE+MNBNjTHFKeKaZAPEzEg+E8LWxKWf1DQVflNEn9N49yAuqKh2mWQ==", + "requires": { + "lodash._stringtopath": "~4.8.0" + } + }, + "lodash._basetostring": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/lodash._basetostring/-/lodash._basetostring-4.12.0.tgz", + "integrity": "sha512-SwcRIbyxnN6CFEEK4K1y+zuApvWdpQdBHM/swxP962s8HIxPO3alBH5t3m/dl+f4CMUug6sJb7Pww8d13/9WSw==" + }, + "lodash._baseuniq": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash._baseuniq/-/lodash._baseuniq-4.6.0.tgz", + "integrity": "sha512-Ja1YevpHZctlI5beLA7oc5KNDhGcPixFhcqSiORHNsp/1QTv7amAXzw+gu4YOvErqVlMVyIJGgtzeepCnnur0A==", + "requires": { + "lodash._createset": "~4.0.0", + "lodash._root": "~3.0.0" + } + }, + "lodash._createset": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/lodash._createset/-/lodash._createset-4.0.3.tgz", + "integrity": "sha512-GTkC6YMprrJZCYU3zcqZj+jkXkrXzq3IPBcF/fIPpNEAB4hZEtXU8zp/RwKOvZl43NUmwDbyRk3+ZTbeRdEBXA==" + }, + "lodash._root": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._root/-/lodash._root-3.0.1.tgz", + "integrity": "sha512-O0pWuFSK6x4EXhM1dhZ8gchNtG7JMqBtrHdoUFUWXD7dJnNSUze1GuyQr5sOs0aCvgGeI3o/OJW8f4ca7FDxmQ==" + }, + "lodash._stringtopath": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/lodash._stringtopath/-/lodash._stringtopath-4.8.0.tgz", + "integrity": "sha512-SXL66C731p0xPDC5LZg4wI5H+dJo/EO4KTqOMwLYCH3+FmmfAKJEZCm6ohGpI+T1xwsDsJCfL4OnhorllvlTPQ==", + "requires": { + "lodash._basetostring": "~4.12.0" + } + }, "lodash.clonedeep": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", @@ -22573,6 +22722,15 @@ "integrity": "sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=", "dev": true }, + "lodash.uniqby": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.uniqby/-/lodash.uniqby-4.5.0.tgz", + "integrity": "sha512-IRt7cfTtHy6f1aRVA5n7kT8rgN3N1nH6MOWLcHfpWG2SH19E3JksLK38MktLxZDhlAjCP9jpIXkOnRXlu6oByQ==", + "requires": { + "lodash._baseiteratee": "~4.7.0", + "lodash._baseuniq": "~4.6.0" + } + }, "log-symbols": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", @@ -24460,6 +24618,16 @@ "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=", "dev": true }, + "proper-lockfile": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/proper-lockfile/-/proper-lockfile-4.1.2.tgz", + "integrity": "sha512-TjNPblN4BwAWMXU8s9AEz4JmQxnD1NNL7bNOY/AKUzyamc379FWASUhc/K1pL2noVb+XmZKLL68cjzLsiOAMaA==", + "requires": { + "graceful-fs": "^4.2.4", + "retry": "^0.12.0", + "signal-exit": "^3.0.2" + } + }, "proxy-addr": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz", @@ -24592,8 +24760,7 @@ "querystringify": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", - "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", - "dev": true + "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==" }, "randombytes": { "version": "2.1.0", @@ -24879,8 +25046,7 @@ "requires-port": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", - "dev": true + "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=" }, "resolve": { "version": "1.20.0", @@ -24932,8 +25098,7 @@ "retry": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", - "integrity": "sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs=", - "dev": true + "integrity": "sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs=" }, "rgb-regex": { "version": "1.0.1", @@ -25264,8 +25429,7 @@ "signal-exit": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", - "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", - "dev": true + "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==" }, "simple-swizzle": { "version": "0.2.2", @@ -26306,6 +26470,32 @@ "safe-buffer": "^5.0.1" } }, + "tus-js-client": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/tus-js-client/-/tus-js-client-3.1.0.tgz", + "integrity": "sha512-Hfpc8ho4C9Lhs/OflPUA/nHUHZJUrKD5upoPBq7dYJJ9DQhWocsjJU2RZYfN16Y5n19j9dFDszwCvVZ5sfcogw==", + "requires": { + "buffer-from": "^1.1.2", + "combine-errors": "^3.0.3", + "is-stream": "^2.0.0", + "js-base64": "^3.7.2", + "lodash.throttle": "^4.1.1", + "proper-lockfile": "^4.1.2", + "url-parse": "^1.5.7" + }, + "dependencies": { + "is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==" + }, + "js-base64": { + "version": "3.7.5", + "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-3.7.5.tgz", + "integrity": "sha512-3MEt5DTINKqfScXKfJFrRbxkrnk2AxPWGBL/ycjz4dK8iqiSJ06UxD8jh8xuh6p10TX4t2+7FsBYVxxQbMg+qA==" + } + } + }, "tweetnacl": { "version": "0.14.5", "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", @@ -26575,7 +26765,6 @@ "version": "1.5.10", "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", - "dev": true, "requires": { "querystringify": "^2.1.1", "requires-port": "^1.0.0" @@ -27647,9 +27836,9 @@ "dev": true }, "word-wrap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.4.tgz", + "integrity": "sha512-2V81OA4ugVo5pRo46hAoD2ivUJx8jXmWXfUkY4KFNw0hEptvN0QfH3K4nHiwzGeKl5rFKedV48QVoqYavy4YpA==", "dev": true }, "worker-farm": { diff --git a/frontend/package.json b/frontend/package.json index 33ab2ff5..1573f407 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -23,6 +23,7 @@ "noty": "^3.2.0-beta", "pretty-bytes": "^6.0.0", "qrcode.vue": "^1.7.0", + "tus-js-client": "^3.1.0", "utif": "^3.1.0", "vue": "^2.6.10", "vue-async-computed": "^3.9.0", diff --git a/frontend/src/api/files.js b/frontend/src/api/files.js index a91ba4b2..1c2ea80a 100644 --- a/frontend/src/api/files.js +++ b/frontend/src/api/files.js @@ -1,6 +1,7 @@ import { createURL, fetchURL, removePrefix } from "./utils"; import { baseURL } from "@/utils/constants"; import store from "@/store"; +import { upload as postTus, useTus } from "./tus"; export async function fetch(url) { url = removePrefix(url); @@ -78,6 +79,21 @@ export function download(format, ...files) { } export async function post(url, content = "", overwrite = false, onupload) { + // Use the pre-existing API if: + const useResourcesApi = + // a folder is being created + url.endsWith("/") || + // We're not using http(s) + (content instanceof Blob && + !["http:", "https:"].includes(window.location.protocol)) || + // Tus is disabled / not applicable + !(await useTus(content)); + return useResourcesApi + ? postResources(url, content, overwrite, onupload) + : postTus(url, content, overwrite, onupload); +} + +async function postResources(url, content = "", overwrite = false, onupload) { url = removePrefix(url); let bufferContent; diff --git a/frontend/src/api/tus.js b/frontend/src/api/tus.js new file mode 100644 index 00000000..bda4f40c --- /dev/null +++ b/frontend/src/api/tus.js @@ -0,0 +1,90 @@ +import * as tus from "tus-js-client"; +import { baseURL, tusEndpoint, tusSettings } from "@/utils/constants"; +import store from "@/store"; +import { removePrefix } from "@/api/utils"; +import { fetchURL } from "./utils"; + +const RETRY_BASE_DELAY = 1000; +const RETRY_MAX_DELAY = 20000; + +export async function upload( + filePath, + content = "", + overwrite = false, + onupload +) { + if (!tusSettings) { + // Shouldn't happen as we check for tus support before calling this function + throw new Error("Tus.io settings are not defined"); + } + + filePath = removePrefix(filePath); + let resourcePath = `${tusEndpoint}${filePath}?override=${overwrite}`; + + await createUpload(resourcePath); + + return new Promise((resolve, reject) => { + let upload = new tus.Upload(content, { + uploadUrl: `${baseURL}${resourcePath}`, + chunkSize: tusSettings.chunkSize, + retryDelays: computeRetryDelays(tusSettings), + parallelUploads: 1, + storeFingerprintForResuming: false, + headers: { + "X-Auth": store.state.jwt, + }, + onError: function (error) { + reject("Upload failed: " + error); + }, + onProgress: function (bytesUploaded) { + // Emulate ProgressEvent.loaded which is used by calling functions + // loaded is specified in bytes (https://developer.mozilla.org/en-US/docs/Web/API/ProgressEvent/loaded) + if (typeof onupload === "function") { + onupload({ loaded: bytesUploaded }); + } + }, + onSuccess: function () { + resolve(); + }, + }); + upload.start(); + }); +} + +async function createUpload(resourcePath) { + let headResp = await fetchURL(resourcePath, { + method: "POST", + }); + if (headResp.status !== 201) { + throw new Error( + `Failed to create an upload: ${headResp.status} ${headResp.statusText}` + ); + } +} + +function computeRetryDelays(tusSettings) { + if (!tusSettings.retryCount || tusSettings.retryCount < 1) { + // Disable retries altogether + return null; + } + // The tus client expects our retries as an array with computed backoffs + // E.g.: [0, 3000, 5000, 10000, 20000] + const retryDelays = []; + let delay = 0; + + for (let i = 0; i < tusSettings.retryCount; i++) { + retryDelays.push(Math.min(delay, RETRY_MAX_DELAY)); + delay = + delay === 0 ? RETRY_BASE_DELAY : Math.min(delay * 2, RETRY_MAX_DELAY); + } + + return retryDelays; +} + +export async function useTus(content) { + return isTusSupported() && content instanceof Blob; +} + +function isTusSupported() { + return tus.isSupported === true; +} diff --git a/frontend/src/api/utils.js b/frontend/src/api/utils.js index 87d6a243..7883c4ce 100644 --- a/frontend/src/api/utils.js +++ b/frontend/src/api/utils.js @@ -8,7 +8,6 @@ export async function fetchURL(url, opts, auth = true) { opts.headers = opts.headers || {}; let { headers, ...rest } = opts; - let res; try { res = await fetch(`${baseURL}${url}`, { diff --git a/frontend/src/components/Shell.vue b/frontend/src/components/Shell.vue index 47c3d67c..dd5bf319 100644 --- a/frontend/src/components/Shell.vue +++ b/frontend/src/components/Shell.vue @@ -113,7 +113,10 @@ export default { this.scroll(); }, () => { - results.text = results.text.trimEnd(); + results.text = results.text + // eslint-disable-next-line no-control-regex + .replace(/\u001b\[[0-9;]+m/g, "") // Filter ANSI color for now + .trimEnd(); this.canInput = true; this.$refs.input.focus(); this.scroll(); diff --git a/frontend/src/components/prompts/Replace.vue b/frontend/src/components/prompts/Replace.vue index 82ede1d6..a525bbbc 100644 --- a/frontend/src/components/prompts/Replace.vue +++ b/frontend/src/components/prompts/Replace.vue @@ -17,6 +17,14 @@ > {{ $t("buttons.cancel") }} +