diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs new file mode 100644 index 00000000..e16d5382 --- /dev/null +++ b/.git-blame-ignore-revs @@ -0,0 +1,2 @@ +# Scala Steward: Reformat with scalafmt 3.8.2 +1c566cd5182d41f4cc06040fc347ddb4be617779 diff --git a/.github/release-drafter.yml b/.github/release-drafter.yml new file mode 100644 index 00000000..28f16def --- /dev/null +++ b/.github/release-drafter.yml @@ -0,0 +1,42 @@ +name-template: "$RESOLVED_VERSION" +tag-template: "$RESOLVED_VERSION" +template: | + ## What’s Changed + + $CHANGES + +categories: + - title: "🚀 Features" + labels: + - 'feature' + - 'enhancement' + - title: "🐛 Bug Fixes" + labels: + - 'fix' + - 'bug' + - title: "💚 Maintenance" + labels: + - 'chore' + - 'documentation' + - title: "🧱 Dependencies" + labels: + - 'dependencies' + - 'type: dependencies' + +change-template: '- $TITLE @$AUTHOR (#$NUMBER)' +version-resolver: + major: + labels: + - 'breaking' + minor: + labels: + - 'feature' + - 'enhancement' + patch: + labels: + - 'chore' + - 'documentation' + - 'dependencies' + default: patch +exclude-labels: + - 'skip-changelog' diff --git a/.github/renovate.json b/.github/renovate.json index defbaef7..92f7d7ca 100644 --- a/.github/renovate.json +++ b/.github/renovate.json @@ -1,6 +1,6 @@ { "automerge": true, - "labels": ["type: dependencies"], + "labels": ["dependencies"], "packageRules": [ { "matchManagers": [ diff --git a/.github/stale.yml b/.github/stale.yml deleted file mode 100644 index 2ee655a6..00000000 --- a/.github/stale.yml +++ /dev/null @@ -1,16 +0,0 @@ -# Number of days of inactivity before an issue becomes stale -daysUntilStale: 30 -# Number of days of inactivity before a stale issue is closed -daysUntilClose: 7 -onlyLabels: - - question -# Label to use when marking an issue as stale -staleLabel: stale -# Comment to post when marking an issue as stale. Set to `false` to disable -markComment: > - This issue has been automatically marked as stale because it has not - had recent activity. It will be closed if no further activity - occurs. This only applies to 'question' issues. Always feel free to - reopen or create new issues. Thank you! -# Comment to post when closing a stale issue. Set to `false` to disable -closeComment: false diff --git a/.github/workflows/ci-docs.yml b/.github/workflows/ci-docs.yml index 4d3bb379..ac80e94e 100644 --- a/.github/workflows/ci-docs.yml +++ b/.github/workflows/ci-docs.yml @@ -6,20 +6,13 @@ on: - "master" jobs: check-website: - runs-on: ubuntu-22.04 + runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4.1.1 + - uses: actions/checkout@v4.1.7 with: fetch-depth: 0 + - uses: cachix/install-nix-action@v27 - name: Set current version run: echo "DOCSPELL_VERSION=$(cat version.sbt | grep version | cut -d= -f2 | xargs)" >> $GITHUB_ENV - - uses: jorelali/setup-elm@v5 - with: - elm-version: 0.19.1 - - uses: cachix/install-nix-action@v25 - with: - nix_path: nixpkgs=channel:nixos-23.05 - - name: Print nixpkgs version - run: nix-instantiate --eval -E '(import {}).lib.version' - name: Build website (${{ env.DOCSPELL_VERSION }}) - run: nix-shell website/shell.nix --run "sbt make-website" + run: nix develop .#ci --command sbt make-website diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0748dfc0..28d3d6ae 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -5,30 +5,18 @@ on: - master jobs: ci-matrix: - runs-on: ubuntu-22.04 + runs-on: ubuntu-latest strategy: fail-fast: false - matrix: - java: [ 'openjdk@1.17' ] steps: - - uses: actions/checkout@v4.1.1 + - uses: actions/checkout@v4.1.7 with: fetch-depth: 100 - - uses: jorelali/setup-elm@v5 - with: - elm-version: 0.19.1 - - uses: bahmutov/npm-install@v1 - with: - working-directory: modules/webapp - name: Fetch tags run: git fetch --depth=100 origin +refs/tags/*:refs/tags/* - - uses: olafurpg/setup-scala@v14 - with: - java-version: ${{ matrix.java }} - # - name: Coursier cache - # uses: coursier/cache-action@v6 + - uses: cachix/install-nix-action@v27 - name: sbt ci ${{ github.ref }} - run: sbt ci + run: nix develop .#ci --command sbt ci ci: runs-on: ubuntu-22.04 needs: [ci-matrix] diff --git a/.github/workflows/docker-image.yml b/.github/workflows/docker-image.yml index 997e0972..3f998d10 100644 --- a/.github/workflows/docker-image.yml +++ b/.github/workflows/docker-image.yml @@ -4,9 +4,9 @@ on: types: [ published ] jobs: docker-images: - runs-on: ubuntu-22.04 + runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4.1.1 + - uses: actions/checkout@v4.1.7 with: fetch-depth: 0 - name: Set current version diff --git a/.github/workflows/release-drafter.yml b/.github/workflows/release-drafter.yml new file mode 100644 index 00000000..99fe14db --- /dev/null +++ b/.github/workflows/release-drafter.yml @@ -0,0 +1,14 @@ +name: Release Drafter + +on: + push: + branches: + - master + +jobs: + update_release_draft: + runs-on: ubuntu-latest + steps: + - uses: release-drafter/release-drafter@v6 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/release-nightly.yml b/.github/workflows/release-nightly.yml index 100a044b..e955927b 100644 --- a/.github/workflows/release-nightly.yml +++ b/.github/workflows/release-nightly.yml @@ -5,32 +5,20 @@ on: - "master" jobs: release-nightly: - runs-on: ubuntu-22.04 + runs-on: ubuntu-latest strategy: fail-fast: true - matrix: - java: [ 'openjdk@1.17' ] steps: - - uses: actions/checkout@v4.1.1 + - uses: actions/checkout@v4.1.7 with: fetch-depth: 0 - - uses: olafurpg/setup-scala@v14 - with: - java-version: ${{ matrix.java }} - - uses: jorelali/setup-elm@v5 - with: - elm-version: 0.19.1 - - uses: bahmutov/npm-install@v1 - with: - working-directory: modules/webapp - # - name: Coursier cache - # uses: coursier/cache-action@v6 + - uses: cachix/install-nix-action@v27 - name: Set current version run: echo "DOCSPELL_VERSION=$(cat version.sbt | grep version | cut -d= -f2 | xargs)" >> $GITHUB_ENV - name: sbt ci ${{ github.ref }} - run: sbt ci + run: nix develop .#ci --command sbt ci - name: sbt make-pkg (${{ env.DOCSPELL_VERSION }}) - run: sbt make-pkg + run: nix develop .#ci --command sbt make-pkg - uses: "marvinpinto/action-automatic-releases@latest" with: repo_token: "${{ secrets.GITHUB_TOKEN }}" diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 411e57fc..244b917d 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -5,30 +5,18 @@ on: - 'v*' jobs: release: - runs-on: ubuntu-22.04 + runs-on: ubuntu-latest strategy: fail-fast: true - matrix: - java: [ 'openjdk@1.17' ] steps: - - uses: actions/checkout@v4.1.1 + - uses: actions/checkout@v4.1.7 with: fetch-depth: 0 - - uses: olafurpg/setup-scala@v14 - with: - java-version: ${{ matrix.java }} - - uses: jorelali/setup-elm@v5 - with: - elm-version: 0.19.1 - - uses: bahmutov/npm-install@v1 - with: - working-directory: modules/webapp - # - name: Coursier cache - # uses: coursier/cache-action@v6 + - uses: cachix/install-nix-action@v27 - name: Set current version run: echo "DOCSPELL_VERSION=$(cat version.sbt | grep version | cut -d= -f2 | xargs)" >> $GITHUB_ENV - name: sbt make-pkg (${{ env.DOCSPELL_VERSION }}) - run: sbt make-pkg + run: nix develop .#ci --command sbt make-pkg - uses: meeDamian/github-release@2.0 with: token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml new file mode 100644 index 00000000..acd334f9 --- /dev/null +++ b/.github/workflows/stale.yml @@ -0,0 +1,21 @@ +name: 'Handle stale issues' +on: + schedule: + - cron: '30 1 * * *' + +jobs: + stale: + runs-on: ubuntu-latest + steps: + # https://github.com/actions/stale + - uses: actions/stale@v9 + with: + days-before-stale: 30 + days-before-close: 7 + only-labels: question + stale-issue-label: stale + stale-issue-message: > + This issue has been automatically marked as stale because it has not + had recent activity. It will be closed if no further activity + occurs. This only applies to 'question' issues. Always feel free to + reopen or create new issues. Thank you! diff --git a/.github/workflows/website.yml b/.github/workflows/website.yml index d402cab0..85762855 100644 --- a/.github/workflows/website.yml +++ b/.github/workflows/website.yml @@ -5,24 +5,17 @@ on: - "current-docs" jobs: publish-website: - runs-on: ubuntu-22.04 + runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4.1.1 + - uses: actions/checkout@v4.1.7 with: fetch-depth: 0 + - uses: cachix/install-nix-action@v27 - name: Set current version run: echo "DOCSPELL_VERSION=$(cat version.sbt | grep version | cut -d= -f2 | xargs)" >> $GITHUB_ENV - - uses: jorelali/setup-elm@v5 - with: - elm-version: 0.19.1 - - uses: cachix/install-nix-action@v25 - with: - nix_path: nixpkgs=channel:nixos-23.05 - - name: Print nixpkgs version - run: nix-instantiate --eval -E '(import {}).lib.version' - name: Build website (${{ env.DOCSPELL_VERSION }}) - run: nix-shell website/shell.nix --run "sbt make-website" + run: nix develop .#ci --command sbt make-website - name: Publish website (${{ env.DOCSPELL_VERSION }}) env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: sbt publish-website + run: nix develop .#ci --command sbt publish-website diff --git a/.gitignore b/.gitignore index 18234e40..a921d704 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ #artwork/*.png +.envrc target/ local/ node_modules/ diff --git a/.mergify.yml b/.mergify.yml index ec6b13f2..ea6f9791 100644 --- a/.mergify.yml +++ b/.mergify.yml @@ -6,7 +6,7 @@ pull_request_rules: assign: users: [eikek] label: - add: ["type: dependencies"] + add: ["dependencies"] - name: automatically merge Scala Steward PRs on CI success conditions: - author=eikek-scala-steward[bot] diff --git a/.scalafmt.conf b/.scalafmt.conf index 45fff15e..151f8450 100644 --- a/.scalafmt.conf +++ b/.scalafmt.conf @@ -1,4 +1,4 @@ -version = "3.7.17" +version = "3.8.2" preset = default align.preset = some diff --git a/Changelog.md b/Changelog.md index efa13671..6b67a983 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1020,7 +1020,7 @@ Additionally there are some other minor features and bug fixes. to be able to add a request header. Check [this for firefox](https://addons.mozilla.org/en-US/firefox/addon/modheader-firefox/) or [this for - chromium](https://chrome.google.com/webstore/detail/modheader/idgpnmonknjnojddfkpgkljpfnnfcklj) + chromium](https://chromewebstore.google.com/detail/modheader-modify-http-hea/idgpnmonknjnojddfkpgkljpfnnfcklj) - then add the request header `Docspell-Ui` with value `1`. Reloading the page gets you back the old ui. - With new Web-UI, certain features and fixes were realized, but not diff --git a/build.sbt b/build.sbt index b51afe39..04556cb7 100644 --- a/build.sbt +++ b/build.sbt @@ -15,11 +15,14 @@ val scalafixSettings = Seq( val sharedSettings = Seq( organization := "com.github.eikek", - scalaVersion := "2.13.12", + scalaVersion := "2.13.14", organizationName := "Eike K. & Contributors", - licenses += ("AGPL-3.0-or-later", url( - "https://spdx.org/licenses/AGPL-3.0-or-later.html" - )), + licenses += ( + "AGPL-3.0-or-later", + url( + "https://spdx.org/licenses/AGPL-3.0-or-later.html" + ) + ), startYear := Some(2020), headerLicenseStyle := HeaderLicenseStyle.SpdxSyntax, headerSources / excludeFilter := HiddenFileFilter || "*.java" || "StringUtil.scala", @@ -677,7 +680,11 @@ val restapi = project openapiTargetLanguage := Language.Scala, openapiPackage := Pkg("docspell.restapi.model"), openapiSpec := (Compile / resourceDirectory).value / "docspell-openapi.yml", - openapiStaticGen := OpenApiDocGenerator.Redoc + openapiStaticGen := OpenApiDocGenerator.Redoc, + openapiRedoclyCmd := Seq("redocly-cli"), + openapiRedoclyConfig := Some( + (LocalRootProject / baseDirectory).value / "project" / "redocly.yml" + ) ) .dependsOn(common, query.jvm, notificationApi, jsonminiq, addonlib) @@ -697,7 +704,11 @@ val joexapi = project openapiTargetLanguage := Language.Scala, openapiPackage := Pkg("docspell.joexapi.model"), openapiSpec := (Compile / resourceDirectory).value / "joex-openapi.yml", - openapiStaticGen := OpenApiDocGenerator.Redoc + openapiStaticGen := OpenApiDocGenerator.Redoc, + openapiRedoclyCmd := Seq("redocly-cli"), + openapiRedoclyConfig := Some( + (LocalRootProject / baseDirectory).value / "project" / "redocly.yml" + ) ) .dependsOn(common, loggingScribe, addonlib) diff --git a/docker/docker-compose/docker-compose.yml b/docker/docker-compose/docker-compose.yml index 4a8af01c..a78b63fb 100644 --- a/docker/docker-compose/docker-compose.yml +++ b/docker/docker-compose/docker-compose.yml @@ -109,7 +109,7 @@ services: - restserver db: - image: postgres:16.1 + image: postgres:16.3 container_name: postgres_db restart: unless-stopped volumes: diff --git a/docker/dockerfiles/joex.dockerfile b/docker/dockerfiles/joex.dockerfile index c99f5e19..3744abaa 100644 --- a/docker/dockerfiles/joex.dockerfile +++ b/docker/dockerfiles/joex.dockerfile @@ -1,4 +1,4 @@ -FROM alpine:20231219 +FROM alpine:3.20.2 ARG version= ARG joex_url= @@ -77,7 +77,7 @@ RUN \ wget https://github.com/tesseract-ocr/tessdata/raw/main/khm.traineddata && \ mv khm.traineddata /usr/share/tessdata -# Using these data files for japanese, because they work better. See #973 +# Using these data files for japanese, because they work better. Includes vertical data. See #973 and #2445. RUN \ wget https://raw.githubusercontent.com/tesseract-ocr/tessdata_fast/master/jpn_vert.traineddata && \ wget https://raw.githubusercontent.com/tesseract-ocr/tessdata_fast/master/jpn.traineddata && \ diff --git a/docker/dockerfiles/restserver.dockerfile b/docker/dockerfiles/restserver.dockerfile index 482324f8..a0d11781 100644 --- a/docker/dockerfiles/restserver.dockerfile +++ b/docker/dockerfiles/restserver.dockerfile @@ -1,4 +1,4 @@ -FROM alpine:20231219 +FROM alpine:3.20.2 ARG version= ARG restserver_url= diff --git a/flake.lock b/flake.lock new file mode 100644 index 00000000..8b912198 --- /dev/null +++ b/flake.lock @@ -0,0 +1,130 @@ +{ + "nodes": { + "devshell-tools": { + "inputs": { + "flake-utils": "flake-utils", + "nixpkgs": "nixpkgs" + }, + "locked": { + "lastModified": 1710099997, + "narHash": "sha256-WmBKTLdth6I/D+0//9enbIXohGsBjepbjIAm9pCYj0U=", + "owner": "eikek", + "repo": "devshell-tools", + "rev": "e82faf976d318b3829f6f7f6785db6f3c7b65267", + "type": "github" + }, + "original": { + "owner": "eikek", + "repo": "devshell-tools", + "type": "github" + } + }, + "flake-utils": { + "inputs": { + "systems": "systems" + }, + "locked": { + "lastModified": 1709126324, + "narHash": "sha256-q6EQdSeUZOG26WelxqkmR7kArjgWCdw5sfJVHPH/7j8=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "d465f4819400de7c8d874d50b982301f28a84605", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_2": { + "inputs": { + "systems": "systems_2" + }, + "locked": { + "lastModified": 1709126324, + "narHash": "sha256-q6EQdSeUZOG26WelxqkmR7kArjgWCdw5sfJVHPH/7j8=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "d465f4819400de7c8d874d50b982301f28a84605", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1709309926, + "narHash": "sha256-VZFBtXGVD9LWTecGi6eXrE0hJ/mVB3zGUlHImUs2Qak=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "79baff8812a0d68e24a836df0a364c678089e2c7", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-23.11", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_2": { + "locked": { + "lastModified": 1709677081, + "narHash": "sha256-tix36Y7u0rkn6mTm0lA45b45oab2cFLqAzDbJxeXS+c=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "880992dcc006a5e00dd0591446fdf723e6a51a64", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-23.11", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "devshell-tools": "devshell-tools", + "flake-utils": "flake-utils_2", + "nixpkgs": "nixpkgs_2" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "systems_2": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 00000000..cb6bc2e0 --- /dev/null +++ b/flake.nix @@ -0,0 +1,193 @@ +{ + description = "Docspell"; + + inputs = { + nixpkgs.url = "github:NixOS/nixpkgs/nixos-23.11"; + devshell-tools.url = "github:eikek/devshell-tools"; + flake-utils.url = "github:numtide/flake-utils"; + }; + + outputs = { + self, + nixpkgs, + flake-utils, + devshell-tools, + }: + flake-utils.lib.eachDefaultSystem (system: let + pkgs = nixpkgs.legacyPackages.${system}; + sbt17 = pkgs.sbt.override {jre = pkgs.jdk17;}; + ciPkgs = with pkgs; [ + sbt17 + jdk17 + dpkg + elmPackages.elm + fakeroot + zola + yarn + nodejs + redocly-cli + tailwindcss + ]; + devshellPkgs = + ciPkgs + ++ (with pkgs; [ + jq + scala-cli + netcat + wget + which + inotifyTools + ]); + docspellPkgs = pkgs.callPackage (import ./nix/pkg.nix) {}; + dockerAmd64 = pkgs.pkgsCross.gnu64.callPackage (import ./nix/docker.nix) { + inherit (docspellPkgs) docspell-restserver docspell-joex; + }; + dockerArm64 = pkgs.pkgsCross.aarch64-multiplatform.callPackage (import ./nix/docker.nix) { + inherit (docspellPkgs) docspell-restserver docspell-joex; + }; + in { + formatter = pkgs.alejandra; + + packages = { + inherit (docspellPkgs) docspell-restserver docspell-joex; + }; + + legacyPackages = { + docker = { + amd64 = { + inherit (dockerAmd64) docspell-restserver docspell-joex; + }; + arm64 = { + inherit (dockerArm64) docspell-restserver docspell-joex; + }; + }; + }; + + checks = { + build-server = self.packages.${system}.docspell-restserver; + build-joex = self.packages.${system}.docspell-joex; + + test = with import (nixpkgs + "/nixos/lib/testing-python.nix") + { + inherit system; + }; + makeTest { + name = "docspell"; + nodes = { + machine = {...}: { + nixpkgs.overlays = [self.overlays.default]; + imports = [ + self.nixosModules.default + ./nix/checks + ]; + }; + }; + + testScript = builtins.readFile ./nix/checks/testScript.py; + }; + }; + + devShells = { + dev-cnt = pkgs.mkShellNoCC { + buildInputs = + (builtins.attrValues devshell-tools.legacyPackages.${system}.cnt-scripts) + ++ devshellPkgs; + + DOCSPELL_ENV = "dev"; + DEV_CONTAINER = "docsp-dev"; + SBT_OPTS = "-Xmx2G -Xss4m"; + }; + dev-vm = pkgs.mkShellNoCC { + buildInputs = + (builtins.attrValues devshell-tools.legacyPackages.${system}.vm-scripts) + ++ devshellPkgs; + + DOCSPELL_ENV = "dev"; + SBT_OPTS = "-Xmx2G -Xss4m"; + DEV_VM = "dev-vm"; + VM_SSH_PORT = "10022"; + }; + ci = pkgs.mkShellNoCC { + buildInputs = ciPkgs; + SBT_OPTS = "-Xmx2G -Xss4m"; + }; + }; + }) + // { + nixosModules = { + default = {...}: { + imports = [ + ./nix/modules/server.nix + ./nix/modules/joex.nix + ]; + }; + server = import ./nix/modules/server.nix; + joex = import ./nix/modules/joex.nix; + }; + + overlays.default = final: prev: let + docspellPkgs = final.callPackage (import ./nix/pkg.nix) {}; + in { + inherit (docspellPkgs) docspell-restserver docspell-joex; + }; + + nixosConfigurations = { + test-vm = devshell-tools.lib.mkVm { + system = "x86_64-linux"; + modules = [ + self.nixosModules.default + { + nixpkgs.overlays = [self.overlays.default]; + } + ./nix/test-vm.nix + ]; + }; + docsp-dev = devshell-tools.lib.mkContainer { + system = "x86_64-linux"; + modules = [ + { + services.dev-postgres = { + enable = true; + databases = ["docspell"]; + }; + services.dev-email.enable = true; + services.dev-minio.enable = true; + services.dev-solr = { + enable = true; + cores = ["docspell"]; + }; + } + ]; + }; + dev-vm = devshell-tools.lib.mkVm { + system = "x86_64-linux"; + modules = [ + { + networking.hostName = "dev-vm"; + virtualisation.memorySize = 2048; + + services.dev-postgres = { + enable = true; + databases = ["docspell"]; + }; + services.dev-email.enable = true; + services.dev-minio.enable = true; + services.dev-solr = { + enable = true; + cores = ["docspell"]; + heap = 512; + }; + port-forward.ssh = 10022; + port-forward.dev-postgres = 6534; + port-forward.dev-smtp = 10025; + port-forward.dev-imap = 10143; + port-forward.dev-webmail = 8080; + port-forward.dev-minio-api = 9000; + port-forward.dev-minio-console = 9001; + port-forward.dev-solr = 8983; + } + ]; + }; + }; + }; +} diff --git a/modules/addonlib/src/main/scala/docspell/addons/AddonArchive.scala b/modules/addonlib/src/main/scala/docspell/addons/AddonArchive.scala index d4a367be..95725c1a 100644 --- a/modules/addonlib/src/main/scala/docspell/addons/AddonArchive.scala +++ b/modules/addonlib/src/main/scala/docspell/addons/AddonArchive.scala @@ -38,9 +38,9 @@ final case class AddonArchive(url: LenientUri, name: String, version: String) { Files[F].createDirectories(target) *> reader(url) .through(Zip[F](logger.some).unzip(glob = glob, targetDir = target.some)) - .evalTap(_ => Directory.unwrapSingle[F](logger, target)) .compile .drain + .flatTap(_ => Directory.unwrapSingle[F](logger, target)) .as(target) } } diff --git a/modules/addonlib/src/main/scala/docspell/addons/runner/RunnerUtil.scala b/modules/addonlib/src/main/scala/docspell/addons/runner/RunnerUtil.scala index 7f44dcea..39c2a52f 100644 --- a/modules/addonlib/src/main/scala/docspell/addons/runner/RunnerUtil.scala +++ b/modules/addonlib/src/main/scala/docspell/addons/runner/RunnerUtil.scala @@ -110,7 +110,7 @@ private[addons] object RunnerUtil { ): F[AddonResult] = for { stdout <- - if (ctx.meta.options.exists(_.collectOutput)) CollectOut.buffer[F] + if (ctx.meta.parseResult) CollectOut.buffer[F] else CollectOut.none[F].pure[F] cmdResult <- SysExec(cmd, logger, ctx.baseDir.some) .flatMap( @@ -135,7 +135,7 @@ private[addons] object RunnerUtil { out <- stdout.get _ <- logger.debug(s"Addon stdout: $out") result = Option - .when(ctx.meta.options.exists(_.collectOutput) && out.nonEmpty)( + .when(ctx.meta.parseResult && out.nonEmpty)( JsonParser .decode[AddonOutput](out) .fold(AddonResult.decodingError, AddonResult.success) diff --git a/modules/addonlib/src/test/resources/docspell-addon-single-file.zip b/modules/addonlib/src/test/resources/docspell-addon-single-file.zip new file mode 100644 index 00000000..94735d98 Binary files /dev/null and b/modules/addonlib/src/test/resources/docspell-addon-single-file.zip differ diff --git a/modules/addonlib/src/test/scala/docspell/addons/AddonArchiveTest.scala b/modules/addonlib/src/test/scala/docspell/addons/AddonArchiveTest.scala index 7cd98dcd..b49dbab8 100644 --- a/modules/addonlib/src/test/scala/docspell/addons/AddonArchiveTest.scala +++ b/modules/addonlib/src/test/scala/docspell/addons/AddonArchiveTest.scala @@ -9,7 +9,7 @@ package docspell.addons import cats.effect._ import cats.syntax.option._ -import docspell.common.UrlReader +import docspell.common._ import docspell.logging.TestLoggingConfig import munit._ @@ -42,10 +42,20 @@ class AddonArchiveTest extends CatsEffectSuite with TestLoggingConfig with Fixtu } yield () } + tempDir.test("read archive from zip with yaml only") { dir => + for { + aa <- AddonArchive.read[IO](singleFileAddonUrl, UrlReader.defaultReader[IO], None) + _ = assertEquals(aa.version, "0.7.0") + path <- aa.extractTo(UrlReader.defaultReader[IO], dir) + read <- AddonArchive.read[IO](aa.url, UrlReader.defaultReader[IO], path.some) + _ = assertEquals(aa, read) + } yield () + } + tempDir.test("Read generated addon from path") { dir => AddonGenerator.successAddon("mini-addon").use { addon => for { - archive <- IO(AddonArchive(addon.url, "", "")) + archive <- IO(AddonArchive(addon.url, "test-addon", "0.1.0")) path <- archive.extractTo[IO](UrlReader.defaultReader[IO], dir) read <- AddonArchive.read[IO](addon.url, UrlReader.defaultReader[IO], path.some) diff --git a/modules/addonlib/src/test/scala/docspell/addons/AddonExecutorTest.scala b/modules/addonlib/src/test/scala/docspell/addons/AddonExecutorTest.scala index ec2bd862..940fe091 100644 --- a/modules/addonlib/src/test/scala/docspell/addons/AddonExecutorTest.scala +++ b/modules/addonlib/src/test/scala/docspell/addons/AddonExecutorTest.scala @@ -142,7 +142,7 @@ class AddonExecutorTest extends CatsEffectSuite with Fixtures with TestLoggingCo AddonExecutionResult.executionResultMonoid .combine( AddonExecutionResult.empty, - AddonExecutionResult(Nil, true) + AddonExecutionResult(Nil, pure = true) ) .pure ) diff --git a/modules/addonlib/src/test/scala/docspell/addons/AddonGenerator.scala b/modules/addonlib/src/test/scala/docspell/addons/AddonGenerator.scala index 63c162ee..1f80f5d2 100644 --- a/modules/addonlib/src/test/scala/docspell/addons/AddonGenerator.scala +++ b/modules/addonlib/src/test/scala/docspell/addons/AddonGenerator.scala @@ -27,9 +27,9 @@ object AddonGenerator { ): Resource[IO, AddonArchive] = output match { case None => - generate(name, version, false)("exit 0") + generate(name, version, collectOutput = false)("exit 0") case Some(out) => - generate(name, version, true)( + generate(name, version, collectOutput = true)( s""" |cat <<-EOF |${out.asJson.noSpaces} @@ -77,8 +77,9 @@ object AddonGenerator { meta = AddonMeta.Meta(name, version, None), triggers = Set(AddonTriggerType.ExistingItem: AddonTriggerType).some, args = None, - runner = - AddonMeta.Runner(None, None, AddonMeta.TrivialRunner(true, "addon.sh").some).some, + runner = AddonMeta + .Runner(None, None, AddonMeta.TrivialRunner(enable = true, "addon.sh").some) + .some, options = AddonMeta.Options(networking = !collectOutput, collectOutput = collectOutput).some ) diff --git a/modules/addonlib/src/test/scala/docspell/addons/AddonMetaTest.scala b/modules/addonlib/src/test/scala/docspell/addons/AddonMetaTest.scala index 38e37b38..7f5ffca8 100644 --- a/modules/addonlib/src/test/scala/docspell/addons/AddonMetaTest.scala +++ b/modules/addonlib/src/test/scala/docspell/addons/AddonMetaTest.scala @@ -35,4 +35,13 @@ class AddonMetaTest extends CatsEffectSuite with TestLoggingConfig with Fixtures _ = assertEquals(meta, dummyAddonMeta) } yield () } + + test("parse yaml with defaults") { + val yamlStr = """meta: + | name: "test" + | version: "0.1.0" + |""".stripMargin + val meta = AddonMeta.fromYamlString(yamlStr).fold(throw _, identity) + assert(meta.parseResult) + } } diff --git a/modules/addonlib/src/test/scala/docspell/addons/Fixtures.scala b/modules/addonlib/src/test/scala/docspell/addons/Fixtures.scala index 12cb24c8..be38b800 100644 --- a/modules/addonlib/src/test/scala/docspell/addons/Fixtures.scala +++ b/modules/addonlib/src/test/scala/docspell/addons/Fixtures.scala @@ -31,6 +31,9 @@ trait Fixtures extends TestLoggingConfig { self: CatsEffectSuite => val miniAddonUrl = LenientUri.fromJava(getClass.getResource("/minimal-addon.zip")) + val singleFileAddonUrl = + LenientUri.fromJava(getClass.getResource("/docspell-addon-single-file.zip")) + val dummyAddonMeta = AddonMeta( meta = @@ -40,13 +43,13 @@ trait Fixtures extends TestLoggingConfig { self: CatsEffectSuite => ), None, runner = Runner( - nix = NixRunner(true).some, + nix = NixRunner(enable = true).some, docker = DockerRunner( enable = true, image = None, build = "Dockerfile".some ).some, - trivial = TrivialRunner(true, "src/addon.sh").some + trivial = TrivialRunner(enable = true, "src/addon.sh").some ).some, options = Options(networking = true, collectOutput = true).some ) @@ -55,7 +58,7 @@ trait Fixtures extends TestLoggingConfig { self: CatsEffectSuite => Path(s"/tmp/target/test-temp") val tempDir = - ResourceFixture[Path]( + ResourceFunFixture[Path]( Resource.eval(Files[IO].createDirectories(baseTempDir)) *> Files[IO] .tempDirectory(baseTempDir.some, "run-", PosixPermissions.fromOctal("777")) @@ -65,7 +68,7 @@ trait Fixtures extends TestLoggingConfig { self: CatsEffectSuite => runner: RunnerType, runners: RunnerType* ): AddonExecutorConfig = { - val nspawn = NSpawn(false, "sudo", "systemd-nspawn", Duration.millis(100)) + val nspawn = NSpawn(enabled = false, "sudo", "systemd-nspawn", Duration.millis(100)) AddonExecutorConfig( runner = runner :: runners.toList, runTimeout = Duration.minutes(2), diff --git a/modules/analysis/src/main/scala/docspell/analysis/date/DateFind.scala b/modules/analysis/src/main/scala/docspell/analysis/date/DateFind.scala index 1260a3db..c78bc81b 100644 --- a/modules/analysis/src/main/scala/docspell/analysis/date/DateFind.scala +++ b/modules/analysis/src/main/scala/docspell/analysis/date/DateFind.scala @@ -125,6 +125,7 @@ object DateFind { case Language.Dutch => dmy.or(ymd).or(mdy) case Language.Latvian => dmy.or(lavLong).or(ymd) case Language.Japanese => ymd + case Language.JpnVert => ymd case Language.Hebrew => dmy case Language.Lithuanian => ymd case Language.Polish => dmy diff --git a/modules/analysis/src/main/scala/docspell/analysis/date/MonthName.scala b/modules/analysis/src/main/scala/docspell/analysis/date/MonthName.scala index b646b46b..4693440e 100644 --- a/modules/analysis/src/main/scala/docspell/analysis/date/MonthName.scala +++ b/modules/analysis/src/main/scala/docspell/analysis/date/MonthName.scala @@ -54,6 +54,8 @@ object MonthName { latvian case Language.Japanese => japanese + case Language.JpnVert => + japanese case Language.Hebrew => hebrew case Language.Lithuanian => diff --git a/modules/analysis/src/test/scala/docspell/analysis/nlp/StanfordNerAnnotatorSuite.scala b/modules/analysis/src/test/scala/docspell/analysis/nlp/StanfordNerAnnotatorSuite.scala index 15bc0704..fc4b0010 100644 --- a/modules/analysis/src/test/scala/docspell/analysis/nlp/StanfordNerAnnotatorSuite.scala +++ b/modules/analysis/src/test/scala/docspell/analysis/nlp/StanfordNerAnnotatorSuite.scala @@ -22,7 +22,7 @@ import munit._ class StanfordNerAnnotatorSuite extends FunSuite with TestLoggingConfig { lazy val germanClassifier = - new StanfordCoreNLP(Properties.nerGerman(None, false)) + new StanfordCoreNLP(Properties.nerGerman(None, highRecall = false)) lazy val englishClassifier = new StanfordCoreNLP(Properties.nerEnglish(None)) diff --git a/modules/backend/src/main/scala/docspell/backend/Config.scala b/modules/backend/src/main/scala/docspell/backend/Config.scala index 721f30d5..9f4497fc 100644 --- a/modules/backend/src/main/scala/docspell/backend/Config.scala +++ b/modules/backend/src/main/scala/docspell/backend/Config.scala @@ -90,6 +90,6 @@ object Config { } object Addons { val disabled: Addons = - Addons(false, false, UrlMatcher.False, UrlMatcher.True) + Addons(enabled = false, allowImpure = false, UrlMatcher.False, UrlMatcher.True) } } diff --git a/modules/backend/src/main/scala/docspell/backend/auth/Login.scala b/modules/backend/src/main/scala/docspell/backend/auth/Login.scala index f8003505..00403b7f 100644 --- a/modules/backend/src/main/scala/docspell/backend/auth/Login.scala +++ b/modules/backend/src/main/scala/docspell/backend/auth/Login.scala @@ -127,7 +127,7 @@ object Login { _ <- logF.trace(s"Account lookup: $data") res <- data match { case Some(d) if checkNoPassword(d, Set(AccountSource.OpenId)) => - doLogin(config, d.account, false) + doLogin(config, d.account, rememberMe = false) case Some(d) if checkNoPassword(d, Set(AccountSource.Local)) => config.onAccountSourceConflict match { case OnAccountSourceConflict.Fail => @@ -145,7 +145,7 @@ object Login { AccountSource.OpenId ) ) - res <- doLogin(config, d.account, false) + res <- doLogin(config, d.account, rememberMe = false) } yield res } case _ => @@ -212,7 +212,12 @@ object Login { val okResult: F[Result] = for { _ <- store.transact(RUser.updateLogin(sf.token.account)) - newToken <- AuthToken.user(sf.token.account, false, config.serverSecret, None) + newToken <- AuthToken.user( + sf.token.account, + requireSecondFactor = false, + config.serverSecret, + None + ) rem <- OptionT .whenF(sf.rememberMe && config.rememberMe.enabled)( insertRememberToken(store, sf.token.account, config) @@ -239,7 +244,9 @@ object Login { (for { _ <- validateToken key <- EitherT.fromOptionF( - store.transact(RTotp.findEnabledByUserId(sf.token.account.userId, true)), + store.transact( + RTotp.findEnabledByUserId(sf.token.account.userId, enabled = true) + ), Result.invalidAuth ) now <- EitherT.right[Result](Timestamp.current[F]) @@ -255,7 +262,12 @@ object Login { def okResult(acc: AccountInfo) = for { _ <- store.transact(RUser.updateLogin(acc)) - token <- AuthToken.user(acc, false, config.serverSecret, None) + token <- AuthToken.user( + acc, + requireSecondFactor = false, + config.serverSecret, + None + ) } yield Result.ok(token, None) def rememberedLogin(rid: Ident) = diff --git a/modules/backend/src/main/scala/docspell/backend/joex/AddonOps.scala b/modules/backend/src/main/scala/docspell/backend/joex/AddonOps.scala index 1cfa2a9e..52ccaf8c 100644 --- a/modules/backend/src/main/scala/docspell/backend/joex/AddonOps.scala +++ b/modules/backend/src/main/scala/docspell/backend/joex/AddonOps.scala @@ -93,7 +93,7 @@ object AddonOps { AddonResult.executionFailed( new Exception(s"Addon run config ${id.id} not found.") ) :: Nil, - false + pure = false ) :: Nil, Nil ) diff --git a/modules/backend/src/main/scala/docspell/backend/joex/AddonPrepare.scala b/modules/backend/src/main/scala/docspell/backend/joex/AddonPrepare.scala index 505b781d..63d4c7d0 100644 --- a/modules/backend/src/main/scala/docspell/backend/joex/AddonPrepare.scala +++ b/modules/backend/src/main/scala/docspell/backend/joex/AddonPrepare.scala @@ -72,7 +72,7 @@ private[joex] class AddonPrepare[F[_]: Sync](store: Store[F]) extends LoggerExte token <- AuthToken.user( account, - false, + requireSecondFactor = false, secret.getOrElse(ByteVector.empty), tokenValidity.some ) diff --git a/modules/backend/src/main/scala/docspell/backend/ops/OCollective.scala b/modules/backend/src/main/scala/docspell/backend/ops/OCollective.scala index d96a7333..b75db20e 100644 --- a/modules/backend/src/main/scala/docspell/backend/ops/OCollective.scala +++ b/modules/backend/src/main/scala/docspell/backend/ops/OCollective.scala @@ -194,7 +194,14 @@ object OCollective { id <- Ident.randomId[F] settings = sett.emptyTrash.getOrElse(EmptyTrash.default) args = EmptyTrashArgs(cid, settings.minAge) - ut = UserTask(id, EmptyTrashArgs.taskName, true, settings.schedule, None, args) + ut = UserTask( + id, + EmptyTrashArgs.taskName, + enabled = true, + settings.schedule, + None, + args + ) _ <- uts.updateOneTask(UserTaskScope.collective(cid), args.makeSubject.some, ut) _ <- joex.notifyAllNodes } yield () @@ -220,7 +227,7 @@ object OCollective { ut = UserTask( id, LearnClassifierArgs.taskName, - true, + enabled = true, CalEvent(WeekdayComponent.All, DateEvent.All, TimeEvent.All), None, args @@ -239,7 +246,7 @@ object OCollective { ut = UserTask( id, EmptyTrashArgs.taskName, - true, + enabled = true, CalEvent(WeekdayComponent.All, DateEvent.All, TimeEvent.All), None, args diff --git a/modules/backend/src/main/scala/docspell/backend/ops/ONotification.scala b/modules/backend/src/main/scala/docspell/backend/ops/ONotification.scala index 445efab6..1cfb793b 100644 --- a/modules/backend/src/main/scala/docspell/backend/ops/ONotification.scala +++ b/modules/backend/src/main/scala/docspell/backend/ops/ONotification.scala @@ -114,14 +114,14 @@ object ONotification { ) _ <- notMod.send(logbuf._2.andThen(log), ev, ch) logs <- logbuf._1.get - res = SendTestResult(true, logs) + res = SendTestResult(success = true, logs) } yield res).attempt .map { case Right(res) => res case Left(ex) => val ev = LogEvent.of(Level.Error, "Failed sending sample event").addError(ex) - SendTestResult(false, Vector(ev)) + SendTestResult(success = false, Vector(ev)) } def listChannels(userId: Ident): F[Vector[Channel]] = diff --git a/modules/backend/src/main/scala/docspell/backend/ops/OTotp.scala b/modules/backend/src/main/scala/docspell/backend/ops/OTotp.scala index 4f18a52a..768ba552 100644 --- a/modules/backend/src/main/scala/docspell/backend/ops/OTotp.scala +++ b/modules/backend/src/main/scala/docspell/backend/ops/OTotp.scala @@ -120,7 +120,9 @@ object OTotp { def confirmInit(accountId: AccountInfo, otp: OnetimePassword): F[ConfirmResult] = for { _ <- log.info(s"Confirm TOTP setup for account ${accountId.asString}") - key <- store.transact(RTotp.findEnabledByUserId(accountId.userId, false)) + key <- store.transact( + RTotp.findEnabledByUserId(accountId.userId, enabled = false) + ) now <- Timestamp.current[F] res <- key match { case None => @@ -129,7 +131,7 @@ object OTotp { val check = totp.checkPassword(r.secret, otp, now.value) if (check) store - .transact(RTotp.setEnabled(accountId.userId, true)) + .transact(RTotp.setEnabled(accountId.userId, enabled = true)) .map(_ => ConfirmResult.Success) else ConfirmResult.Failed.pure[F] } @@ -140,7 +142,7 @@ object OTotp { case Some(pw) => for { _ <- log.info(s"Validating TOTP, because it is requested to disable it.") - key <- store.transact(RTotp.findEnabledByLogin(accountId, true)) + key <- store.transact(RTotp.findEnabledByLogin(accountId, enabled = true)) now <- Timestamp.current[F] res <- key match { case None => @@ -149,7 +151,7 @@ object OTotp { val check = totp.checkPassword(r.secret, pw, now.value) if (check) UpdateResult.fromUpdate( - store.transact(RTotp.setEnabled(r.userId, false)) + store.transact(RTotp.setEnabled(r.userId, enabled = false)) ) else log.info(s"TOTP code was invalid. Not disabling it.") *> UpdateResult @@ -160,15 +162,15 @@ object OTotp { case None => UpdateResult.fromUpdate { (for { - key <- OptionT(RTotp.findEnabledByLogin(accountId, true)) - n <- OptionT.liftF(RTotp.setEnabled(key.userId, false)) + key <- OptionT(RTotp.findEnabledByLogin(accountId, enabled = true)) + n <- OptionT.liftF(RTotp.setEnabled(key.userId, enabled = false)) } yield n).mapK(store.transform).getOrElse(0) } } def state(acc: AccountInfo): F[OtpState] = for { - record <- store.transact(RTotp.findEnabledByUserId(acc.userId, true)) + record <- store.transact(RTotp.findEnabledByUserId(acc.userId, enabled = true)) result = record match { case Some(r) => OtpState.Enabled(r.created) diff --git a/modules/backend/src/main/scala/docspell/backend/ops/OUpload.scala b/modules/backend/src/main/scala/docspell/backend/ops/OUpload.scala index 398543d4..a5e5f9eb 100644 --- a/modules/backend/src/main/scala/docspell/backend/ops/OUpload.scala +++ b/modules/backend/src/main/scala/docspell/backend/ops/OUpload.scala @@ -159,7 +159,7 @@ object OUpload { data.meta.skipDuplicates, data.meta.fileFilter.some, data.meta.tags.some, - false, + reprocess = false, data.meta.attachmentsOnly, data.meta.customData ) diff --git a/modules/backend/src/test/scala/docspell/backend/auth/AuthTokenTest.scala b/modules/backend/src/test/scala/docspell/backend/auth/AuthTokenTest.scala index 8c6e111f..4f453bf3 100644 --- a/modules/backend/src/test/scala/docspell/backend/auth/AuthTokenTest.scala +++ b/modules/backend/src/test/scala/docspell/backend/auth/AuthTokenTest.scala @@ -32,9 +32,12 @@ class AuthTokenTest extends CatsEffectSuite { val otherSecret = ByteVector.fromValidHex("16bad") test("validate") { - val token1 = AuthToken.user[IO](user, false, secret, None).unsafeRunSync() + val token1 = + AuthToken.user[IO](user, requireSecondFactor = false, secret, None).unsafeRunSync() val token2 = - AuthToken.user[IO](user, false, secret, Duration.seconds(10).some).unsafeRunSync() + AuthToken + .user[IO](user, requireSecondFactor = false, secret, Duration.seconds(10).some) + .unsafeRunSync() assert(token1.validate(secret, Duration.seconds(5))) assert(!token1.validate(otherSecret, Duration.seconds(5))) assert(!token1.copy(account = john).validate(secret, Duration.seconds(5))) @@ -46,9 +49,12 @@ class AuthTokenTest extends CatsEffectSuite { } test("signature") { - val token1 = AuthToken.user[IO](user, false, secret, None).unsafeRunSync() + val token1 = + AuthToken.user[IO](user, requireSecondFactor = false, secret, None).unsafeRunSync() val token2 = - AuthToken.user[IO](user, false, secret, Duration.seconds(10).some).unsafeRunSync() + AuthToken + .user[IO](user, requireSecondFactor = false, secret, Duration.seconds(10).some) + .unsafeRunSync() assert(token1.sigValid(secret)) assert(token1.sigInvalid(otherSecret)) diff --git a/modules/common/src/main/scala/docspell/common/Language.scala b/modules/common/src/main/scala/docspell/common/Language.scala index 7b7ef815..d1ae6e06 100644 --- a/modules/common/src/main/scala/docspell/common/Language.scala +++ b/modules/common/src/main/scala/docspell/common/Language.scala @@ -123,6 +123,11 @@ object Language { val iso3 = "jpn" } + /*It's not an ISO value, but this needs to be unique and tesseract will need jpn_vert for it's scan from the config of /etc/docspell-joex/docspell-joex.conf.*/ + case object JpnVert extends Language { + val iso2 = "ja_vert" + val iso3 = "jpn_vert" + } case object Hebrew extends Language { val iso2 = "he" val iso3 = "heb" @@ -172,6 +177,7 @@ object Language { Romanian, Latvian, Japanese, + JpnVert, Hebrew, Lithuanian, Polish, diff --git a/modules/common/src/main/scala/docspell/common/LenientUri.scala b/modules/common/src/main/scala/docspell/common/LenientUri.scala index c9f797ab..2e2e17a0 100644 --- a/modules/common/src/main/scala/docspell/common/LenientUri.scala +++ b/modules/common/src/main/scala/docspell/common/LenientUri.scala @@ -78,7 +78,11 @@ case class LenientUri( .covary[F] .rethrow .flatMap(url => - fs2.io.readInputStream(Sync[F].delay(url.openStream()), chunkSize, true) + fs2.io.readInputStream( + Sync[F].delay(url.openStream()), + chunkSize, + closeAfterUse = true + ) ) def readText[F[_]: Sync](chunkSize: Int): F[String] = @@ -121,7 +125,7 @@ object LenientUri { val isRoot = true val isEmpty = false def /(seg: String): Path = - NonEmptyPath(NonEmptyList.of(seg), false) + NonEmptyPath(NonEmptyList.of(seg), trailingSlash = false) def asString = "/" } case object EmptyPath extends Path { @@ -129,7 +133,7 @@ object LenientUri { val isRoot = false val isEmpty = true def /(seg: String): Path = - NonEmptyPath(NonEmptyList.of(seg), false) + NonEmptyPath(NonEmptyList.of(seg), trailingSlash = false) def asString = "" } case class NonEmptyPath(segs: NonEmptyList[String], trailingSlash: Boolean) diff --git a/modules/common/src/main/scala/docspell/common/MimeType.scala b/modules/common/src/main/scala/docspell/common/MimeType.scala index 9a0e29af..8b74a2c7 100644 --- a/modules/common/src/main/scala/docspell/common/MimeType.scala +++ b/modules/common/src/main/scala/docspell/common/MimeType.scala @@ -194,7 +194,7 @@ object MimeType { val csValueStart = in.substring(n + "charset=".length).trim val csName = csValueStart.indexOf(';') match { case -1 => unquote(csValueStart).trim - case n => unquote(csValueStart.substring(0, n)).trim + case n2 => unquote(csValueStart.substring(0, n2)).trim } if (Charset.isSupported(csName)) Right((Some(Charset.forName(csName)), "")) else Right((None, "")) diff --git a/modules/common/src/main/scala/docspell/common/SystemCommand.scala b/modules/common/src/main/scala/docspell/common/SystemCommand.scala deleted file mode 100644 index 702c546d..00000000 --- a/modules/common/src/main/scala/docspell/common/SystemCommand.scala +++ /dev/null @@ -1,212 +0,0 @@ -/* - * Copyright 2020 Eike K. & Contributors - * - * SPDX-License-Identifier: AGPL-3.0-or-later - */ - -package docspell.common - -import java.io.InputStream -import java.lang.ProcessBuilder.Redirect -import java.util.concurrent.TimeUnit - -import scala.jdk.CollectionConverters._ - -import cats.effect._ -import cats.implicits._ -import fs2.io.file.Path -import fs2.{Stream, io, text} - -import docspell.common.{exec => newExec} -import docspell.logging.Logger - -// better use `SysCmd` and `SysExec` -object SystemCommand { - - final case class Config( - program: String, - args: Seq[String], - timeout: Duration, - env: Map[String, String] = Map.empty - ) { - - def toSysCmd = newExec - .SysCmd(program, newExec.Args(args)) - .withTimeout(timeout) - .addEnv(newExec.Env(env)) - - def mapArgs(f: String => String): Config = - Config(program, args.map(f), timeout) - - def replace(repl: Map[String, String]): Config = - mapArgs(s => - repl.foldLeft(s) { case (res, (k, v)) => - res.replace(k, v) - } - ) - - def withEnv(key: String, value: String): Config = - copy(env = env.updated(key, value)) - - def addEnv(moreEnv: Map[String, String]): Config = - copy(env = env ++ moreEnv) - - def appendArgs(extraArgs: Args): Config = - copy(args = args ++ extraArgs.args) - - def appendArgs(extraArgs: Seq[String]): Config = - copy(args = args ++ extraArgs) - - def toCmd: List[String] = - program :: args.toList - - lazy val cmdString: String = - toCmd.mkString(" ") - } - - final case class Args(args: Vector[String]) extends Iterable[String] { - override def iterator = args.iterator - - def prepend(a: String): Args = Args(a +: args) - - def prependWhen(flag: Boolean)(a: String): Args = - prependOption(Option.when(flag)(a)) - - def prependOption(value: Option[String]): Args = - value.map(prepend).getOrElse(this) - - def append(a: String, as: String*): Args = - Args(args ++ (a +: as.toVector)) - - def appendOption(value: Option[String]): Args = - value.map(append(_)).getOrElse(this) - - def appendOptionVal(first: String, second: Option[String]): Args = - second.map(b => append(first, b)).getOrElse(this) - - def appendWhen(flag: Boolean)(a: String, as: String*): Args = - if (flag) append(a, as: _*) else this - - def appendWhenNot(flag: Boolean)(a: String, as: String*): Args = - if (!flag) append(a, as: _*) else this - - def append(p: Path): Args = - append(p.toString) - - def append(as: Iterable[String]): Args = - Args(args ++ as.toVector) - } - object Args { - val empty: Args = Args() - - def apply(as: String*): Args = - Args(as.toVector) - } - - final case class Result(rc: Int, stdout: String, stderr: String) - - def exec[F[_]: Sync]( - cmd: Config, - logger: Logger[F], - wd: Option[Path] = None, - stdin: Stream[F, Byte] = Stream.empty - ): Stream[F, Result] = - startProcess(cmd, wd, logger, stdin) { proc => - Stream.eval { - for { - _ <- writeToProcess(stdin, proc) - term <- Sync[F].blocking(proc.waitFor(cmd.timeout.seconds, TimeUnit.SECONDS)) - _ <- - if (term) - logger.debug(s"Command `${cmd.cmdString}` finished: ${proc.exitValue}") - else - logger.warn( - s"Command `${cmd.cmdString}` did not finish in ${cmd.timeout.formatExact}!" - ) - _ <- if (!term) timeoutError(proc, cmd) else Sync[F].pure(()) - out <- - if (term) inputStreamToString(proc.getInputStream) - else Sync[F].pure("") - err <- - if (term) inputStreamToString(proc.getErrorStream) - else Sync[F].pure("") - } yield Result(proc.exitValue, out, err) - } - } - - def execSuccess[F[_]: Sync]( - cmd: Config, - logger: Logger[F], - wd: Option[Path] = None, - stdin: Stream[F, Byte] = Stream.empty - ): Stream[F, Result] = - exec(cmd, logger, wd, stdin).flatMap { r => - if (r.rc != 0) - Stream.raiseError[F]( - new Exception( - s"Command `${cmd.cmdString}` returned non-zero exit code ${r.rc}. Stderr: ${r.stderr}" - ) - ) - else Stream.emit(r) - } - - private def startProcess[F[_]: Sync, A]( - cmd: Config, - wd: Option[Path], - logger: Logger[F], - stdin: Stream[F, Byte] - )( - f: Process => Stream[F, A] - ): Stream[F, A] = { - val log = logger.debug(s"Running external command: ${cmd.cmdString}") - val hasStdin = stdin.take(1).compile.last.map(_.isDefined) - val proc = log *> hasStdin.flatMap(flag => - Sync[F].blocking { - val pb = new ProcessBuilder(cmd.toCmd.asJava) - .redirectInput(if (flag) Redirect.PIPE else Redirect.INHERIT) - .redirectError(Redirect.PIPE) - .redirectOutput(Redirect.PIPE) - - val pbEnv = pb.environment() - cmd.env.foreach { case (key, value) => - pbEnv.put(key, value) - } - wd.map(_.toNioPath.toFile).foreach(pb.directory) - pb.start() - } - ) - Stream - .bracket(proc)(p => - logger.debug(s"Closing process: `${cmd.cmdString}`").map(_ => p.destroy()) - ) - .flatMap(f) - } - - private def inputStreamToString[F[_]: Sync](in: InputStream): F[String] = - io.readInputStream(Sync[F].pure(in), 16 * 1024, closeAfterUse = false) - .through(text.utf8.decode) - .chunks - .map(_.toVector.mkString) - .fold1(_ + _) - .compile - .last - .map(_.getOrElse("")) - - private def writeToProcess[F[_]: Sync]( - data: Stream[F, Byte], - proc: Process - ): F[Unit] = - data - .through(io.writeOutputStream(Sync[F].blocking(proc.getOutputStream))) - .compile - .drain - - private def timeoutError[F[_]: Sync](proc: Process, cmd: Config): F[Unit] = - Sync[F].blocking(proc.destroyForcibly()).attempt *> { - Sync[F].raiseError( - new Exception( - s"Command `${cmd.cmdString}` timed out (${cmd.timeout.formatExact})" - ) - ) - } -} diff --git a/modules/common/src/main/scala/docspell/common/UrlMatcher.scala b/modules/common/src/main/scala/docspell/common/UrlMatcher.scala index de978dd9..7c58d5d7 100644 --- a/modules/common/src/main/scala/docspell/common/UrlMatcher.scala +++ b/modules/common/src/main/scala/docspell/common/UrlMatcher.scala @@ -62,7 +62,7 @@ object UrlMatcher { // strip path to only match prefixes val mPath: LenientUri.Path = NonEmptyList.fromList(url.path.segments.take(pathSegmentCount)) match { - case Some(nel) => LenientUri.NonEmptyPath(nel, false) + case Some(nel) => LenientUri.NonEmptyPath(nel, trailingSlash = false) case None => LenientUri.RootPath } diff --git a/modules/common/src/main/scala/docspell/common/exec/Env.scala b/modules/common/src/main/scala/docspell/common/exec/Env.scala index 2524d35a..c4bdfafb 100644 --- a/modules/common/src/main/scala/docspell/common/exec/Env.scala +++ b/modules/common/src/main/scala/docspell/common/exec/Env.scala @@ -17,6 +17,9 @@ case class Env(values: Map[String, String]) { def addAll(e: Env): Env = Env(values ++ e.values) + def modifyValue(f: String => String): Env = + Env(values.view.mapValues(f).toMap) + def ++(e: Env) = addAll(e) def foreach(f: (String, String) => Unit): Unit = diff --git a/modules/common/src/main/scala/docspell/common/exec/ExternalCommand.scala b/modules/common/src/main/scala/docspell/common/exec/ExternalCommand.scala new file mode 100644 index 00000000..47b003b0 --- /dev/null +++ b/modules/common/src/main/scala/docspell/common/exec/ExternalCommand.scala @@ -0,0 +1,89 @@ +/* + * Copyright 2020 Eike K. & Contributors + * + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +package docspell.common.exec + +import docspell.common.Duration +import docspell.common.Ident +import docspell.common.exec.Env +import docspell.common.exec.ExternalCommand.ArgMapping +import docspell.common.exec.SysCmd + +final case class ExternalCommand( + program: String, + args: Seq[String], + timeout: Duration, + env: Map[String, String] = Map.empty, + argMappings: Map[Ident, ArgMapping] = Map.empty +) { + def withVars(vars: Map[String, String]): ExternalCommand.WithVars = + ExternalCommand.WithVars(this, vars) + + import ExternalCommand.pattern + + def resolve(vars: Map[String, String]): SysCmd = { + val replace = ExternalCommand.replaceString(vars) _ + val resolvedArgMappings = + argMappings.view.mapValues(_.resolve(replace).firstMatch).toMap + val resolvedArgs = args.map(replace).flatMap { arg => + resolvedArgMappings + .find(e => pattern(e._1.id) == arg) + .map(_._2) + .getOrElse(List(arg)) + } + + SysCmd(replace(program), resolvedArgs: _*) + .withTimeout(timeout) + .withEnv(_ => Env(env).modifyValue(replace)) + } +} + +object ExternalCommand { + private val openPattern = "{{" + private val closePattern = "}}" + + private def pattern(s: String): String = s"${openPattern}${s}${closePattern}" + + def apply(program: String, args: Seq[String], timeout: Duration): ExternalCommand = + ExternalCommand(program, args, timeout, Map.empty, Map.empty) + + final case class ArgMapping( + value: String, + mappings: List[ArgMatch] + ) { + private[exec] def resolve(replace: String => String): ArgMapping = + ArgMapping(replace(value), mappings.map(_.resolve(replace))) + + def firstMatch: List[String] = + mappings.find(am => value.matches(am.matches)).map(_.args).getOrElse(Nil) + } + + final case class ArgMatch( + matches: String, + args: List[String] + ) { + private[exec] def resolve(replace: String => String): ArgMatch = + ArgMatch(replace(matches), args.map(replace)) + } + + private def replaceString(vars: Map[String, String])(in: String): String = + vars.foldLeft(in) { case (result, (name, value)) => + val key = s"{{$name}}" + result.replace(key, value) + } + + final case class WithVars(cmd: ExternalCommand, vars: Map[String, String]) { + def resolved: SysCmd = cmd.resolve(vars) + def append(more: (String, String)*): WithVars = + WithVars(cmd, vars ++ more.toMap) + + def withVar(key: String, value: String): WithVars = + WithVars(cmd, vars.updated(key, value)) + + def withVarOption(key: String, value: Option[String]): WithVars = + value.map(withVar(key, _)).getOrElse(this) + } +} diff --git a/modules/common/src/main/scala/docspell/common/exec/SysExec.scala b/modules/common/src/main/scala/docspell/common/exec/SysExec.scala index da7b10c2..a53a4c6f 100644 --- a/modules/common/src/main/scala/docspell/common/exec/SysExec.scala +++ b/modules/common/src/main/scala/docspell/common/exec/SysExec.scala @@ -38,6 +38,20 @@ trait SysExec[F[_]] { def waitFor(timeout: Option[Duration] = None): F[Int] + /** Uses `waitFor` and throws when return code is non-zero. Logs stderr and stdout while + * waiting. + */ + def runToSuccess(logger: Logger[F], timeout: Option[Duration] = None)(implicit + F: Async[F] + ): F[Int] + + /** Uses `waitFor` and throws when return code is non-zero. Logs stderr while waiting + * and collects stdout once finished successfully. + */ + def runToSuccessStdout(logger: Logger[F], timeout: Option[Duration] = None)(implicit + F: Async[F] + ): F[String] + /** Sends a signal to the process to terminate it immediately */ def cancel: F[Unit] @@ -75,6 +89,12 @@ object SysExec { proc <- startProcess(logger, cmd, workdir, stdin) fibers <- Resource.eval(Ref.of[F, List[F[Unit]]](Nil)) } yield new SysExec[F] { + private lazy val basicName: String = + cmd.program.lastIndexOf(java.io.File.separatorChar.toInt) match { + case n if n > 0 => cmd.program.drop(n + 1) + case _ => cmd.program.takeRight(16) + } + def stdout: Stream[F, Byte] = fs2.io.readInputStream( Sync[F].blocking(proc.getInputStream), @@ -107,6 +127,39 @@ object SysExec { ) } + def runToSuccess(logger: Logger[F], timeout: Option[Duration])(implicit + F: Async[F] + ): F[Int] = + logOutputs(logger, basicName).use(_.waitFor(timeout).flatMap { + case rc if rc == 0 => Sync[F].pure(0) + case rc => + Sync[F].raiseError( + new Exception(s"Command `${cmd.program}` returned non-zero exit code ${rc}") + ) + }) + + def runToSuccessStdout(logger: Logger[F], timeout: Option[Duration])(implicit + F: Async[F] + ): F[String] = + F.background( + stderrLines + .through(line => Stream.eval(logger.debug(s"[$basicName (err)]: $line"))) + .compile + .drain + ).use { f1 => + waitFor(timeout) + .flatMap { + case rc if rc == 0 => stdout.through(fs2.text.utf8.decode).compile.string + case rc => + Sync[F].raiseError[String]( + new Exception( + s"Command `${cmd.program}` returned non-zero exit code ${rc}" + ) + ) + } + .flatTap(_ => f1) + } + def consumeOutputs(out: Pipe[F, String, Unit], err: Pipe[F, String, Unit])(implicit F: Async[F] ): Resource[F, SysExec[F]] = diff --git a/modules/common/src/main/scala/docspell/common/util/Directory.scala b/modules/common/src/main/scala/docspell/common/util/Directory.scala index fcde4ebb..8002bc85 100644 --- a/modules/common/src/main/scala/docspell/common/util/Directory.scala +++ b/modules/common/src/main/scala/docspell/common/util/Directory.scala @@ -6,6 +6,7 @@ package docspell.common.util +import cats.data.OptionT import cats.effect._ import cats.syntax.all._ import cats.{Applicative, Monad} @@ -26,10 +27,10 @@ object Directory { (dir :: dirs.toList).traverse_(Files[F].createDirectories(_)) def nonEmpty[F[_]: Files: Sync](dir: Path): F[Boolean] = - List( - Files[F].isDirectory(dir), - Files[F].list(dir).take(1).compile.last.map(_.isDefined) - ).sequence.map(_.forall(identity)) + OptionT + .whenM(Files[F].isDirectory(dir))(Files[F].list(dir).take(1).compile.toList) + .map(_.nonEmpty) + .isDefined def isEmpty[F[_]: Files: Sync](dir: Path): F[Boolean] = nonEmpty(dir).map(b => !b) diff --git a/modules/common/src/test/scala/docspell/common/exec/ExternalCommandTest.scala b/modules/common/src/test/scala/docspell/common/exec/ExternalCommandTest.scala new file mode 100644 index 00000000..120e68cf --- /dev/null +++ b/modules/common/src/test/scala/docspell/common/exec/ExternalCommandTest.scala @@ -0,0 +1,74 @@ +/* + * Copyright 2020 Eike K. & Contributors + * + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +package docspell.common.exec + +import docspell.common.Duration +import docspell.common.Ident +import docspell.common.exec.Args +import docspell.common.exec.Env +import docspell.common.exec.ExternalCommand._ +import docspell.common.exec.SysCmd + +import munit.FunSuite + +class ExternalCommandTest extends FunSuite { + + test("resolve") { + val cmd = ExternalCommand( + program = "tesseract", + args = "{{infile}}" :: "{{lang-spec}}" :: "out" :: "pdf" :: "txt" :: Nil, + timeout = Duration.minutes(5), + env = Map.empty, + argMappings = Map( + Ident.unsafe("lang-spec") -> ArgMapping( + value = "{{lang}}", + mappings = List( + ArgMatch( + matches = "jpn_vert", + args = List("-l", "jpn_vert", "-c", "preserve_interword_spaces=1") + ), + ArgMatch( + matches = ".*", + args = List("-l", "{{lang}}") + ) + ) + ) + ) + ) + + val varsDe = Map("lang" -> "de", "encoding" -> "UTF_8", "infile" -> "text.jpg") + assertEquals( + cmd.resolve(varsDe), + SysCmd( + "tesseract", + Args.of("text.jpg", "-l", "de", "out", "pdf", "txt"), + Env.empty, + Duration.minutes(5) + ) + ) + + val varsJpnVert = varsDe.updated("lang", "jpn_vert") + assertEquals( + cmd.resolve(varsJpnVert), + SysCmd( + "tesseract", + Args.of( + "text.jpg", + "-l", + "jpn_vert", + "-c", + "preserve_interword_spaces=1", + "out", + "pdf", + "txt" + ), + Env.empty, + Duration.minutes(5) + ) + ) + } +} diff --git a/modules/common/src/test/scala/docspell/common/util/DirectoryTest.scala b/modules/common/src/test/scala/docspell/common/util/DirectoryTest.scala index a760dcc1..7d1cf6d1 100644 --- a/modules/common/src/test/scala/docspell/common/util/DirectoryTest.scala +++ b/modules/common/src/test/scala/docspell/common/util/DirectoryTest.scala @@ -16,7 +16,7 @@ import munit.CatsEffectSuite class DirectoryTest extends CatsEffectSuite with TestLoggingConfig { val logger = docspell.logging.getLogger[IO] - val tempDir = ResourceFixture( + val tempDir = ResourceFunFixture( Files[IO].tempDirectory(Path("target").some, "directory-test-", None) ) diff --git a/modules/convert/src/main/scala/docspell/convert/extern/ExternConv.scala b/modules/convert/src/main/scala/docspell/convert/extern/ExternConv.scala index 5f1253f5..0b7981cd 100644 --- a/modules/convert/src/main/scala/docspell/convert/extern/ExternConv.scala +++ b/modules/convert/src/main/scala/docspell/convert/extern/ExternConv.scala @@ -11,7 +11,8 @@ import cats.implicits._ import fs2.io.file.{Files, Path} import fs2.{Pipe, Stream} -import docspell.common._ +import docspell.common.exec.ExternalCommand +import docspell.common.exec.SysExec import docspell.common.util.File import docspell.convert.ConversionResult import docspell.convert.ConversionResult.{Handler, successPdf, successPdfTxt} @@ -21,11 +22,11 @@ private[extern] object ExternConv { def toPDF[F[_]: Async: Files, A]( name: String, - cmdCfg: SystemCommand.Config, + cmdCfg: ExternalCommand.WithVars, wd: Path, useStdin: Boolean, logger: Logger[F], - reader: (Path, SystemCommand.Result) => F[ConversionResult[F]] + reader: (Path, Int) => F[ConversionResult[F]] )(in: Stream[F, Byte], handler: Handler[F, A]): F[A] = Stream .resource(File.withTempDir[F](wd, s"docspell-$name")) @@ -33,32 +34,21 @@ private[extern] object ExternConv { val inFile = dir.resolve("infile").absolute.normalize val out = dir.resolve("out.pdf").absolute.normalize val sysCfg = - cmdCfg.replace( - Map( - "{{outfile}}" -> out.toString - ) ++ - (if (!useStdin) Map("{{infile}}" -> inFile.toString) - else Map.empty) - ) + cmdCfg + .withVar("outfile", out.toString) + .withVarOption("infile", Option.when(!useStdin)(inFile.toString)) + .resolved val createInput: Pipe[F, Byte, Unit] = if (useStdin) _ => Stream.emit(()) else storeDataToFile(name, logger, inFile) - in.through(createInput).flatMap { _ => - SystemCommand - .exec[F]( - sysCfg, - logger, - Some(dir), - if (useStdin) in - else Stream.empty - ) - .evalMap(result => - logResult(name, result, logger) - .flatMap(_ => reader(out, result)) - .flatMap(handler.run) - ) + in.through(createInput).evalMap { _ => + SysExec(sysCfg, logger, Some(dir), Option.when(useStdin)(in)) + .flatMap(_.logOutputs(logger, name)) + .use { proc => + proc.waitFor().flatMap(rc => reader(out, rc).flatMap(handler.run)) + } } } .compile @@ -74,9 +64,9 @@ private[extern] object ExternConv { def readResult[F[_]: Async: Files]( chunkSize: Int, logger: Logger[F] - )(out: Path, result: SystemCommand.Result): F[ConversionResult[F]] = + )(out: Path, result: Int): F[ConversionResult[F]] = File.existsNonEmpty[F](out).flatMap { - case true if result.rc == 0 => + case true if result == 0 => val outTxt = out.resolveSibling(out.fileName.toString + ".txt") File.existsNonEmpty[F](outTxt).flatMap { case true => @@ -88,13 +78,13 @@ private[extern] object ExternConv { successPdf(File.readAll(out, chunkSize)).pure[F] } case true => - logger.warn(s"Command not successful (rc=${result.rc}), but file exists.") *> + logger.warn(s"Command not successful (rc=${result}), but file exists.") *> successPdf(File.readAll(out, chunkSize)).pure[F] case false => ConversionResult .failure[F]( - new Exception(s"Command result=${result.rc}. No output file found.") + new Exception(s"Command result=${result}. No output file found.") ) .pure[F] } @@ -103,25 +93,25 @@ private[extern] object ExternConv { outPrefix: String, chunkSize: Int, logger: Logger[F] - )(out: Path, result: SystemCommand.Result): F[ConversionResult[F]] = { + )(out: Path, result: Int): F[ConversionResult[F]] = { val outPdf = out.resolveSibling(s"$outPrefix.pdf") File.existsNonEmpty[F](outPdf).flatMap { case true => val outTxt = out.resolveSibling(s"$outPrefix.txt") File.exists(outTxt).flatMap { txtExists => val pdfData = File.readAll(out, chunkSize) - if (result.rc == 0) + if (result == 0) if (txtExists) successPdfTxt(pdfData, File.readText(outTxt)).pure[F] else successPdf(pdfData).pure[F] else - logger.warn(s"Command not successful (rc=${result.rc}), but file exists.") *> + logger.warn(s"Command not successful (rc=${result}), but file exists.") *> successPdf(pdfData).pure[F] } case false => ConversionResult .failure[F]( - new Exception(s"Command result=${result.rc}. No output file found.") + new Exception(s"Command result=${result}. No output file found.") ) .pure[F] } @@ -138,14 +128,6 @@ private[extern] object ExternConv { .drain ++ Stream.eval(storeFile(in, inFile)) - private def logResult[F[_]: Sync]( - name: String, - result: SystemCommand.Result, - logger: Logger[F] - ): F[Unit] = - logger.debug(s"$name stdout: ${result.stdout}") *> - logger.debug(s"$name stderr: ${result.stderr}") - private def storeFile[F[_]: Async: Files]( in: Stream[F, Byte], target: Path diff --git a/modules/convert/src/main/scala/docspell/convert/extern/OcrMyPdf.scala b/modules/convert/src/main/scala/docspell/convert/extern/OcrMyPdf.scala index 1fc778ef..9b350ba4 100644 --- a/modules/convert/src/main/scala/docspell/convert/extern/OcrMyPdf.scala +++ b/modules/convert/src/main/scala/docspell/convert/extern/OcrMyPdf.scala @@ -24,14 +24,16 @@ object OcrMyPdf { logger: Logger[F] )(in: Stream[F, Byte], handler: Handler[F, A]): F[A] = if (cfg.enabled) { - val reader: (Path, SystemCommand.Result) => F[ConversionResult[F]] = + val reader: (Path, Int) => F[ConversionResult[F]] = ExternConv.readResult[F](chunkSize, logger) + val cmd = cfg.command.withVars(Map("lang" -> lang.iso3)) + ExternConv.toPDF[F, A]( "ocrmypdf", - cfg.command.replace(Map("{{lang}}" -> lang.iso3)), + cmd, cfg.workingDir, - false, + useStdin = false, logger, reader )(in, handler) diff --git a/modules/convert/src/main/scala/docspell/convert/extern/OcrMyPdfConfig.scala b/modules/convert/src/main/scala/docspell/convert/extern/OcrMyPdfConfig.scala index 726469ce..fa85b4ee 100644 --- a/modules/convert/src/main/scala/docspell/convert/extern/OcrMyPdfConfig.scala +++ b/modules/convert/src/main/scala/docspell/convert/extern/OcrMyPdfConfig.scala @@ -8,10 +8,10 @@ package docspell.convert.extern import fs2.io.file.Path -import docspell.common.SystemCommand +import docspell.common.exec.ExternalCommand case class OcrMyPdfConfig( enabled: Boolean, - command: SystemCommand.Config, + command: ExternalCommand, workingDir: Path ) diff --git a/modules/convert/src/main/scala/docspell/convert/extern/Tesseract.scala b/modules/convert/src/main/scala/docspell/convert/extern/Tesseract.scala index 95875f8f..50ea2dd9 100644 --- a/modules/convert/src/main/scala/docspell/convert/extern/Tesseract.scala +++ b/modules/convert/src/main/scala/docspell/convert/extern/Tesseract.scala @@ -24,17 +24,18 @@ object Tesseract { logger: Logger[F] )(in: Stream[F, Byte], handler: Handler[F, A]): F[A] = { val outBase = cfg.command.args.tail.headOption.getOrElse("out") - val reader: (Path, SystemCommand.Result) => F[ConversionResult[F]] = + val reader: (Path, Int) => F[ConversionResult[F]] = ExternConv.readResultTesseract[F](outBase, chunkSize, logger) + val cmd = cfg.command.withVars(Map("lang" -> lang.iso3)) + ExternConv.toPDF[F, A]( "tesseract", - cfg.command.replace(Map("{{lang}}" -> lang.iso3)), + cmd, cfg.workingDir, - false, + useStdin = false, logger, reader )(in, handler) } - } diff --git a/modules/convert/src/main/scala/docspell/convert/extern/TesseractConfig.scala b/modules/convert/src/main/scala/docspell/convert/extern/TesseractConfig.scala index d2f09780..aae31fcc 100644 --- a/modules/convert/src/main/scala/docspell/convert/extern/TesseractConfig.scala +++ b/modules/convert/src/main/scala/docspell/convert/extern/TesseractConfig.scala @@ -8,6 +8,6 @@ package docspell.convert.extern import fs2.io.file.Path -import docspell.common.SystemCommand +import docspell.common.exec.ExternalCommand -case class TesseractConfig(command: SystemCommand.Config, workingDir: Path) +case class TesseractConfig(command: ExternalCommand, workingDir: Path) diff --git a/modules/convert/src/main/scala/docspell/convert/extern/Unoconv.scala b/modules/convert/src/main/scala/docspell/convert/extern/Unoconv.scala index cbe0db87..102987d2 100644 --- a/modules/convert/src/main/scala/docspell/convert/extern/Unoconv.scala +++ b/modules/convert/src/main/scala/docspell/convert/extern/Unoconv.scala @@ -10,7 +10,6 @@ import cats.effect._ import fs2.Stream import fs2.io.file.{Files, Path} -import docspell.common._ import docspell.convert.ConversionResult import docspell.convert.ConversionResult.Handler import docspell.logging.Logger @@ -22,14 +21,15 @@ object Unoconv { chunkSize: Int, logger: Logger[F] )(in: Stream[F, Byte], handler: Handler[F, A]): F[A] = { - val reader: (Path, SystemCommand.Result) => F[ConversionResult[F]] = + val reader: (Path, Int) => F[ConversionResult[F]] = ExternConv.readResult[F](chunkSize, logger) + val cmd = cfg.command.withVars(Map.empty) ExternConv.toPDF[F, A]( "unoconv", - cfg.command, + cmd, cfg.workingDir, - false, + useStdin = false, logger, reader )( @@ -37,5 +37,4 @@ object Unoconv { handler ) } - } diff --git a/modules/convert/src/main/scala/docspell/convert/extern/UnoconvConfig.scala b/modules/convert/src/main/scala/docspell/convert/extern/UnoconvConfig.scala index 8fe0d209..14084966 100644 --- a/modules/convert/src/main/scala/docspell/convert/extern/UnoconvConfig.scala +++ b/modules/convert/src/main/scala/docspell/convert/extern/UnoconvConfig.scala @@ -8,6 +8,6 @@ package docspell.convert.extern import fs2.io.file.Path -import docspell.common.SystemCommand +import docspell.common.exec.ExternalCommand -case class UnoconvConfig(command: SystemCommand.Config, workingDir: Path) +case class UnoconvConfig(command: ExternalCommand, workingDir: Path) diff --git a/modules/convert/src/main/scala/docspell/convert/extern/Weasyprint.scala b/modules/convert/src/main/scala/docspell/convert/extern/Weasyprint.scala index 2470d0fe..5c411d34 100644 --- a/modules/convert/src/main/scala/docspell/convert/extern/Weasyprint.scala +++ b/modules/convert/src/main/scala/docspell/convert/extern/Weasyprint.scala @@ -27,10 +27,10 @@ object Weasyprint { sanitizeHtml: SanitizeHtml, logger: Logger[F] )(in: Stream[F, Byte], handler: Handler[F, A]): F[A] = { - val reader: (Path, SystemCommand.Result) => F[ConversionResult[F]] = + val reader: (Path, Int) => F[ConversionResult[F]] = ExternConv.readResult[F](chunkSize, logger) - val cmdCfg = cfg.command.replace(Map("{{encoding}}" -> charset.name())) + val cmdCfg = cfg.command.withVars(Map("encoding" -> charset.name())) // html sanitize should (among other) remove links to invalid // protocols like cid: which is not supported by further @@ -51,5 +51,4 @@ object Weasyprint { handler ) } - } diff --git a/modules/convert/src/main/scala/docspell/convert/extern/WeasyprintConfig.scala b/modules/convert/src/main/scala/docspell/convert/extern/WeasyprintConfig.scala index 2ce485cc..dca425a8 100644 --- a/modules/convert/src/main/scala/docspell/convert/extern/WeasyprintConfig.scala +++ b/modules/convert/src/main/scala/docspell/convert/extern/WeasyprintConfig.scala @@ -8,6 +8,6 @@ package docspell.convert.extern import fs2.io.file.Path -import docspell.common.SystemCommand +import docspell.common.exec.ExternalCommand -case class WeasyprintConfig(command: SystemCommand.Config, workingDir: Path) +case class WeasyprintConfig(command: ExternalCommand, workingDir: Path) diff --git a/modules/convert/src/main/scala/docspell/convert/extern/WkHtmlPdf.scala b/modules/convert/src/main/scala/docspell/convert/extern/WkHtmlPdf.scala index 04e973fe..f22d9ada 100644 --- a/modules/convert/src/main/scala/docspell/convert/extern/WkHtmlPdf.scala +++ b/modules/convert/src/main/scala/docspell/convert/extern/WkHtmlPdf.scala @@ -27,10 +27,10 @@ object WkHtmlPdf { sanitizeHtml: SanitizeHtml, logger: Logger[F] )(in: Stream[F, Byte], handler: Handler[F, A]): F[A] = { - val reader: (Path, SystemCommand.Result) => F[ConversionResult[F]] = + val reader: (Path, Int) => F[ConversionResult[F]] = ExternConv.readResult[F](chunkSize, logger) - val cmdCfg = cfg.command.replace(Map("{{encoding}}" -> charset.name())) + val cmdCfg = cfg.command.withVars(Map("encoding" -> charset.name())) // html sanitize should (among other) remove links to invalid // protocols like cid: which is not supported by further @@ -58,5 +58,4 @@ object WkHtmlPdf { handler ) } - } diff --git a/modules/convert/src/main/scala/docspell/convert/extern/WkHtmlPdfConfig.scala b/modules/convert/src/main/scala/docspell/convert/extern/WkHtmlPdfConfig.scala index 52b71ea3..293d15aa 100644 --- a/modules/convert/src/main/scala/docspell/convert/extern/WkHtmlPdfConfig.scala +++ b/modules/convert/src/main/scala/docspell/convert/extern/WkHtmlPdfConfig.scala @@ -8,6 +8,6 @@ package docspell.convert.extern import fs2.io.file.Path -import docspell.common.SystemCommand +import docspell.common.exec.ExternalCommand -case class WkHtmlPdfConfig(command: SystemCommand.Config, workingDir: Path) +case class WkHtmlPdfConfig(command: ExternalCommand, workingDir: Path) diff --git a/modules/convert/src/test/scala/docspell/convert/ConversionTest.scala b/modules/convert/src/test/scala/docspell/convert/ConversionTest.scala index 35dfcfa6..cfbd0837 100644 --- a/modules/convert/src/test/scala/docspell/convert/ConversionTest.scala +++ b/modules/convert/src/test/scala/docspell/convert/ConversionTest.scala @@ -15,6 +15,7 @@ import cats.implicits._ import fs2.Stream import docspell.common._ +import docspell.common.exec._ import docspell.common.util.File import docspell.convert.ConversionResult.Handler import docspell.convert.ConvertConfig.HtmlConverter @@ -36,7 +37,7 @@ class ConversionTest extends FunSuite with FileChecks with TestLoggingConfig { 3000 * 3000, MarkdownConfig("body { padding: 2em 5em; }"), WkHtmlPdfConfig( - SystemCommand.Config( + ExternalCommand( "wkhtmltopdf", Seq("-s", "A4", "--encoding", "UTF-8", "-", "{{outfile}}"), Duration.seconds(20) @@ -44,7 +45,7 @@ class ConversionTest extends FunSuite with FileChecks with TestLoggingConfig { target ), WeasyprintConfig( - SystemCommand.Config( + ExternalCommand( "weasyprint", Seq("--encoding", "UTF-8", "-", "{{outfile}}"), Duration.seconds(20) @@ -53,7 +54,7 @@ class ConversionTest extends FunSuite with FileChecks with TestLoggingConfig { ), HtmlConverter.Wkhtmltopdf, TesseractConfig( - SystemCommand.Config( + ExternalCommand( "tesseract", Seq("{{infile}}", "out", "-l", "deu", "pdf", "txt"), Duration.seconds(20) @@ -61,7 +62,7 @@ class ConversionTest extends FunSuite with FileChecks with TestLoggingConfig { target ), UnoconvConfig( - SystemCommand.Config( + ExternalCommand( "unoconv", Seq("-f", "pdf", "-o", "{{outfile}}", "{{infile}}"), Duration.seconds(20) @@ -69,8 +70,8 @@ class ConversionTest extends FunSuite with FileChecks with TestLoggingConfig { target ), OcrMyPdfConfig( - true, - SystemCommand.Config( + enabled = true, + ExternalCommand( "ocrmypdf", Seq( "-l", @@ -86,7 +87,7 @@ class ConversionTest extends FunSuite with FileChecks with TestLoggingConfig { ), target ), - ConvertConfig.DecryptPdf(true, Nil) + ConvertConfig.DecryptPdf(enabled = true, Nil) ) val conversion = diff --git a/modules/convert/src/test/scala/docspell/convert/extern/ExternConvTest.scala b/modules/convert/src/test/scala/docspell/convert/extern/ExternConvTest.scala index 9beaed28..67d1e5ae 100644 --- a/modules/convert/src/test/scala/docspell/convert/extern/ExternConvTest.scala +++ b/modules/convert/src/test/scala/docspell/convert/extern/ExternConvTest.scala @@ -14,6 +14,7 @@ import cats.effect.unsafe.implicits.global import fs2.io.file.Path import docspell.common._ +import docspell.common.exec._ import docspell.common.util.File import docspell.convert._ import docspell.files.ExampleFiles @@ -27,7 +28,7 @@ class ExternConvTest extends FunSuite with FileChecks with TestLoggingConfig { val target = File.path(Paths.get("target")) test("convert html to pdf") { - val cfg = SystemCommand.Config( + val cfg = ExternalCommand( "wkhtmltopdf", Seq("-s", "A4", "--encoding", "UTF-8", "-", "{{outfile}}"), Duration.seconds(20) @@ -53,7 +54,7 @@ class ExternConvTest extends FunSuite with FileChecks with TestLoggingConfig { } test("convert office to pdf") { - val cfg = SystemCommand.Config( + val cfg = ExternalCommand( "unoconv", Seq("-f", "pdf", "-o", "{{outfile}}", "{{infile}}"), Duration.seconds(20) @@ -80,7 +81,7 @@ class ExternConvTest extends FunSuite with FileChecks with TestLoggingConfig { } test("convert image to pdf") { - val cfg = SystemCommand.Config( + val cfg = ExternalCommand( "tesseract", Seq("{{infile}}", "out", "-l", "deu", "pdf", "txt"), Duration.seconds(20) @@ -105,5 +106,4 @@ class ExternConvTest extends FunSuite with FileChecks with TestLoggingConfig { ) .unsafeRunSync() } - } diff --git a/modules/extract/src/main/scala/docspell/extract/ocr/Ocr.scala b/modules/extract/src/main/scala/docspell/extract/ocr/Ocr.scala index b0828201..f70c46b6 100644 --- a/modules/extract/src/main/scala/docspell/extract/ocr/Ocr.scala +++ b/modules/extract/src/main/scala/docspell/extract/ocr/Ocr.scala @@ -10,7 +10,8 @@ import cats.effect._ import fs2.Stream import fs2.io.file.{Files, Path} -import docspell.common._ +import docspell.common.exec.ExternalCommand +import docspell.common.exec.SysExec import docspell.common.util.File import docspell.logging.Logger @@ -77,14 +78,17 @@ object Ocr { else cfg.ghostscript.command.args val cmd = cfg.ghostscript.command .copy(args = xargs) - .replace( + .withVars( Map( - "{{infile}}" -> "-", - "{{outfile}}" -> "%d.tif" + "infile" -> "-", + "outfile" -> "%d.tif" ) ) - SystemCommand - .execSuccess(cmd, logger, wd = Some(wd), stdin = pdf) + .resolved + + Stream + .resource(SysExec(cmd, logger, Some(wd), Some(pdf))) + .evalMap(_.runToSuccess(logger)) .flatMap(_ => File.listFiles(pathEndsWith(".tif"), wd)) } @@ -93,18 +97,22 @@ object Ocr { */ private[extract] def runGhostscriptFile[F[_]: Async: Files]( pdf: Path, - ghostscript: SystemCommand.Config, + ghostscript: ExternalCommand, wd: Path, logger: Logger[F] ): Stream[F, Path] = { - val cmd = ghostscript.replace( - Map( - "{{infile}}" -> pdf.absolute.toString, - "{{outfile}}" -> "%d.tif" + val cmd = ghostscript + .withVars( + Map( + "infile" -> pdf.absolute.toString, + "outfile" -> "%d.tif" + ) ) - ) - SystemCommand - .execSuccess[F](cmd, logger, wd = Some(wd)) + .resolved + + Stream + .resource(SysExec(cmd, logger, Some(wd))) + .evalMap(_.runToSuccess(logger)) .flatMap(_ => File.listFiles(pathEndsWith(".tif"), wd)) } @@ -116,19 +124,23 @@ object Ocr { */ private[extract] def runUnpaperFile[F[_]: Async]( img: Path, - unpaper: SystemCommand.Config, + unpaper: ExternalCommand, wd: Option[Path], logger: Logger[F] ): Stream[F, Path] = { val targetFile = img.resolveSibling("u-" + img.fileName.toString).absolute - val cmd = unpaper.replace( - Map( - "{{infile}}" -> img.absolute.toString, - "{{outfile}}" -> targetFile.toString + val cmd = unpaper + .withVars( + Map( + "infile" -> img.absolute.toString, + "outfile" -> targetFile.toString + ) ) - ) - SystemCommand - .execSuccess[F](cmd, logger, wd = wd) + .resolved + + Stream + .resource(SysExec(cmd, logger, wd)) + .evalMap(_.runToSuccess(logger)) .map(_ => targetFile) .handleErrorWith { th => logger @@ -150,12 +162,14 @@ object Ocr { // so use the parent as working dir runUnpaperFile(img, config.unpaper.command, img.parent, logger).flatMap { uimg => val cmd = config.tesseract.command - .replace( - Map("{{file}}" -> uimg.fileName.toString, "{{lang}}" -> fixLanguage(lang)) + .withVars( + Map("file" -> uimg.fileName.toString, "lang" -> fixLanguage(lang)) ) - SystemCommand - .execSuccess[F](cmd, logger, wd = uimg.parent) - .map(_.stdout) + .resolved + + Stream + .resource(SysExec(cmd, logger, uimg.parent)) + .evalMap(_.runToSuccessStdout(logger)) } /** Run tesseract on the given image file and return the extracted text. */ @@ -166,8 +180,12 @@ object Ocr { config: OcrConfig ): Stream[F, String] = { val cmd = config.tesseract.command - .replace(Map("{{file}}" -> "stdin", "{{lang}}" -> fixLanguage(lang))) - SystemCommand.execSuccess(cmd, logger, stdin = img).map(_.stdout) + .withVars(Map("file" -> "stdin", "lang" -> fixLanguage(lang))) + .resolved + + Stream + .resource(SysExec(cmd, logger, None, Some(img))) + .evalMap(_.runToSuccessStdout(logger)) } private def fixLanguage(lang: String): String = diff --git a/modules/extract/src/main/scala/docspell/extract/ocr/OcrConfig.scala b/modules/extract/src/main/scala/docspell/extract/ocr/OcrConfig.scala index 856c21a3..6170f62b 100644 --- a/modules/extract/src/main/scala/docspell/extract/ocr/OcrConfig.scala +++ b/modules/extract/src/main/scala/docspell/extract/ocr/OcrConfig.scala @@ -6,12 +6,9 @@ package docspell.extract.ocr -import java.nio.file.Paths - import fs2.io.file.Path -import docspell.common._ -import docspell.common.util.File +import docspell.common.exec.ExternalCommand case class OcrConfig( maxImageSize: Int, @@ -25,43 +22,10 @@ object OcrConfig { case class PageRange(begin: Int) - case class Ghostscript(command: SystemCommand.Config, workingDir: Path) + case class Ghostscript(command: ExternalCommand, workingDir: Path) - case class Tesseract(command: SystemCommand.Config) + case class Tesseract(command: ExternalCommand) - case class Unpaper(command: SystemCommand.Config) + case class Unpaper(command: ExternalCommand) - val default = OcrConfig( - maxImageSize = 3000 * 3000, - pageRange = PageRange(10), - ghostscript = Ghostscript( - SystemCommand.Config( - "gs", - Seq( - "-dNOPAUSE", - "-dBATCH", - "-dSAFER", - "-sDEVICE=tiffscaled8", - "-sOutputFile={{outfile}}", - "{{infile}}" - ), - Duration.seconds(30) - ), - File.path( - Paths.get(System.getProperty("java.io.tmpdir")).resolve("docspell-extraction") - ) - ), - unpaper = Unpaper( - SystemCommand - .Config("unpaper", Seq("{{infile}}", "{{outfile}}"), Duration.seconds(30)) - ), - tesseract = Tesseract( - SystemCommand - .Config( - "tesseract", - Seq("{{file}}", "stdout", "-l", "{{lang}}"), - Duration.minutes(1) - ) - ) - ) } diff --git a/modules/extract/src/test/scala/docspell/extract/ocr/TextExtractionSuite.scala b/modules/extract/src/test/scala/docspell/extract/ocr/TextExtractionSuite.scala index 71d55ad8..7aa6a072 100644 --- a/modules/extract/src/test/scala/docspell/extract/ocr/TextExtractionSuite.scala +++ b/modules/extract/src/test/scala/docspell/extract/ocr/TextExtractionSuite.scala @@ -6,9 +6,14 @@ package docspell.extract.ocr +import java.nio.file.Paths + import cats.effect.IO import cats.effect.unsafe.implicits.global +import docspell.common.Duration +import docspell.common.exec.ExternalCommand +import docspell.common.util.File import docspell.files.TestFiles import docspell.logging.TestLoggingConfig @@ -21,7 +26,7 @@ class TextExtractionSuite extends FunSuite with TestLoggingConfig { test("extract english pdf".ignore) { val text = TextExtract - .extract[IO](letterSourceEN, logger, "eng", OcrConfig.default) + .extract[IO](letterSourceEN, logger, "eng", TextExtractionSuite.defaultConfig) .compile .lastOrError .unsafeRunSync() @@ -31,7 +36,7 @@ class TextExtractionSuite extends FunSuite with TestLoggingConfig { test("extract german pdf".ignore) { val expect = TestFiles.letterDEText val extract = TextExtract - .extract[IO](letterSourceDE, logger, "deu", OcrConfig.default) + .extract[IO](letterSourceDE, logger, "deu", TextExtractionSuite.defaultConfig) .compile .lastOrError .unsafeRunSync() @@ -39,3 +44,37 @@ class TextExtractionSuite extends FunSuite with TestLoggingConfig { assertEquals(extract.value, expect) } } + +object TextExtractionSuite { + val defaultConfig = OcrConfig( + maxImageSize = 3000 * 3000, + pageRange = OcrConfig.PageRange(10), + ghostscript = OcrConfig.Ghostscript( + ExternalCommand( + "gs", + Seq( + "-dNOPAUSE", + "-dBATCH", + "-dSAFER", + "-sDEVICE=tiffscaled8", + "-sOutputFile={{outfile}}", + "{{infile}}" + ), + Duration.seconds(30) + ), + File.path( + Paths.get(System.getProperty("java.io.tmpdir")).resolve("docspell-extraction") + ) + ), + unpaper = OcrConfig.Unpaper( + ExternalCommand("unpaper", Seq("{{infile}}", "{{outfile}}"), Duration.seconds(30)) + ), + tesseract = OcrConfig.Tesseract( + ExternalCommand( + "tesseract", + Seq("{{file}}", "stdout", "-l", "{{lang}}"), + Duration.minutes(1) + ) + ) + ) +} diff --git a/modules/files/src/test/scala/docspell/files/ZipTest.scala b/modules/files/src/test/scala/docspell/files/ZipTest.scala index 45d86d0e..935fb69a 100644 --- a/modules/files/src/test/scala/docspell/files/ZipTest.scala +++ b/modules/files/src/test/scala/docspell/files/ZipTest.scala @@ -19,7 +19,7 @@ import munit._ class ZipTest extends CatsEffectSuite with TestLoggingConfig { val logger = docspell.logging.getLogger[IO] - val tempDir = ResourceFixture( + val tempDir = ResourceFunFixture( Files[IO].tempDirectory(Path("target").some, "zip-test-", None) ) diff --git a/modules/fts-psql/src/main/scala/docspell/ftspsql/FtsRepository.scala b/modules/fts-psql/src/main/scala/docspell/ftspsql/FtsRepository.scala index eecacbc9..1be93be7 100644 --- a/modules/fts-psql/src/main/scala/docspell/ftspsql/FtsRepository.scala +++ b/modules/fts-psql/src/main/scala/docspell/ftspsql/FtsRepository.scala @@ -201,6 +201,7 @@ object FtsRepository extends DoobieMeta { case Language.Czech => "simple" case Language.Latvian => "simple" case Language.Japanese => "simple" + case Language.JpnVert => "simple" case Language.Hebrew => "simple" case Language.Lithuanian => "simple" case Language.Polish => "simple" diff --git a/modules/fts-solr/src/main/scala/docspell/ftssolr/SolrMigration.scala b/modules/fts-solr/src/main/scala/docspell/ftssolr/SolrMigration.scala index 2a61dac8..1ee5301a 100644 --- a/modules/fts-solr/src/main/scala/docspell/ftssolr/SolrMigration.scala +++ b/modules/fts-solr/src/main/scala/docspell/ftssolr/SolrMigration.scala @@ -45,7 +45,7 @@ object SolrMigration { description, FtsMigration.Result.reIndexAll.pure[F] ), - true + dataChangeOnly = true ) def indexAll[F[_]: Applicative]( @@ -59,7 +59,7 @@ object SolrMigration { description, FtsMigration.Result.indexAll.pure[F] ), - true + dataChangeOnly = true ) def apply[F[_]: Functor]( @@ -74,6 +74,6 @@ object SolrMigration { description, task.map(_ => FtsMigration.Result.workDone) ), - false + dataChangeOnly = false ) } diff --git a/modules/fts-solr/src/main/scala/docspell/ftssolr/SolrSetup.scala b/modules/fts-solr/src/main/scala/docspell/ftssolr/SolrSetup.scala index cf4f7edf..05649747 100644 --- a/modules/fts-solr/src/main/scala/docspell/ftssolr/SolrSetup.scala +++ b/modules/fts-solr/src/main/scala/docspell/ftssolr/SolrSetup.scala @@ -299,14 +299,22 @@ object SolrSetup { Map("add-field" -> body.asJson).asJson def string(field: Field): AddField = - AddField(field, "string", true, true, false) + AddField(field, "string", stored = true, indexed = true, multiValued = false) def textGeneral(field: Field): AddField = - AddField(field, "text_general", true, true, false) + AddField(field, "text_general", stored = true, indexed = true, multiValued = false) def textLang(field: Field, lang: Language): AddField = - if (lang == Language.Czech) AddField(field, s"text_cz", true, true, false) - else AddField(field, s"text_${lang.iso2}", true, true, false) + if (lang == Language.Czech) + AddField(field, s"text_cz", stored = true, indexed = true, multiValued = false) + else + AddField( + field, + s"text_${lang.iso2}", + stored = true, + indexed = true, + multiValued = false + ) } case class DeleteField(name: Field) diff --git a/modules/joex/src/main/resources/reference.conf b/modules/joex/src/main/resources/reference.conf index 3f740c7d..b2303afb 100644 --- a/modules/joex/src/main/resources/reference.conf +++ b/modules/joex/src/main/resources/reference.conf @@ -595,11 +595,30 @@ Docpell Update Check tesseract = { command = { program = "tesseract" + # Custom Language Mappings Below + # Japanese Vertical Mapping + arg-mappings = { + "tesseract_lang" = { + value = "{{lang}}" + mappings = [ + { + matches = "jpn_vert" + args = [ "-l", "jpn_vert", "-c", "preserve_interword_spaces=1" ] + }, + # Start Other Custom Language Mappings Here + # Default Mapping Below + { + matches = ".*" + args = [ "-l", "{{lang}}" ] + } + ] + } + } + # Default arguments for all processing go below. args = [ "{{infile}}", "out", - "-l", - "{{lang}}", + "{{tesseract_lang}}", "pdf", "txt" ] @@ -651,8 +670,34 @@ Docpell Update Check enabled = true command = { program = "ocrmypdf" + # Custom argument mappings for this program. + arg-mappings = { + "ocr_lang" = { + value = "{{lang}}" + # Custom Language Mappings Below + # Japanese Vertical Mapping + mappings = [ + { + matches = "jpn_vert" + args = [ "-l", "jpn_vert", "--pdf-renderer", "sandwich", "--tesseract-pagesegmode", "5", "--output-type", "pdf" ] + }, + # Japanese Mapping for OCR Optimization + { + matches = "jpn" + args = [ "-l", "jpn", "--output-type", "pdf" ] + }, + # Start Other Custom Language Mappings Here + # Default Mapping Below + { + matches = ".*" + args = [ "-l", "{{lang}}" ] + } + ] + } + } + # Default arguments for all processing go below. args = [ - "-l", "{{lang}}", + "{{ocr_lang}}", "--skip-text", "--deskew", "-j", "1", @@ -893,4 +938,4 @@ Docpell Update Check } } } -} \ No newline at end of file +} diff --git a/modules/joex/src/main/scala/docspell/joex/emptytrash/EmptyTrashTask.scala b/modules/joex/src/main/scala/docspell/joex/emptytrash/EmptyTrashTask.scala index 536fd83f..41a03b3a 100644 --- a/modules/joex/src/main/scala/docspell/joex/emptytrash/EmptyTrashTask.scala +++ b/modules/joex/src/main/scala/docspell/joex/emptytrash/EmptyTrashTask.scala @@ -30,7 +30,7 @@ object EmptyTrashTask { UserTask( args.periodicTaskId, EmptyTrashArgs.taskName, - true, + enabled = true, ce, None, args diff --git a/modules/joex/src/main/scala/docspell/joex/filecopy/FileCopyTask.scala b/modules/joex/src/main/scala/docspell/joex/filecopy/FileCopyTask.scala index c3b4a660..7f044fe5 100644 --- a/modules/joex/src/main/scala/docspell/joex/filecopy/FileCopyTask.scala +++ b/modules/joex/src/main/scala/docspell/joex/filecopy/FileCopyTask.scala @@ -29,23 +29,23 @@ object FileCopyTask { case class CopyResult(success: Boolean, message: String, counter: List[Counter]) object CopyResult { def noSourceImpl: CopyResult = - CopyResult(false, "No source BinaryStore implementation found!", Nil) + CopyResult(success = false, "No source BinaryStore implementation found!", Nil) def noTargetImpl: CopyResult = - CopyResult(false, "No target BinaryStore implementation found!", Nil) + CopyResult(success = false, "No target BinaryStore implementation found!", Nil) def noSourceStore(id: Ident): CopyResult = CopyResult( - false, + success = false, s"No source file repo found with id: ${id.id}. Make sure it is present in the config.", Nil ) def noTargetStore: CopyResult = - CopyResult(false, "No target file repositories defined", Nil) + CopyResult(success = false, "No target file repositories defined", Nil) def success(counter: NonEmptyList[Counter]): CopyResult = - CopyResult(true, "Done", counter.toList) + CopyResult(success = true, "Done", counter.toList) implicit val binaryIdCodec: Codec[BinaryId] = Codec.from( @@ -96,8 +96,10 @@ object FileCopyTask { .fromList(targets.filter(_ != srcConfig)) .toRight(CopyResult.noTargetStore) - srcRepo = store.createFileRepository(srcConfig, true) - targetRepos = trgConfig.map(store.createFileRepository(_, false)) + srcRepo = store.createFileRepository(srcConfig, withAttributeStore = true) + targetRepos = trgConfig.map( + store.createFileRepository(_, withAttributeStore = false) + ) } yield (srcRepo, targetRepos) data match { diff --git a/modules/joex/src/main/scala/docspell/joex/hk/CleanupResult.scala b/modules/joex/src/main/scala/docspell/joex/hk/CleanupResult.scala index 931f6714..04b82435 100644 --- a/modules/joex/src/main/scala/docspell/joex/hk/CleanupResult.scala +++ b/modules/joex/src/main/scala/docspell/joex/hk/CleanupResult.scala @@ -13,8 +13,8 @@ case class CleanupResult(removed: Int, disabled: Boolean) { def asString = if (disabled) "disabled" else s"$removed" } object CleanupResult { - def of(n: Int): CleanupResult = CleanupResult(n, false) - def disabled: CleanupResult = CleanupResult(0, true) + def of(n: Int): CleanupResult = CleanupResult(n, disabled = false) + def disabled: CleanupResult = CleanupResult(0, disabled = true) implicit val jsonEncoder: Encoder[CleanupResult] = deriveEncoder diff --git a/modules/joex/src/main/scala/docspell/joex/hk/HouseKeepingTask.scala b/modules/joex/src/main/scala/docspell/joex/hk/HouseKeepingTask.scala index 519cfa03..5aa9c58a 100644 --- a/modules/joex/src/main/scala/docspell/joex/hk/HouseKeepingTask.scala +++ b/modules/joex/src/main/scala/docspell/joex/hk/HouseKeepingTask.scala @@ -55,7 +55,7 @@ object HouseKeepingTask { UserTask( periodicId, taskName, - true, + enabled = true, ce, "Docspell house-keeping".some, () diff --git a/modules/joex/src/main/scala/docspell/joex/process/FindProposal.scala b/modules/joex/src/main/scala/docspell/joex/process/FindProposal.scala index b5cf948a..5581d555 100644 --- a/modules/joex/src/main/scala/docspell/joex/process/FindProposal.scala +++ b/modules/joex/src/main/scala/docspell/joex/process/FindProposal.scala @@ -222,13 +222,13 @@ object FindProposal { def searchExact[F[_]: Sync](ctx: Context[F, Args], store: Store[F]): Finder[F] = labels => labels.toList - .traverse(nl => search(nl, true, ctx, store)) + .traverse(nl => search(nl, exact = true, ctx, store)) .map(MetaProposalList.flatten) def searchFuzzy[F[_]: Sync](ctx: Context[F, Args], store: Store[F]): Finder[F] = labels => labels.toList - .traverse(nl => search(nl, false, ctx, store)) + .traverse(nl => search(nl, exact = false, ctx, store)) .map(MetaProposalList.flatten) } diff --git a/modules/joex/src/main/scala/docspell/joex/process/ReProcessItem.scala b/modules/joex/src/main/scala/docspell/joex/process/ReProcessItem.scala index 19a5193d..39337ee7 100644 --- a/modules/joex/src/main/scala/docspell/joex/process/ReProcessItem.scala +++ b/modules/joex/src/main/scala/docspell/joex/process/ReProcessItem.scala @@ -131,10 +131,10 @@ object ReProcessItem { data.item.source, // source-id None, // folder Seq.empty, - false, + skipDuplicate = false, None, None, - true, + reprocess = true, None, // attachOnly (not used when reprocessing attachments) None // cannot retain customData from an already existing item ), diff --git a/modules/joex/src/main/scala/docspell/joex/process/TextAnalysis.scala b/modules/joex/src/main/scala/docspell/joex/process/TextAnalysis.scala index ee268949..30ff4494 100644 --- a/modules/joex/src/main/scala/docspell/joex/process/TextAnalysis.scala +++ b/modules/joex/src/main/scala/docspell/joex/process/TextAnalysis.scala @@ -75,7 +75,7 @@ object TextAnalysis { analyser: TextAnalyser[F], nerFile: RegexNerFile[F] )(rm: RAttachmentMeta): F[(RAttachmentMeta, AttachmentDates)] = { - val settings = NlpSettings(ctx.args.meta.language, false, None) + val settings = NlpSettings(ctx.args.meta.language, highRecall = false, None) for { customNer <- nerFile.makeFile(ctx.args.meta.collective) sett = settings.copy(regexNer = customNer) diff --git a/modules/joex/src/main/scala/docspell/joex/routes/JoexRoutes.scala b/modules/joex/src/main/scala/docspell/joex/routes/JoexRoutes.scala index e02ff31d..0bbc5264 100644 --- a/modules/joex/src/main/scala/docspell/joex/routes/JoexRoutes.scala +++ b/modules/joex/src/main/scala/docspell/joex/routes/JoexRoutes.scala @@ -28,7 +28,7 @@ object JoexRoutes { for { _ <- app.scheduler.notifyChange _ <- app.periodicScheduler.notifyChange - resp <- Ok(BasicResult(true, "Schedulers notified.")) + resp <- Ok(BasicResult(success = true, "Schedulers notified.")) } yield resp case GET -> Root / "running" => @@ -43,7 +43,7 @@ object JoexRoutes { _ <- Async[F].start( Temporal[F].sleep(Duration.seconds(1).toScala) *> app.initShutdown ) - resp <- Ok(BasicResult(true, "Shutdown initiated.")) + resp <- Ok(BasicResult(success = true, "Shutdown initiated.")) } yield resp case GET -> Root / "job" / Ident(id) => @@ -54,7 +54,9 @@ object JoexRoutes { job <- optJob log <- optLog } yield mkJobLog(job, log) - resp <- jAndL.map(Ok(_)).getOrElse(NotFound(BasicResult(false, "Not found"))) + resp <- jAndL + .map(Ok(_)) + .getOrElse(NotFound(BasicResult(success = false, "Not found"))) } yield resp case POST -> Root / "job" / Ident(id) / "cancel" => diff --git a/modules/joex/src/main/scala/docspell/joex/scanmailbox/ScanMailboxTask.scala b/modules/joex/src/main/scala/docspell/joex/scanmailbox/ScanMailboxTask.scala index e0219121..cdff89ea 100644 --- a/modules/joex/src/main/scala/docspell/joex/scanmailbox/ScanMailboxTask.scala +++ b/modules/joex/src/main/scala/docspell/joex/scanmailbox/ScanMailboxTask.scala @@ -323,7 +323,7 @@ object ScanMailboxTask { s"mailbox-${ctx.args.account.login.id}", args.itemFolder, Seq.empty, - true, + skipDuplicates = true, args.fileFilter.getOrElse(Glob.all), args.tags.getOrElse(Nil), args.language, diff --git a/modules/joexapi/src/main/resources/joex-openapi.yml b/modules/joexapi/src/main/resources/joex-openapi.yml index e840a918..b6e05c7e 100644 --- a/modules/joexapi/src/main/resources/joex-openapi.yml +++ b/modules/joexapi/src/main/resources/joex-openapi.yml @@ -18,6 +18,8 @@ servers: - url: /api/v1 description: Current host +security: [] + paths: /api/info/version: get: diff --git a/modules/notification/api/src/main/scala/docspell/notification/api/Event.scala b/modules/notification/api/src/main/scala/docspell/notification/api/Event.scala index 47519dfc..54aff624 100644 --- a/modules/notification/api/src/main/scala/docspell/notification/api/Event.scala +++ b/modules/notification/api/src/main/scala/docspell/notification/api/Event.scala @@ -164,7 +164,7 @@ object Event { for { id1 <- Ident.randomId[F] id2 <- Ident.randomId[F] - } yield ItemSelection(account, Nel.of(id1, id2), true, baseUrl, None) + } yield ItemSelection(account, Nel.of(id1, id2), more = true, baseUrl, None) } /** Event when a new job is added to the queue */ diff --git a/modules/pubsub/naive/src/test/scala/docspell/pubsub/naive/Fixtures.scala b/modules/pubsub/naive/src/test/scala/docspell/pubsub/naive/Fixtures.scala index 848fc387..d472b1c5 100644 --- a/modules/pubsub/naive/src/test/scala/docspell/pubsub/naive/Fixtures.scala +++ b/modules/pubsub/naive/src/test/scala/docspell/pubsub/naive/Fixtures.scala @@ -20,9 +20,9 @@ import org.typelevel.ci._ trait Fixtures extends HttpClientOps { self: CatsEffectSuite => - val pubsubEnv = ResourceFixture(Fixtures.envResource("node-1")) + val pubsubEnv = ResourceFunFixture(Fixtures.envResource("node-1")) - val pubsubT = ResourceFixture { + val pubsubT = ResourceFunFixture { Fixtures .envResource("node-1") .flatMap(_.pubSub) diff --git a/modules/query/shared/src/main/scala/docspell/query/ParseFailure.scala b/modules/query/shared/src/main/scala/docspell/query/ParseFailure.scala index 9f24383c..cd63e4f2 100644 --- a/modules/query/shared/src/main/scala/docspell/query/ParseFailure.scala +++ b/modules/query/shared/src/main/scala/docspell/query/ParseFailure.scala @@ -87,10 +87,10 @@ object ParseFailure { SimpleMessage(offset, message) case InRange(offset, lower, upper) => - if (lower == upper) ExpectMessage(offset, List(lower.toString), true) + if (lower == upper) ExpectMessage(offset, List(lower.toString), exhaustive = true) else { val expect = s"$lower-$upper" - ExpectMessage(offset, List(expect), true) + ExpectMessage(offset, List(expect), exhaustive = true) } case Length(offset, expected, actual) => @@ -110,6 +110,10 @@ object ParseFailure { ExpectMessage(offset, options.take(7), options.size < 8) case WithContext(ctx, expect) => - ExpectMessage(expect.offset, s"Failed to parse near: $ctx" :: Nil, true) + ExpectMessage( + expect.offset, + s"Failed to parse near: $ctx" :: Nil, + exhaustive = true + ) } } diff --git a/modules/restapi/src/main/resources/docspell-openapi.yml b/modules/restapi/src/main/resources/docspell-openapi.yml index 39366ab8..added30a 100644 --- a/modules/restapi/src/main/resources/docspell-openapi.yml +++ b/modules/restapi/src/main/resources/docspell-openapi.yml @@ -27,6 +27,8 @@ servers: - url: /api/v1 description: Current host +security: [] + paths: /api/info/version: get: diff --git a/modules/restserver/src/main/scala/docspell/restserver/conv/Conversions.scala b/modules/restserver/src/main/scala/docspell/restserver/conv/Conversions.scala index cc745186..78babc04 100644 --- a/modules/restserver/src/main/scala/docspell/restserver/conv/Conversions.scala +++ b/modules/restserver/src/main/scala/docspell/restserver/conv/Conversions.scala @@ -329,7 +329,7 @@ trait Conversions { sourceName, None, validFileTypes, - false, + skipDuplicates = false, Glob.all, Nil, None, @@ -641,82 +641,86 @@ trait Conversions { def basicResult(r: SetValueResult): BasicResult = r match { case SetValueResult.FieldNotFound => - BasicResult(false, "The given field is unknown") + BasicResult(success = false, "The given field is unknown") case SetValueResult.ItemNotFound => - BasicResult(false, "The given item is unknown") + BasicResult(success = false, "The given item is unknown") case SetValueResult.ValueInvalid(msg) => - BasicResult(false, s"The value is invalid: $msg") + BasicResult(success = false, s"The value is invalid: $msg") case SetValueResult.Success => - BasicResult(true, "Custom field value set successfully.") + BasicResult(success = true, "Custom field value set successfully.") } def basicResult(cr: JobCancelResult): BasicResult = cr match { - case JobCancelResult.JobNotFound => BasicResult(false, "Job not found") + case JobCancelResult.JobNotFound => BasicResult(success = false, "Job not found") case JobCancelResult.CancelRequested => - BasicResult(true, "Cancel was requested at the job executor") + BasicResult(success = true, "Cancel was requested at the job executor") case JobCancelResult.Removed => - BasicResult(true, "The job has been removed from the queue.") + BasicResult(success = true, "The job has been removed from the queue.") } def idResult(ar: AddResult, id: Ident, successMsg: String): IdResult = ar match { - case AddResult.Success => IdResult(true, successMsg, id) - case AddResult.EntityExists(msg) => IdResult(false, msg, Ident.unsafe("")) + case AddResult.Success => IdResult(success = true, successMsg, id) + case AddResult.EntityExists(msg) => IdResult(success = false, msg, Ident.unsafe("")) case AddResult.Failure(ex) => - IdResult(false, s"Internal error: ${ex.getMessage}", Ident.unsafe("")) + IdResult(success = false, s"Internal error: ${ex.getMessage}", Ident.unsafe("")) } def basicResult(ar: AddResult, successMsg: String): BasicResult = ar match { - case AddResult.Success => BasicResult(true, successMsg) - case AddResult.EntityExists(msg) => BasicResult(false, msg) + case AddResult.Success => BasicResult(success = true, successMsg) + case AddResult.EntityExists(msg) => BasicResult(success = false, msg) case AddResult.Failure(ex) => - BasicResult(false, s"Internal error: ${ex.getMessage}") + BasicResult(success = false, s"Internal error: ${ex.getMessage}") } def basicResult(ar: UpdateResult, successMsg: String): BasicResult = ar match { - case UpdateResult.Success => BasicResult(true, successMsg) - case UpdateResult.NotFound => BasicResult(false, "Not found") + case UpdateResult.Success => BasicResult(success = true, successMsg) + case UpdateResult.NotFound => BasicResult(success = false, "Not found") case UpdateResult.Failure(ex) => - BasicResult(false, s"Error: ${ex.getMessage}") + BasicResult(success = false, s"Error: ${ex.getMessage}") } def basicResult(ur: OUpload.UploadResult): BasicResult = ur match { - case UploadResult.Success => BasicResult(true, "Files submitted.") - case UploadResult.NoFiles => BasicResult(false, "There were no files to submit.") - case UploadResult.NoSource => BasicResult(false, "The source id is not valid.") - case UploadResult.NoItem => BasicResult(false, "The item could not be found.") + case UploadResult.Success => BasicResult(success = true, "Files submitted.") + case UploadResult.NoFiles => + BasicResult(success = false, "There were no files to submit.") + case UploadResult.NoSource => + BasicResult(success = false, "The source id is not valid.") + case UploadResult.NoItem => + BasicResult(success = false, "The item could not be found.") case UploadResult.NoCollective => - BasicResult(false, "The collective could not be found.") + BasicResult(success = false, "The collective could not be found.") case UploadResult.StoreFailure(_) => BasicResult( - false, + success = false, "There were errors storing a file! See the server logs for details." ) } def basicResult(cr: PassChangeResult): BasicResult = cr match { - case PassChangeResult.Success => BasicResult(true, "Password changed.") + case PassChangeResult.Success => BasicResult(success = true, "Password changed.") case PassChangeResult.UpdateFailed => - BasicResult(false, "The database update failed.") + BasicResult(success = false, "The database update failed.") case PassChangeResult.PasswordMismatch => - BasicResult(false, "The current password is incorrect.") - case PassChangeResult.UserNotFound => BasicResult(false, "User not found.") + BasicResult(success = false, "The current password is incorrect.") + case PassChangeResult.UserNotFound => + BasicResult(success = false, "User not found.") case PassChangeResult.InvalidSource(source) => BasicResult( - false, + success = false, s"User has invalid soure: $source. Passwords are managed elsewhere." ) } def basicResult(e: Either[Throwable, _], successMsg: String): BasicResult = e match { - case Right(_) => BasicResult(true, successMsg) - case Left(ex) => BasicResult(false, ex.getMessage) + case Right(_) => BasicResult(success = true, successMsg) + case Left(ex) => BasicResult(success = false, ex.getMessage) } // MIME Type diff --git a/modules/restserver/src/main/scala/docspell/restserver/http4s/BinaryUtil.scala b/modules/restserver/src/main/scala/docspell/restserver/http4s/BinaryUtil.scala index d0bca31c..12534f47 100644 --- a/modules/restserver/src/main/scala/docspell/restserver/http4s/BinaryUtil.scala +++ b/modules/restserver/src/main/scala/docspell/restserver/http4s/BinaryUtil.scala @@ -38,7 +38,7 @@ object BinaryUtil { if (matches) withResponseHeaders(dsl, NotModified())(data) else makeByteResp(dsl)(data) } - .getOrElse(NotFound(BasicResult(false, "Not found"))) + .getOrElse(NotFound(BasicResult(success = false, "Not found"))) } def respondHead[F[_]: Async](dsl: Http4sDsl[F])( @@ -48,7 +48,7 @@ object BinaryUtil { fileData .map(data => withResponseHeaders(dsl, Ok())(data)) - .getOrElse(NotFound(BasicResult(false, "Not found"))) + .getOrElse(NotFound(BasicResult(success = false, "Not found"))) } def respondPreview[F[_]: Async](dsl: Http4sDsl[F], req: Request[F])( @@ -56,7 +56,7 @@ object BinaryUtil { ): F[Response[F]] = { import dsl._ def notFound = - NotFound(BasicResult(false, "Not found")) + NotFound(BasicResult(success = false, "Not found")) QP.WithFallback.unapply(req.multiParams) match { case Some(bool) => @@ -75,7 +75,7 @@ object BinaryUtil { ) case None => - BadRequest(BasicResult(false, "Invalid query parameter 'withFallback'")) + BadRequest(BasicResult(success = false, "Invalid query parameter 'withFallback'")) } } @@ -85,7 +85,7 @@ object BinaryUtil { import dsl._ fileData .map(data => withResponseHeaders(dsl, Ok())(data)) - .getOrElse(NotFound(BasicResult(false, "Not found"))) + .getOrElse(NotFound(BasicResult(success = false, "Not found"))) } def withResponseHeaders[F[_]: Sync](dsl: Http4sDsl[F], resp: F[Response[F]])( diff --git a/modules/restserver/src/main/scala/docspell/restserver/http4s/ThrowableResponseMapper.scala b/modules/restserver/src/main/scala/docspell/restserver/http4s/ThrowableResponseMapper.scala index ceeabadc..dd25a00a 100644 --- a/modules/restserver/src/main/scala/docspell/restserver/http4s/ThrowableResponseMapper.scala +++ b/modules/restserver/src/main/scala/docspell/restserver/http4s/ThrowableResponseMapper.scala @@ -33,10 +33,10 @@ object ThrowableResponseMapper { def toResponse(ex: Throwable): F[Response[F]] = ex match { case _: IllegalArgumentException => - BadRequest(BasicResult(false, ex.getMessage)) + BadRequest(BasicResult(success = false, ex.getMessage)) case _ => - InternalServerError(BasicResult(false, ex.getMessage)) + InternalServerError(BasicResult(success = false, ex.getMessage)) } } } diff --git a/modules/restserver/src/main/scala/docspell/restserver/routes/AddonArchiveRoutes.scala b/modules/restserver/src/main/scala/docspell/restserver/routes/AddonArchiveRoutes.scala index 637b6763..10e1e655 100644 --- a/modules/restserver/src/main/scala/docspell/restserver/routes/AddonArchiveRoutes.scala +++ b/modules/restserver/src/main/scala/docspell/restserver/routes/AddonArchiveRoutes.scala @@ -52,7 +52,7 @@ object AddonArchiveRoutes extends AddonValidationSupport { case req @ POST -> Root :? Sync(sync) => def create(r: Option[RAddonArchive]) = IdResult( - true, + success = true, r.fold("Addon submitted for installation")(r => s"Addon installed: ${r.id.id}" ), @@ -77,7 +77,7 @@ object AddonArchiveRoutes extends AddonValidationSupport { case PUT -> Root / Ident(id) :? Sync(sync) => def create(r: Option[AddonMeta]) = BasicResult( - true, + success = true, r.fold("Addon updated in background")(m => s"Addon updated: ${m.nameAndVersion}" ) @@ -99,8 +99,8 @@ object AddonArchiveRoutes extends AddonValidationSupport { for { flag <- backend.addons.deleteAddon(token.account.collectiveId, id) resp <- - if (flag) Ok(BasicResult(true, "Addon deleted")) - else NotFound(BasicResult(false, "Addon not found")) + if (flag) Ok(BasicResult(success = true, "Addon deleted")) + else NotFound(BasicResult(success = false, "Addon not found")) } yield resp } } @@ -112,11 +112,11 @@ object AddonArchiveRoutes extends AddonValidationSupport { import dsl._ def failWith(msg: String): F[Response[F]] = - Ok(IdResult(false, msg, Ident.unsafe(""))) + Ok(IdResult(success = false, msg, Ident.unsafe(""))) e match { case AddonValidationError.AddonNotFound => - NotFound(BasicResult(false, "Addon not found.")) + NotFound(BasicResult(success = false, "Addon not found.")) case _ => failWith(validationErrorToMessage(e)) diff --git a/modules/restserver/src/main/scala/docspell/restserver/routes/AddonRoutes.scala b/modules/restserver/src/main/scala/docspell/restserver/routes/AddonRoutes.scala index 192f6ccb..d9b4fb59 100644 --- a/modules/restserver/src/main/scala/docspell/restserver/routes/AddonRoutes.scala +++ b/modules/restserver/src/main/scala/docspell/restserver/routes/AddonRoutes.scala @@ -35,5 +35,5 @@ object AddonRoutes { "run" -> AddonRunRoutes(backend, token) ) else - Responses.notFoundRoute(BasicResult(false, "Addons disabled")) + Responses.notFoundRoute(BasicResult(success = false, "Addons disabled")) } diff --git a/modules/restserver/src/main/scala/docspell/restserver/routes/AddonRunConfigRoutes.scala b/modules/restserver/src/main/scala/docspell/restserver/routes/AddonRunConfigRoutes.scala index 4f93c9cf..4b6a7496 100644 --- a/modules/restserver/src/main/scala/docspell/restserver/routes/AddonRunConfigRoutes.scala +++ b/modules/restserver/src/main/scala/docspell/restserver/routes/AddonRunConfigRoutes.scala @@ -43,8 +43,8 @@ object AddonRunConfigRoutes { .map(_.leftMap(_.message)) ) resp <- res.fold( - msg => Ok(BasicResult(false, msg)), - id => Ok(IdResult(true, s"Addon run config added", id)) + msg => Ok(BasicResult(success = false, msg)), + id => Ok(IdResult(success = true, s"Addon run config added", id)) ) } yield resp @@ -58,8 +58,8 @@ object AddonRunConfigRoutes { .map(_.leftMap(_.message)) ) resp <- res.fold( - msg => Ok(BasicResult(false, msg)), - id => Ok(IdResult(true, s"Addon run config updated", id)) + msg => Ok(BasicResult(success = false, msg)), + id => Ok(IdResult(success = true, s"Addon run config updated", id)) ) } yield resp @@ -67,8 +67,8 @@ object AddonRunConfigRoutes { for { flag <- backend.addons.deleteAddonRunConfig(token.account.collectiveId, id) resp <- - if (flag) Ok(BasicResult(true, "Addon task deleted")) - else NotFound(BasicResult(false, "Addon task not found")) + if (flag) Ok(BasicResult(success = true, "Addon task deleted")) + else NotFound(BasicResult(success = false, "Addon task not found")) } yield resp } } diff --git a/modules/restserver/src/main/scala/docspell/restserver/routes/AddonRunRoutes.scala b/modules/restserver/src/main/scala/docspell/restserver/routes/AddonRunRoutes.scala index 7b7a977d..c46b5880 100644 --- a/modules/restserver/src/main/scala/docspell/restserver/routes/AddonRunRoutes.scala +++ b/modules/restserver/src/main/scala/docspell/restserver/routes/AddonRunRoutes.scala @@ -35,7 +35,7 @@ object AddonRunRoutes { input.addonRunConfigIds.toSet, UserTaskScope(token.account) ) - resp <- Ok(BasicResult(true, "Job for running addons submitted.")) + resp <- Ok(BasicResult(success = true, "Job for running addons submitted.")) } yield resp } } diff --git a/modules/restserver/src/main/scala/docspell/restserver/routes/AttachmentRoutes.scala b/modules/restserver/src/main/scala/docspell/restserver/routes/AttachmentRoutes.scala index ac43b3ba..89a59af4 100644 --- a/modules/restserver/src/main/scala/docspell/restserver/routes/AttachmentRoutes.scala +++ b/modules/restserver/src/main/scala/docspell/restserver/routes/AttachmentRoutes.scala @@ -66,7 +66,7 @@ object AttachmentRoutes { resp <- fileData .map(data => withResponseHeaders(Ok())(data)) - .getOrElse(NotFound(BasicResult(false, "Not found"))) + .getOrElse(NotFound(BasicResult(success = false, "Not found"))) } yield resp case req @ GET -> Root / Ident(id) / "original" => @@ -83,7 +83,7 @@ object AttachmentRoutes { if (matches) withResponseHeaders(NotModified())(data) else makeByteResp(data) } - .getOrElse(NotFound(BasicResult(false, "Not found"))) + .getOrElse(NotFound(BasicResult(success = false, "Not found"))) } yield resp case HEAD -> Root / Ident(id) / "archive" => @@ -93,7 +93,7 @@ object AttachmentRoutes { resp <- fileData .map(data => withResponseHeaders(Ok())(data)) - .getOrElse(NotFound(BasicResult(false, "Not found"))) + .getOrElse(NotFound(BasicResult(success = false, "Not found"))) } yield resp case req @ GET -> Root / Ident(id) / "archive" => @@ -108,7 +108,7 @@ object AttachmentRoutes { if (matches) withResponseHeaders(NotModified())(data) else makeByteResp(data) } - .getOrElse(NotFound(BasicResult(false, "Not found"))) + .getOrElse(NotFound(BasicResult(success = false, "Not found"))) } yield resp case req @ GET -> Root / Ident(id) / "preview" => @@ -148,7 +148,9 @@ object AttachmentRoutes { for { rm <- backend.itemSearch.findAttachmentMeta(id, user.account.collectiveId) md = rm.map(Conversions.mkAttachmentMeta) - resp <- md.map(Ok(_)).getOrElse(NotFound(BasicResult(false, "Not found."))) + resp <- md + .map(Ok(_)) + .getOrElse(NotFound(BasicResult(success = false, "Not found."))) } yield resp case req @ POST -> Root / Ident(id) / "name" => @@ -169,8 +171,11 @@ object AttachmentRoutes { backend.attachment .setExtractedText(user.account.collectiveId, itemId, id, newText) ) - resp <- OptionT.liftF(Ok(BasicResult(true, "Extracted text updated."))) - } yield resp).getOrElseF(NotFound(BasicResult(false, "Attachment not found"))) + resp <- OptionT.liftF( + Ok(BasicResult(success = true, "Extracted text updated.")) + ) + } yield resp) + .getOrElseF(NotFound(BasicResult(success = false, "Attachment not found"))) case DELETE -> Root / Ident(id) / "extracted-text" => (for { @@ -181,7 +186,9 @@ object AttachmentRoutes { backend.attachment .setExtractedText(user.account.collectiveId, itemId, id, "".pure[F]) ) - resp <- OptionT.liftF(Ok(BasicResult(true, "Extracted text cleared."))) + resp <- OptionT.liftF( + Ok(BasicResult(success = true, "Extracted text cleared.")) + ) } yield resp).getOrElseF(NotFound()) case GET -> Root / Ident(id) / "extracted-text" => @@ -190,14 +197,15 @@ object AttachmentRoutes { backend.itemSearch.findAttachmentMeta(id, user.account.collectiveId) ) resp <- OptionT.liftF(Ok(OptionalText(meta.content))) - } yield resp).getOrElseF(NotFound(BasicResult(false, "Attachment not found"))) + } yield resp) + .getOrElseF(NotFound(BasicResult(success = false, "Attachment not found"))) case DELETE -> Root / Ident(id) => for { n <- backend.item.deleteAttachment(id, user.account.collectiveId) res = - if (n == 0) BasicResult(false, "Attachment not found") - else BasicResult(true, "Attachment deleted.") + if (n == 0) BasicResult(success = false, "Attachment not found") + else BasicResult(success = true, "Attachment deleted.") resp <- Ok(res) } yield resp } diff --git a/modules/restserver/src/main/scala/docspell/restserver/routes/CalEventCheckRoutes.scala b/modules/restserver/src/main/scala/docspell/restserver/routes/CalEventCheckRoutes.scala index 39689f73..7ac2b4f0 100644 --- a/modules/restserver/src/main/scala/docspell/restserver/routes/CalEventCheckRoutes.scala +++ b/modules/restserver/src/main/scala/docspell/restserver/routes/CalEventCheckRoutes.scala @@ -40,9 +40,9 @@ object CalEventCheckRoutes { val next = ev .nextElapses(now.toUtcDateTime, 2) .map(Timestamp.atUtc) - CalEventCheckResult(true, "Valid.", ev.some, next) + CalEventCheckResult(success = true, "Valid.", ev.some, next) case Left(err) => - CalEventCheckResult(false, err, None, Nil) + CalEventCheckResult(success = false, err, None, Nil) } } } diff --git a/modules/restserver/src/main/scala/docspell/restserver/routes/ClientSettingsRoutes.scala b/modules/restserver/src/main/scala/docspell/restserver/routes/ClientSettingsRoutes.scala index f259103c..f61aa37f 100644 --- a/modules/restserver/src/main/scala/docspell/restserver/routes/ClientSettingsRoutes.scala +++ b/modules/restserver/src/main/scala/docspell/restserver/routes/ClientSettingsRoutes.scala @@ -66,7 +66,7 @@ object ClientSettingsRoutes { for { data <- req.as[Json] _ <- backend.clientSettings.saveUser(clientId, user.account.userId, data) - res <- Ok(BasicResult(true, "Settings stored")) + res <- Ok(BasicResult(success = true, "Settings stored")) } yield res case GET -> Root / "user" / Ident(clientId) => @@ -97,7 +97,7 @@ object ClientSettingsRoutes { user.account.collectiveId, data ) - res <- Ok(BasicResult(true, "Settings stored")) + res <- Ok(BasicResult(success = true, "Settings stored")) } yield res case GET -> Root / "collective" / Ident(clientId) => diff --git a/modules/restserver/src/main/scala/docspell/restserver/routes/CollectiveRoutes.scala b/modules/restserver/src/main/scala/docspell/restserver/routes/CollectiveRoutes.scala index faedbac0..ee80d567 100644 --- a/modules/restserver/src/main/scala/docspell/restserver/routes/CollectiveRoutes.scala +++ b/modules/restserver/src/main/scala/docspell/restserver/routes/CollectiveRoutes.scala @@ -118,7 +118,7 @@ object CollectiveRoutes { case POST -> Root / "classifier" / "startonce" => for { _ <- backend.collective.startLearnClassifier(user.account.collectiveId) - resp <- Ok(BasicResult(true, "Task submitted")) + resp <- Ok(BasicResult(success = true, "Task submitted")) } yield resp case req @ POST -> Root / "emptytrash" / "startonce" => @@ -127,7 +127,7 @@ object CollectiveRoutes { _ <- backend.collective.startEmptyTrash( EmptyTrashArgs(user.account.collectiveId, data.minAge) ) - resp <- Ok(BasicResult(true, "Task submitted")) + resp <- Ok(BasicResult(success = true, "Task submitted")) } yield resp } } diff --git a/modules/restserver/src/main/scala/docspell/restserver/routes/CustomFieldRoutes.scala b/modules/restserver/src/main/scala/docspell/restserver/routes/CustomFieldRoutes.scala index 83492974..4942da27 100644 --- a/modules/restserver/src/main/scala/docspell/restserver/routes/CustomFieldRoutes.scala +++ b/modules/restserver/src/main/scala/docspell/restserver/routes/CustomFieldRoutes.scala @@ -56,7 +56,7 @@ object CustomFieldRoutes { (for { field <- OptionT(backend.customFields.findById(user.account.collectiveId, id)) res <- OptionT.liftF(Ok(convertField(field))) - } yield res).getOrElseF(NotFound(BasicResult(false, "Not found"))) + } yield res).getOrElseF(NotFound(BasicResult(success = false, "Not found"))) case req @ PUT -> Root / Ident(id) => for { diff --git a/modules/restserver/src/main/scala/docspell/restserver/routes/DownloadAllRoutes.scala b/modules/restserver/src/main/scala/docspell/restserver/routes/DownloadAllRoutes.scala index 65cf2b7c..e6bde446 100644 --- a/modules/restserver/src/main/scala/docspell/restserver/routes/DownloadAllRoutes.scala +++ b/modules/restserver/src/main/scala/docspell/restserver/routes/DownloadAllRoutes.scala @@ -126,7 +126,7 @@ object DownloadAllRoutes { case DELETE -> Root / "file" / Ident(id) => for { _ <- backend.downloadAll.deleteFile(id) - resp <- Ok(BasicResult(true, "File deleted.")) + resp <- Ok(BasicResult(success = true, "File deleted.")) } yield resp case PUT -> Root / "cancel" / Ident(id) => diff --git a/modules/restserver/src/main/scala/docspell/restserver/routes/FolderRoutes.scala b/modules/restserver/src/main/scala/docspell/restserver/routes/FolderRoutes.scala index 463f20e1..f9e10320 100644 --- a/modules/restserver/src/main/scala/docspell/restserver/routes/FolderRoutes.scala +++ b/modules/restserver/src/main/scala/docspell/restserver/routes/FolderRoutes.scala @@ -118,12 +118,12 @@ object FolderRoutes { private def mkFolderChangeResult(r: OFolder.FolderChangeResult): BasicResult = r match { case OFolder.FolderChangeResult.Success => - BasicResult(true, "Successfully changed folder.") + BasicResult(success = true, "Successfully changed folder.") case OFolder.FolderChangeResult.NotFound => - BasicResult(false, "Folder or user not found.") + BasicResult(success = false, "Folder or user not found.") case OFolder.FolderChangeResult.Forbidden => - BasicResult(false, "Not allowed to edit folder.") + BasicResult(success = false, "Not allowed to edit folder.") case OFolder.FolderChangeResult.Exists => - BasicResult(false, "The member already exists.") + BasicResult(success = false, "The member already exists.") } } diff --git a/modules/restserver/src/main/scala/docspell/restserver/routes/ItemLinkRoutes.scala b/modules/restserver/src/main/scala/docspell/restserver/routes/ItemLinkRoutes.scala index 097f162e..5a9c70bc 100644 --- a/modules/restserver/src/main/scala/docspell/restserver/routes/ItemLinkRoutes.scala +++ b/modules/restserver/src/main/scala/docspell/restserver/routes/ItemLinkRoutes.scala @@ -37,7 +37,7 @@ class ItemLinkRoutes[F[_]: Async](account: AccountInfo, backend: OItemLink[F]) case DELETE -> Root / Ident(target) / Ident(id) => for { _ <- backend.removeAll(account.collectiveId, target, NonEmptyList.of(id)) - resp <- Ok(BasicResult(true, "Related items removed")) + resp <- Ok(BasicResult(success = true, "Related items removed")) } yield resp case req @ POST -> Root / "addAll" => @@ -58,19 +58,21 @@ class ItemLinkRoutes[F[_]: Async](account: AccountInfo, backend: OItemLink[F]) _ <- related .map(backend.removeAll(account.collectiveId, input.item, _)) .getOrElse( - BadRequest(BasicResult(false, "List of related items must not be empty")) + BadRequest( + BasicResult(success = false, "List of related items must not be empty") + ) ) - resp <- Ok(BasicResult(true, "Related items removed")) + resp <- Ok(BasicResult(success = true, "Related items removed")) } yield resp } private def convertResult(r: Option[LinkResult]): BasicResult = r match { - case Some(LinkResult.Success) => BasicResult(true, "Related items added") + case Some(LinkResult.Success) => BasicResult(success = true, "Related items added") case Some(LinkResult.LinkTargetItemError) => - BasicResult(false, "Items cannot be related to itself.") + BasicResult(success = false, "Items cannot be related to itself.") case None => - BasicResult(false, "List of related items must not be empty") + BasicResult(success = false, "List of related items must not be empty") } } diff --git a/modules/restserver/src/main/scala/docspell/restserver/routes/ItemRoutes.scala b/modules/restserver/src/main/scala/docspell/restserver/routes/ItemRoutes.scala index 464bacff..1c3e2954 100644 --- a/modules/restserver/src/main/scala/docspell/restserver/routes/ItemRoutes.scala +++ b/modules/restserver/src/main/scala/docspell/restserver/routes/ItemRoutes.scala @@ -49,7 +49,7 @@ object ItemRoutes { resp <- result .map(r => Ok(r)) - .getOrElse(NotFound(BasicResult(false, "Not found."))) + .getOrElse(NotFound(BasicResult(success = false, "Not found."))) } yield resp case POST -> Root / Ident(id) / "confirm" => @@ -285,7 +285,7 @@ object ItemRoutes { case req @ GET -> Root / Ident(id) / "preview" :? QP.WithFallback(flag) => def notFound = - NotFound(BasicResult(false, "Not found")) + NotFound(BasicResult(success = false, "Not found")) for { preview <- backend.itemSearch.findItemPreview(id, user.account.collectiveId) inm = req.headers.get[`If-None-Match`].flatMap(_.tags) @@ -309,7 +309,7 @@ object ItemRoutes { resp <- preview .map(data => BinaryUtil.withResponseHeaders(dsl, Ok())(data)) - .getOrElse(NotFound(BasicResult(false, "Not found"))) + .getOrElse(NotFound(BasicResult(success = false, "Not found"))) } yield resp case req @ POST -> Root / Ident(id) / "reprocess" => diff --git a/modules/restserver/src/main/scala/docspell/restserver/routes/ItemSearchPart.scala b/modules/restserver/src/main/scala/docspell/restserver/routes/ItemSearchPart.scala index 3b9e8d3a..4aea2b8e 100644 --- a/modules/restserver/src/main/scala/docspell/restserver/routes/ItemSearchPart.scala +++ b/modules/restserver/src/main/scala/docspell/restserver/routes/ItemSearchPart.scala @@ -196,17 +196,17 @@ final class ItemSearchPart[F[_]: Async]( Right(s) case QueryParseResult.ParseFailed(err) => - BadRequest(BasicResult(false, s"Invalid query: $err")).asLeft + BadRequest(BasicResult(success = false, s"Invalid query: $err")).asLeft case QueryParseResult.FulltextMismatch(Result.TooMany) => BadRequest( - BasicResult(false, "Only one fulltext search expression is allowed.") + BasicResult(success = false, "Only one fulltext search expression is allowed.") ).asLeft case QueryParseResult.FulltextMismatch(Result.UnsupportedPosition) => BadRequest( BasicResult( - false, + success = false, "A fulltext search may only appear in the root and expression." ) ).asLeft diff --git a/modules/restserver/src/main/scala/docspell/restserver/routes/LoginRoutes.scala b/modules/restserver/src/main/scala/docspell/restserver/routes/LoginRoutes.scala index 464bd149..5c3d4775 100644 --- a/modules/restserver/src/main/scala/docspell/restserver/routes/LoginRoutes.scala +++ b/modules/restserver/src/main/scala/docspell/restserver/routes/LoginRoutes.scala @@ -41,7 +41,9 @@ object LoginRoutes { makeResponse(dsl, cfg, req, result, token.account.asString) ) case Left(err) => - BadRequest(BasicResult(false, s"Invalid authentication token: $err")) + BadRequest( + BasicResult(success = false, s"Invalid authentication token: $err") + ) } } yield resp @@ -97,7 +99,7 @@ object LoginRoutes { AuthResult( token.account.collective.id, token.account.login.id, - true, + success = true, "Login successful", Some(cd.asString), cfg.auth.sessionValid.millis, @@ -112,7 +114,17 @@ object LoginRoutes { } yield resp case _ => - Ok(AuthResult("", account, false, "Login failed.", None, 0L, false)) + Ok( + AuthResult( + "", + account, + success = false, + "Login failed.", + None, + 0L, + requireSecondFactor = false + ) + ) } } diff --git a/modules/restserver/src/main/scala/docspell/restserver/routes/MailSendRoutes.scala b/modules/restserver/src/main/scala/docspell/restserver/routes/MailSendRoutes.scala index 15ceceac..076b153b 100644 --- a/modules/restserver/src/main/scala/docspell/restserver/routes/MailSendRoutes.scala +++ b/modules/restserver/src/main/scala/docspell/restserver/routes/MailSendRoutes.scala @@ -36,7 +36,7 @@ object MailSendRoutes { backend.mail.sendMail(user.account.userId, user.account.collectiveId, name, m) ) resp <- res.fold( - err => Ok(BasicResult(false, s"Invalid mail data: $err")), + err => Ok(BasicResult(success = false, s"Invalid mail data: $err")), res => Ok(convertOut(res)) ) } yield resp @@ -56,15 +56,15 @@ object MailSendRoutes { def convertOut(res: SendResult): BasicResult = res match { case SendResult.Success(_) => - BasicResult(true, "Mail sent.") + BasicResult(success = true, "Mail sent.") case SendResult.SendFailure(ex) => - BasicResult(false, s"Mail sending failed: ${ex.getMessage}") + BasicResult(success = false, s"Mail sending failed: ${ex.getMessage}") case SendResult.StoreFailure(ex) => BasicResult( - false, + success = false, s"Mail was sent, but could not be store to database: ${ex.getMessage}" ) case SendResult.NotFound => - BasicResult(false, s"There was no mail-connection or item found.") + BasicResult(success = false, s"There was no mail-connection or item found.") } } diff --git a/modules/restserver/src/main/scala/docspell/restserver/routes/MailSettingsRoutes.scala b/modules/restserver/src/main/scala/docspell/restserver/routes/MailSettingsRoutes.scala index ff391d67..6e9ed286 100644 --- a/modules/restserver/src/main/scala/docspell/restserver/routes/MailSettingsRoutes.scala +++ b/modules/restserver/src/main/scala/docspell/restserver/routes/MailSettingsRoutes.scala @@ -69,7 +69,7 @@ object MailSettingsRoutes { resp <- OptionT.liftF( Ok( up.fold( - err => BasicResult(false, err), + err => BasicResult(success = false, err), ar => Conversions.basicResult(ar, "Mail settings stored.") ) ) @@ -86,7 +86,7 @@ object MailSettingsRoutes { resp <- OptionT.liftF( Ok( up.fold( - err => BasicResult(false, err), + err => BasicResult(success = false, err), ar => Conversions.basicResult(ar, "Mail settings stored.") ) ) @@ -105,10 +105,10 @@ object MailSettingsRoutes { resp <- OptionT.liftF( Ok( up.fold( - err => BasicResult(false, err), + err => BasicResult(success = false, err), n => - if (n > 0) BasicResult(true, "Mail settings stored.") - else BasicResult(false, "Mail settings could not be saved") + if (n > 0) BasicResult(success = true, "Mail settings stored.") + else BasicResult(success = false, "Mail settings could not be saved") ) ) ) @@ -126,10 +126,10 @@ object MailSettingsRoutes { resp <- OptionT.liftF( Ok( up.fold( - err => BasicResult(false, err), + err => BasicResult(success = false, err), n => - if (n > 0) BasicResult(true, "Mail settings stored.") - else BasicResult(false, "Mail settings could not be saved") + if (n > 0) BasicResult(success = true, "Mail settings stored.") + else BasicResult(success = false, "Mail settings could not be saved") ) ) ) @@ -139,8 +139,8 @@ object MailSettingsRoutes { for { n <- backend.mail.deleteSmtpSettings(user.account.userId, name) resp <- Ok( - if (n > 0) BasicResult(true, "Mail settings removed") - else BasicResult(false, "Mail settings could not be removed") + if (n > 0) BasicResult(success = true, "Mail settings removed") + else BasicResult(success = false, "Mail settings could not be removed") ) } yield resp @@ -148,8 +148,8 @@ object MailSettingsRoutes { for { n <- backend.mail.deleteImapSettings(user.account.userId, name) resp <- Ok( - if (n > 0) BasicResult(true, "Mail settings removed") - else BasicResult(false, "Mail settings could not be removed") + if (n > 0) BasicResult(success = true, "Mail settings removed") + else BasicResult(success = false, "Mail settings could not be removed") ) } yield resp } diff --git a/modules/restserver/src/main/scala/docspell/restserver/routes/NotificationRoutes.scala b/modules/restserver/src/main/scala/docspell/restserver/routes/NotificationRoutes.scala index 2e5940d0..b28b6852 100644 --- a/modules/restserver/src/main/scala/docspell/restserver/routes/NotificationRoutes.scala +++ b/modules/restserver/src/main/scala/docspell/restserver/routes/NotificationRoutes.scala @@ -72,7 +72,7 @@ object NotificationRoutes extends NonEmptyListSupport { .createChannel(c, user.account.userId) .map(res => Conversions.basicResult(res, "Channel created")) } - .foldF(ex => BadRequest(BasicResult(false, ex.getMessage)), Ok(_)) + .foldF(ex => BadRequest(BasicResult(success = false, ex.getMessage)), Ok(_)) } yield resp case req @ PUT -> Root => @@ -86,7 +86,7 @@ object NotificationRoutes extends NonEmptyListSupport { .updateChannel(c, user.account.userId) .map(res => Conversions.basicResult(res, "Channel created")) } - .foldF(ex => BadRequest(BasicResult(false, ex.getMessage)), Ok(_)) + .foldF(ex => BadRequest(BasicResult(success = false, ex.getMessage)), Ok(_)) } yield resp } } @@ -173,7 +173,7 @@ object NotificationRoutes extends NonEmptyListSupport { resp <- data.asJsonWithMessage match { case Right(m) => Ok(m) case Left(err) => - BadRequest(BasicResult(false, s"Unable to render message: $err")) + BadRequest(BasicResult(success = false, s"Unable to render message: $err")) } } yield resp } diff --git a/modules/restserver/src/main/scala/docspell/restserver/routes/NotifyDueItemsRoutes.scala b/modules/restserver/src/main/scala/docspell/restserver/routes/NotifyDueItemsRoutes.scala index c09cd1f4..50c3db70 100644 --- a/modules/restserver/src/main/scala/docspell/restserver/routes/NotifyDueItemsRoutes.scala +++ b/modules/restserver/src/main/scala/docspell/restserver/routes/NotifyDueItemsRoutes.scala @@ -86,7 +86,8 @@ object NotifyDueItemsRoutes extends MailAddressCodec with NonEmptyListSupport { for { data <- req.as[PeriodicDueItemsSettings] resp <- - if (data.id.isEmpty) Ok(BasicResult(false, "Empty id is not allowed")) + if (data.id.isEmpty) + Ok(BasicResult(success = false, "Empty id is not allowed")) else run(data) } yield resp diff --git a/modules/restserver/src/main/scala/docspell/restserver/routes/PeriodicQueryRoutes.scala b/modules/restserver/src/main/scala/docspell/restserver/routes/PeriodicQueryRoutes.scala index 0245216a..910dbd5a 100644 --- a/modules/restserver/src/main/scala/docspell/restserver/routes/PeriodicQueryRoutes.scala +++ b/modules/restserver/src/main/scala/docspell/restserver/routes/PeriodicQueryRoutes.scala @@ -87,7 +87,8 @@ object PeriodicQueryRoutes extends MailAddressCodec with NonEmptyListSupport { for { data <- req.as[PeriodicQuerySettings] resp <- - if (data.id.isEmpty) Ok(BasicResult(false, "Empty id is not allowed")) + if (data.id.isEmpty) + Ok(BasicResult(success = false, "Empty id is not allowed")) else run(data) } yield resp diff --git a/modules/restserver/src/main/scala/docspell/restserver/routes/RegisterRoutes.scala b/modules/restserver/src/main/scala/docspell/restserver/routes/RegisterRoutes.scala index d8efaacb..685dc6ed 100644 --- a/modules/restserver/src/main/scala/docspell/restserver/routes/RegisterRoutes.scala +++ b/modules/restserver/src/main/scala/docspell/restserver/routes/RegisterRoutes.scala @@ -48,26 +48,26 @@ object RegisterRoutes { def convert(r: NewInviteResult): InviteResult = r match { case NewInviteResult.Success(id) => - InviteResult(true, "New invitation created.", Some(id)) + InviteResult(success = true, "New invitation created.", Some(id)) case NewInviteResult.InvitationDisabled => - InviteResult(false, "Signing up is not enabled for invitations.", None) + InviteResult(success = false, "Signing up is not enabled for invitations.", None) case NewInviteResult.PasswordMismatch => - InviteResult(false, "Password is invalid.", None) + InviteResult(success = false, "Password is invalid.", None) } def convert(r: SignupResult): BasicResult = r match { case SignupResult.CollectiveExists => - BasicResult(false, "A collective with this name already exists.") + BasicResult(success = false, "A collective with this name already exists.") case SignupResult.InvalidInvitationKey => - BasicResult(false, "Invalid invitation key.") + BasicResult(success = false, "Invalid invitation key.") case SignupResult.SignupClosed => - BasicResult(false, "Sorry, registration is closed.") + BasicResult(success = false, "Sorry, registration is closed.") case SignupResult.Failure(ex) => logger.error(ex)("Error signing up") - BasicResult(false, s"Internal error: ${ex.getMessage}") + BasicResult(success = false, s"Internal error: ${ex.getMessage}") case SignupResult.Success => - BasicResult(true, "Signup successful") + BasicResult(success = true, "Signup successful") } def convert(r: Registration): RegisterData = diff --git a/modules/restserver/src/main/scala/docspell/restserver/routes/ScanMailboxRoutes.scala b/modules/restserver/src/main/scala/docspell/restserver/routes/ScanMailboxRoutes.scala index 563eb795..07764333 100644 --- a/modules/restserver/src/main/scala/docspell/restserver/routes/ScanMailboxRoutes.scala +++ b/modules/restserver/src/main/scala/docspell/restserver/routes/ScanMailboxRoutes.scala @@ -82,7 +82,8 @@ object ScanMailboxRoutes { for { data <- req.as[ScanMailboxSettings] resp <- - if (data.id.isEmpty) Ok(BasicResult(false, "Empty id is not allowed")) + if (data.id.isEmpty) + Ok(BasicResult(success = false, "Empty id is not allowed")) else run(data) } yield resp diff --git a/modules/restserver/src/main/scala/docspell/restserver/routes/ShareItemRoutes.scala b/modules/restserver/src/main/scala/docspell/restserver/routes/ShareItemRoutes.scala index 38c3d041..fe883366 100644 --- a/modules/restserver/src/main/scala/docspell/restserver/routes/ShareItemRoutes.scala +++ b/modules/restserver/src/main/scala/docspell/restserver/routes/ShareItemRoutes.scala @@ -34,7 +34,7 @@ object ShareItemRoutes { resp <- result .map(r => Ok(r)) - .getOrElse(NotFound(BasicResult(false, "Not found."))) + .getOrElse(NotFound(BasicResult(success = false, "Not found."))) } yield resp } } diff --git a/modules/restserver/src/main/scala/docspell/restserver/routes/ShareRoutes.scala b/modules/restserver/src/main/scala/docspell/restserver/routes/ShareRoutes.scala index d40b766f..9e56f942 100644 --- a/modules/restserver/src/main/scala/docspell/restserver/routes/ShareRoutes.scala +++ b/modules/restserver/src/main/scala/docspell/restserver/routes/ShareRoutes.scala @@ -81,7 +81,7 @@ object ShareRoutes { .sendMail(user.account.collectiveId, user.account.userId, name, m) ) resp <- res.fold( - err => Ok(BasicResult(false, s"Invalid mail data: $err")), + err => Ok(BasicResult(success = false, s"Invalid mail data: $err")), res => Ok(convertOut(res)) ) } yield resp @@ -100,14 +100,46 @@ object ShareRoutes { resp <- res match { case VerifyResult.Success(token, name) => val cd = ShareCookieData(token) - Ok(ShareVerifyResult(true, token.asString, false, "Success", name)) + Ok( + ShareVerifyResult( + success = true, + token.asString, + passwordRequired = false, + "Success", + name + ) + ) .map(cd.addCookie(ClientRequestInfo.getBaseUrl(cfg, req))) case VerifyResult.PasswordMismatch => - Ok(ShareVerifyResult(false, "", true, "Failed", None)) + Ok( + ShareVerifyResult( + success = false, + "", + passwordRequired = true, + "Failed", + None + ) + ) case VerifyResult.NotFound => - Ok(ShareVerifyResult(false, "", false, "Failed", None)) + Ok( + ShareVerifyResult( + success = false, + "", + passwordRequired = false, + "Failed", + None + ) + ) case VerifyResult.InvalidToken => - Ok(ShareVerifyResult(false, "", false, "Failed", None)) + Ok( + ShareVerifyResult( + success = false, + "", + passwordRequired = false, + "Failed", + None + ) + ) } } yield resp } @@ -125,18 +157,18 @@ object ShareRoutes { def mkIdResult(r: OShare.ChangeResult, msg: => String): IdResult = r match { - case OShare.ChangeResult.Success(id) => IdResult(true, msg, id) + case OShare.ChangeResult.Success(id) => IdResult(success = true, msg, id) case OShare.ChangeResult.PublishUntilInPast => - IdResult(false, "Until date must not be in the past", Ident.unsafe("")) + IdResult(success = false, "Until date must not be in the past", Ident.unsafe("")) case OShare.ChangeResult.NotFound => IdResult( - false, + success = false, "Share not found or not owner. Only the owner can update a share.", Ident.unsafe("") ) case OShare.ChangeResult.QueryWithFulltext => IdResult( - false, + success = false, "Sorry, shares with fulltext queries are currently not supported.", Ident.unsafe("") ) @@ -144,17 +176,17 @@ object ShareRoutes { def mkBasicResult(r: OShare.ChangeResult, msg: => String): BasicResult = r match { - case OShare.ChangeResult.Success(_) => BasicResult(true, msg) + case OShare.ChangeResult.Success(_) => BasicResult(success = true, msg) case OShare.ChangeResult.PublishUntilInPast => - BasicResult(false, "Until date must not be in the past") + BasicResult(success = false, "Until date must not be in the past") case OShare.ChangeResult.NotFound => BasicResult( - false, + success = false, "Share not found or not owner. Only the owner can update a share." ) case OShare.ChangeResult.QueryWithFulltext => BasicResult( - false, + success = false, "Sorry, shares with fulltext queries are currently not supported." ) } @@ -184,10 +216,10 @@ object ShareRoutes { def convertOut(res: SendResult): BasicResult = res match { case SendResult.Success(_) => - BasicResult(true, "Mail sent.") + BasicResult(success = true, "Mail sent.") case SendResult.SendFailure(ex) => - BasicResult(false, s"Mail sending failed: ${ex.getMessage}") + BasicResult(success = false, s"Mail sending failed: ${ex.getMessage}") case SendResult.NotFound => - BasicResult(false, s"There was no mail-connection or item found.") + BasicResult(success = false, s"There was no mail-connection or item found.") } } diff --git a/modules/restserver/src/main/scala/docspell/restserver/routes/TotpRoutes.scala b/modules/restserver/src/main/scala/docspell/restserver/routes/TotpRoutes.scala index 1199eb06..b4825710 100644 --- a/modules/restserver/src/main/scala/docspell/restserver/routes/TotpRoutes.scala +++ b/modules/restserver/src/main/scala/docspell/restserver/routes/TotpRoutes.scala @@ -36,7 +36,10 @@ object TotpRoutes { for { result <- backend.totp.state(user.account) resp <- Ok( - result.fold(en => OtpState(true, en.created.some), _ => OtpState(false, None)) + result.fold( + en => OtpState(enabled = true, en.created.some), + _ => OtpState(enabled = false, None) + ) ) } yield resp case POST -> Root / "init" => @@ -44,11 +47,13 @@ object TotpRoutes { result <- backend.totp.initialize(user.account) resp <- result match { case OTotp.InitResult.AlreadyExists => - UnprocessableEntity(BasicResult(false, "A totp setup already exists!")) + UnprocessableEntity( + BasicResult(success = false, "A totp setup already exists!") + ) case OTotp.InitResult.NotFound => - NotFound(BasicResult(false, "User not found")) + NotFound(BasicResult(success = false, "User not found")) case OTotp.InitResult.Failed(ex) => - InternalServerError(BasicResult(false, ex.getMessage)) + InternalServerError(BasicResult(success = false, ex.getMessage)) case s @ OTotp.InitResult.Success(_, key) => val issuer = cfg.appName val uri = s.authenticatorUrl(issuer) @@ -62,9 +67,9 @@ object TotpRoutes { result <- backend.totp.confirmInit(user.account, OnetimePassword(data.otp.pass)) resp <- result match { case OTotp.ConfirmResult.Success => - Ok(BasicResult(true, "TOTP setup successful.")) + Ok(BasicResult(success = true, "TOTP setup successful.")) case OTotp.ConfirmResult.Failed => - Ok(BasicResult(false, "TOTP setup failed!")) + Ok(BasicResult(success = false, "TOTP setup failed!")) } } yield resp diff --git a/modules/restserver/src/main/scala/docspell/restserver/routes/UserRoutes.scala b/modules/restserver/src/main/scala/docspell/restserver/routes/UserRoutes.scala index a3f84aff..b93829c0 100644 --- a/modules/restserver/src/main/scala/docspell/restserver/routes/UserRoutes.scala +++ b/modules/restserver/src/main/scala/docspell/restserver/routes/UserRoutes.scala @@ -97,7 +97,7 @@ object UserRoutes { ) case None => - NotFound(BasicResult(false, s"User '${username.id}' not found")) + NotFound(BasicResult(success = false, s"User '${username.id}' not found")) } } yield resp } @@ -119,16 +119,16 @@ object UserRoutes { ) resp <- Ok(result match { case OCollective.PassResetResult.Success(np) => - ResetPasswordResult(true, np, "Password updated") + ResetPasswordResult(success = true, np, "Password updated") case OCollective.PassResetResult.NotFound => ResetPasswordResult( - false, + success = false, Password(""), "Password update failed. User not found." ) case OCollective.PassResetResult.InvalidSource(source) => ResetPasswordResult( - false, + success = false, Password(""), s"Password update failed. User has unexpected source: $source. Passwords are managed externally." ) diff --git a/modules/scheduler/impl/src/main/scala/docspell/scheduler/impl/PeriodicSchedulerImpl.scala b/modules/scheduler/impl/src/main/scala/docspell/scheduler/impl/PeriodicSchedulerImpl.scala index ada53b9d..45797b7d 100644 --- a/modules/scheduler/impl/src/main/scala/docspell/scheduler/impl/PeriodicSchedulerImpl.scala +++ b/modules/scheduler/impl/src/main/scala/docspell/scheduler/impl/PeriodicSchedulerImpl.scala @@ -169,7 +169,7 @@ final class PeriodicSchedulerImpl[F[_]: Async]( object PeriodicSchedulerImpl { def emptyState[F[_]]: State[F] = - State(false, None) + State(shutdownRequest = false, None) case class State[F[_]]( shutdownRequest: Boolean, diff --git a/modules/scheduler/impl/src/main/scala/docspell/scheduler/impl/SchedulerImpl.scala b/modules/scheduler/impl/src/main/scala/docspell/scheduler/impl/SchedulerImpl.scala index 5d427700..5a7e8197 100644 --- a/modules/scheduler/impl/src/main/scala/docspell/scheduler/impl/SchedulerImpl.scala +++ b/modules/scheduler/impl/src/main/scala/docspell/scheduler/impl/SchedulerImpl.scala @@ -348,7 +348,7 @@ object SchedulerImpl { type CancelToken[F[_]] = F[Unit] def emptyState[F[_]]: State[F] = - State(Map.empty, Set.empty, Map.empty, false) + State(Map.empty, Set.empty, Map.empty, shutdownRequest = false) case class State[F[_]]( counters: Map[Ident, CountingScheme], diff --git a/modules/store/src/main/scala/db/migration/common/MigrateDueItemTasks.scala b/modules/store/src/main/scala/db/migration/common/MigrateDueItemTasks.scala index c169c42f..e421dcf6 100644 --- a/modules/store/src/main/scala/db/migration/common/MigrateDueItemTasks.scala +++ b/modules/store/src/main/scala/db/migration/common/MigrateDueItemTasks.scala @@ -43,8 +43,11 @@ object MigrateDueItemTasks extends TransactorSupport with JsonCodecs { ) _ <- tasks2.traverse(migratePeriodicDueItemsTask) _ <- tasks3.traverse(migratePeriodicQueryTask) - _ <- RPeriodicTask.setEnabledByTask(PeriodicQueryArgsOld.taskName, false) - _ <- RPeriodicTask.setEnabledByTask(PeriodicDueItemsArgsOld.taskName, false) + _ <- RPeriodicTask.setEnabledByTask(PeriodicQueryArgsOld.taskName, enabled = false) + _ <- RPeriodicTask.setEnabledByTask( + PeriodicDueItemsArgsOld.taskName, + enabled = false + ) } yield () private def migratePeriodicQueryTask(old: RPeriodicTask): ConnectionIO[Int] = diff --git a/modules/store/src/main/scala/db/migration/common/MigrateNotifyTasks.scala b/modules/store/src/main/scala/db/migration/common/MigrateNotifyTasks.scala index df3d85bd..f06636ec 100644 --- a/modules/store/src/main/scala/db/migration/common/MigrateNotifyTasks.scala +++ b/modules/store/src/main/scala/db/migration/common/MigrateNotifyTasks.scala @@ -38,7 +38,7 @@ object MigrateNotifyTasks extends TransactorSupport { logger.info(s"Starting to migrate ${tasks.size} user tasks") ) _ <- tasks.traverse(migrateDueItemTask1) - _ <- RPeriodicTask.setEnabledByTask(NotifyDueItemsArgs.taskName, false) + _ <- RPeriodicTask.setEnabledByTask(NotifyDueItemsArgs.taskName, enabled = false) } yield () private def migrateDueItemTask1(old: RPeriodicTask): ConnectionIO[Int] = { diff --git a/modules/store/src/main/scala/docspell/store/SchemaMigrateConfig.scala b/modules/store/src/main/scala/docspell/store/SchemaMigrateConfig.scala index 8659ef99..de3d33f7 100644 --- a/modules/store/src/main/scala/docspell/store/SchemaMigrateConfig.scala +++ b/modules/store/src/main/scala/docspell/store/SchemaMigrateConfig.scala @@ -13,5 +13,9 @@ case class SchemaMigrateConfig( ) object SchemaMigrateConfig { - val defaults = SchemaMigrateConfig(true, true, false) + val defaults = SchemaMigrateConfig( + runMainMigrations = true, + runFixupMigrations = true, + repairSchema = false + ) } diff --git a/modules/store/src/main/scala/docspell/store/file/FileUrlReader.scala b/modules/store/src/main/scala/docspell/store/file/FileUrlReader.scala index bd4e41ee..dfdd1bd1 100644 --- a/modules/store/src/main/scala/docspell/store/file/FileUrlReader.scala +++ b/modules/store/src/main/scala/docspell/store/file/FileUrlReader.scala @@ -25,7 +25,7 @@ object FileUrlReader { authority = Some(""), path = LenientUri.NonEmptyPath( Nel.of(key.collective.valueAsString, key.category.id.id, key.id.id), - false + trailingSlash = false ), query = None, fragment = None diff --git a/modules/store/src/main/scala/docspell/store/qb/DBFunction.scala b/modules/store/src/main/scala/docspell/store/qb/DBFunction.scala index 1f83a318..d7a64bff 100644 --- a/modules/store/src/main/scala/docspell/store/qb/DBFunction.scala +++ b/modules/store/src/main/scala/docspell/store/qb/DBFunction.scala @@ -15,7 +15,7 @@ object DBFunction { val countAll: DBFunction = CountAll def countAs[A](column: Column[A]): DBFunction = - Count(column, false) + Count(column, distinct = false) case object CountAll extends DBFunction diff --git a/modules/store/src/main/scala/docspell/store/qb/DSL.scala b/modules/store/src/main/scala/docspell/store/qb/DSL.scala index f5c8ddb4..01055373 100644 --- a/modules/store/src/main/scala/docspell/store/qb/DSL.scala +++ b/modules/store/src/main/scala/docspell/store/qb/DSL.scala @@ -78,10 +78,10 @@ trait DSL extends DoobieMeta { FromExpr.From(sel, alias) def count(c: Column[_]): DBFunction = - DBFunction.Count(c, false) + DBFunction.Count(c, distinct = false) def countDistinct(c: Column[_]): DBFunction = - DBFunction.Count(c, true) + DBFunction.Count(c, distinct = true) def countAll: DBFunction = DBFunction.CountAll @@ -250,22 +250,22 @@ trait DSL extends DoobieMeta { in(subsel).negate def in(values: Nel[A])(implicit P: Put[A]): Condition = - Condition.InValues(col.s, values, false) + Condition.InValues(col.s, values, lower = false) def notIn(values: Nel[A])(implicit P: Put[A]): Condition = in(values).negate def inLower(values: Nel[String]): Condition = - Condition.InValues(col.s, values.map(_.toLowerCase), true) + Condition.InValues(col.s, values.map(_.toLowerCase), lower = true) def inLowerA(values: Nel[A])(implicit P: Put[A]): Condition = - Condition.InValues(col.s, values, true) + Condition.InValues(col.s, values, lower = true) def notInLower(values: Nel[String]): Condition = - Condition.InValues(col.s, values.map(_.toLowerCase), true).negate + Condition.InValues(col.s, values.map(_.toLowerCase), lower = true).negate def notInLowerA(values: Nel[A])(implicit P: Put[A]): Condition = - Condition.InValues(col.s, values, true).negate + Condition.InValues(col.s, values, lower = true).negate def isNull: Condition = Condition.IsNull(col.s) @@ -382,7 +382,7 @@ trait DSL extends DoobieMeta { Condition.CompareFVal(sel, Operator.Neq, value) def in[A](values: Nel[A])(implicit P: Put[A]): Condition = - Condition.InValues(sel, values, false) + Condition.InValues(sel, values, lower = false) } } diff --git a/modules/store/src/main/scala/docspell/store/qb/Select.scala b/modules/store/src/main/scala/docspell/store/qb/Select.scala index 7f2e6916..45773834 100644 --- a/modules/store/src/main/scala/docspell/store/qb/Select.scala +++ b/modules/store/src/main/scala/docspell/store/qb/Select.scala @@ -76,32 +76,38 @@ sealed trait Select { object Select { def apply(projection: SelectExpr) = - SimpleSelect(false, Nel.of(projection), None, Condition.unit, None) + SimpleSelect(distinctFlag = false, Nel.of(projection), None, Condition.unit, None) def apply(projection: Nel[SelectExpr], from: FromExpr) = - SimpleSelect(false, projection, from.some, Condition.unit, None) + SimpleSelect(distinctFlag = false, projection, from.some, Condition.unit, None) def apply(projection: SelectExpr, from: FromExpr) = - SimpleSelect(false, Nel.of(projection), from.some, Condition.unit, None) + SimpleSelect( + distinctFlag = false, + Nel.of(projection), + from.some, + Condition.unit, + None + ) def apply( projection: Nel[SelectExpr], from: FromExpr, where: Condition - ) = SimpleSelect(false, projection, from.some, where, None) + ) = SimpleSelect(distinctFlag = false, projection, from.some, where, None) def apply( projection: SelectExpr, from: FromExpr, where: Condition - ) = SimpleSelect(false, Nel.of(projection), from.some, where, None) + ) = SimpleSelect(distinctFlag = false, Nel.of(projection), from.some, where, None) def apply( projection: Nel[SelectExpr], from: FromExpr, where: Condition, groupBy: GroupBy - ) = SimpleSelect(false, projection, from.some, where, Some(groupBy)) + ) = SimpleSelect(distinctFlag = false, projection, from.some, where, Some(groupBy)) case class SimpleSelect( distinctFlag: Boolean, diff --git a/modules/store/src/main/scala/docspell/store/records/RCollective.scala b/modules/store/src/main/scala/docspell/store/records/RCollective.scala index 48b431c6..1454f186 100644 --- a/modules/store/src/main/scala/docspell/store/records/RCollective.scala +++ b/modules/store/src/main/scala/docspell/store/records/RCollective.scala @@ -46,7 +46,7 @@ object RCollective { collName, CollectiveState.Active, Language.German, - true, + integrationEnabled = true, created ) diff --git a/modules/store/src/main/scala/docspell/store/records/RTag.scala b/modules/store/src/main/scala/docspell/store/records/RTag.scala index fc66f6e8..b1e432c6 100644 --- a/modules/store/src/main/scala/docspell/store/records/RTag.scala +++ b/modules/store/src/main/scala/docspell/store/records/RTag.scala @@ -180,8 +180,8 @@ object RTag { .sortBy(_._1) byCat match { - case (None, tags) :: rest => - rest.flatMap(_._2) ++ tags + case (None, tagsByCat) :: rest => + rest.flatMap(_._2) ++ tagsByCat case _ => byCat.flatMap(_._2) } diff --git a/modules/store/src/main/scala/docspell/store/records/RTotp.scala b/modules/store/src/main/scala/docspell/store/records/RTotp.scala index 00148b18..4a67d389 100644 --- a/modules/store/src/main/scala/docspell/store/records/RTotp.scala +++ b/modules/store/src/main/scala/docspell/store/records/RTotp.scala @@ -44,7 +44,7 @@ object RTotp { for { now <- Timestamp.current[F] key <- Key.generate[F](mac) - } yield RTotp(userId, false, key, now) + } yield RTotp(userId, enabled = false, key, now) def insert(r: RTotp): ConnectionIO[Int] = DML.insert(T, T.all, sql"${r.userId},${r.enabled},${r.secret},${r.created}") diff --git a/modules/store/src/main/scala/docspell/store/records/RUserEmail.scala b/modules/store/src/main/scala/docspell/store/records/RUserEmail.scala index 22995f1d..e6952954 100644 --- a/modules/store/src/main/scala/docspell/store/records/RUserEmail.scala +++ b/modules/store/src/main/scala/docspell/store/records/RUserEmail.scala @@ -199,10 +199,10 @@ object RUserEmail { userId: Ident, nameQ: Option[String] ): ConnectionIO[Vector[RUserEmail]] = - findByAccount0(userId, nameQ, false).to[Vector] + findByAccount0(userId, nameQ, exact = false).to[Vector] def getByName(userId: Ident, name: Ident): ConnectionIO[Option[RUserEmail]] = - findByAccount0(userId, Some(name.id), true).option + findByAccount0(userId, Some(name.id), exact = true).option def getById(id: Ident): ConnectionIO[Option[RUserEmail]] = { val t = Table(None) diff --git a/modules/store/src/main/scala/docspell/store/records/RUserImap.scala b/modules/store/src/main/scala/docspell/store/records/RUserImap.scala index 127d82fe..fefe1e8d 100644 --- a/modules/store/src/main/scala/docspell/store/records/RUserImap.scala +++ b/modules/store/src/main/scala/docspell/store/records/RUserImap.scala @@ -195,13 +195,13 @@ object RUserImap { userId: Ident, nameQ: Option[String] ): ConnectionIO[Vector[RUserImap]] = - findByAccount0(userId, nameQ, false).to[Vector] + findByAccount0(userId, nameQ, exact = false).to[Vector] def getByName( userId: Ident, name: Ident ): ConnectionIO[Option[RUserImap]] = - findByAccount0(userId, Some(name.id), true).option + findByAccount0(userId, Some(name.id), exact = true).option def delete( userId: Ident, diff --git a/modules/store/src/test/scala/docspell/store/DatabaseTest.scala b/modules/store/src/test/scala/docspell/store/DatabaseTest.scala index feaa994e..46cc0a25 100644 --- a/modules/store/src/test/scala/docspell/store/DatabaseTest.scala +++ b/modules/store/src/test/scala/docspell/store/DatabaseTest.scala @@ -66,7 +66,7 @@ trait DatabaseTest } yield res ) - lazy val newH2DataSource = ResourceFixture(for { + lazy val newH2DataSource = ResourceFunFixture(for { jdbc <- Resource.eval(IO(StoreFixture.memoryDB(UUID.randomUUID().toString))) ds <- StoreFixture.dataSource(jdbc) } yield (jdbc, ds)) diff --git a/modules/store/src/test/scala/docspell/store/StoreFixture.scala b/modules/store/src/test/scala/docspell/store/StoreFixture.scala index a6696a39..03fb9cb1 100644 --- a/modules/store/src/test/scala/docspell/store/StoreFixture.scala +++ b/modules/store/src/test/scala/docspell/store/StoreFixture.scala @@ -26,7 +26,7 @@ trait StoreFixture extends CatsEffectFunFixtures { self: CatsEffectSuite => def schemaMigrateConfig = StoreFixture.schemaMigrateConfig - val xa = ResourceFixture { + val xa = ResourceFunFixture { val cfg = StoreFixture.memoryDB("test") for { ds <- StoreFixture.dataSource(cfg) @@ -35,7 +35,7 @@ trait StoreFixture extends CatsEffectFunFixtures { self: CatsEffectSuite => } yield xa } - val store = ResourceFixture { + val store = ResourceFunFixture { val cfg = StoreFixture.memoryDB("test") for { store <- StoreFixture.store(cfg) @@ -106,7 +106,7 @@ object StoreFixture { for { xa <- makeXA(ds) cfg = FileRepositoryConfig.Database(64 * 1024) - fr = FileRepository[IO](xa, ds, cfg, true) + fr = FileRepository[IO](xa, ds, cfg, withAttributeStore = true) store = new StoreImpl[IO](fr, jdbc, schemaMigrateConfig, ds, xa) _ <- Resource.eval(store.migrate) } yield store diff --git a/modules/store/src/test/scala/docspell/store/fts/TempFtsOpsTest.scala b/modules/store/src/test/scala/docspell/store/fts/TempFtsOpsTest.scala index 83d5006a..ee0f5a4b 100644 --- a/modules/store/src/test/scala/docspell/store/fts/TempFtsOpsTest.scala +++ b/modules/store/src/test/scala/docspell/store/fts/TempFtsOpsTest.scala @@ -193,7 +193,7 @@ class TempFtsOpsTest extends DatabaseTest { DocspellSystem.account.collective, CollectiveState.Active, Language.English, - true, + integrationEnabled = true, ts ) diff --git a/modules/store/src/test/scala/docspell/store/qb/QueryBuilderTest.scala b/modules/store/src/test/scala/docspell/store/qb/QueryBuilderTest.scala index 69a63410..059df6cd 100644 --- a/modules/store/src/test/scala/docspell/store/qb/QueryBuilderTest.scala +++ b/modules/store/src/test/scala/docspell/store/qb/QueryBuilderTest.scala @@ -39,7 +39,7 @@ class QueryBuilderTest extends FunSuite with TestLoggingConfig { val q = Select(proj, tables, cond).orderBy(c.name.desc) q match { case Select.Ordered( - Select.SimpleSelect(false, proj, from, where, group), + Select.SimpleSelect(false, projs, from, where, group), sb, vempty ) => @@ -48,7 +48,7 @@ class QueryBuilderTest extends FunSuite with TestLoggingConfig { sb, OrderBy(SelectExpr.SelectColumn(c.name, None), OrderBy.OrderType.Desc) ) - assertEquals(11, proj.size) + assertEquals(11, projs.size) from match { case None => fail("Unexpected from value") diff --git a/modules/webapp/elm.json b/modules/webapp/elm.json index 2d5a8a4a..3fe27352 100644 --- a/modules/webapp/elm.json +++ b/modules/webapp/elm.json @@ -25,7 +25,7 @@ "justinmimbs/timezone-data": "5.1.2", "norpan/elm-html5-drag-drop": "3.1.4", "pablohirafuji/elm-qrcode": "4.0.1", - "ryannhg/date-format": "2.3.0", + "ryan-haskell/date-format": "1.0.0", "truqu/elm-base64": "2.0.4", "ursi/elm-scroll": "1.0.0", "ursi/elm-throttle": "1.0.1" diff --git a/modules/webapp/package-lock.json b/modules/webapp/package-lock.json index b9b2cc19..9ca63987 100644 --- a/modules/webapp/package-lock.json +++ b/modules/webapp/package-lock.json @@ -1,30 +1,25 @@ { "name": "docspell-css", "version": "1.0.0", - "lockfileVersion": 2, + "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "docspell-css", "version": "1.0.0", + "dependencies": { + "tailwindcss": "^3.4.1" + }, "devDependencies": { "@fortawesome/fontawesome-free": "^6.0.0", "@tailwindcss/forms": "^0.5.0", - "autoprefixer": "^10.4.2", - "cssnano": "^6.0.0", - "flag-icon-css": "^3.5.0", - "postcss": "^8.4.7", - "postcss-cli": "^11.0.0", - "postcss-import": "^16.0.0", - "postcss-purgecss": "^5.0.0", - "tailwindcss": "^3.0.23" + "flag-icons": "^7.2.0" } }, "node_modules/@alloc/quick-lru": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", - "dev": true, "engines": { "node": ">=10" }, @@ -33,43 +28,56 @@ } }, "node_modules/@fortawesome/fontawesome-free": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-free/-/fontawesome-free-6.5.1.tgz", - "integrity": "sha512-CNy5vSwN3fsUStPRLX7fUYojyuzoEMSXPl7zSLJ8TgtRfjv24LOnOWKT2zYwaHZCJGkdyRnTmstR0P+Ah503Gw==", + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-free/-/fontawesome-free-6.6.0.tgz", + "integrity": "sha512-60G28ke/sXdtS9KZCpZSHHkCbdsOGEhIUGlwq6yhY74UpTiToIh8np7A8yphhM4BWsvNFtIvLpi4co+h9Mr9Ow==", "dev": true, - "hasInstallScript": true, + "license": "(CC-BY-4.0 AND OFL-1.1 AND MIT)", "engines": { "node": ">=6" } }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", - "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", - "dev": true, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", "dependencies": { - "@jridgewell/set-array": "^1.0.1", + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", + "dependencies": { + "@jridgewell/set-array": "^1.2.1", "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" + "@jridgewell/trace-mapping": "^0.3.24" }, "engines": { "node": ">=6.0.0" } }, "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", - "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", - "dev": true, + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", "engines": { "node": ">=6.0.0" } }, "node_modules/@jridgewell/set-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", - "dev": true, + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", "engines": { "node": ">=6.0.0" } @@ -77,30 +85,21 @@ "node_modules/@jridgewell/sourcemap-codec": { "version": "1.4.15", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", - "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", - "dev": true + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==" }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.18", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.18.tgz", - "integrity": "sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA==", - "dev": true, + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", "dependencies": { - "@jridgewell/resolve-uri": "3.1.0", - "@jridgewell/sourcemap-codec": "1.4.14" + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" } }, - "node_modules/@jridgewell/trace-mapping/node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.14", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", - "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", - "dev": true - }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" @@ -113,7 +112,6 @@ "version": "2.0.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true, "engines": { "node": ">= 8" } @@ -122,7 +120,6 @@ "version": "1.2.8", "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" @@ -131,16 +128,13 @@ "node": ">= 8" } }, - "node_modules/@sindresorhus/merge-streams": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-1.0.0.tgz", - "integrity": "sha512-rUV5WyJrJLoloD4NDN1V1+LDMDWOa4OTsT4yYJwQNpTU6FWxkxHpL7eu4w+DmiH8x/EAM1otkPE1+LaspIbplw==", - "dev": true, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "optional": true, "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=14" } }, "node_modules/@tailwindcss/forms": { @@ -155,34 +149,23 @@ "tailwindcss": ">=3.0.0 || >= 3.0.0-alpha.1" } }, - "node_modules/@trysound/sax": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", - "integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==", - "dev": true, - "engines": { - "node": ">=10.13.0" - } - }, "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, "node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", "engines": { - "node": ">=8" + "node": ">=12" }, "funding": { "url": "https://github.com/chalk/ansi-styles?sponsor=1" @@ -191,14 +174,12 @@ "node_modules/any-promise": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", - "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", - "dev": true + "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==" }, "node_modules/anymatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", - "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", - "dev": true, + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" @@ -210,172 +191,52 @@ "node_modules/arg": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", - "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", - "dev": true - }, - "node_modules/autoprefixer": { - "version": "10.4.17", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.17.tgz", - "integrity": "sha512-/cpVNRLSfhOtcGflT13P2794gVSgmPgTR+erw5ifnMLZb0UnSlkK4tquLmkd3BhA+nLo5tX8Cu0upUsGKvKbmg==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/autoprefixer" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "dependencies": { - "browserslist": "^4.22.2", - "caniuse-lite": "^1.0.30001578", - "fraction.js": "^4.3.7", - "normalize-range": "^0.1.2", - "picocolors": "^1.0.0", - "postcss-value-parser": "^4.2.0" - }, - "bin": { - "autoprefixer": "bin/autoprefixer" - }, - "engines": { - "node": "^10 || ^12 || >=14" - }, - "peerDependencies": { - "postcss": "^8.1.0" - } + "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==" }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, "node_modules/binary-extensions": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", - "dev": true, "engines": { "node": ">=8" } }, - "node_modules/boolbase": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", - "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", - "dev": true - }, "node_modules/brace-expansion": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, "dependencies": { "balanced-match": "^1.0.0" } }, "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dependencies": { - "fill-range": "^7.0.1" + "fill-range": "^7.1.1" }, "engines": { "node": ">=8" } }, - "node_modules/browserslist": { - "version": "4.22.2", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.2.tgz", - "integrity": "sha512-0UgcrvQmBDvZHFGdYUehrCNIazki7/lUP3kkoi/r3YB2amZbFM9J43ZRkJTXBUZK4gmx56+Sqk9+Vs9mwZx9+A==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "dependencies": { - "caniuse-lite": "^1.0.30001565", - "electron-to-chromium": "^1.4.601", - "node-releases": "^2.0.14", - "update-browserslist-db": "^1.0.13" - }, - "bin": { - "browserslist": "cli.js" - }, - "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" - } - }, "node_modules/camelcase-css": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", - "dev": true, "engines": { "node": ">= 6" } }, - "node_modules/caniuse-api": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz", - "integrity": "sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==", - "dev": true, - "dependencies": { - "browserslist": "^4.0.0", - "caniuse-lite": "^1.0.0", - "lodash.memoize": "^4.1.2", - "lodash.uniq": "^4.5.0" - } - }, - "node_modules/caniuse-lite": { - "version": "1.0.30001578", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001578.tgz", - "integrity": "sha512-J/jkFgsQ3NEl4w2lCoM9ZPxrD+FoBNJ7uJUpGVjIg/j0OwJosWM36EPDv+Yyi0V4twBk9pPmlFS+PLykgEvUmg==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/caniuse-lite" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ] - }, "node_modules/chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", @@ -388,26 +249,28 @@ "engines": { "node": ">= 8.10.0" }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, "optionalDependencies": { "fsevents": "~2.3.2" } }, - "node_modules/cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "dev": true, + "node_modules/chokidar/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" } }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, "dependencies": { "color-name": "~1.1.4" }, @@ -418,88 +281,33 @@ "node_modules/color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/colord": { - "version": "2.9.3", - "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz", - "integrity": "sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==", - "dev": true + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, "node_modules/commander": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", - "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", - "dev": true, - "engines": { - "node": ">= 10" - } - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true - }, - "node_modules/css-declaration-sorter": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-7.1.1.tgz", - "integrity": "sha512-dZ3bVTEEc1vxr3Bek9vGwfB5Z6ESPULhcRvO472mfjVnj8jRcTnKO8/JTczlvxM10Myb+wBM++1MtdO76eWcaQ==", - "dev": true, - "engines": { - "node": "^14 || ^16 || >=18" - }, - "peerDependencies": { - "postcss": "^8.0.9" - } - }, - "node_modules/css-select": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz", - "integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==", - "dev": true, - "dependencies": { - "boolbase": "^1.0.0", - "css-what": "^6.1.0", - "domhandler": "^5.0.2", - "domutils": "^3.0.1", - "nth-check": "^2.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, - "node_modules/css-tree": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.3.1.tgz", - "integrity": "sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==", - "dev": true, - "dependencies": { - "mdn-data": "2.0.30", - "source-map-js": "^1.0.1" - }, - "engines": { - "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0" - } - }, - "node_modules/css-what": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", - "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", - "dev": true, + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", "engines": { "node": ">= 6" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" }, - "funding": { - "url": "https://github.com/sponsors/fb55" + "engines": { + "node": ">= 8" } }, "node_modules/cssesc": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", - "dev": true, "bin": { "cssesc": "bin/cssesc" }, @@ -507,237 +315,30 @@ "node": ">=4" } }, - "node_modules/cssnano": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-6.0.3.tgz", - "integrity": "sha512-MRq4CIj8pnyZpcI2qs6wswoYoDD1t0aL28n+41c1Ukcpm56m1h6mCexIHBGjfZfnTqtGSSCP4/fB1ovxgjBOiw==", - "dev": true, - "dependencies": { - "cssnano-preset-default": "^6.0.3", - "lilconfig": "^3.0.0" - }, - "engines": { - "node": "^14 || ^16 || >=18.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/cssnano" - }, - "peerDependencies": { - "postcss": "^8.4.31" - } - }, - "node_modules/cssnano-preset-default": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-6.0.3.tgz", - "integrity": "sha512-4y3H370aZCkT9Ev8P4SO4bZbt+AExeKhh8wTbms/X7OLDo5E7AYUUy6YPxa/uF5Grf+AJwNcCnxKhZynJ6luBA==", - "dev": true, - "dependencies": { - "css-declaration-sorter": "^7.1.1", - "cssnano-utils": "^4.0.1", - "postcss-calc": "^9.0.1", - "postcss-colormin": "^6.0.2", - "postcss-convert-values": "^6.0.2", - "postcss-discard-comments": "^6.0.1", - "postcss-discard-duplicates": "^6.0.1", - "postcss-discard-empty": "^6.0.1", - "postcss-discard-overridden": "^6.0.1", - "postcss-merge-longhand": "^6.0.2", - "postcss-merge-rules": "^6.0.3", - "postcss-minify-font-values": "^6.0.1", - "postcss-minify-gradients": "^6.0.1", - "postcss-minify-params": "^6.0.2", - "postcss-minify-selectors": "^6.0.2", - "postcss-normalize-charset": "^6.0.1", - "postcss-normalize-display-values": "^6.0.1", - "postcss-normalize-positions": "^6.0.1", - "postcss-normalize-repeat-style": "^6.0.1", - "postcss-normalize-string": "^6.0.1", - "postcss-normalize-timing-functions": "^6.0.1", - "postcss-normalize-unicode": "^6.0.2", - "postcss-normalize-url": "^6.0.1", - "postcss-normalize-whitespace": "^6.0.1", - "postcss-ordered-values": "^6.0.1", - "postcss-reduce-initial": "^6.0.2", - "postcss-reduce-transforms": "^6.0.1", - "postcss-svgo": "^6.0.2", - "postcss-unique-selectors": "^6.0.2" - }, - "engines": { - "node": "^14 || ^16 || >=18.0" - }, - "peerDependencies": { - "postcss": "^8.4.31" - } - }, - "node_modules/cssnano-utils": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/cssnano-utils/-/cssnano-utils-4.0.1.tgz", - "integrity": "sha512-6qQuYDqsGoiXssZ3zct6dcMxiqfT6epy7x4R0TQJadd4LWO3sPR6JH6ZByOvVLoZ6EdwPGgd7+DR1EmX3tiXQQ==", - "dev": true, - "engines": { - "node": "^14 || ^16 || >=18.0" - }, - "peerDependencies": { - "postcss": "^8.4.31" - } - }, - "node_modules/cssnano/node_modules/lilconfig": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.0.0.tgz", - "integrity": "sha512-K2U4W2Ff5ibV7j7ydLr+zLAkIg5JJ4lPn1Ltsdt+Tz/IjQ8buJ55pZAxoP34lqIiwtF9iAvtLv3JGv7CAyAg+g==", - "dev": true, - "engines": { - "node": ">=14" - } - }, - "node_modules/csso": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/csso/-/csso-5.0.5.tgz", - "integrity": "sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==", - "dev": true, - "dependencies": { - "css-tree": "~2.2.0" - }, - "engines": { - "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0", - "npm": ">=7.0.0" - } - }, - "node_modules/csso/node_modules/css-tree": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.2.1.tgz", - "integrity": "sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA==", - "dev": true, - "dependencies": { - "mdn-data": "2.0.28", - "source-map-js": "^1.0.1" - }, - "engines": { - "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0", - "npm": ">=7.0.0" - } - }, - "node_modules/csso/node_modules/mdn-data": { - "version": "2.0.28", - "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.28.tgz", - "integrity": "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==", - "dev": true - }, - "node_modules/dependency-graph": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/dependency-graph/-/dependency-graph-0.11.0.tgz", - "integrity": "sha512-JeMq7fEshyepOWDfcfHK06N3MhyPhz++vtqWhMT5O9A3K42rdsEDpfdVqjaqaAhsw6a+ZqeDvQVtD0hFHQWrzg==", - "dev": true, - "engines": { - "node": ">= 0.6.0" - } - }, "node_modules/didyoumean": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", - "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==", - "dev": true + "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==" }, "node_modules/dlv": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", - "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", - "dev": true + "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==" }, - "node_modules/dom-serializer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", - "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", - "dev": true, - "dependencies": { - "domelementtype": "^2.3.0", - "domhandler": "^5.0.2", - "entities": "^4.2.0" - }, - "funding": { - "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" - } - }, - "node_modules/domelementtype": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", - "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ] - }, - "node_modules/domhandler": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", - "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", - "dev": true, - "dependencies": { - "domelementtype": "^2.3.0" - }, - "engines": { - "node": ">= 4" - }, - "funding": { - "url": "https://github.com/fb55/domhandler?sponsor=1" - } - }, - "node_modules/domutils": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz", - "integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==", - "dev": true, - "dependencies": { - "dom-serializer": "^2.0.0", - "domelementtype": "^2.3.0", - "domhandler": "^5.0.3" - }, - "funding": { - "url": "https://github.com/fb55/domutils?sponsor=1" - } - }, - "node_modules/electron-to-chromium": { - "version": "1.4.618", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.618.tgz", - "integrity": "sha512-mTM2HieHLxs1RbD/R/ZoQLMsGI8lWIkP17G7cx32mJRBJt9wlNPkXwE3sYg/OnNb5GBkus98lXatSthoL8Y5Ag==", - "dev": true + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" }, "node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "node_modules/entities": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", - "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", - "dev": true, - "engines": { - "node": ">=0.12" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "dev": true, - "engines": { - "node": ">=6" - } + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" }, "node_modules/fast-glob": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", - "dev": true, "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", @@ -749,20 +350,29 @@ "node": ">=8.6.0" } }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/fastq": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", - "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", - "dev": true, + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", + "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", "dependencies": { "reusify": "^1.0.4" } }, "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dependencies": { "to-regex-range": "^5.0.1" }, @@ -770,51 +380,32 @@ "node": ">=8" } }, - "node_modules/flag-icon-css": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/flag-icon-css/-/flag-icon-css-3.5.0.tgz", - "integrity": "sha512-pgJnJLrtb0tcDgU1fzGaQXmR8h++nXvILJ+r5SmOXaaL/2pocunQo2a8TAXhjQnBpRLPtZ1KCz/TYpqeNuE2ew==", - "deprecated": "The project has been renamed to flag-icons", - "dev": true - }, - "node_modules/fraction.js": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz", - "integrity": "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==", + "node_modules/flag-icons": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/flag-icons/-/flag-icons-7.2.3.tgz", + "integrity": "sha512-X2gUdteNuqdNqob2KKTJTS+ZCvyWeLCtDz9Ty8uJP17Y4o82Y+U/Vd4JNrdwTAjagYsRznOn9DZ+E/Q52qbmqg==", "dev": true, + "license": "MIT" + }, + "node_modules/foreground-child": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", + "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, "engines": { - "node": "*" + "node": ">=14" }, "funding": { - "type": "patreon", - "url": "https://github.com/sponsors/rawify" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/fs-extra": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.1.0.tgz", - "integrity": "sha512-0rcTq621PD5jM/e0a3EJoGC/1TC5ZBCERW82LQuwfGnCa1V8w7dpYH1yNu+SLb6E5dkeCBzKEyLGlFrnr+dUyw==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=14.14" - } - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true - }, "node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", "hasInstallScript": true, "optional": true, "os": [ @@ -825,131 +416,60 @@ } }, "node_modules/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true - }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true, - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "node_modules/get-stdin": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-9.0.0.tgz", - "integrity": "sha512-dVKBjfWisLAicarI2Sf+JuBE/DghV4UzNAVe9yhEJuzeREd3JhOTE9cUaJTeSa77fsbQUK3pcOpJfM59+VKZaA==", - "dev": true, - "engines": { - "node": ">=12" - }, + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/glob": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", - "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", - "dev": true, + "version": "10.3.10", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", + "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^5.0.1", - "once": "^1.3.0" + "foreground-child": "^3.1.0", + "jackspeak": "^2.3.5", + "minimatch": "^9.0.1", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", + "path-scurry": "^1.10.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" }, "engines": { - "node": ">=12" + "node": ">=16 || 14 >=14.17" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, "node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", "dependencies": { - "is-glob": "^4.0.1" + "is-glob": "^4.0.3" }, "engines": { - "node": ">= 6" + "node": ">=10.13.0" } }, - "node_modules/globby": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-14.0.0.tgz", - "integrity": "sha512-/1WM/LNHRAOH9lZta77uGbq0dAEQM+XjNesWwhlERDVenqothRbnzTrL3/LrIoEPPjeUHC3vrS6TwoyxeHs7MQ==", - "dev": true, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", "dependencies": { - "@sindresorhus/merge-streams": "^1.0.0", - "fast-glob": "^3.3.2", - "ignore": "^5.2.4", - "path-type": "^5.0.0", - "slash": "^5.1.0", - "unicorn-magic": "^0.1.0" + "function-bind": "^1.1.2" }, "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">= 0.4" } }, - "node_modules/graceful-fs": { - "version": "4.2.10", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", - "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", - "dev": true - }, - "node_modules/has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.1" - }, - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/ignore": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.0.tgz", - "integrity": "sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, "node_modules/is-binary-path": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, "dependencies": { "binary-extensions": "^2.0.0" }, @@ -958,12 +478,11 @@ } }, "node_modules/is-core-module": { - "version": "2.12.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.12.0.tgz", - "integrity": "sha512-RECHCBCd/viahWmwj6enj19sKbHfJrddi/6cBDsNTKbNq0f7VeaUkBo60BqzvPqo/W54ChS62Z5qyun7cfOMqQ==", - "dev": true, + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", + "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", "dependencies": { - "has": "^1.0.3" + "hasown": "^2.0.0" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -972,8 +491,7 @@ "node_modules/is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true, + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", "engines": { "node": ">=0.10.0" } @@ -982,7 +500,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, "engines": { "node": ">=8" } @@ -991,7 +508,6 @@ "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, "dependencies": { "is-extglob": "^2.1.1" }, @@ -1003,37 +519,44 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, "engines": { "node": ">=0.12.0" } }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" + }, + "node_modules/jackspeak": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", + "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, "node_modules/jiti": { "version": "1.21.0", "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.0.tgz", "integrity": "sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q==", - "dev": true, "bin": { "jiti": "bin/jiti.js" } }, - "node_modules/jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, "node_modules/lilconfig": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==", - "dev": true, "engines": { "node": ">=10" } @@ -1041,32 +564,20 @@ "node_modules/lines-and-columns": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", - "dev": true + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==" }, - "node_modules/lodash.memoize": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", - "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", - "dev": true - }, - "node_modules/lodash.uniq": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", - "integrity": "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==", - "dev": true - }, - "node_modules/mdn-data": { - "version": "2.0.30", - "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz", - "integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==", - "dev": true + "node_modules/lru-cache": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.0.tgz", + "integrity": "sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==", + "engines": { + "node": "14 || >=16.14" + } }, "node_modules/merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true, "engines": { "node": ">= 8" } @@ -1075,7 +586,6 @@ "version": "4.0.5", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", - "dev": true, "dependencies": { "braces": "^3.0.2", "picomatch": "^2.3.1" @@ -1085,31 +595,40 @@ } }, "node_modules/mini-svg-data-uri": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/mini-svg-data-uri/-/mini-svg-data-uri-1.4.3.tgz", - "integrity": "sha512-gSfqpMRC8IxghvMcxzzmMnWpXAChSA+vy4cia33RgerMS8Fex95akUyQZPbxJJmeBGiGmK7n/1OpUX8ksRjIdA==", + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/mini-svg-data-uri/-/mini-svg-data-uri-1.4.4.tgz", + "integrity": "sha512-r9deDe9p5FJUPZAk3A59wGH7Ii9YrjjWw0jmw/liSbHl2CHiyXj6FcDXDu2K3TjVAXqiJdaw3xxwlZZr9E6nHg==", "dev": true, "bin": { "mini-svg-data-uri": "cli.js" } }, "node_modules/minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", - "dev": true, + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", "dependencies": { "brace-expansion": "^2.0.1" }, "engines": { - "node": ">=10" + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/minipass": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", + "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", + "engines": { + "node": ">=16 || 14 >=14.17" } }, "node_modules/mz": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", - "dev": true, "dependencies": { "any-promise": "^1.0.0", "object-assign": "^4.0.1", @@ -1120,7 +639,6 @@ "version": "3.3.7", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", - "dev": true, "funding": [ { "type": "github", @@ -1134,47 +652,18 @@ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, - "node_modules/node-releases": { - "version": "2.0.14", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", - "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", - "dev": true - }, "node_modules/normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true, "engines": { "node": ">=0.10.0" } }, - "node_modules/normalize-range": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", - "integrity": "sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/nth-check": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", - "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", - "dev": true, - "dependencies": { - "boolbase": "^1.0.0" - }, - "funding": { - "url": "https://github.com/fb55/nth-check?sponsor=1" - } - }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -1183,58 +672,47 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", - "dev": true, "engines": { "node": ">= 6" } }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, "node_modules/path-parse": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" }, - "node_modules/path-type": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-5.0.0.tgz", - "integrity": "sha512-5HviZNaZcfqP95rwpv+1HDgUamezbqdSYTyzjTvwtJSnIH+3vnbmWsItli8OFEndS984VT55M3jduxZbX351gg==", - "dev": true, + "node_modules/path-scurry": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz", + "integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==", + "dependencies": { + "lru-cache": "^9.1.1 || ^10.0.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, "engines": { - "node": ">=12" + "node": ">=16 || 14 >=14.17" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/isaacs" } }, "node_modules/picocolors": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", - "dev": true + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" }, "node_modules/picomatch": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, "engines": { "node": ">=8.6" }, @@ -1245,17 +723,15 @@ "node_modules/pify": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true, + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", "engines": { "node": ">=0.10.0" } }, "node_modules/pirates": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.5.tgz", - "integrity": "sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ==", - "dev": true, + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", + "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", "engines": { "node": ">= 6" } @@ -1264,7 +740,6 @@ "version": "8.4.35", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.35.tgz", "integrity": "sha512-u5U8qYpBCpN13BsiEB0CbR1Hhh4Gc0zLFuedrHJKMctHCHAGrMdG0PRM/KErzAL3CU6/eckEtmHNB3x6e3c0vA==", - "dev": true, "funding": [ { "type": "opencollective", @@ -1288,189 +763,17 @@ "node": "^10 || ^12 || >=14" } }, - "node_modules/postcss-calc": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-9.0.1.tgz", - "integrity": "sha512-TipgjGyzP5QzEhsOZUaIkeO5mKeMFpebWzRogWG/ysonUlnHcq5aJe0jOjpfzUU8PeSaBQnrE8ehR0QA5vs8PQ==", - "dev": true, - "dependencies": { - "postcss-selector-parser": "^6.0.11", - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^14 || ^16 || >=18.0" - }, - "peerDependencies": { - "postcss": "^8.2.2" - } - }, - "node_modules/postcss-cli": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/postcss-cli/-/postcss-cli-11.0.0.tgz", - "integrity": "sha512-xMITAI7M0u1yolVcXJ9XTZiO9aO49mcoKQy6pCDFdMh9kGqhzLVpWxeD/32M/QBmkhcGypZFFOLNLmIW4Pg4RA==", - "dev": true, - "dependencies": { - "chokidar": "^3.3.0", - "dependency-graph": "^0.11.0", - "fs-extra": "^11.0.0", - "get-stdin": "^9.0.0", - "globby": "^14.0.0", - "picocolors": "^1.0.0", - "postcss-load-config": "^5.0.0", - "postcss-reporter": "^7.0.0", - "pretty-hrtime": "^1.0.3", - "read-cache": "^1.0.0", - "slash": "^5.0.0", - "yargs": "^17.0.0" - }, - "bin": { - "postcss": "index.js" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "postcss": "^8.0.0" - } - }, - "node_modules/postcss-cli/node_modules/lilconfig": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.0.0.tgz", - "integrity": "sha512-K2U4W2Ff5ibV7j7ydLr+zLAkIg5JJ4lPn1Ltsdt+Tz/IjQ8buJ55pZAxoP34lqIiwtF9iAvtLv3JGv7CAyAg+g==", - "dev": true, - "engines": { - "node": ">=14" - } - }, - "node_modules/postcss-cli/node_modules/postcss-load-config": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-5.0.2.tgz", - "integrity": "sha512-Q8QR3FYbqOKa0bnC1UQ2bFq9/ulHX5Bi34muzitMr8aDtUelO5xKeJEYC/5smE0jNE9zdB/NBnOwXKexELbRlw==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "dependencies": { - "lilconfig": "^3.0.0", - "yaml": "^2.3.4" - }, - "engines": { - "node": ">= 18" - }, - "peerDependencies": { - "jiti": ">=1.21.0", - "postcss": ">=8.0.9" - }, - "peerDependenciesMeta": { - "jiti": { - "optional": true - }, - "postcss": { - "optional": true - } - } - }, - "node_modules/postcss-colormin": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-6.0.2.tgz", - "integrity": "sha512-TXKOxs9LWcdYo5cgmcSHPkyrLAh86hX1ijmyy6J8SbOhyv6ua053M3ZAM/0j44UsnQNIWdl8gb5L7xX2htKeLw==", - "dev": true, - "dependencies": { - "browserslist": "^4.22.2", - "caniuse-api": "^3.0.0", - "colord": "^2.9.1", - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^14 || ^16 || >=18.0" - }, - "peerDependencies": { - "postcss": "^8.4.31" - } - }, - "node_modules/postcss-convert-values": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-6.0.2.tgz", - "integrity": "sha512-aeBmaTnGQ+NUSVQT8aY0sKyAD/BaLJenEKZ03YK0JnDE1w1Rr8XShoxdal2V2H26xTJKr3v5haByOhJuyT4UYw==", - "dev": true, - "dependencies": { - "browserslist": "^4.22.2", - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^14 || ^16 || >=18.0" - }, - "peerDependencies": { - "postcss": "^8.4.31" - } - }, - "node_modules/postcss-discard-comments": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-6.0.1.tgz", - "integrity": "sha512-f1KYNPtqYLUeZGCHQPKzzFtsHaRuECe6jLakf/RjSRqvF5XHLZnM2+fXLhb8Qh/HBFHs3M4cSLb1k3B899RYIg==", - "dev": true, - "engines": { - "node": "^14 || ^16 || >=18.0" - }, - "peerDependencies": { - "postcss": "^8.4.31" - } - }, - "node_modules/postcss-discard-duplicates": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-6.0.1.tgz", - "integrity": "sha512-1hvUs76HLYR8zkScbwyJ8oJEugfPV+WchpnA+26fpJ7Smzs51CzGBHC32RS03psuX/2l0l0UKh2StzNxOrKCYg==", - "dev": true, - "engines": { - "node": "^14 || ^16 || >=18.0" - }, - "peerDependencies": { - "postcss": "^8.4.31" - } - }, - "node_modules/postcss-discard-empty": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-6.0.1.tgz", - "integrity": "sha512-yitcmKwmVWtNsrrRqGJ7/C0YRy53i0mjexBDQ9zYxDwTWVBgbU4+C9jIZLmQlTDT9zhml+u0OMFJh8+31krmOg==", - "dev": true, - "engines": { - "node": "^14 || ^16 || >=18.0" - }, - "peerDependencies": { - "postcss": "^8.4.31" - } - }, - "node_modules/postcss-discard-overridden": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-6.0.1.tgz", - "integrity": "sha512-qs0ehZMMZpSESbRkw1+inkf51kak6OOzNRaoLd/U7Fatp0aN2HQ1rxGOrJvYcRAN9VpX8kUF13R2ofn8OlvFVA==", - "dev": true, - "engines": { - "node": "^14 || ^16 || >=18.0" - }, - "peerDependencies": { - "postcss": "^8.4.31" - } - }, "node_modules/postcss-import": { - "version": "16.0.0", - "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-16.0.0.tgz", - "integrity": "sha512-e77lhVvrD1I2y7dYmBv0k9ULTdArgEYZt97T4w6sFIU5uxIHvDFQlKgUUyY7v7Barj0Yf/zm5A4OquZN7jKm5Q==", - "dev": true, + "version": "15.1.0", + "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz", + "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==", "dependencies": { "postcss-value-parser": "^4.0.0", "read-cache": "^1.0.0", "resolve": "^1.1.7" }, "engines": { - "node": ">=18.0.0" + "node": ">=14.0.0" }, "peerDependencies": { "postcss": "^8.0.0" @@ -1480,7 +783,6 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz", "integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==", - "dev": true, "dependencies": { "camelcase-css": "^2.0.1" }, @@ -1496,21 +798,26 @@ } }, "node_modules/postcss-load-config": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.1.tgz", - "integrity": "sha512-vEJIc8RdiBRu3oRAI0ymerOn+7rPuMvRXslTvZUKZonDHFIczxztIyJ1urxM1x9JXEikvpWWTUUqal5j/8QgvA==", - "dev": true, + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.2.tgz", + "integrity": "sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], "dependencies": { - "lilconfig": "^2.0.5", - "yaml": "^2.1.1" + "lilconfig": "^3.0.0", + "yaml": "^2.3.4" }, "engines": { "node": ">= 14" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, "peerDependencies": { "postcss": ">=8.0.9", "ts-node": ">=9.0.0" @@ -1524,109 +831,21 @@ } } }, - "node_modules/postcss-merge-longhand": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-6.0.2.tgz", - "integrity": "sha512-+yfVB7gEM8SrCo9w2lCApKIEzrTKl5yS1F4yGhV3kSim6JzbfLGJyhR1B6X+6vOT0U33Mgx7iv4X9MVWuaSAfw==", - "dev": true, - "dependencies": { - "postcss-value-parser": "^4.2.0", - "stylehacks": "^6.0.2" - }, + "node_modules/postcss-load-config/node_modules/lilconfig": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.1.tgz", + "integrity": "sha512-O18pf7nyvHTckunPWCV1XUNXU1piu01y2b7ATJ0ppkUkk8ocqVWBrYjJBCwHDjD/ZWcfyrA0P4gKhzWGi5EINQ==", "engines": { - "node": "^14 || ^16 || >=18.0" + "node": ">=14" }, - "peerDependencies": { - "postcss": "^8.4.31" - } - }, - "node_modules/postcss-merge-rules": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-6.0.3.tgz", - "integrity": "sha512-yfkDqSHGohy8sGYIJwBmIGDv4K4/WrJPX355XrxQb/CSsT4Kc/RxDi6akqn5s9bap85AWgv21ArcUWwWdGNSHA==", - "dev": true, - "dependencies": { - "browserslist": "^4.22.2", - "caniuse-api": "^3.0.0", - "cssnano-utils": "^4.0.1", - "postcss-selector-parser": "^6.0.15" - }, - "engines": { - "node": "^14 || ^16 || >=18.0" - }, - "peerDependencies": { - "postcss": "^8.4.31" - } - }, - "node_modules/postcss-minify-font-values": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-6.0.1.tgz", - "integrity": "sha512-tIwmF1zUPoN6xOtA/2FgVk1ZKrLcCvE0dpZLtzyyte0j9zUeB8RTbCqrHZGjJlxOvNWKMYtunLrrl7HPOiR46w==", - "dev": true, - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^14 || ^16 || >=18.0" - }, - "peerDependencies": { - "postcss": "^8.4.31" - } - }, - "node_modules/postcss-minify-gradients": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-6.0.1.tgz", - "integrity": "sha512-M1RJWVjd6IOLPl1hYiOd5HQHgpp6cvJVLrieQYS9y07Yo8itAr6jaekzJphaJFR0tcg4kRewCk3kna9uHBxn/w==", - "dev": true, - "dependencies": { - "colord": "^2.9.1", - "cssnano-utils": "^4.0.1", - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^14 || ^16 || >=18.0" - }, - "peerDependencies": { - "postcss": "^8.4.31" - } - }, - "node_modules/postcss-minify-params": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-6.0.2.tgz", - "integrity": "sha512-zwQtbrPEBDj+ApELZ6QylLf2/c5zmASoOuA4DzolyVGdV38iR2I5QRMsZcHkcdkZzxpN8RS4cN7LPskOkTwTZw==", - "dev": true, - "dependencies": { - "browserslist": "^4.22.2", - "cssnano-utils": "^4.0.1", - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^14 || ^16 || >=18.0" - }, - "peerDependencies": { - "postcss": "^8.4.31" - } - }, - "node_modules/postcss-minify-selectors": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-6.0.2.tgz", - "integrity": "sha512-0b+m+w7OAvZejPQdN2GjsXLv5o0jqYHX3aoV0e7RBKPCsB7TYG5KKWBFhGnB/iP3213Ts8c5H4wLPLMm7z28Sg==", - "dev": true, - "dependencies": { - "postcss-selector-parser": "^6.0.15" - }, - "engines": { - "node": "^14 || ^16 || >=18.0" - }, - "peerDependencies": { - "postcss": "^8.4.31" + "funding": { + "url": "https://github.com/sponsors/antonk52" } }, "node_modules/postcss-nested": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.0.1.tgz", "integrity": "sha512-mEp4xPMi5bSWiMbsgoPfcP74lsWLHkQbZc3sY+jWYd65CUwXrUaTp0fmNpa01ZcETKlIgUdFN/MpS2xZtqL9dQ==", - "dev": true, "dependencies": { "postcss-selector-parser": "^6.0.11" }, @@ -1641,224 +860,10 @@ "postcss": "^8.2.14" } }, - "node_modules/postcss-normalize-charset": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-6.0.1.tgz", - "integrity": "sha512-aW5LbMNRZ+oDV57PF9K+WI1Z8MPnF+A8qbajg/T8PP126YrGX1f9IQx21GI2OlGz7XFJi/fNi0GTbY948XJtXg==", - "dev": true, - "engines": { - "node": "^14 || ^16 || >=18.0" - }, - "peerDependencies": { - "postcss": "^8.4.31" - } - }, - "node_modules/postcss-normalize-display-values": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/postcss-normalize-display-values/-/postcss-normalize-display-values-6.0.1.tgz", - "integrity": "sha512-mc3vxp2bEuCb4LgCcmG1y6lKJu1Co8T+rKHrcbShJwUmKJiEl761qb/QQCfFwlrvSeET3jksolCR/RZuMURudw==", - "dev": true, - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^14 || ^16 || >=18.0" - }, - "peerDependencies": { - "postcss": "^8.4.31" - } - }, - "node_modules/postcss-normalize-positions": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/postcss-normalize-positions/-/postcss-normalize-positions-6.0.1.tgz", - "integrity": "sha512-HRsq8u/0unKNvm0cvwxcOUEcakFXqZ41fv3FOdPn916XFUrympjr+03oaLkuZENz3HE9RrQE9yU0Xv43ThWjQg==", - "dev": true, - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^14 || ^16 || >=18.0" - }, - "peerDependencies": { - "postcss": "^8.4.31" - } - }, - "node_modules/postcss-normalize-repeat-style": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-6.0.1.tgz", - "integrity": "sha512-Gbb2nmCy6tTiA7Sh2MBs3fj9W8swonk6lw+dFFeQT68B0Pzwp1kvisJQkdV6rbbMSd9brMlS8I8ts52tAGWmGQ==", - "dev": true, - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^14 || ^16 || >=18.0" - }, - "peerDependencies": { - "postcss": "^8.4.31" - } - }, - "node_modules/postcss-normalize-string": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/postcss-normalize-string/-/postcss-normalize-string-6.0.1.tgz", - "integrity": "sha512-5Fhx/+xzALJD9EI26Aq23hXwmv97Zfy2VFrt5PLT8lAhnBIZvmaT5pQk+NuJ/GWj/QWaKSKbnoKDGLbV6qnhXg==", - "dev": true, - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^14 || ^16 || >=18.0" - }, - "peerDependencies": { - "postcss": "^8.4.31" - } - }, - "node_modules/postcss-normalize-timing-functions": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-6.0.1.tgz", - "integrity": "sha512-4zcczzHqmCU7L5dqTB9rzeqPWRMc0K2HoR+Bfl+FSMbqGBUcP5LRfgcH4BdRtLuzVQK1/FHdFoGT3F7rkEnY+g==", - "dev": true, - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^14 || ^16 || >=18.0" - }, - "peerDependencies": { - "postcss": "^8.4.31" - } - }, - "node_modules/postcss-normalize-unicode": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/postcss-normalize-unicode/-/postcss-normalize-unicode-6.0.2.tgz", - "integrity": "sha512-Ff2VdAYCTGyMUwpevTZPZ4w0+mPjbZzLLyoLh/RMpqUqeQKZ+xMm31hkxBavDcGKcxm6ACzGk0nBfZ8LZkStKA==", - "dev": true, - "dependencies": { - "browserslist": "^4.22.2", - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^14 || ^16 || >=18.0" - }, - "peerDependencies": { - "postcss": "^8.4.31" - } - }, - "node_modules/postcss-normalize-url": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-6.0.1.tgz", - "integrity": "sha512-jEXL15tXSvbjm0yzUV7FBiEXwhIa9H88JOXDGQzmcWoB4mSjZIsmtto066s2iW9FYuIrIF4k04HA2BKAOpbsaQ==", - "dev": true, - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^14 || ^16 || >=18.0" - }, - "peerDependencies": { - "postcss": "^8.4.31" - } - }, - "node_modules/postcss-normalize-whitespace": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/postcss-normalize-whitespace/-/postcss-normalize-whitespace-6.0.1.tgz", - "integrity": "sha512-76i3NpWf6bB8UHlVuLRxG4zW2YykF9CTEcq/9LGAiz2qBuX5cBStadkk0jSkg9a9TCIXbMQz7yzrygKoCW9JuA==", - "dev": true, - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^14 || ^16 || >=18.0" - }, - "peerDependencies": { - "postcss": "^8.4.31" - } - }, - "node_modules/postcss-ordered-values": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-6.0.1.tgz", - "integrity": "sha512-XXbb1O/MW9HdEhnBxitZpPFbIvDgbo9NK4c/5bOfiKpnIGZDoL2xd7/e6jW5DYLsWxBbs+1nZEnVgnjnlFViaA==", - "dev": true, - "dependencies": { - "cssnano-utils": "^4.0.1", - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^14 || ^16 || >=18.0" - }, - "peerDependencies": { - "postcss": "^8.4.31" - } - }, - "node_modules/postcss-purgecss": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/postcss-purgecss/-/postcss-purgecss-5.0.0.tgz", - "integrity": "sha512-qmvyvcy9ph0Fgsjq4z8ilm3+/B/EG52XKgITe5J7Txhk7EpfRo2hDl6dXDOlp8uEUO8TLnGkxfLPnEejT+/nAQ==", - "deprecated": "use @fullhuman/postcss-purgecss instead", - "dev": true, - "dependencies": { - "purgecss": "^5.0.0" - }, - "peerDependencies": { - "postcss": "^8.0.0" - } - }, - "node_modules/postcss-reduce-initial": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-6.0.2.tgz", - "integrity": "sha512-YGKalhNlCLcjcLvjU5nF8FyeCTkCO5UtvJEt0hrPZVCTtRLSOH4z00T1UntQPj4dUmIYZgMj8qK77JbSX95hSw==", - "dev": true, - "dependencies": { - "browserslist": "^4.22.2", - "caniuse-api": "^3.0.0" - }, - "engines": { - "node": "^14 || ^16 || >=18.0" - }, - "peerDependencies": { - "postcss": "^8.4.31" - } - }, - "node_modules/postcss-reduce-transforms": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-6.0.1.tgz", - "integrity": "sha512-fUbV81OkUe75JM+VYO1gr/IoA2b/dRiH6HvMwhrIBSUrxq3jNZQZitSnugcTLDi1KkQh1eR/zi+iyxviUNBkcQ==", - "dev": true, - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^14 || ^16 || >=18.0" - }, - "peerDependencies": { - "postcss": "^8.4.31" - } - }, - "node_modules/postcss-reporter": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/postcss-reporter/-/postcss-reporter-7.0.5.tgz", - "integrity": "sha512-glWg7VZBilooZGOFPhN9msJ3FQs19Hie7l5a/eE6WglzYqVeH3ong3ShFcp9kDWJT1g2Y/wd59cocf9XxBtkWA==", - "dev": true, - "dependencies": { - "picocolors": "^1.0.0", - "thenby": "^1.3.4" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - "peerDependencies": { - "postcss": "^8.1.0" - } - }, "node_modules/postcss-selector-parser": { "version": "6.0.15", "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.15.tgz", "integrity": "sha512-rEYkQOMUCEMhsKbK66tbEU9QVIxbhN18YiniAwA7XQYTVBqrBy+P2p5JcdqsHgKM2zWylp8d7J6eszocfds5Sw==", - "dev": true, "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" @@ -1867,81 +872,15 @@ "node": ">=4" } }, - "node_modules/postcss-svgo": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-6.0.2.tgz", - "integrity": "sha512-IH5R9SjkTkh0kfFOQDImyy1+mTCb+E830+9SV1O+AaDcoHTvfsvt6WwJeo7KwcHbFnevZVCsXhDmjFiGVuwqFQ==", - "dev": true, - "dependencies": { - "postcss-value-parser": "^4.2.0", - "svgo": "^3.2.0" - }, - "engines": { - "node": "^14 || ^16 || >= 18" - }, - "peerDependencies": { - "postcss": "^8.4.31" - } - }, - "node_modules/postcss-unique-selectors": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-6.0.2.tgz", - "integrity": "sha512-8IZGQ94nechdG7Y9Sh9FlIY2b4uS8/k8kdKRX040XHsS3B6d1HrJAkXrBSsSu4SuARruSsUjW3nlSw8BHkaAYQ==", - "dev": true, - "dependencies": { - "postcss-selector-parser": "^6.0.15" - }, - "engines": { - "node": "^14 || ^16 || >=18.0" - }, - "peerDependencies": { - "postcss": "^8.4.31" - } - }, "node_modules/postcss-value-parser": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true - }, - "node_modules/pretty-hrtime": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", - "integrity": "sha512-66hKPCr+72mlfiSjlEB1+45IjXSqvVAIy6mocupoww4tBFE9R9IhwwUGoI4G++Tc9Aq+2rxOt0RFU6gPcrte0A==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/purgecss": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/purgecss/-/purgecss-5.0.0.tgz", - "integrity": "sha512-RAnuxrGuVyLLTr8uMbKaxDRGWMgK5CCYDfRyUNNcaz5P3kGgD2b7ymQGYEyo2ST7Tl/ScwFgf5l3slKMxHSbrw==", - "dev": true, - "dependencies": { - "commander": "^9.0.0", - "glob": "^8.0.3", - "postcss": "^8.4.4", - "postcss-selector-parser": "^6.0.7" - }, - "bin": { - "purgecss": "bin/purgecss.js" - } - }, - "node_modules/purgecss/node_modules/commander": { - "version": "9.5.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz", - "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==", - "dev": true, - "engines": { - "node": "^12.20.0 || >=14" - } + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true, "funding": [ { "type": "github", @@ -1960,8 +899,7 @@ "node_modules/read-cache": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", - "integrity": "sha1-5mTvMRYRZsl1HNvo28+GtftY93Q=", - "dev": true, + "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", "dependencies": { "pify": "^2.3.0" } @@ -1970,7 +908,6 @@ "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, "dependencies": { "picomatch": "^2.2.1" }, @@ -1978,22 +915,12 @@ "node": ">=8.10.0" } }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/resolve": { - "version": "1.22.2", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.2.tgz", - "integrity": "sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==", - "dev": true, + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", "dependencies": { - "is-core-module": "^2.11.0", + "is-core-module": "^2.13.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, @@ -2008,7 +935,6 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true, "engines": { "iojs": ">=1.0.0", "node": ">=0.10.0" @@ -2018,7 +944,6 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, "funding": [ { "type": "github", @@ -2037,32 +962,65 @@ "queue-microtask": "^1.2.2" } }, - "node_modules/slash": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz", - "integrity": "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==", - "dev": true, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dependencies": { + "shebang-regex": "^3.0.0" + }, "engines": { - "node": ">=14.16" + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "engines": { + "node": ">=8" + } + }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "engines": { + "node": ">=14" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/isaacs" } }, "node_modules/source-map-js": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", - "dev": true, "engines": { "node": ">=0.10.0" } }, "node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -2072,11 +1030,23 @@ "node": ">=8" } }, - "node_modules/strip-ansi": { + "node_modules/string-width-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "node_modules/string-width-cjs/node_modules/strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, "dependencies": { "ansi-regex": "^5.0.1" }, @@ -2084,31 +1054,48 @@ "node": ">=8" } }, - "node_modules/stylehacks": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-6.0.2.tgz", - "integrity": "sha512-00zvJGnCu64EpMjX8b5iCZ3us2Ptyw8+toEkb92VdmkEaRaSGBNKAoK6aWZckhXxmQP8zWiTaFaiMGIU8Ve8sg==", - "dev": true, + "node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "dependencies": { - "browserslist": "^4.22.2", - "postcss-selector-parser": "^6.0.15" + "ansi-regex": "^6.0.1" }, "engines": { - "node": "^14 || ^16 || >=18.0" + "node": ">=12" }, - "peerDependencies": { - "postcss": "^8.4.31" + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" } }, "node_modules/sucrase": { - "version": "3.32.0", - "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.32.0.tgz", - "integrity": "sha512-ydQOU34rpSyj2TGyz4D2p8rbktIOZ8QY9s+DGLvFU1i5pWJE8vkpruCjGCMHsdXwnD7JDcS+noSwM/a7zyNFDQ==", - "dev": true, + "version": "3.35.0", + "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz", + "integrity": "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==", "dependencies": { "@jridgewell/gen-mapping": "^0.3.2", "commander": "^4.0.0", - "glob": "7.1.6", + "glob": "^10.3.10", "lines-and-columns": "^1.1.6", "mz": "^2.7.0", "pirates": "^4.0.1", @@ -2119,65 +1106,13 @@ "sucrase-node": "bin/sucrase-node" }, "engines": { - "node": ">=8" - } - }, - "node_modules/sucrase/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/sucrase/node_modules/commander": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", - "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", - "dev": true, - "engines": { - "node": ">= 6" - } - }, - "node_modules/sucrase/node_modules/glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/sucrase/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" + "node": ">=16 || 14 >=14.17" } }, "node_modules/supports-preserve-symlinks-flag": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true, "engines": { "node": ">= 0.4" }, @@ -2185,36 +1120,11 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/svgo": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/svgo/-/svgo-3.2.0.tgz", - "integrity": "sha512-4PP6CMW/V7l/GmKRKzsLR8xxjdHTV4IMvhTnpuHwwBazSIlw5W/5SmPjN8Dwyt7lKbSJrRDgp4t9ph0HgChFBQ==", - "dev": true, - "dependencies": { - "@trysound/sax": "0.2.0", - "commander": "^7.2.0", - "css-select": "^5.1.0", - "css-tree": "^2.3.1", - "css-what": "^6.1.0", - "csso": "^5.0.5", - "picocolors": "^1.0.0" - }, - "bin": { - "svgo": "bin/svgo" - }, - "engines": { - "node": ">=14.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/svgo" - } - }, "node_modules/tailwindcss": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.1.tgz", - "integrity": "sha512-qAYmXRfk3ENzuPBakNK0SRrUDipP8NQnEY6772uDhflcQz5EhRdD7JNZxyrFHVQNCwULPBn6FNPp9brpO7ctcA==", - "dev": true, + "version": "3.4.7", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.7.tgz", + "integrity": "sha512-rxWZbe87YJb4OcSopb7up2Ba4U82BoiSGUdoDr3Ydrg9ckxFS/YWsvhN323GMcddgU65QRy7JndC7ahhInhvlQ==", + "license": "MIT", "dependencies": { "@alloc/quick-lru": "^5.2.0", "arg": "^5.0.2", @@ -2224,7 +1134,7 @@ "fast-glob": "^3.3.0", "glob-parent": "^6.0.2", "is-glob": "^4.0.3", - "jiti": "^1.19.1", + "jiti": "^1.21.0", "lilconfig": "^2.1.0", "micromatch": "^4.0.5", "normalize-path": "^3.0.0", @@ -2247,46 +1157,10 @@ "node": ">=14.0.0" } }, - "node_modules/tailwindcss/node_modules/glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.3" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/tailwindcss/node_modules/postcss-import": { - "version": "15.1.0", - "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz", - "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==", - "dev": true, - "dependencies": { - "postcss-value-parser": "^4.0.0", - "read-cache": "^1.0.0", - "resolve": "^1.1.7" - }, - "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "postcss": "^8.0.0" - } - }, - "node_modules/thenby": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/thenby/-/thenby-1.3.4.tgz", - "integrity": "sha512-89Gi5raiWA3QZ4b2ePcEwswC3me9JIg+ToSgtE0JWeCynLnLxNr/f9G+xfo9K+Oj4AFdom8YNJjibIARTJmapQ==", - "dev": true - }, "node_modules/thenify": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", - "dev": true, "dependencies": { "any-promise": "^1.0.0" } @@ -2295,7 +1169,6 @@ "version": "1.6.0", "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", - "dev": true, "dependencies": { "thenify": ">= 3.1.0 < 4" }, @@ -2307,7 +1180,6 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, "dependencies": { "is-number": "^7.0.0" }, @@ -2318,71 +1190,48 @@ "node_modules/ts-interface-checker": { "version": "0.1.13", "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", - "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", - "dev": true - }, - "node_modules/unicorn-magic": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.1.0.tgz", - "integrity": "sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==", - "dev": true, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", - "dev": true, - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/update-browserslist-db": { - "version": "1.0.13", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", - "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "dependencies": { - "escalade": "^3.1.1", - "picocolors": "^1.0.0" - }, - "bin": { - "update-browserslist-db": "cli.js" - }, - "peerDependencies": { - "browserslist": ">= 4.21.0" - } + "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==" }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", - "dev": true + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } }, "node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -2395,1687 +1244,67 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true - }, - "node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/yaml": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.4.tgz", - "integrity": "sha512-8aAvwVUSHpfEqTQ4w/KMlf3HcRdt50E5ODIQJBw1fQ5RL34xabzxtUlzTXVqc4rkZsPbvrXKWnABCD7kWSmocA==", - "dev": true, - "engines": { - "node": ">= 14" - } - }, - "node_modules/yargs": { - "version": "17.5.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.5.1.tgz", - "integrity": "sha512-t6YAJcxDkNX7NFYiVtKvWUz8l+PaKTLiL63mJYWR2GnHq2gjEWISzsLp9wg3aY36dY1j+gfIEL3pIF+XlJJfbA==", - "dev": true, - "dependencies": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/yargs-parser": { - "version": "21.0.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.0.1.tgz", - "integrity": "sha512-9BK1jFpLzJROCI5TzwZL/TU4gqjK5xiHV/RfWLOahrjAko/e4DJkRDZQXfvqAsiZzzYhgAzbgz6lg48jcm4GLg==", - "dev": true, - "engines": { - "node": ">=12" - } - } - }, - "dependencies": { - "@alloc/quick-lru": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", - "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", - "dev": true - }, - "@fortawesome/fontawesome-free": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-free/-/fontawesome-free-6.5.1.tgz", - "integrity": "sha512-CNy5vSwN3fsUStPRLX7fUYojyuzoEMSXPl7zSLJ8TgtRfjv24LOnOWKT2zYwaHZCJGkdyRnTmstR0P+Ah503Gw==", - "dev": true - }, - "@jridgewell/gen-mapping": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", - "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", - "dev": true, - "requires": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" - } - }, - "@jridgewell/resolve-uri": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", - "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", - "dev": true - }, - "@jridgewell/set-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", - "dev": true - }, - "@jridgewell/sourcemap-codec": { - "version": "1.4.15", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", - "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", - "dev": true - }, - "@jridgewell/trace-mapping": { - "version": "0.3.18", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.18.tgz", - "integrity": "sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA==", - "dev": true, - "requires": { - "@jridgewell/resolve-uri": "3.1.0", - "@jridgewell/sourcemap-codec": "1.4.14" - }, - "dependencies": { - "@jridgewell/sourcemap-codec": { - "version": "1.4.14", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", - "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", - "dev": true - } - } - }, - "@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, - "requires": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - } - }, - "@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true - }, - "@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, - "requires": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - } - }, - "@sindresorhus/merge-streams": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-1.0.0.tgz", - "integrity": "sha512-rUV5WyJrJLoloD4NDN1V1+LDMDWOa4OTsT4yYJwQNpTU6FWxkxHpL7eu4w+DmiH8x/EAM1otkPE1+LaspIbplw==", - "dev": true - }, - "@tailwindcss/forms": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/@tailwindcss/forms/-/forms-0.5.7.tgz", - "integrity": "sha512-QE7X69iQI+ZXwldE+rzasvbJiyV/ju1FGHH0Qn2W3FKbuYtqp8LKcy6iSw79fVUT5/Vvf+0XgLCeYVG+UV6hOw==", - "dev": true, - "requires": { - "mini-svg-data-uri": "^1.2.3" - } - }, - "@trysound/sax": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", - "integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==", - "dev": true - }, - "ansi-regex": { + "node_modules/wrap-ansi-cjs/node_modules/ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true + "engines": { + "node": ">=8" + } }, - "ansi-styles": { + "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { + "dependencies": { "color-convert": "^2.0.1" - } - }, - "any-promise": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", - "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", - "dev": true - }, - "anymatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", - "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", - "dev": true, - "requires": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - } - }, - "arg": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", - "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", - "dev": true - }, - "autoprefixer": { - "version": "10.4.17", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.17.tgz", - "integrity": "sha512-/cpVNRLSfhOtcGflT13P2794gVSgmPgTR+erw5ifnMLZb0UnSlkK4tquLmkd3BhA+nLo5tX8Cu0upUsGKvKbmg==", - "dev": true, - "requires": { - "browserslist": "^4.22.2", - "caniuse-lite": "^1.0.30001578", - "fraction.js": "^4.3.7", - "normalize-range": "^0.1.2", - "picocolors": "^1.0.0", - "postcss-value-parser": "^4.2.0" - } - }, - "balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true - }, - "binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", - "dev": true - }, - "boolbase": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", - "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", - "dev": true - }, - "brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0" - } - }, - "braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "requires": { - "fill-range": "^7.0.1" - } - }, - "browserslist": { - "version": "4.22.2", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.2.tgz", - "integrity": "sha512-0UgcrvQmBDvZHFGdYUehrCNIazki7/lUP3kkoi/r3YB2amZbFM9J43ZRkJTXBUZK4gmx56+Sqk9+Vs9mwZx9+A==", - "dev": true, - "requires": { - "caniuse-lite": "^1.0.30001565", - "electron-to-chromium": "^1.4.601", - "node-releases": "^2.0.14", - "update-browserslist-db": "^1.0.13" - } - }, - "camelcase-css": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", - "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", - "dev": true - }, - "caniuse-api": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz", - "integrity": "sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==", - "dev": true, - "requires": { - "browserslist": "^4.0.0", - "caniuse-lite": "^1.0.0", - "lodash.memoize": "^4.1.2", - "lodash.uniq": "^4.5.0" - } - }, - "caniuse-lite": { - "version": "1.0.30001578", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001578.tgz", - "integrity": "sha512-J/jkFgsQ3NEl4w2lCoM9ZPxrD+FoBNJ7uJUpGVjIg/j0OwJosWM36EPDv+Yyi0V4twBk9pPmlFS+PLykgEvUmg==", - "dev": true - }, - "chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", - "dev": true, - "requires": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "fsevents": "~2.3.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - } - }, - "cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "dev": true, - "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "colord": { - "version": "2.9.3", - "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz", - "integrity": "sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==", - "dev": true - }, - "commander": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", - "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", - "dev": true - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true - }, - "css-declaration-sorter": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-7.1.1.tgz", - "integrity": "sha512-dZ3bVTEEc1vxr3Bek9vGwfB5Z6ESPULhcRvO472mfjVnj8jRcTnKO8/JTczlvxM10Myb+wBM++1MtdO76eWcaQ==", - "dev": true, - "requires": {} - }, - "css-select": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz", - "integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==", - "dev": true, - "requires": { - "boolbase": "^1.0.0", - "css-what": "^6.1.0", - "domhandler": "^5.0.2", - "domutils": "^3.0.1", - "nth-check": "^2.0.1" - } - }, - "css-tree": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.3.1.tgz", - "integrity": "sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==", - "dev": true, - "requires": { - "mdn-data": "2.0.30", - "source-map-js": "^1.0.1" - } - }, - "css-what": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", - "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", - "dev": true - }, - "cssesc": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", - "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", - "dev": true - }, - "cssnano": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-6.0.3.tgz", - "integrity": "sha512-MRq4CIj8pnyZpcI2qs6wswoYoDD1t0aL28n+41c1Ukcpm56m1h6mCexIHBGjfZfnTqtGSSCP4/fB1ovxgjBOiw==", - "dev": true, - "requires": { - "cssnano-preset-default": "^6.0.3", - "lilconfig": "^3.0.0" }, - "dependencies": { - "lilconfig": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.0.0.tgz", - "integrity": "sha512-K2U4W2Ff5ibV7j7ydLr+zLAkIg5JJ4lPn1Ltsdt+Tz/IjQ8buJ55pZAxoP34lqIiwtF9iAvtLv3JGv7CAyAg+g==", - "dev": true - } - } - }, - "cssnano-preset-default": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-6.0.3.tgz", - "integrity": "sha512-4y3H370aZCkT9Ev8P4SO4bZbt+AExeKhh8wTbms/X7OLDo5E7AYUUy6YPxa/uF5Grf+AJwNcCnxKhZynJ6luBA==", - "dev": true, - "requires": { - "css-declaration-sorter": "^7.1.1", - "cssnano-utils": "^4.0.1", - "postcss-calc": "^9.0.1", - "postcss-colormin": "^6.0.2", - "postcss-convert-values": "^6.0.2", - "postcss-discard-comments": "^6.0.1", - "postcss-discard-duplicates": "^6.0.1", - "postcss-discard-empty": "^6.0.1", - "postcss-discard-overridden": "^6.0.1", - "postcss-merge-longhand": "^6.0.2", - "postcss-merge-rules": "^6.0.3", - "postcss-minify-font-values": "^6.0.1", - "postcss-minify-gradients": "^6.0.1", - "postcss-minify-params": "^6.0.2", - "postcss-minify-selectors": "^6.0.2", - "postcss-normalize-charset": "^6.0.1", - "postcss-normalize-display-values": "^6.0.1", - "postcss-normalize-positions": "^6.0.1", - "postcss-normalize-repeat-style": "^6.0.1", - "postcss-normalize-string": "^6.0.1", - "postcss-normalize-timing-functions": "^6.0.1", - "postcss-normalize-unicode": "^6.0.2", - "postcss-normalize-url": "^6.0.1", - "postcss-normalize-whitespace": "^6.0.1", - "postcss-ordered-values": "^6.0.1", - "postcss-reduce-initial": "^6.0.2", - "postcss-reduce-transforms": "^6.0.1", - "postcss-svgo": "^6.0.2", - "postcss-unique-selectors": "^6.0.2" - } - }, - "cssnano-utils": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/cssnano-utils/-/cssnano-utils-4.0.1.tgz", - "integrity": "sha512-6qQuYDqsGoiXssZ3zct6dcMxiqfT6epy7x4R0TQJadd4LWO3sPR6JH6ZByOvVLoZ6EdwPGgd7+DR1EmX3tiXQQ==", - "dev": true, - "requires": {} - }, - "csso": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/csso/-/csso-5.0.5.tgz", - "integrity": "sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==", - "dev": true, - "requires": { - "css-tree": "~2.2.0" + "engines": { + "node": ">=8" }, - "dependencies": { - "css-tree": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.2.1.tgz", - "integrity": "sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA==", - "dev": true, - "requires": { - "mdn-data": "2.0.28", - "source-map-js": "^1.0.1" - } - }, - "mdn-data": { - "version": "2.0.28", - "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.28.tgz", - "integrity": "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==", - "dev": true - } + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "dependency-graph": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/dependency-graph/-/dependency-graph-0.11.0.tgz", - "integrity": "sha512-JeMq7fEshyepOWDfcfHK06N3MhyPhz++vtqWhMT5O9A3K42rdsEDpfdVqjaqaAhsw6a+ZqeDvQVtD0hFHQWrzg==", - "dev": true - }, - "didyoumean": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", - "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==", - "dev": true - }, - "dlv": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", - "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", - "dev": true - }, - "dom-serializer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", - "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", - "dev": true, - "requires": { - "domelementtype": "^2.3.0", - "domhandler": "^5.0.2", - "entities": "^4.2.0" - } - }, - "domelementtype": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", - "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", - "dev": true - }, - "domhandler": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", - "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", - "dev": true, - "requires": { - "domelementtype": "^2.3.0" - } - }, - "domutils": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz", - "integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==", - "dev": true, - "requires": { - "dom-serializer": "^2.0.0", - "domelementtype": "^2.3.0", - "domhandler": "^5.0.3" - } - }, - "electron-to-chromium": { - "version": "1.4.618", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.618.tgz", - "integrity": "sha512-mTM2HieHLxs1RbD/R/ZoQLMsGI8lWIkP17G7cx32mJRBJt9wlNPkXwE3sYg/OnNb5GBkus98lXatSthoL8Y5Ag==", - "dev": true - }, - "emoji-regex": { + "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, - "entities": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", - "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", - "dev": true - }, - "escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "dev": true - }, - "fast-glob": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", - "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", - "dev": true, - "requires": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" - } - }, - "fastq": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", - "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", - "dev": true, - "requires": { - "reusify": "^1.0.4" - } - }, - "fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, - "requires": { - "to-regex-range": "^5.0.1" - } - }, - "flag-icon-css": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/flag-icon-css/-/flag-icon-css-3.5.0.tgz", - "integrity": "sha512-pgJnJLrtb0tcDgU1fzGaQXmR8h++nXvILJ+r5SmOXaaL/2pocunQo2a8TAXhjQnBpRLPtZ1KCz/TYpqeNuE2ew==", - "dev": true - }, - "fraction.js": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz", - "integrity": "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==", - "dev": true - }, - "fs-extra": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.1.0.tgz", - "integrity": "sha512-0rcTq621PD5jM/e0a3EJoGC/1TC5ZBCERW82LQuwfGnCa1V8w7dpYH1yNu+SLb6E5dkeCBzKEyLGlFrnr+dUyw==", - "dev": true, - "requires": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - } - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true - }, - "fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, - "optional": true - }, - "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true - }, - "get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true - }, - "get-stdin": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-9.0.0.tgz", - "integrity": "sha512-dVKBjfWisLAicarI2Sf+JuBE/DghV4UzNAVe9yhEJuzeREd3JhOTE9cUaJTeSa77fsbQUK3pcOpJfM59+VKZaA==", - "dev": true - }, - "glob": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", - "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^5.0.1", - "once": "^1.3.0" - } - }, - "glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "requires": { - "is-glob": "^4.0.1" - } - }, - "globby": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-14.0.0.tgz", - "integrity": "sha512-/1WM/LNHRAOH9lZta77uGbq0dAEQM+XjNesWwhlERDVenqothRbnzTrL3/LrIoEPPjeUHC3vrS6TwoyxeHs7MQ==", - "dev": true, - "requires": { - "@sindresorhus/merge-streams": "^1.0.0", - "fast-glob": "^3.3.2", - "ignore": "^5.2.4", - "path-type": "^5.0.0", - "slash": "^5.1.0", - "unicorn-magic": "^0.1.0" - } - }, - "graceful-fs": { - "version": "4.2.10", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", - "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", - "dev": true - }, - "has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, - "requires": { - "function-bind": "^1.1.1" - } - }, - "ignore": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.0.tgz", - "integrity": "sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg==", - "dev": true - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "requires": { - "binary-extensions": "^2.0.0" - } - }, - "is-core-module": { - "version": "2.12.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.12.0.tgz", - "integrity": "sha512-RECHCBCd/viahWmwj6enj19sKbHfJrddi/6cBDsNTKbNq0f7VeaUkBo60BqzvPqo/W54ChS62Z5qyun7cfOMqQ==", - "dev": true, - "requires": { - "has": "^1.0.3" - } - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true - }, - "is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "requires": { - "is-extglob": "^2.1.1" - } - }, - "is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true - }, - "jiti": { - "version": "1.21.0", - "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.0.tgz", - "integrity": "sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q==", - "dev": true - }, - "jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.6", - "universalify": "^2.0.0" - } - }, - "lilconfig": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", - "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==", - "dev": true - }, - "lines-and-columns": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", - "dev": true - }, - "lodash.memoize": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", - "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", - "dev": true - }, - "lodash.uniq": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", - "integrity": "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==", - "dev": true - }, - "mdn-data": { - "version": "2.0.30", - "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz", - "integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==", - "dev": true - }, - "merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true - }, - "micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", - "dev": true, - "requires": { - "braces": "^3.0.2", - "picomatch": "^2.3.1" - } - }, - "mini-svg-data-uri": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/mini-svg-data-uri/-/mini-svg-data-uri-1.4.3.tgz", - "integrity": "sha512-gSfqpMRC8IxghvMcxzzmMnWpXAChSA+vy4cia33RgerMS8Fex95akUyQZPbxJJmeBGiGmK7n/1OpUX8ksRjIdA==", - "dev": true - }, - "minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", - "dev": true, - "requires": { - "brace-expansion": "^2.0.1" - } - }, - "mz": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", - "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", - "dev": true, - "requires": { - "any-promise": "^1.0.0", - "object-assign": "^4.0.1", - "thenify-all": "^1.0.0" - } - }, - "nanoid": { - "version": "3.3.7", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", - "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", - "dev": true - }, - "node-releases": { - "version": "2.0.14", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", - "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", - "dev": true - }, - "normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true - }, - "normalize-range": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", - "integrity": "sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=", - "dev": true - }, - "nth-check": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", - "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", - "dev": true, - "requires": { - "boolbase": "^1.0.0" - } - }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "dev": true - }, - "object-hash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", - "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", - "dev": true - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, - "requires": { - "wrappy": "1" - } - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true - }, - "path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true - }, - "path-type": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-5.0.0.tgz", - "integrity": "sha512-5HviZNaZcfqP95rwpv+1HDgUamezbqdSYTyzjTvwtJSnIH+3vnbmWsItli8OFEndS984VT55M3jduxZbX351gg==", - "dev": true - }, - "picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", - "dev": true - }, - "picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true - }, - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true - }, - "pirates": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.5.tgz", - "integrity": "sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ==", - "dev": true - }, - "postcss": { - "version": "8.4.35", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.35.tgz", - "integrity": "sha512-u5U8qYpBCpN13BsiEB0CbR1Hhh4Gc0zLFuedrHJKMctHCHAGrMdG0PRM/KErzAL3CU6/eckEtmHNB3x6e3c0vA==", - "dev": true, - "requires": { - "nanoid": "^3.3.7", - "picocolors": "^1.0.0", - "source-map-js": "^1.0.2" - } - }, - "postcss-calc": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-9.0.1.tgz", - "integrity": "sha512-TipgjGyzP5QzEhsOZUaIkeO5mKeMFpebWzRogWG/ysonUlnHcq5aJe0jOjpfzUU8PeSaBQnrE8ehR0QA5vs8PQ==", - "dev": true, - "requires": { - "postcss-selector-parser": "^6.0.11", - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-cli": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/postcss-cli/-/postcss-cli-11.0.0.tgz", - "integrity": "sha512-xMITAI7M0u1yolVcXJ9XTZiO9aO49mcoKQy6pCDFdMh9kGqhzLVpWxeD/32M/QBmkhcGypZFFOLNLmIW4Pg4RA==", - "dev": true, - "requires": { - "chokidar": "^3.3.0", - "dependency-graph": "^0.11.0", - "fs-extra": "^11.0.0", - "get-stdin": "^9.0.0", - "globby": "^14.0.0", - "picocolors": "^1.0.0", - "postcss-load-config": "^5.0.0", - "postcss-reporter": "^7.0.0", - "pretty-hrtime": "^1.0.3", - "read-cache": "^1.0.0", - "slash": "^5.0.0", - "yargs": "^17.0.0" - }, - "dependencies": { - "lilconfig": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.0.0.tgz", - "integrity": "sha512-K2U4W2Ff5ibV7j7ydLr+zLAkIg5JJ4lPn1Ltsdt+Tz/IjQ8buJ55pZAxoP34lqIiwtF9iAvtLv3JGv7CAyAg+g==", - "dev": true - }, - "postcss-load-config": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-5.0.2.tgz", - "integrity": "sha512-Q8QR3FYbqOKa0bnC1UQ2bFq9/ulHX5Bi34muzitMr8aDtUelO5xKeJEYC/5smE0jNE9zdB/NBnOwXKexELbRlw==", - "dev": true, - "requires": { - "lilconfig": "^3.0.0", - "yaml": "^2.3.4" - } - } - } - }, - "postcss-colormin": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-6.0.2.tgz", - "integrity": "sha512-TXKOxs9LWcdYo5cgmcSHPkyrLAh86hX1ijmyy6J8SbOhyv6ua053M3ZAM/0j44UsnQNIWdl8gb5L7xX2htKeLw==", - "dev": true, - "requires": { - "browserslist": "^4.22.2", - "caniuse-api": "^3.0.0", - "colord": "^2.9.1", - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-convert-values": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-6.0.2.tgz", - "integrity": "sha512-aeBmaTnGQ+NUSVQT8aY0sKyAD/BaLJenEKZ03YK0JnDE1w1Rr8XShoxdal2V2H26xTJKr3v5haByOhJuyT4UYw==", - "dev": true, - "requires": { - "browserslist": "^4.22.2", - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-discard-comments": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-6.0.1.tgz", - "integrity": "sha512-f1KYNPtqYLUeZGCHQPKzzFtsHaRuECe6jLakf/RjSRqvF5XHLZnM2+fXLhb8Qh/HBFHs3M4cSLb1k3B899RYIg==", - "dev": true, - "requires": {} - }, - "postcss-discard-duplicates": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-6.0.1.tgz", - "integrity": "sha512-1hvUs76HLYR8zkScbwyJ8oJEugfPV+WchpnA+26fpJ7Smzs51CzGBHC32RS03psuX/2l0l0UKh2StzNxOrKCYg==", - "dev": true, - "requires": {} - }, - "postcss-discard-empty": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-6.0.1.tgz", - "integrity": "sha512-yitcmKwmVWtNsrrRqGJ7/C0YRy53i0mjexBDQ9zYxDwTWVBgbU4+C9jIZLmQlTDT9zhml+u0OMFJh8+31krmOg==", - "dev": true, - "requires": {} - }, - "postcss-discard-overridden": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-6.0.1.tgz", - "integrity": "sha512-qs0ehZMMZpSESbRkw1+inkf51kak6OOzNRaoLd/U7Fatp0aN2HQ1rxGOrJvYcRAN9VpX8kUF13R2ofn8OlvFVA==", - "dev": true, - "requires": {} - }, - "postcss-import": { - "version": "16.0.0", - "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-16.0.0.tgz", - "integrity": "sha512-e77lhVvrD1I2y7dYmBv0k9ULTdArgEYZt97T4w6sFIU5uxIHvDFQlKgUUyY7v7Barj0Yf/zm5A4OquZN7jKm5Q==", - "dev": true, - "requires": { - "postcss-value-parser": "^4.0.0", - "read-cache": "^1.0.0", - "resolve": "^1.1.7" - } - }, - "postcss-js": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz", - "integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==", - "dev": true, - "requires": { - "camelcase-css": "^2.0.1" - } - }, - "postcss-load-config": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.1.tgz", - "integrity": "sha512-vEJIc8RdiBRu3oRAI0ymerOn+7rPuMvRXslTvZUKZonDHFIczxztIyJ1urxM1x9JXEikvpWWTUUqal5j/8QgvA==", - "dev": true, - "requires": { - "lilconfig": "^2.0.5", - "yaml": "^2.1.1" - } - }, - "postcss-merge-longhand": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-6.0.2.tgz", - "integrity": "sha512-+yfVB7gEM8SrCo9w2lCApKIEzrTKl5yS1F4yGhV3kSim6JzbfLGJyhR1B6X+6vOT0U33Mgx7iv4X9MVWuaSAfw==", - "dev": true, - "requires": { - "postcss-value-parser": "^4.2.0", - "stylehacks": "^6.0.2" - } - }, - "postcss-merge-rules": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-6.0.3.tgz", - "integrity": "sha512-yfkDqSHGohy8sGYIJwBmIGDv4K4/WrJPX355XrxQb/CSsT4Kc/RxDi6akqn5s9bap85AWgv21ArcUWwWdGNSHA==", - "dev": true, - "requires": { - "browserslist": "^4.22.2", - "caniuse-api": "^3.0.0", - "cssnano-utils": "^4.0.1", - "postcss-selector-parser": "^6.0.15" - } - }, - "postcss-minify-font-values": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-6.0.1.tgz", - "integrity": "sha512-tIwmF1zUPoN6xOtA/2FgVk1ZKrLcCvE0dpZLtzyyte0j9zUeB8RTbCqrHZGjJlxOvNWKMYtunLrrl7HPOiR46w==", - "dev": true, - "requires": { - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-minify-gradients": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-6.0.1.tgz", - "integrity": "sha512-M1RJWVjd6IOLPl1hYiOd5HQHgpp6cvJVLrieQYS9y07Yo8itAr6jaekzJphaJFR0tcg4kRewCk3kna9uHBxn/w==", - "dev": true, - "requires": { - "colord": "^2.9.1", - "cssnano-utils": "^4.0.1", - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-minify-params": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-6.0.2.tgz", - "integrity": "sha512-zwQtbrPEBDj+ApELZ6QylLf2/c5zmASoOuA4DzolyVGdV38iR2I5QRMsZcHkcdkZzxpN8RS4cN7LPskOkTwTZw==", - "dev": true, - "requires": { - "browserslist": "^4.22.2", - "cssnano-utils": "^4.0.1", - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-minify-selectors": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-6.0.2.tgz", - "integrity": "sha512-0b+m+w7OAvZejPQdN2GjsXLv5o0jqYHX3aoV0e7RBKPCsB7TYG5KKWBFhGnB/iP3213Ts8c5H4wLPLMm7z28Sg==", - "dev": true, - "requires": { - "postcss-selector-parser": "^6.0.15" - } - }, - "postcss-nested": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.0.1.tgz", - "integrity": "sha512-mEp4xPMi5bSWiMbsgoPfcP74lsWLHkQbZc3sY+jWYd65CUwXrUaTp0fmNpa01ZcETKlIgUdFN/MpS2xZtqL9dQ==", - "dev": true, - "requires": { - "postcss-selector-parser": "^6.0.11" - } - }, - "postcss-normalize-charset": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-6.0.1.tgz", - "integrity": "sha512-aW5LbMNRZ+oDV57PF9K+WI1Z8MPnF+A8qbajg/T8PP126YrGX1f9IQx21GI2OlGz7XFJi/fNi0GTbY948XJtXg==", - "dev": true, - "requires": {} - }, - "postcss-normalize-display-values": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/postcss-normalize-display-values/-/postcss-normalize-display-values-6.0.1.tgz", - "integrity": "sha512-mc3vxp2bEuCb4LgCcmG1y6lKJu1Co8T+rKHrcbShJwUmKJiEl761qb/QQCfFwlrvSeET3jksolCR/RZuMURudw==", - "dev": true, - "requires": { - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-normalize-positions": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/postcss-normalize-positions/-/postcss-normalize-positions-6.0.1.tgz", - "integrity": "sha512-HRsq8u/0unKNvm0cvwxcOUEcakFXqZ41fv3FOdPn916XFUrympjr+03oaLkuZENz3HE9RrQE9yU0Xv43ThWjQg==", - "dev": true, - "requires": { - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-normalize-repeat-style": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-6.0.1.tgz", - "integrity": "sha512-Gbb2nmCy6tTiA7Sh2MBs3fj9W8swonk6lw+dFFeQT68B0Pzwp1kvisJQkdV6rbbMSd9brMlS8I8ts52tAGWmGQ==", - "dev": true, - "requires": { - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-normalize-string": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/postcss-normalize-string/-/postcss-normalize-string-6.0.1.tgz", - "integrity": "sha512-5Fhx/+xzALJD9EI26Aq23hXwmv97Zfy2VFrt5PLT8lAhnBIZvmaT5pQk+NuJ/GWj/QWaKSKbnoKDGLbV6qnhXg==", - "dev": true, - "requires": { - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-normalize-timing-functions": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-6.0.1.tgz", - "integrity": "sha512-4zcczzHqmCU7L5dqTB9rzeqPWRMc0K2HoR+Bfl+FSMbqGBUcP5LRfgcH4BdRtLuzVQK1/FHdFoGT3F7rkEnY+g==", - "dev": true, - "requires": { - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-normalize-unicode": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/postcss-normalize-unicode/-/postcss-normalize-unicode-6.0.2.tgz", - "integrity": "sha512-Ff2VdAYCTGyMUwpevTZPZ4w0+mPjbZzLLyoLh/RMpqUqeQKZ+xMm31hkxBavDcGKcxm6ACzGk0nBfZ8LZkStKA==", - "dev": true, - "requires": { - "browserslist": "^4.22.2", - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-normalize-url": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-6.0.1.tgz", - "integrity": "sha512-jEXL15tXSvbjm0yzUV7FBiEXwhIa9H88JOXDGQzmcWoB4mSjZIsmtto066s2iW9FYuIrIF4k04HA2BKAOpbsaQ==", - "dev": true, - "requires": { - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-normalize-whitespace": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/postcss-normalize-whitespace/-/postcss-normalize-whitespace-6.0.1.tgz", - "integrity": "sha512-76i3NpWf6bB8UHlVuLRxG4zW2YykF9CTEcq/9LGAiz2qBuX5cBStadkk0jSkg9a9TCIXbMQz7yzrygKoCW9JuA==", - "dev": true, - "requires": { - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-ordered-values": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-6.0.1.tgz", - "integrity": "sha512-XXbb1O/MW9HdEhnBxitZpPFbIvDgbo9NK4c/5bOfiKpnIGZDoL2xd7/e6jW5DYLsWxBbs+1nZEnVgnjnlFViaA==", - "dev": true, - "requires": { - "cssnano-utils": "^4.0.1", - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-purgecss": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/postcss-purgecss/-/postcss-purgecss-5.0.0.tgz", - "integrity": "sha512-qmvyvcy9ph0Fgsjq4z8ilm3+/B/EG52XKgITe5J7Txhk7EpfRo2hDl6dXDOlp8uEUO8TLnGkxfLPnEejT+/nAQ==", - "dev": true, - "requires": { - "purgecss": "^5.0.0" - } - }, - "postcss-reduce-initial": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-6.0.2.tgz", - "integrity": "sha512-YGKalhNlCLcjcLvjU5nF8FyeCTkCO5UtvJEt0hrPZVCTtRLSOH4z00T1UntQPj4dUmIYZgMj8qK77JbSX95hSw==", - "dev": true, - "requires": { - "browserslist": "^4.22.2", - "caniuse-api": "^3.0.0" - } - }, - "postcss-reduce-transforms": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-6.0.1.tgz", - "integrity": "sha512-fUbV81OkUe75JM+VYO1gr/IoA2b/dRiH6HvMwhrIBSUrxq3jNZQZitSnugcTLDi1KkQh1eR/zi+iyxviUNBkcQ==", - "dev": true, - "requires": { - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-reporter": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/postcss-reporter/-/postcss-reporter-7.0.5.tgz", - "integrity": "sha512-glWg7VZBilooZGOFPhN9msJ3FQs19Hie7l5a/eE6WglzYqVeH3ong3ShFcp9kDWJT1g2Y/wd59cocf9XxBtkWA==", - "dev": true, - "requires": { - "picocolors": "^1.0.0", - "thenby": "^1.3.4" - } - }, - "postcss-selector-parser": { - "version": "6.0.15", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.15.tgz", - "integrity": "sha512-rEYkQOMUCEMhsKbK66tbEU9QVIxbhN18YiniAwA7XQYTVBqrBy+P2p5JcdqsHgKM2zWylp8d7J6eszocfds5Sw==", - "dev": true, - "requires": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" - } - }, - "postcss-svgo": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-6.0.2.tgz", - "integrity": "sha512-IH5R9SjkTkh0kfFOQDImyy1+mTCb+E830+9SV1O+AaDcoHTvfsvt6WwJeo7KwcHbFnevZVCsXhDmjFiGVuwqFQ==", - "dev": true, - "requires": { - "postcss-value-parser": "^4.2.0", - "svgo": "^3.2.0" - } - }, - "postcss-unique-selectors": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-6.0.2.tgz", - "integrity": "sha512-8IZGQ94nechdG7Y9Sh9FlIY2b4uS8/k8kdKRX040XHsS3B6d1HrJAkXrBSsSu4SuARruSsUjW3nlSw8BHkaAYQ==", - "dev": true, - "requires": { - "postcss-selector-parser": "^6.0.15" - } - }, - "postcss-value-parser": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true - }, - "pretty-hrtime": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", - "integrity": "sha512-66hKPCr+72mlfiSjlEB1+45IjXSqvVAIy6mocupoww4tBFE9R9IhwwUGoI4G++Tc9Aq+2rxOt0RFU6gPcrte0A==", - "dev": true - }, - "purgecss": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/purgecss/-/purgecss-5.0.0.tgz", - "integrity": "sha512-RAnuxrGuVyLLTr8uMbKaxDRGWMgK5CCYDfRyUNNcaz5P3kGgD2b7ymQGYEyo2ST7Tl/ScwFgf5l3slKMxHSbrw==", - "dev": true, - "requires": { - "commander": "^9.0.0", - "glob": "^8.0.3", - "postcss": "^8.4.4", - "postcss-selector-parser": "^6.0.7" - }, - "dependencies": { - "commander": { - "version": "9.5.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz", - "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==", - "dev": true - } - } - }, - "queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true - }, - "read-cache": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", - "integrity": "sha1-5mTvMRYRZsl1HNvo28+GtftY93Q=", - "dev": true, - "requires": { - "pify": "^2.3.0" - } - }, - "readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, - "requires": { - "picomatch": "^2.2.1" - } - }, - "require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", - "dev": true - }, - "resolve": { - "version": "1.22.2", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.2.tgz", - "integrity": "sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==", - "dev": true, - "requires": { - "is-core-module": "^2.11.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - } - }, - "reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true - }, - "run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, - "requires": { - "queue-microtask": "^1.2.2" - } - }, - "slash": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz", - "integrity": "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==", - "dev": true - }, - "source-map-js": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", - "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", - "dev": true - }, - "string-width": { + "node_modules/wrap-ansi-cjs/node_modules/string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "requires": { + "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" } }, - "strip-ansi": { + "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "requires": { + "dependencies": { "ansi-regex": "^5.0.1" - } - }, - "stylehacks": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-6.0.2.tgz", - "integrity": "sha512-00zvJGnCu64EpMjX8b5iCZ3us2Ptyw8+toEkb92VdmkEaRaSGBNKAoK6aWZckhXxmQP8zWiTaFaiMGIU8Ve8sg==", - "dev": true, - "requires": { - "browserslist": "^4.22.2", - "postcss-selector-parser": "^6.0.15" - } - }, - "sucrase": { - "version": "3.32.0", - "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.32.0.tgz", - "integrity": "sha512-ydQOU34rpSyj2TGyz4D2p8rbktIOZ8QY9s+DGLvFU1i5pWJE8vkpruCjGCMHsdXwnD7JDcS+noSwM/a7zyNFDQ==", - "dev": true, - "requires": { - "@jridgewell/gen-mapping": "^0.3.2", - "commander": "^4.0.0", - "glob": "7.1.6", - "lines-and-columns": "^1.1.6", - "mz": "^2.7.0", - "pirates": "^4.0.1", - "ts-interface-checker": "^0.1.9" }, - "dependencies": { - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "commander": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", - "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", - "dev": true - }, - "glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - } + "engines": { + "node": ">=8" } }, - "supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true - }, - "svgo": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/svgo/-/svgo-3.2.0.tgz", - "integrity": "sha512-4PP6CMW/V7l/GmKRKzsLR8xxjdHTV4IMvhTnpuHwwBazSIlw5W/5SmPjN8Dwyt7lKbSJrRDgp4t9ph0HgChFBQ==", - "dev": true, - "requires": { - "@trysound/sax": "0.2.0", - "commander": "^7.2.0", - "css-select": "^5.1.0", - "css-tree": "^2.3.1", - "css-what": "^6.1.0", - "csso": "^5.0.5", - "picocolors": "^1.0.0" - } - }, - "tailwindcss": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.1.tgz", - "integrity": "sha512-qAYmXRfk3ENzuPBakNK0SRrUDipP8NQnEY6772uDhflcQz5EhRdD7JNZxyrFHVQNCwULPBn6FNPp9brpO7ctcA==", - "dev": true, - "requires": { - "@alloc/quick-lru": "^5.2.0", - "arg": "^5.0.2", - "chokidar": "^3.5.3", - "didyoumean": "^1.2.2", - "dlv": "^1.1.3", - "fast-glob": "^3.3.0", - "glob-parent": "^6.0.2", - "is-glob": "^4.0.3", - "jiti": "^1.19.1", - "lilconfig": "^2.1.0", - "micromatch": "^4.0.5", - "normalize-path": "^3.0.0", - "object-hash": "^3.0.0", - "picocolors": "^1.0.0", - "postcss": "^8.4.23", - "postcss-import": "^15.1.0", - "postcss-js": "^4.0.1", - "postcss-load-config": "^4.0.1", - "postcss-nested": "^6.0.1", - "postcss-selector-parser": "^6.0.11", - "resolve": "^1.22.2", - "sucrase": "^3.32.0" + "node_modules/yaml": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.4.1.tgz", + "integrity": "sha512-pIXzoImaqmfOrL7teGUBt/T7ZDnyeGBWyXQBvOVhLkWLN37GXv8NMLK406UY6dS51JfcQHsmcW5cJ441bHg6Lg==", + "bin": { + "yaml": "bin.mjs" }, - "dependencies": { - "glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, - "requires": { - "is-glob": "^4.0.3" - } - }, - "postcss-import": { - "version": "15.1.0", - "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz", - "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==", - "dev": true, - "requires": { - "postcss-value-parser": "^4.0.0", - "read-cache": "^1.0.0", - "resolve": "^1.1.7" - } - } + "engines": { + "node": ">= 14" } - }, - "thenby": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/thenby/-/thenby-1.3.4.tgz", - "integrity": "sha512-89Gi5raiWA3QZ4b2ePcEwswC3me9JIg+ToSgtE0JWeCynLnLxNr/f9G+xfo9K+Oj4AFdom8YNJjibIARTJmapQ==", - "dev": true - }, - "thenify": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", - "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", - "dev": true, - "requires": { - "any-promise": "^1.0.0" - } - }, - "thenify-all": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", - "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", - "dev": true, - "requires": { - "thenify": ">= 3.1.0 < 4" - } - }, - "to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "requires": { - "is-number": "^7.0.0" - } - }, - "ts-interface-checker": { - "version": "0.1.13", - "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", - "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", - "dev": true - }, - "unicorn-magic": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.1.0.tgz", - "integrity": "sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==", - "dev": true - }, - "universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", - "dev": true - }, - "update-browserslist-db": { - "version": "1.0.13", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", - "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", - "dev": true, - "requires": { - "escalade": "^3.1.1", - "picocolors": "^1.0.0" - } - }, - "util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", - "dev": true - }, - "wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - } - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true - }, - "y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true - }, - "yaml": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.4.tgz", - "integrity": "sha512-8aAvwVUSHpfEqTQ4w/KMlf3HcRdt50E5ODIQJBw1fQ5RL34xabzxtUlzTXVqc4rkZsPbvrXKWnABCD7kWSmocA==", - "dev": true - }, - "yargs": { - "version": "17.5.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.5.1.tgz", - "integrity": "sha512-t6YAJcxDkNX7NFYiVtKvWUz8l+PaKTLiL63mJYWR2GnHq2gjEWISzsLp9wg3aY36dY1j+gfIEL3pIF+XlJJfbA==", - "dev": true, - "requires": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.0.0" - } - }, - "yargs-parser": { - "version": "21.0.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.0.1.tgz", - "integrity": "sha512-9BK1jFpLzJROCI5TzwZL/TU4gqjK5xiHV/RfWLOahrjAko/e4DJkRDZQXfvqAsiZzzYhgAzbgz6lg48jcm4GLg==", - "dev": true } } } diff --git a/modules/webapp/package.json b/modules/webapp/package.json index c9bd65c0..689843cf 100644 --- a/modules/webapp/package.json +++ b/modules/webapp/package.json @@ -5,13 +5,9 @@ "devDependencies": { "@fortawesome/fontawesome-free": "^6.0.0", "@tailwindcss/forms": "^0.5.0", - "autoprefixer": "^10.4.2", - "cssnano": "^6.0.0", - "flag-icon-css": "^3.5.0", - "postcss": "^8.4.7", - "postcss-cli": "^11.0.0", - "postcss-import": "^16.0.0", - "postcss-purgecss": "^5.0.0", - "tailwindcss": "^3.0.23" + "flag-icons": "^7.2.0" + }, + "dependencies": { + "tailwindcss": "^3.4.1" } } diff --git a/modules/webapp/src/main/elm/Data/Language.elm b/modules/webapp/src/main/elm/Data/Language.elm index 0d863f38..56a6f69b 100644 --- a/modules/webapp/src/main/elm/Data/Language.elm +++ b/modules/webapp/src/main/elm/Data/Language.elm @@ -30,6 +30,7 @@ type Language | Dutch | Latvian | Japanese + | JpnVert | Hebrew | Hungarian | Lithuanian @@ -90,6 +91,9 @@ fromString str = else if str == "jpn" || str == "ja" || str == "japanese" then Just Japanese + else if str == "jpn_vert" || str == "ja_vert" || str == "jpnvert" then + Just JpnVert + else if str == "heb" || str == "he" || str == "hebrew" then Just Hebrew @@ -169,6 +173,9 @@ toIso3 lang = Japanese -> "jpn" + JpnVert -> + "jpn_vert" + Hebrew -> "heb" @@ -212,6 +219,7 @@ all = , Romanian , Latvian , Japanese + , JpnVert , Hebrew , Hungarian , Lithuanian diff --git a/modules/webapp/src/main/elm/Messages.elm b/modules/webapp/src/main/elm/Messages.elm index d3cd405c..75517c7e 100644 --- a/modules/webapp/src/main/elm/Messages.elm +++ b/modules/webapp/src/main/elm/Messages.elm @@ -109,7 +109,7 @@ gb tz = , timeZone = tz , iso2 = "gb" , label = "English" - , flagIcon = "flag-icon flag-icon-gb" + , flagIcon = "fi fi-gb" , app = Messages.App.gb , collectiveSettings = Messages.Page.CollectiveSettings.gb tz , login = Messages.Page.Login.gb @@ -133,7 +133,7 @@ de tz = , timeZone = tz , iso2 = "de" , label = "Deutsch" - , flagIcon = "flag-icon flag-icon-de" + , flagIcon = "fi fi-de" , app = Messages.App.de , collectiveSettings = Messages.Page.CollectiveSettings.de tz , login = Messages.Page.Login.de @@ -157,7 +157,7 @@ fr tz = , timeZone = tz , iso2 = "fr" , label = "Français" - , flagIcon = "flag-icon flag-icon-fr" + , flagIcon = "fi fi-fr" , app = Messages.App.fr , collectiveSettings = Messages.Page.CollectiveSettings.fr tz , login = Messages.Page.Login.fr diff --git a/modules/webapp/src/main/elm/Messages/Data/Language.elm b/modules/webapp/src/main/elm/Messages/Data/Language.elm index 2369a5a4..3bba9d7e 100644 --- a/modules/webapp/src/main/elm/Messages/Data/Language.elm +++ b/modules/webapp/src/main/elm/Messages/Data/Language.elm @@ -65,6 +65,9 @@ gb lang = Japanese -> "Japanese" + JpnVert -> + "JpnVert" + Hebrew -> "Hebrew" @@ -141,6 +144,9 @@ de lang = Japanese -> "Japanisch" + JpnVert -> + "JpnVert" + Hebrew -> "Hebräisch" @@ -217,6 +223,9 @@ fr lang = Japanese -> "Japonnais" + JpnVert -> + "JpnVert" + Hebrew -> "Hébreu" diff --git a/modules/webapp/src/main/styles/custom-utilities.css b/modules/webapp/src/main/styles/custom-utilities.css index 0da52b61..b1390228 100644 --- a/modules/webapp/src/main/styles/custom-utilities.css +++ b/modules/webapp/src/main/styles/custom-utilities.css @@ -24,11 +24,8 @@ z-index: 35; } - @variants responsive { - .min-h-7 { - min-height: 1.75rem; - } - + .min-h-7 { + min-height: 1.75rem; } .scrollbar-none { @@ -47,37 +44,35 @@ width: 8px; } - @variants dark { - .scrollbar-dark-sidebar { - scrollbar-color: rgba(15,23,42,0.9) rgba(15,23,42,0.3); - } - .scrollbar-light-sidebar { - scrollbar-color: rgba(219, 234, 254, 1.0) rgba(219, 234, 254,0.3); - } - .scrollbar-main { - scrollbar-color: rgba(156, 163, 175,0.9) rgba(156, 163, 175,0.3); - } + .scrollbar-dark-sidebar { + scrollbar-color: rgba(15,23,42,0.9) rgba(15,23,42,0.3); + } + .scrollbar-light-sidebar { + scrollbar-color: rgba(219, 234, 254, 1.0) rgba(219, 234, 254,0.3); + } + .scrollbar-main { + scrollbar-color: rgba(156, 163, 175,0.9) rgba(156, 163, 175,0.3); + } - .scrollbar-dark-sidebar::-webkit-scrollbar { - background-color: rgba(15,23,42,0.3); - } - .scrollbar-dark-sidebar::-webkit-scrollbar-thumb { - background: rgba(15,23,42,0.9); - } + .scrollbar-dark-sidebar::-webkit-scrollbar { + background-color: rgba(15,23,42,0.3); + } + .scrollbar-dark-sidebar::-webkit-scrollbar-thumb { + background: rgba(15,23,42,0.9); + } - .scrollbar-light-sidebar::-webkit-scrollbar { - background-color: rgba(219, 234, 254, 0.3); - } - .scrollbar-light-sidebar::-webkit-scrollbar-thumb { - background: rgba(219, 234, 254, 1.0); - } + .scrollbar-light-sidebar::-webkit-scrollbar { + background-color: rgba(219, 234, 254, 0.3); + } + .scrollbar-light-sidebar::-webkit-scrollbar-thumb { + background: rgba(219, 234, 254, 1.0); + } - .scrollbar-main::-webkit-scrollbar { - background-color: rgba(156, 163, 175, 0.3); - } - .scrollbar-main::-webkit-scrollbar-thumb { - background: rgba(156, 163, 175, 0.9); - } + .scrollbar-main::-webkit-scrollbar { + background-color: rgba(156, 163, 175, 0.3); + } + .scrollbar-main::-webkit-scrollbar-thumb { + background: rgba(156, 163, 175, 0.9); } .ds-card-search-hl strong { diff --git a/modules/webapp/src/main/styles/index.css b/modules/webapp/src/main/styles/index.css index d6be45b1..581638dc 100644 --- a/modules/webapp/src/main/styles/index.css +++ b/modules/webapp/src/main/styles/index.css @@ -1,5 +1,5 @@ @import "@fortawesome/fontawesome-free/css/all"; -@import "flag-icon-css/css/flag-icon.min"; +@import "flag-icons/css/flag-icons.min"; @import "tailwindcss/base"; @import "tailwindcss/components"; diff --git a/modules/webapp/src/main/webjar/docspell.js b/modules/webapp/src/main/webjar/docspell.js index 8a9d24f6..1c5d5b5d 100644 --- a/modules/webapp/src/main/webjar/docspell.js +++ b/modules/webapp/src/main/webjar/docspell.js @@ -152,6 +152,8 @@ function initWS() { var dataJSON = JSON.parse(event.data); if (dataJSON.tag !== "keep-alive") { elmApp.ports.receiveWsMessage.send(dataJSON); + } else { + dsWebSocket.send(event.data); } } }); diff --git a/modules/webapp/tailwind.config.js b/modules/webapp/tailwind.config.js index 3e25d8b8..5ab402fa 100644 --- a/modules/webapp/tailwind.config.js +++ b/modules/webapp/tailwind.config.js @@ -19,14 +19,7 @@ module.exports = { } } }, - variants: { - extend: { - backgroundOpacity: ['dark'] - } - }, - purge: false, plugins: [ require('@tailwindcss/forms') ] -// prefix: 'tw-' } diff --git a/nix/checks/configuration-test.nix b/nix/checks/configuration-test.nix index 84ccb577..ac1ec897 100644 --- a/nix/checks/configuration-test.nix +++ b/nix/checks/configuration-test.nix @@ -1,5 +1,8 @@ -{ config, pkgs, ... }: -let +{ + config, + pkgs, + ... +}: let full-text-search = { enabled = true; backend = "postgresql"; @@ -9,9 +12,7 @@ let }; }; }; -in -{ - +in { i18n = { defaultLocale = "en_US.UTF-8"; }; @@ -21,12 +22,11 @@ in password = "root"; }; - services.docspell-joex = { enable = true; bind.address = "0.0.0.0"; base-url = "http://localhost:7878"; - jvmArgs = [ "-J-Xmx1536M" ]; + jvmArgs = ["-J-Xmx1536M"]; inherit full-text-search; }; services.docspell-restserver = { @@ -69,14 +69,12 @@ in }; }; - environment.systemPackages = - [ - pkgs.jq - pkgs.inetutils - pkgs.htop - pkgs.jdk17 - ]; - + environment.systemPackages = [ + pkgs.jq + pkgs.inetutils + pkgs.htop + pkgs.jdk17 + ]; services.xserver = { enable = false; @@ -84,12 +82,11 @@ in networking = { hostName = "docspelltest"; - firewall.allowedTCPPorts = [ 7880 ]; + firewall.allowedTCPPorts = [7880]; }; system.stateVersion = "22.11"; # This slows down the build of a vm documentation.enable = false; - } diff --git a/nix/checks/default.nix b/nix/checks/default.nix index d3eb6f37..97ae31c1 100644 --- a/nix/checks/default.nix +++ b/nix/checks/default.nix @@ -1,5 +1,4 @@ -{ ... }: -{ +{...}: { imports = [ ./configuration-test.nix ]; diff --git a/nix/dev-vm/default.nix b/nix/dev-vm/default.nix deleted file mode 100644 index 01e172a1..00000000 --- a/nix/dev-vm/default.nix +++ /dev/null @@ -1,28 +0,0 @@ -# NOTE: modulesPath and imports are taken from nixpkgs#59219 -{ modulesPath, pkgs, lib, ... }: { - imports = [ (modulesPath + "/virtualisation/qemu-vm.nix") ]; - services.openssh = { - enable = true; - permitRootLogin = "yes"; - }; - - services.docspell-restserver = { - openid = lib.mkForce [ ]; - backend = lib.mkForce { - signup = { - mode = "open"; - }; - }; - }; - - # Otherwise oomkiller kills docspell - virtualisation.memorySize = 4096; - - virtualisation.forwardPorts = [ - # SSH - { from = "host"; host.port = 64022; guest.port = 22; } - # Docspell - { from = "host"; host.port = 64080; guest.port = 7880; } - ]; - -} diff --git a/nix/docker.nix b/nix/docker.nix new file mode 100644 index 00000000..29e9f870 --- /dev/null +++ b/nix/docker.nix @@ -0,0 +1,79 @@ +{ + dockerTools, + busybox, + cacert, + wget, + unpaper, + ghostscript, + ocrmypdf, + tesseract4, + python3Packages, + unoconv, + docspell-restserver, + docspell-joex, +}: let + mkImage = { + name, + port, + pkg, + tools, + }: + dockerTools.buildLayeredImage { + inherit name; + created = "now"; + contents = + [ + busybox + cacert + wget + pkg + ] + ++ tools; + + extraCommands = "mkdir -m 0777 tmp"; + + #https://github.com/moby/docker-image-spec/blob/main/spec.md#image-json-description + config = { + Entrypoint = ["bin/${name}" "-Dconfig.file="]; + #Cmd = ["bin/${name}" "-Dconfig.file="]; + ExposedPorts = { + "${builtins.toString port}/tcp" = {}; + }; + Env = [ + "PATH=/bin" + "SSL_CERT_FILE=${cacert}/etc/ssl/certs/ca-bundle.crt" + ]; + Healthcheck = { + Test = [ + "CMD" + "wget" + "--spider" + "http://localhost:${builtins.toString port}/api/info/version" + ]; + Interval = 60000000000; #1min + Timeout = 10000000000; #10s + Retries = 2; + StartInterval = 10000000000; + }; + Labels = { + #https://github.com/microscaling/microscaling/blob/55a2d7b91ce7513e07f8b1fd91bbed8df59aed5a/Dockerfile#L22-L33 + "org.label-schema.vcs-ref" = "v${pkg.version}"; + "org.label-schema.vcs-url" = "https://github.com/eikek/docspell"; + }; + }; + tag = "v${pkg.version}"; + }; +in { + docspell-restserver = mkImage { + name = "docspell-restserver"; + port = 7880; + pkg = docspell-restserver; + tools = []; + }; + docspell-joex = mkImage { + name = "docspell-joex"; + port = 7878; + pkg = docspell-joex; + tools = [unpaper ghostscript ocrmypdf tesseract4 python3Packages.weasyprint unoconv]; + }; +} diff --git a/nix/flake.lock b/nix/flake.lock deleted file mode 100644 index 61eca2df..00000000 --- a/nix/flake.lock +++ /dev/null @@ -1,26 +0,0 @@ -{ - "nodes": { - "nixpkgs": { - "locked": { - "lastModified": 1706373441, - "narHash": "sha256-S1hbgNbVYhuY2L05OANWqmRzj4cElcbLuIkXTb69xkk=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "56911ef3403a9318b7621ce745f5452fb9ef6867", - "type": "github" - }, - "original": { - "id": "nixpkgs", - "ref": "nixos-23.11", - "type": "indirect" - } - }, - "root": { - "inputs": { - "nixpkgs": "nixpkgs" - } - } - }, - "root": "root", - "version": 7 -} diff --git a/nix/flake.nix b/nix/flake.nix deleted file mode 100644 index a8cb0785..00000000 --- a/nix/flake.nix +++ /dev/null @@ -1,134 +0,0 @@ -{ - description = "Docspell flake"; - inputs = { - nixpkgs.url = "nixpkgs/nixos-23.11"; - }; - - outputs = { self, nixpkgs }: - let - supportedSystems = [ "x86_64-linux" "aarch64-linux" ]; - forAllSystems = nixpkgs.lib.genAttrs supportedSystems; - nixpkgsFor = forAllSystems (system: import nixpkgs { inherit system; }); - # Version config - cfg = { - v0_41_0 = rec { - version = "0.41.0"; - server = { - url = "https://github.com/eikek/docspell/releases/download/v${version}/docspell-restserver-${version}.zip"; - sha256 = "sha256-JFftIzI94UNLLh96I++qFsBZhOkquPIPhNhtS2Ov8wI="; - }; - joex = { - url = "https://github.com/eikek/docspell/releases/download/v${version}/docspell-joex-${version}.zip"; - sha256 = "sha256-flKWjEsMd2/XT3Bu6EjFgf3lCojvLbKFDEXemP1K+/8="; - }; - }; - }; - current_version = cfg.v0_41_0; - inherit (current_version) version; - in - rec - { - overlays.default = final: prev: { - docspell-server = with final; stdenv.mkDerivation { - inherit version; - pname = "docspell-server"; - - src = fetchzip current_version.server; - buildInputs = [ jdk17 ]; - buildPhase = "true"; - - installPhase = '' - mkdir -p $out/{bin,docspell-restserver-${version}} - cp -R * $out/docspell-restserver-${version}/ - cat > $out/bin/docspell-restserver <<-EOF - #!${bash}/bin/bash - $out/docspell-restserver-${version}/bin/docspell-restserver -java-home ${jdk17} "\$@" - EOF - chmod 755 $out/bin/docspell-restserver - ''; - }; - docspell-joex = with final; stdenv.mkDerivation rec { - inherit version; - - pname = "docspell-joex"; - - src = fetchzip current_version.joex; - - buildInputs = [ jdk17 ]; - - buildPhase = "true"; - - installPhase = '' - mkdir -p $out/{bin,docspell-joex-${version}} - cp -R * $out/docspell-joex-${version}/ - cat > $out/bin/docspell-joex <<-EOF - #!${bash}/bin/bash - $out/docspell-joex-${version}/bin/docspell-joex -java-home ${jdk17} "\$@" - EOF - chmod 755 $out/bin/docspell-joex - ''; - }; - - }; - - packages = forAllSystems (system: - { - default = (import nixpkgs { - inherit system; - overlays = [ self.overlays.default ]; - }).docspell-joex; - }); - - checks = forAllSystems - (system: { - build = self.packages.${system}.default; - - test = - with import (nixpkgs + "/nixos/lib/testing-python.nix") - { - inherit system; - }; - - makeTest { - name = "docspell"; - nodes = { - machine = { ... }: { - imports = [ - self.nixosModules.default - ./checks - ]; - }; - }; - - testScript = builtins.readFile ./checks/testScript.py; - }; - }); - - nixosModules = { - default = { ... }: { - imports = [ - ((import ./modules/server.nix) self.overlays.default) - ((import ./modules/joex.nix) self.overlays.default) - ]; - }; - server = ((import ./modules/server.nix) self.overlays.default); - joex = ((import ./modules/joex.nix) self.overlays.default); - }; - - nixosConfigurations = - let - lib = nixpkgs.lib; - in - { - dev-vm = lib.makeOverridable nixpkgs.lib.nixosSystem { - system = "x86_64-linux"; - modules = [ - self.nixosModules.default - ./checks - # nixos-shell specific module. Should be kept outside nix flake checks - ./dev-vm - ]; - }; - }; - }; -} diff --git a/nix/modules/joex.nix b/nix/modules/joex.nix index 7890d690..16789de5 100644 --- a/nix/modules/joex.nix +++ b/nix/modules/joex.nix @@ -1,16 +1,17 @@ -overlay: { config, lib, pkgs, ... }: - -with lib; -let +{ + config, + lib, + pkgs, + ... +}: +with lib; let cfg = config.services.docspell-joex; # Extract the config without the extraConfig attribute. It will be merged later declared_config = attrsets.filterAttrs (n: v: n != "extraConfig") cfg; - user = if cfg.runAs == null then "docspell" else cfg.runAs; - configFile = pkgs.writeText "docspell-joex.conf" '' - {"docspell": { "joex": - ${builtins.toJSON (lib.recursiveUpdate declared_config cfg.extraConfig)} - }} - ''; + user = + if cfg.runAs == null + then "docspell" + else cfg.runAs; defaults = { app-id = "joex1"; base-url = "http://localhost:7878"; @@ -85,7 +86,7 @@ let schedule = "Sun *-*-* 00:00:00 UTC"; sender-account = ""; smtp-id = ""; - recipients = [ ]; + recipients = []; subject = "Docspell {{ latestVersion }} is available"; body = '' Hello, @@ -116,21 +117,21 @@ let working-dir = "/tmp/docspell-extraction"; command = { program = "${pkgs.ghostscript}/bin/gs"; - args = [ "-dNOPAUSE" "-dBATCH" "-dSAFER" "-sDEVICE=tiffscaled8" "-sOutputFile={{outfile}}" "{{infile}}" ]; + args = ["-dNOPAUSE" "-dBATCH" "-dSAFER" "-sDEVICE=tiffscaled8" "-sOutputFile={{outfile}}" "{{infile}}"]; timeout = "5 minutes"; }; }; unpaper = { command = { program = "${pkgs.unpaper}/bin/unpaper"; - args = [ "{{infile}}" "{{outfile}}" ]; + args = ["{{infile}}" "{{outfile}}"]; timeout = "5 minutes"; }; }; tesseract = { command = { program = "${pkgs.tesseract4}/bin/tesseract"; - args = [ "{{file}}" "stdout" "-l" "{{lang}}" ]; + args = ["{{file}}" "stdout" "-l" "{{lang}}"]; timeout = "5 minutes"; }; }; @@ -179,7 +180,7 @@ let wkhtmlpdf = { command = { program = ""; - args = [ "--encoding" "UTF-8" "-" "{{outfile}}" ]; + args = ["--encoding" "UTF-8" "-" "{{outfile}}"]; timeout = "2 minutes"; }; working-dir = "/tmp/docspell-convert"; @@ -204,7 +205,7 @@ let tesseract = { command = { program = "${pkgs.tesseract4}/bin/tesseract"; - args = [ "{{infile}}" "out" "-l" "{{lang}}" "pdf" "txt" ]; + args = ["{{infile}}" "out" "-l" "{{lang}}" "pdf" "txt"]; timeout = "5 minutes"; }; working-dir = "/tmp/docspell-convert"; @@ -213,7 +214,7 @@ let unoconv = { command = { program = "${pkgs.unoconv}/bin/unoconv"; - args = [ "-f" "pdf" "-o" "{{outfile}}" "{{infile}}" ]; + args = ["-f" "pdf" "-o" "{{outfile}}" "{{infile}}"]; timeout = "2 minutes"; }; working-dir = "/tmp/docspell-convert"; @@ -240,7 +241,7 @@ let }; files = { chunk-size = 524288; - valid-mime-types = [ ]; + valid-mime-types = []; }; full-text-search = { enabled = false; @@ -259,9 +260,9 @@ let user = "pguser"; password = ""; }; - pg-config = { }; + pg-config = {}; pg-query-parser = "websearch_to_tsquery"; - pg-rank-normalization = [ 4 ]; + pg-rank-normalization = [4]; }; migration = { index-all-chunk = 10; @@ -291,9 +292,7 @@ let }; }; }; -in -{ - +in { ## interface options = { services.docspell-joex = { @@ -302,6 +301,7 @@ in default = false; description = "Whether to enable docspell docspell job executor."; }; + package = mkPackageOption pkgs "docspell-joex" {}; runAs = mkOption { type = types.nullOr types.str; default = null; @@ -321,11 +321,19 @@ in }; jvmArgs = mkOption { type = types.listOf types.str; - default = [ ]; - example = [ "-J-Xmx1G" ]; + default = []; + example = ["-J-Xmx1G"]; description = "The options passed to the executable for setting jvm arguments."; }; - + configFile = mkOption { + type = types.nullOr types.path; + default = null; + example = literalExpression ''"''${config.sops.secrets.docspell_joex_config.path}"''; + description = '' + Path to an existing configuration file. + If null, a configuration file will be generated at /etc/docspell-joex.conf + ''; + }; app-id = mkOption { type = types.str; @@ -340,7 +348,7 @@ in }; bind = mkOption { - type = types.submodule ({ + type = types.submodule { options = { address = mkOption { type = types.str; @@ -353,13 +361,13 @@ in description = "The port to bind the REST server"; }; }; - }); + }; default = defaults.bind; description = "Address and port bind the rest server."; }; logging = mkOption { - type = types.submodule ({ + type = types.submodule { options = { minimum-level = mkOption { type = types.str; @@ -377,7 +385,7 @@ in description = "Set of logger and their levels"; }; }; - }); + }; default = defaults.logging; description = "Settings for logging"; }; @@ -394,7 +402,7 @@ in }; jdbc = mkOption { - type = types.submodule ({ + type = types.submodule { options = { url = mkOption { type = types.str; @@ -421,13 +429,13 @@ in description = "The password to connect to the database."; }; }; - }); + }; default = defaults.jdbc; description = "Database connection settings"; }; send-mail = mkOption { - type = types.submodule ({ + type = types.submodule { options = { list-id = mkOption { type = types.str; @@ -443,15 +451,14 @@ in https://tools.ietf.org/html/rfc2919 for a formal specification ''; }; - }; - }); + }; default = defaults.send-mail; description = "Settings for sending mails."; }; scheduler = mkOption { - type = types.submodule ({ + type = types.submodule { options = { pool-size = mkOption { type = types.int; @@ -501,13 +508,13 @@ in ''; }; }; - }); + }; default = defaults.scheduler; description = "Settings for the scheduler"; }; periodic-scheduler = mkOption { - type = types.submodule ({ + type = types.submodule { options = { wakeup-period = mkOption { type = types.str; @@ -520,7 +527,7 @@ in ''; }; }; - }); + }; default = defaults.periodic-scheduler; description = '' Settings for the periodic scheduler. @@ -528,10 +535,10 @@ in }; user-tasks = mkOption { - type = types.submodule ({ + type = types.submodule { options = { scan-mailbox = mkOption { - type = types.submodule ({ + type = types.submodule { options = { max-folders = mkOption { type = types.int; @@ -565,18 +572,18 @@ in ''; }; }; - }); + }; default = defaults.user-tasks.scan-mailbox; description = "Allows to import e-mails by scanning a mailbox."; }; }; - }); + }; default = defaults.user-tasks; description = "Configuration for the user tasks."; }; house-keeping = mkOption { - type = types.submodule ({ + type = types.submodule { options = { schedule = mkOption { type = types.str; @@ -587,7 +594,7 @@ in ''; }; cleanup-invites = mkOption { - type = types.submodule ({ + type = types.submodule { options = { enabled = mkOption { type = types.bool; @@ -600,7 +607,7 @@ in description = "The minimum age of invites to be deleted."; }; }; - }); + }; default = defaults.house-keeping.cleanup-invites; description = '' This task removes invitation keys that have been created but not @@ -609,7 +616,7 @@ in ''; }; cleanup-jobs = mkOption { - type = types.submodule ({ + type = types.submodule { options = { enabled = mkOption { type = types.bool; @@ -633,9 +640,8 @@ in whether more or less memory should be used. ''; }; - }; - }); + }; default = defaults.house-keeping.cleanup-jobs; description = '' Jobs store their log output in the database. Normally this data @@ -644,7 +650,7 @@ in ''; }; cleanup-remember-me = mkOption { - type = types.submodule ({ + type = types.submodule { options = { enabled = mkOption { type = types.bool; @@ -657,13 +663,13 @@ in description = "The miminum age of remember me tokens to delete."; }; }; - }); + }; default = defaults.house-keeping.cleanup-remember-me; description = "Settings for cleaning up remember me tokens."; }; cleanup-downloads = mkOption { - type = types.submodule ({ + type = types.submodule { options = { enabled = mkOption { type = types.bool; @@ -676,13 +682,13 @@ in description = "The miminum age of a download file to delete."; }; }; - }); + }; default = defaults.house-keeping.cleanup-downloads; description = ""; }; check-nodes = mkOption { - type = types.submodule ({ + type = types.submodule { options = { enabled = mkOption { type = types.bool; @@ -695,12 +701,12 @@ in description = "How often the node must be unreachable, before it is removed."; }; }; - }); + }; default = defaults.house-keeping.cleanup-nodes; description = "Removes node entries that are not reachable anymore."; }; }; - }); + }; default = defaults.house-keeping; description = '' Docspell uses periodic house keeping tasks, like cleaning expired @@ -709,7 +715,7 @@ in }; update-check = mkOption { - type = types.submodule ({ + type = types.submodule { options = { enabled = mkOption { type = types.bool; @@ -753,7 +759,7 @@ in recipients = mkOption { type = types.listOf types.str; default = defaults.update-check.recipients; - example = [ "josh.doe@gmail.com" ]; + example = ["josh.doe@gmail.com"]; description = '' A list of recipient e-mail addresses. ''; @@ -781,7 +787,7 @@ in ''; }; }; - }); + }; default = defaults.update-check; description = '' A periodic task to check for new releases of docspell. It can @@ -791,10 +797,10 @@ in }; extraction = mkOption { - type = types.submodule ({ + type = types.submodule { options = { pdf = mkOption { - type = types.submodule ({ + type = types.submodule { options = { min-text-len = mkOption { type = types.int; @@ -808,12 +814,12 @@ in ''; }; }; - }); + }; default = defaults.extraction.pdf; description = "Settings for PDF extraction"; }; preview = mkOption { - type = types.submodule ({ + type = types.submodule { options = { dpi = mkOption { type = types.int; @@ -830,12 +836,12 @@ in ''; }; }; - }); + }; default = defaults.extraction.preview; description = ""; }; ocr = mkOption { - type = types.submodule ({ + type = types.submodule { options = { max-image-size = mkOption { type = types.int; @@ -846,7 +852,7 @@ in ''; }; page-range = mkOption { - type = types.submodule ({ + type = types.submodule { options = { begin = mkOption { type = types.int; @@ -854,7 +860,7 @@ in description = "Specifies the first N pages of a file to process."; }; }; - }); + }; default = defaults.extraction.page-range; description = '' Defines what pages to process. If a PDF with 600 pages is @@ -871,7 +877,7 @@ in ''; }; ghostscript = mkOption { - type = types.submodule ({ + type = types.submodule { options = { working-dir = mkOption { type = types.str; @@ -879,7 +885,7 @@ in description = "Directory where the extraction processes can put their temp files"; }; command = mkOption { - type = types.submodule ({ + type = types.submodule { options = { program = mkOption { type = types.str; @@ -897,20 +903,20 @@ in description = "The timeout when executing the command"; }; }; - }); + }; default = defaults.extraction.ghostscript.command; description = "The system command"; }; }; - }); + }; default = defaults.extraction.ghostscript; description = "The ghostscript command."; }; unpaper = mkOption { - type = types.submodule ({ + type = types.submodule { options = { command = mkOption { - type = types.submodule ({ + type = types.submodule { options = { program = mkOption { type = types.str; @@ -928,20 +934,20 @@ in description = "The timeout when executing the command"; }; }; - }); + }; default = defaults.extraction.unpaper.command; description = "The system command"; }; }; - }); + }; default = defaults.extraction.unpaper; description = "The unpaper command."; }; tesseract = mkOption { - type = types.submodule ({ + type = types.submodule { options = { command = mkOption { - type = types.submodule ({ + type = types.submodule { options = { program = mkOption { type = types.str; @@ -959,23 +965,22 @@ in description = "The timeout when executing the command"; }; }; - }); + }; default = defaults.extraction.tesseract.command; description = "The system command"; }; }; - }); + }; default = defaults.extraction.tesseract; description = "The tesseract command."; }; - }; - }); + }; default = defaults.extraction.ocr; description = ""; }; }; - }); + }; default = defaults.extraction; description = '' Configuration of text extraction @@ -990,7 +995,7 @@ in }; text-analysis = mkOption { - type = types.submodule ({ + type = types.submodule { options = { max-length = mkOption { type = types.int; @@ -1015,7 +1020,7 @@ in }; nlp = mkOption { - type = types.submodule ({ + type = types.submodule { options = { mode = mkOption { type = types.str; @@ -1073,7 +1078,7 @@ in }; regex-ner = mkOption { - type = types.submodule ({ + type = types.submodule { options = { max-entries = mkOption { type = types.int; @@ -1104,18 +1109,18 @@ in ''; }; }; - }); + }; default = defaults.text-analysis.nlp.regex-ner; description = ""; }; }; - }); + }; default = defaults.text-analysis.nlp; description = "Configure NLP"; }; classification = mkOption { - type = types.submodule ({ + type = types.submodule { options = { enabled = mkOption { type = types.bool; @@ -1147,9 +1152,8 @@ in good results with *my* dataset. ''; }; - }; - }); + }; default = defaults.text-analysis.classification; description = '' Settings for doing document classification. @@ -1167,13 +1171,13 @@ in ''; }; }; - }); + }; default = defaults.text-analysis; description = "Settings for text analysis"; }; convert = mkOption { - type = types.submodule ({ + type = types.submodule { options = { chunk-size = mkOption { type = types.int; @@ -1202,7 +1206,7 @@ in ''; }; markdown = mkOption { - type = types.submodule ({ + type = types.submodule { options = { internal-css = mkOption { type = types.str; @@ -1212,7 +1216,7 @@ in ''; }; }; - }); + }; default = defaults.convert.markdown; description = '' Settings when processing markdown files (and other text files) @@ -1224,12 +1228,12 @@ in ''; }; html-converter = mkOption { - type = types.enum [ "wkhtmlpdf" "weasyprint" ]; + type = types.enum ["wkhtmlpdf" "weasyprint"]; default = "weasyprint"; description = "Which tool to use for converting html to pdfs"; }; wkhtmlpdf = mkOption { - type = types.submodule ({ + type = types.submodule { options = { working-dir = mkOption { type = types.str; @@ -1237,7 +1241,7 @@ in description = "Directory where the conversion processes can put their temp files"; }; command = mkOption { - type = types.submodule ({ + type = types.submodule { options = { program = mkOption { type = types.str; @@ -1255,12 +1259,12 @@ in description = "The timeout when executing the command"; }; }; - }); + }; default = defaults.convert.wkhtmlpdf.command; description = "The system command"; }; }; - }); + }; default = defaults.convert.wkhtmlpdf; description = '' To convert HTML files into PDF files, the external tool @@ -1268,7 +1272,7 @@ in ''; }; weasyprint = mkOption { - type = types.submodule ({ + type = types.submodule { options = { working-dir = mkOption { type = types.str; @@ -1276,7 +1280,7 @@ in description = "Directory where the conversion processes can put their temp files"; }; command = mkOption { - type = types.submodule ({ + type = types.submodule { options = { program = mkOption { type = types.str; @@ -1294,12 +1298,12 @@ in description = "The timeout when executing the command"; }; }; - }); + }; default = defaults.convert.weasyprint.command; description = "The system command"; }; }; - }); + }; default = defaults.convert.weasyprint; description = '' To convert HTML files into PDF files, the external tool @@ -1307,7 +1311,7 @@ in ''; }; tesseract = mkOption { - type = types.submodule ({ + type = types.submodule { options = { working-dir = mkOption { type = types.str; @@ -1315,7 +1319,7 @@ in description = "Directory where the conversion processes can put their temp files"; }; command = mkOption { - type = types.submodule ({ + type = types.submodule { options = { program = mkOption { type = types.str; @@ -1333,12 +1337,12 @@ in description = "The timeout when executing the command"; }; }; - }); + }; default = defaults.convert.tesseract.command; description = "The system command"; }; }; - }); + }; default = defaults.convert.tesseract; description = '' To convert image files to PDF files, tesseract is used. This @@ -1346,7 +1350,7 @@ in ''; }; unoconv = mkOption { - type = types.submodule ({ + type = types.submodule { options = { working-dir = mkOption { type = types.str; @@ -1354,7 +1358,7 @@ in description = "Directory where the conversion processes can put their temp files"; }; command = mkOption { - type = types.submodule ({ + type = types.submodule { options = { program = mkOption { type = types.str; @@ -1372,12 +1376,12 @@ in description = "The timeout when executing the command"; }; }; - }); + }; default = defaults.convert.unoconv.command; description = "The system command"; }; }; - }); + }; default = defaults.convert.unoconv; description = '' To convert "office" files to PDF files, the external tool @@ -1392,7 +1396,7 @@ in }; ocrmypdf = mkOption { - type = types.submodule ({ + type = types.submodule { options = { enabled = mkOption { type = types.bool; @@ -1405,7 +1409,7 @@ in description = "Directory where the conversion processes can put their temp files"; }; command = mkOption { - type = types.submodule ({ + type = types.submodule { options = { program = mkOption { type = types.str; @@ -1423,12 +1427,12 @@ in description = "The timeout when executing the command"; }; }; - }); + }; default = defaults.convert.ocrmypdf.command; description = "The system command"; }; }; - }); + }; default = defaults.convert.ocrmypdf; description = '' The tool ocrmypdf can be used to convert pdf files to pdf files @@ -1449,9 +1453,8 @@ in converted to PDF/A. ''; }; - }; - }); + }; default = defaults.convert; description = '' Configuration for converting files into PDFs. @@ -1462,7 +1465,7 @@ in ''; }; files = mkOption { - type = types.submodule ({ + type = types.submodule { options = { chunk-size = mkOption { type = types.int; @@ -1489,12 +1492,12 @@ in ''; }; }; - }); + }; default = defaults.files; description = "Settings for how files are stored."; }; full-text-search = mkOption { - type = types.submodule ({ + type = types.submodule { options = { enabled = mkOption { type = types.bool; @@ -1514,7 +1517,7 @@ in }; solr = mkOption { - type = types.submodule ({ + type = types.submodule { options = { url = mkOption { type = types.str; @@ -1546,13 +1549,13 @@ in description = "The default combiner for tokens. One of {AND, OR}."; }; }; - }); + }; default = defaults.full-text-search.solr; description = "Configuration for the SOLR backend."; }; postgresql = mkOption { - type = types.submodule ({ + type = types.submodule { options = { use-default-connection = mkOption { type = types.bool; @@ -1560,7 +1563,7 @@ in description = "Whether to use the primary db connection."; }; jdbc = mkOption { - type = types.submodule ({ + type = types.submodule { options = { url = mkOption { type = types.str; @@ -1580,7 +1583,7 @@ in description = "The password to connect to the database."; }; }; - }); + }; default = defaults.full-text-search.postgresql.jdbc; description = "Database connection settings"; }; @@ -1600,13 +1603,13 @@ in description = ""; }; }; - }); + }; default = defaults.full-text-search.postgresql; description = "PostgreSQL for fulltext search"; }; migration = mkOption { - type = types.submodule ({ + type = types.submodule { options = { index-all-chunk = mkOption { type = types.int; @@ -1618,17 +1621,17 @@ in ''; }; }; - }); + }; default = defaults.full-text-search.migration; description = "Settings for running the index migration tasks"; }; }; - }); + }; default = defaults.full-text-search; description = "Configuration for full-text search."; }; addons = mkOption { - type = types.submodule ({ + type = types.submodule { options = { working-dir = mkOption { type = types.str; @@ -1641,7 +1644,7 @@ in description = "Cache directory"; }; executor-config = mkOption { - type = types.submodule ({ + type = types.submodule { options = { runner = mkOption { type = types.str; @@ -1659,7 +1662,7 @@ in description = ""; }; nspawn = mkOption { - type = types.submodule ({ + type = types.submodule { options = { enabled = mkOption { type = types.bool; @@ -1682,12 +1685,12 @@ in description = ""; }; }; - }); + }; default = defaults.addons.executor-config.nspawn; description = ""; }; nix-runner = mkOption { - type = types.submodule ({ + type = types.submodule { options = { nix-binary = mkOption { type = types.str; @@ -1700,12 +1703,12 @@ in description = ""; }; }; - }); + }; default = defaults.addons.executor-config.nix-runner; description = ""; }; docker-runner = mkOption { - type = types.submodule ({ + type = types.submodule { options = { docker-binary = mkOption { type = types.str; @@ -1718,24 +1721,24 @@ in description = ""; }; }; - }); + }; default = defaults.addons.executor-config.docker-runner; description = ""; }; }; - }); + }; default = defaults.addons.executor-config; description = ""; }; }; - }); + }; default = defaults.addons; description = "Addon executor config"; }; extraConfig = mkOption { type = types.attrs; description = "Extra configuration for docspell server. Overwrites values in case of a conflict."; - default = { }; + default = {}; example = '' { files = { @@ -1754,9 +1757,6 @@ in ## implementation config = mkIf config.services.docspell-joex.enable { - - nixpkgs.overlays = [ overlay ]; - users.users."${user}" = mkIf (cfg.runAs == null) { name = user; isSystemUser = true; @@ -1765,43 +1765,49 @@ in description = "Docspell user"; group = user; }; - users.groups."${user}" = mkIf (cfg.runAs == null) { }; + users.groups."${user}" = mkIf (cfg.runAs == null) {}; + + environment.etc."docspell-joex.conf" = mkIf (cfg.configFile == null) { + text = '' + {"docspell": {"joex": + ${builtins.toJSON (lib.recursiveUpdate declared_config cfg.extraConfig)} + }} + ''; + user = user; + group = user; + mode = "0400"; + }; # Setting up a unoconv listener to improve conversion performance - systemd.services.unoconv = - let - cmd = "${pkgs.unoconv}/bin/unoconv --listener -v"; - in - { - description = "Unoconv Listener"; - after = [ "networking.target" ]; - wantedBy = [ "multi-user.target" ]; - serviceConfig = { - Restart = "always"; - }; - script = - "${pkgs.su}/bin/su -s ${pkgs.bash}/bin/sh ${user} -c \"${cmd}\""; + systemd.services.unoconv = let + cmd = "${pkgs.unoconv}/bin/unoconv --listener -v"; + in { + description = "Unoconv Listener"; + after = ["networking.target"]; + wantedBy = ["multi-user.target"]; + serviceConfig = { + Restart = "always"; }; + script = "${pkgs.su}/bin/su -s ${pkgs.bash}/bin/sh ${user} -c \"${cmd}\""; + }; - systemd.services.docspell-joex = - let - args = builtins.concatStringsSep " " cfg.jvmArgs; - cmd = "${pkgs.docspell-joex}/bin/docspell-joex ${args} -- ${configFile}"; - waitTarget = - if cfg.waitForTarget != null - then - [ cfg.waitForTarget ] - else - [ ]; - in - { - description = "Docspell Joex"; - after = ([ "networking.target" ] ++ waitTarget); - wantedBy = [ "multi-user.target" ]; - path = [ pkgs.gawk ]; + systemd.services.docspell-joex = let + args = builtins.concatStringsSep " " cfg.jvmArgs; + configFile = if cfg.configFile == null + then "/etc/docspell-joex.conf" + else "${cfg.configFile}"; + cmd = "${lib.getExe' cfg.package "docspell-joex"} ${args} -- ${configFile}"; + waitTarget = + if cfg.waitForTarget != null + then [cfg.waitForTarget] + else []; + in { + description = "Docspell Joex"; + after = ["networking.target"] ++ waitTarget; + wantedBy = ["multi-user.target"]; + path = [pkgs.gawk]; - script = - "${pkgs.su}/bin/su -s ${pkgs.bash}/bin/sh ${user} -c \"${cmd}\""; - }; + script = "${pkgs.su}/bin/su -s ${pkgs.bash}/bin/sh ${user} -c \"${cmd}\""; + }; }; } diff --git a/nix/modules/server.nix b/nix/modules/server.nix index 4a98c8dc..28f49e61 100644 --- a/nix/modules/server.nix +++ b/nix/modules/server.nix @@ -1,16 +1,17 @@ -overlay: { config, lib, pkgs, ... }: - -with lib; -let +{ + config, + lib, + pkgs, + ... +}: +with lib; let cfg = config.services.docspell-restserver; # Extract the config without the extraConfig attribute. It will be merged later declared_config = attrsets.filterAttrs (n: v: n != "extraConfig") cfg; - user = if cfg.runAs == null then "docspell" else cfg.runAs; - configFile = pkgs.writeText "docspell-server.conf" '' - {"docspell": {"server": - ${builtins.toJSON (lib.recursiveUpdate declared_config cfg.extraConfig)} - }} - ''; + user = + if cfg.runAs == null + then "docspell" + else cfg.runAs; defaults = { app-name = "Docspell"; app-id = "rest1"; @@ -44,7 +45,7 @@ let source-name = "integration"; allowed-ips = { enabled = false; - ips = [ "127.0.0.1" ]; + ips = ["127.0.0.1"]; }; http-basic = { enabled = false; @@ -78,14 +79,15 @@ let user = "pguser"; password = ""; }; - pg-config = { }; + pg-config = {}; pg-query-parser = "websearch_to_tsquery"; - pg-rank-normalization = [ 4 ]; + pg-rank-normalization = [4]; }; }; auth = { server-secret = "hex:caffee"; session-valid = "5 minutes"; + on-account-source-conflict = "fail"; remember-me = { enabled = true; valid = "30 days"; @@ -105,6 +107,7 @@ let scope = "profile"; authorize-url = null; token-url = null; + logout-url = ""; user-url = null; sign-key = ""; sig-algo = "RS256"; @@ -126,19 +129,17 @@ let }; files = { chunk-size = 524288; - valid-mime-types = [ ]; + valid-mime-types = []; }; addons = { enabled = false; allow-impure = true; - allowed-urls = [ "*" ]; - denied-urls = [ ]; + allowed-urls = ["*"]; + denied-urls = []; }; }; }; -in -{ - +in { ## interface options = { services.docspell-restserver = { @@ -146,6 +147,7 @@ in default = false; description = "Whether to enable docspell."; }; + package = mkPackageOption pkgs "docspell-restserver" {}; runAs = mkOption { type = types.nullOr types.str; default = null; @@ -156,11 +158,19 @@ in }; jvmArgs = mkOption { type = types.listOf types.str; - default = [ ]; - example = [ "-J-Xmx1G" ]; + default = []; + example = ["-J-Xmx1G"]; description = "The options passed to the executable for setting jvm arguments."; }; - + configFile = mkOption { + type = types.nullOr types.path; + default = null; + example = literalExpression ''"''${config.sops.secrets.docspell_restserver_config.path}"''; + description = '' + Path to an existing configuration file. + If null, a configuration file will be generated at /etc/docspell-restserver.conf + ''; + }; app-name = mkOption { type = types.str; @@ -232,7 +242,7 @@ in }; bind = mkOption { - type = types.submodule ({ + type = types.submodule { options = { address = mkOption { type = types.str; @@ -245,13 +255,13 @@ in description = "The port to bind the REST server"; }; }; - }); + }; default = defaults.bind; description = "Address and port bind the rest server."; }; server-options = mkOption { - type = types.submodule ({ + type = types.submodule { options = { enable-http-2 = mkOption { type = types.bool; @@ -269,13 +279,13 @@ in description = "Timeout when waiting for the response."; }; }; - }); + }; default = defaults.server-options; description = "Tuning the http server"; }; logging = mkOption { - type = types.submodule ({ + type = types.submodule { options = { minimum-level = mkOption { type = types.str; @@ -293,13 +303,13 @@ in description = "Set of logger and their levels"; }; }; - }); + }; default = defaults.logging; description = "Settings for logging"; }; auth = mkOption { - type = types.submodule ({ + type = types.submodule { options = { server-secret = mkOption { type = types.str; @@ -319,8 +329,21 @@ in will get a new one periodically. ''; }; + on-account-source-conflict = mkOption { + type = types.enum ["fail" "convert"]; + default = defaults.auth.on-account-source-conflict; + description = '' + Accounts can be local or defined at a remote provider and + integrated via OIDC. If the same account is defined in both + sources, docspell by default fails if a user mixes logins (e.g. + when registering a user locally and then logging in with the + same user via OIDC). When set to `convert` docspell treats it as + being the same and simply updates the account to reflect the new + account source. + ''; + }; remember-me = mkOption { - type = types.submodule ({ + type = types.submodule { options = { enabled = mkOption { type = types.bool; @@ -333,18 +356,18 @@ in description = "The time a remember-me token is valid."; }; }; - }); + }; default = defaults.auth.remember-me; description = "Settings for Remember-Me"; }; }; - }); + }; default = defaults.auth; description = "Authentication"; }; download-all = mkOption { - type = types.submodule ({ + type = types.submodule { options = { max-files = mkOption { type = types.int; @@ -357,7 +380,7 @@ in description = "The maximum (uncompressed) size of the zip file contents."; }; }; - }); + }; default = defaults.download-all; description = ""; }; @@ -387,7 +410,7 @@ in description = "How to retrieve the collective name."; }; provider = mkOption { - type = (types.submodule { + type = types.submodule { options = { provider-id = mkOption { type = types.str; @@ -420,6 +443,11 @@ in default = defaults.openid.provider.token-url; description = "The URL used to retrieve the token."; }; + logout-url = mkOption { + type = types.str; + default = defaults.openid.provider.logout-url; + description = "The URL used for user's logout."; + }; user-url = mkOption { type = types.nullOr types.str; default = defaults.openid.provider.user-url; @@ -436,18 +464,18 @@ in description = "The expected algorithm used to sign the token."; }; }; - }); + }; default = defaults.openid.provider; description = "The config for an OpenID Connect provider."; }; }; }); - default = [ ]; + default = []; description = "A list of OIDC provider configurations."; }; integration-endpoint = mkOption { - type = types.submodule ({ + type = types.submodule { options = { enabled = mkOption { type = types.bool; @@ -467,7 +495,7 @@ in ''; }; allowed-ips = mkOption { - type = types.submodule ({ + type = types.submodule { options = { enabled = mkOption { type = types.bool; @@ -480,7 +508,7 @@ in description = "The ips/ip patterns to allow"; }; }; - }); + }; default = defaults.integration-endpoint.allowed-ips; description = '' IPv4 addresses to allow access. An empty list, if enabled, @@ -491,7 +519,7 @@ in ''; }; http-basic = mkOption { - type = types.submodule ({ + type = types.submodule { options = { enabled = mkOption { type = types.bool; @@ -514,14 +542,14 @@ in description = "The password to check."; }; }; - }); + }; default = defaults.integration-endpoint.http-basic; description = '' Requests are expected to use http basic auth when uploading files. ''; }; http-header = mkOption { - type = types.submodule ({ + type = types.submodule { options = { enabled = mkOption { type = types.bool; @@ -539,7 +567,7 @@ in description = "The value of the header to check."; }; }; - }); + }; default = defaults.integration-endpoint.http-header; description = '' Requests are expected to supply some specific header when @@ -547,7 +575,7 @@ in ''; }; }; - }); + }; default = defaults.integration-endpoint; description = '' This endpoint allows to upload files to any collective. The @@ -566,7 +594,7 @@ in }; admin-endpoint = mkOption { - type = types.submodule ({ + type = types.submodule { options = { secret = mkOption { type = types.str; @@ -574,13 +602,13 @@ in description = "The secret used to call admin endpoints."; }; }; - }); + }; default = defaults.admin-endpoint; description = "An endpoint for administration tasks."; }; full-text-search = mkOption { - type = types.submodule ({ + type = types.submodule { options = { enabled = mkOption { type = types.bool; @@ -597,7 +625,7 @@ in description = "The backend to use, either solr or postgresql"; }; solr = mkOption { - type = types.submodule ({ + type = types.submodule { options = { url = mkOption { type = types.str; @@ -629,13 +657,13 @@ in description = "The default combiner for tokens. One of {AND, OR}."; }; }; - }); + }; default = defaults.full-text-search.solr; description = "Configuration for the SOLR backend."; }; postgresql = mkOption { - type = types.submodule ({ + type = types.submodule { options = { use-default-connection = mkOption { type = types.bool; @@ -643,7 +671,7 @@ in description = "Whether to use the primary db connection."; }; jdbc = mkOption { - type = types.submodule ({ + type = types.submodule { options = { url = mkOption { type = types.str; @@ -663,7 +691,7 @@ in description = "The password to connect to the database."; }; }; - }); + }; default = defaults.full-text-search.postgresql.jdbc; description = "Database connection settings"; }; @@ -683,18 +711,18 @@ in description = ""; }; }; - }); + }; default = defaults.full-text-search.postgresql; description = "PostgreSQL for fulltext search"; }; }; - }); + }; default = defaults.full-text-search; description = "Configuration for full-text search."; }; backend = mkOption { - type = types.submodule ({ + type = types.submodule { options = { mail-debug = mkOption { type = types.bool; @@ -707,7 +735,7 @@ in ''; }; jdbc = mkOption { - type = types.submodule ({ + type = types.submodule { options = { url = mkOption { type = types.str; @@ -734,12 +762,12 @@ in description = "The password to connect to the database."; }; }; - }); + }; default = defaults.backend.jdbc; description = "Database connection settings"; }; signup = mkOption { - type = types.submodule ({ + type = types.submodule { options = { mode = mkOption { type = types.str; @@ -772,12 +800,12 @@ in ''; }; }; - }); + }; default = defaults.backend.signup; description = "Registration settings"; }; files = mkOption { - type = types.submodule ({ + type = types.submodule { options = { chunk-size = mkOption { type = types.int; @@ -804,12 +832,12 @@ in ''; }; }; - }); + }; default = defaults.backend.files; description = "Settings for how files are stored."; }; addons = mkOption { - type = types.submodule ({ + type = types.submodule { options = { enabled = mkOption { type = types.bool; @@ -832,19 +860,19 @@ in description = "Url patterns to deny to install"; }; }; - }); + }; default = defaults.backend.addons; description = "Addon config"; }; }; - }); + }; default = defaults.backend; description = "Configuration for the backend"; }; extraConfig = mkOption { type = types.attrs; description = "Extra configuration for docspell server. Overwrites values in case of a conflict."; - default = { }; + default = {}; example = '' { files = { @@ -863,8 +891,6 @@ in ## implementation config = mkIf config.services.docspell-restserver.enable { - - nixpkgs.overlays = [ overlay ]; users.users."${user}" = mkIf (cfg.runAs == null) { name = user; isSystemUser = true; @@ -873,24 +899,34 @@ in description = "Docspell user"; group = user; }; - users.groups."${user}" = mkIf (cfg.runAs == null) { }; + users.groups."${user}" = mkIf (cfg.runAs == null) {}; + environment.etc."docspell-restserver.conf" = mkIf (cfg.configFile == null) { + text = '' + {"docspell": {"server": + ${builtins.toJSON (lib.recursiveUpdate declared_config cfg.extraConfig)} + }} + ''; + user = user; + group = user; + mode = "0400"; + }; - systemd.services.docspell-restserver = - let - args = builtins.concatStringsSep " " cfg.jvmArgs; - cmd = "${pkgs.docspell-server}/bin/docspell-restserver ${args} -- ${configFile}"; - in - { - description = "Docspell Rest Server"; - after = [ "networking.target" ]; - wantedBy = [ "multi-user.target" ]; - path = [ pkgs.gawk ]; - preStart = '' + systemd.services.docspell-restserver = let + args = builtins.concatStringsSep " " cfg.jvmArgs; + configFile = if cfg.configFile == null + then "/etc/docspell-restserver.conf" + else "${cfg.configFile}"; + cmd = "${lib.getExe' cfg.package "docspell-restserver"} ${args} -- ${configFile}"; + in { + description = "Docspell Rest Server"; + after = ["networking.target"]; + wantedBy = ["multi-user.target"]; + path = [pkgs.gawk]; + preStart = '' ''; - script = - "${pkgs.su}/bin/su -s ${pkgs.bash}/bin/sh ${user} -c \"${cmd}\""; - }; + script = "${pkgs.su}/bin/su -s ${pkgs.bash}/bin/sh ${user} -c \"${cmd}\""; + }; }; } diff --git a/nix/pkg.nix b/nix/pkg.nix new file mode 100644 index 00000000..a37db9c2 --- /dev/null +++ b/nix/pkg.nix @@ -0,0 +1,58 @@ +{ + stdenv, + bash, + fetchzip, + jdk17, +}: let + version = "0.41.0"; + server = { + url = "https://github.com/eikek/docspell/releases/download/v${version}/docspell-restserver-${version}.zip"; + sha256 = "sha256-JFftIzI94UNLLh96I++qFsBZhOkquPIPhNhtS2Ov8wI="; + }; + joex = { + url = "https://github.com/eikek/docspell/releases/download/v${version}/docspell-joex-${version}.zip"; + sha256 = "sha256-flKWjEsMd2/XT3Bu6EjFgf3lCojvLbKFDEXemP1K+/8="; + }; +in { + docspell-restserver = stdenv.mkDerivation { + inherit version; + pname = "docspell-restserver"; + + src = fetchzip server; + buildInputs = [jdk17]; + buildPhase = "true"; + + installPhase = '' + mkdir -p $out/{bin,docspell-restserver-${version}} + cp -R * $out/docspell-restserver-${version}/ + cat > $out/bin/docspell-restserver <<-EOF + #!${bash}/bin/bash + $out/docspell-restserver-${version}/bin/docspell-restserver -java-home ${jdk17} "\$@" + EOF + chmod 755 $out/bin/docspell-restserver + + ''; + }; + + docspell-joex = stdenv.mkDerivation rec { + inherit version; + + pname = "docspell-joex"; + + src = fetchzip joex; + + buildInputs = [jdk17]; + + buildPhase = "true"; + + installPhase = '' + mkdir -p $out/{bin,docspell-joex-${version}} + cp -R * $out/docspell-joex-${version}/ + cat > $out/bin/docspell-joex <<-EOF + #!${bash}/bin/bash + $out/docspell-joex-${version}/bin/docspell-joex -java-home ${jdk17} "\$@" + EOF + chmod 755 $out/bin/docspell-joex + ''; + }; +} diff --git a/nix/test-vm.nix b/nix/test-vm.nix new file mode 100644 index 00000000..96ddf039 --- /dev/null +++ b/nix/test-vm.nix @@ -0,0 +1,86 @@ +{ + config, + pkgs, + ... +}: let + full-text-search = { + enabled = true; + backend = "solr"; + solr.url = "http://localhost:8983/solr/docspell"; + }; + jdbc = { + url = "jdbc:postgresql://localhost:5432/docspell"; + user = "dev"; + password = "dev"; + }; +in { + services.dev-postgres = { + enable = true; + databases = ["docspell"]; + }; + services.dev-email.enable = true; + services.dev-solr = { + enable = true; + cores = ["docspell"]; + heap = 512; + }; + + port-forward.dev-webmail = 8080; + port-forward.dev-solr = 8983; + + environment.systemPackages = with pkgs; [ + jq + htop + iotop + coreutils + ]; + + networking = { + hostName = "docspell-test-vm"; + firewall.allowedTCPPorts = [7880]; + }; + + virtualisation.memorySize = 2048; + virtualisation.cores = 2; + + virtualisation.forwardPorts = [ + { + from = "host"; + host.port = 7881; + guest.port = 7880; + } + ]; + + services.docspell-restserver = { + enable = true; + bind.address = "0.0.0.0"; + backend = { + addons.enabled = true; + signup.mode = "open"; + inherit jdbc; + }; + integration-endpoint = { + enabled = true; + http-header = { + enabled = true; + header-value = "test123"; + }; + }; + admin-endpoint = { + secret = "admin123"; + }; + inherit full-text-search; + }; + + services.docspell-joex = { + enable = true; + bind.address = "0.0.0.0"; + inherit jdbc full-text-search; + addons = { + executor-config = { + runner = "nix-flake,trivial"; + nspawn.enabled = true; + }; + }; + }; +} diff --git a/project/Dependencies.scala b/project/Dependencies.scala index 06ddee2e..33b149be 100644 --- a/project/Dependencies.scala +++ b/project/Dependencies.scala @@ -8,49 +8,49 @@ object Dependencies { val BcryptVersion = "0.4" val BetterMonadicForVersion = "0.3.1" val BinnyVersion = "0.11.0" - val CalevVersion = "0.7.0" + val CalevVersion = "0.7.3" val CatsVersion = "2.10.0" - val CatsEffectVersion = "3.5.3" + val CatsEffectVersion = "3.5.4" val CatsParseVersion = "1.0.0" val CirceVersion = "0.15.0-M1" val CirceGenericExtrasVersion = "0.14.3" - val CirceYamlVersion = "0.15.1" + val CirceYamlVersion = "0.15.3" val ClipboardJsVersion = "2.0.11" val DoobieVersion = "1.0.0-RC5" val EmilVersion = "0.17.0" val FlexmarkVersion = "0.64.8" - val FlywayVersion = "10.8.1" - val Fs2Version = "3.9.4" + val FlywayVersion = "10.13.0" + val Fs2Version = "3.10.2" val H2Version = "2.2.224" - val Http4sVersion = "0.23.25" - val Icu4jVersion = "74.2" + val Http4sVersion = "0.23.27" + val Icu4jVersion = "75.1" val JavaOtpVersion = "0.4.0" - val JsoupVersion = "1.17.2" - val JwtScalaVersion = "10.0.0" + val JsoupVersion = "1.18.1" + val JwtScalaVersion = "10.0.1" val KindProjectorVersion = "0.10.3" - val KittensVersion = "3.2.0" + val KittensVersion = "3.3.0" val LevigoJbig2Version = "2.0" val Log4sVersion = "1.10.0" val LogbackVersion = "1.2.10" - val MariaDbVersion = "3.3.2" - val MUnitVersion = "0.7.29" - val MUnitCatsEffectVersion = "1.0.7" - val PdfboxVersion = "3.0.1" + val MariaDbVersion = "3.4.1" + val MUnitVersion = "1.0.0" + val MUnitCatsEffectVersion = "2.0.0" + val PdfboxVersion = "3.0.2" val PdfjsViewerVersion = "2.12.313" val PoiVersion = "4.1.2" - val PostgresVersion = "42.7.1" - val PureConfigVersion = "0.17.5" - val ScalaJavaTimeVersion = "2.5.0" - val ScodecBitsVersion = "1.1.38" - val ScribeVersion = "3.13.0" - val Slf4jVersion = "2.0.12" - val SourcecodeVersion = "0.3.1" - val StanfordNlpVersion = "4.5.6" - val TikaVersion = "2.9.1" + val PostgresVersion = "42.7.3" + val PureConfigVersion = "0.17.7" + val ScalaJavaTimeVersion = "2.6.0" + val ScodecBitsVersion = "1.2.0" + val ScribeVersion = "3.15.0" + val Slf4jVersion = "2.0.13" + val SourcecodeVersion = "0.4.2" + val StanfordNlpVersion = "4.5.7" + val TikaVersion = "2.9.2" val YamuscaVersion = "0.10.0" - val SwaggerUIVersion = "5.10.3" - val TestContainerVersion = "0.40.14" - val TwelveMonkeysVersion = "3.10.1" + val SwaggerUIVersion = "5.17.14" + val TestContainerVersion = "0.41.4" + val TwelveMonkeysVersion = "3.11.0" val JQueryVersion = "3.5.1" val scribe = Seq( @@ -219,7 +219,7 @@ object Dependencies { "org.apache.tika" % "tika-core" % TikaVersion ) val commonsIO = Seq( - "commons-io" % "commons-io" % "2.15.1" + "commons-io" % "commons-io" % "2.16.1" ) val tikaParser = Seq( "org.apache.tika" % "tika-parsers" % TikaVersion @@ -326,7 +326,7 @@ object Dependencies { val munit = Seq( "org.scalameta" %% "munit" % MUnitVersion, "org.scalameta" %% "munit-scalacheck" % MUnitVersion, - "org.typelevel" %% "munit-cats-effect-3" % MUnitCatsEffectVersion + "org.typelevel" %% "munit-cats-effect" % MUnitCatsEffectVersion ) val kindProjectorPlugin = "org.typelevel" %% "kind-projector" % KindProjectorVersion diff --git a/project/StylesPlugin.scala b/project/StylesPlugin.scala index f47b27fb..b04ab2e5 100644 --- a/project/StylesPlugin.scala +++ b/project/StylesPlugin.scala @@ -23,7 +23,7 @@ object StylesPlugin extends AutoPlugin { val stylesDirectory = settingKey[File]("The directory containing source styles") val stylesOutputDir = settingKey[File]("The directory to put the final outcome") val stylesMode = settingKey[StylesMode]("The compile mode, dev or production") - val stylesNpxCommand = settingKey[String]("The npx executable") + val stylesTwCommand = settingKey[String]("The tailwindcss executable") val stylesNpmCommand = settingKey[String]("The npm executable for installing dependencies") @@ -40,19 +40,19 @@ object StylesPlugin extends AutoPlugin { stylesDirectory := (Compile / sourceDirectory).value / "styles", stylesOutputDir := (Compile / resourceManaged).value / "META-INF" / "resources" / "webjars" / name.value / version.value, - stylesNpxCommand := "npx", + stylesTwCommand := "tailwindcss", stylesNpmCommand := "npm", stylesMode := StylesMode.Dev, stylesBuild := { val logger = streams.value.log - val npx = stylesNpxCommand.value + val tw = stylesTwCommand.value val npm = stylesNpmCommand.value val inDir = stylesDirectory.value val outDir = stylesOutputDir.value val wd = (Compile / baseDirectory).value val mode = stylesMode.value npmInstall(npm, wd, logger) - val files = postCss(npx, inDir, outDir, wd, mode, logger) ++ + val files = runTailwind(tw, inDir, outDir, wd, mode, logger) ++ copyWebfonts(wd, outDir, logger) ++ copyFlags(wd, outDir, logger) logger.info(s"Styles built at $outDir") @@ -77,8 +77,8 @@ object StylesPlugin extends AutoPlugin { } } - def postCss( - npx: String, + def runTailwind( + tailwind: String, inDir: File, outDir: File, wd: File, @@ -86,25 +86,20 @@ object StylesPlugin extends AutoPlugin { logger: Logger ): Seq[File] = { val env = mode match { - case StylesMode.Dev => "development" - case StylesMode.Prod => "production" + case StylesMode.Dev => Seq.empty + case StylesMode.Prod => Seq("--minify") } val target = outDir / "css" / "styles.css" IO.createDirectory(target.getParentFile) logger.info("Compiling css stylesheets…") - Cmd.run( - Seq( - npx, - "postcss", - s"$inDir/index.css", - "-o", - target.absolutePath, - "--env", - env - ), - wd, - logger - ) + val cmd = Seq( + tailwind, + "--input", + s"$inDir/index.css", + "-o", + target.absolutePath + ) ++ env + Cmd.run(cmd, wd, logger) val gz = file(target.toString + ".gz") IO.gzip(target, gz) Seq(target, gz) @@ -121,7 +116,7 @@ object StylesPlugin extends AutoPlugin { def copyFlags(baseDir: File, outDir: File, logger: Logger): Seq[File] = { val flagDir = - baseDir / "node_modules" / "flag-icon-css" / "flags" + baseDir / "node_modules" / "flag-icons" / "flags" val targetDir = outDir / "flags" IO.createDirectory(targetDir) diff --git a/project/build.nix b/project/build.nix deleted file mode 100644 index 0693a950..00000000 --- a/project/build.nix +++ /dev/null @@ -1,23 +0,0 @@ -let - nixpkgs = builtins.fetchTarball { - #url = "https://github.com/NixOS/nixpkgs/archive/92e990a8d6bc35f1089c76dd8ba68b78da90da59.tar.gz"; - url = "channel:nixos-23.05"; - }; - pkgs = import nixpkgs { }; - initScript = pkgs.writeScript "docspell-build-init" '' - export LD_LIBRARY_PATH= - ${pkgs.bash}/bin/bash -c "sbt -mem 4096 -java-home ${pkgs.openjdk17}/lib/openjdk" - ''; -in with pkgs; - -buildFHSUserEnv { - name = "docspell-sbt"; - targetPkgs = pkgs: with pkgs; [ - netcat jdk17 wget which dpkg sbt git elmPackages.elm ncurses fakeroot mc - zola yarn - - # haskells http client needs this (to download elm packages) - iana-etc - ]; - runScript = initScript; -} diff --git a/project/build.properties b/project/build.properties index abbbce5d..ee4c672c 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=1.9.8 +sbt.version=1.10.1 diff --git a/project/build.sbt b/project/build.sbt index 6bb9a065..4f90b20e 100644 --- a/project/build.sbt +++ b/project/build.sbt @@ -1,2 +1,7 @@ -libraryDependencies ++= - Seq("com.typesafe" % "config" % "1.4.3") +libraryDependencies ++= Seq( + "com.typesafe" % "config" % "1.4.3", + // sbt-native-packager and sbt-github-pages pull in an incompatible + // version of sbt-io which will break the build as soon as the + // sbt-bloop plugin is also present + "org.scala-sbt" %% "io" % sbtVersion.value +) diff --git a/project/dev-ui-build.sh b/project/dev-ui-build.sh index 0fa46b5f..a6d291fc 100755 --- a/project/dev-ui-build.sh +++ b/project/dev-ui-build.sh @@ -23,7 +23,7 @@ compile_css() { echo "Building css …" local srcs="$wdir/modules/webapp/src/main/styles/index.css" local target="$targetbase/css/styles.css" - cd $wdir/modules/webapp && npx tailwindcss --input "$srcs" -o "$target" --config ./tailwind.config.js --postcss ./postcss.config.js --env development && cd - + cd $wdir/modules/webapp && tailwindcss --input "$srcs" -o "$target" --config ./tailwind.config.js --postcss ./postcss.config.js --env development && cd - cat "$target" | gzip > "$targetbase/css/styles.css.gz" cp "$targetbase/css/styles.css" "$resourcebase/css/" cp "$targetbase/css/styles.css.gz" "$resourcebase/css/" @@ -47,7 +47,7 @@ watch_css() { local srcs="$wdir/modules/webapp/src/main/styles/index.css" local target="$targetbase/css/styles.css" cd $wdir/modules/webapp && \ - npx tailwindcss --input "$srcs" \ + tailwindcss --input "$srcs" \ -o "$target" -m \ --config ./tailwind.config.js \ --postcss ./postcss.config.js --watch diff --git a/project/plugins.sbt b/project/plugins.sbt index c0842f3c..24b11948 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -1,14 +1,14 @@ -addSbtPlugin("ch.epfl.scala" % "sbt-scalafix" % "0.11.1") -addSbtPlugin("com.eed3si9n" % "sbt-buildinfo" % "0.11.0") -addSbtPlugin("com.github.eikek" % "sbt-openapi-schema" % "0.11.0") +addSbtPlugin("ch.epfl.scala" % "sbt-scalafix" % "0.12.1") +addSbtPlugin("com.eed3si9n" % "sbt-buildinfo" % "0.12.0") +addSbtPlugin("com.github.eikek" % "sbt-openapi-schema" % "0.13.1") addSbtPlugin("com.github.sbt" % "sbt-pgp" % "2.2.1") addSbtPlugin("com.github.sbt" % "sbt-release" % "1.4.0") addSbtPlugin("com.github.sbt" % "sbt-git" % "2.0.1") -addSbtPlugin("com.github.sbt" % "sbt-native-packager" % "1.9.16") +addSbtPlugin("com.github.sbt" % "sbt-native-packager" % "1.10.0") addSbtPlugin("de.heikoseeberger" % "sbt-header" % "5.10.0") -addSbtPlugin("io.kevinlee" % "sbt-github-pages" % "0.13.0") +addSbtPlugin("io.kevinlee" % "sbt-github-pages" % "0.14.0") addSbtPlugin("io.spray" % "sbt-revolver" % "0.10.0") addSbtPlugin("org.portable-scala" % "sbt-scalajs-crossproject" % "1.3.2") -addSbtPlugin("org.scala-js" % "sbt-scalajs" % "1.15.0") +addSbtPlugin("org.scala-js" % "sbt-scalajs" % "1.16.0") addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.5.2") -addSbtPlugin("org.xerial.sbt" % "sbt-sonatype" % "3.10.0") +addSbtPlugin("org.xerial.sbt" % "sbt-sonatype" % "3.11.0") diff --git a/project/redocly.yml b/project/redocly.yml new file mode 100644 index 00000000..c2373f57 --- /dev/null +++ b/project/redocly.yml @@ -0,0 +1,2 @@ +extends: + - recommended diff --git a/website/README.md b/website/README.md index 66c63ed6..a3d2df97 100644 --- a/website/README.md +++ b/website/README.md @@ -15,19 +15,20 @@ Sbt is used to build the site. Install things by running `yarn install`. -Open terminal for each script below: +Use a dev [environment](https://docspell.org/docs/dev/development/) +and open terminal for each script below: 1. Starting the server ``` shell - nix-shell --run "cd site && zola serve" + cd site && zola serve ``` 2. Building the stylesheet ``` shell - nix-shell --run ./scripts/run-styles.sh + ./scripts/run-styles.sh ``` 3. Building some javascript files ``` shell - nix-shell --run ./scripts/run-elm.sh + ./scripts/run-elm.sh ``` Open browser at `localhost:1111`. @@ -40,7 +41,7 @@ be finally deployed. To see this, start sbt and change into the website project. ``` shell -nix-shell website/shell.nix --run sbt +$ sbt sbt> project website ``` diff --git a/website/package.json b/website/package.json index 270947b0..e1a6368d 100644 --- a/website/package.json +++ b/website/package.json @@ -7,7 +7,7 @@ "@fortawesome/fontawesome-free": "^6.0.0", "@tailwindcss/forms": "^0.5.0", "autoprefixer": "^10.4", - "cssnano": "^6.0.0", + "cssnano": "^7.0.0", "postcss": "^8.4.5", "postcss-cli": "^11.0.0", "postcss-import": "^16.0.0", diff --git a/website/push-docs.sh b/website/push-docs.sh index bc017433..d2c090a6 100755 --- a/website/push-docs.sh +++ b/website/push-docs.sh @@ -37,7 +37,7 @@ git clone git@github.com:eikek/docspell.git "$temp" cd "$temp" && git checkout --track origin/gh-pages && rm -rf "$temp"/* echo "Create new website from current working directory" -cd $cdir && nix-shell website/shell.nix --run 'sbt make-website' +cd $cdir && sbt make-website echo "Copying new site to target" cp -R "$cdir"/website/target/zola-site/* "$temp/" diff --git a/website/shell.nix b/website/shell.nix deleted file mode 100644 index 8c531cfc..00000000 --- a/website/shell.nix +++ /dev/null @@ -1,20 +0,0 @@ -let - nixpkgs = builtins.fetchTarball { - url = "channel:nixos-23.05"; - #url = "https://github.com/NixOS/nixpkgs/archive/e6badb26fc0d238fda2432c45b7dd4e782eb8200.tar.gz"; - #url = "https://github.com/NixOs/nixpkgs/archive/0f316e4d72daed659233817ffe52bf08e081b5de.tar.gz"; #21.11 - }; - pkgs = import nixpkgs { }; -in -with pkgs; - - mkShell { - buildInputs = [ - zola - yarn - sbt - elmPackages.elm - nodejs - inotifyTools - ]; - } diff --git a/website/site/config.toml b/website/site/config.toml index bd8f66c1..3c513b60 100644 --- a/website/site/config.toml +++ b/website/site/config.toml @@ -20,11 +20,14 @@ highlight_themes_css = [ ] [link_checker] +external_level = "warn" skip_prefixes = [ "http://localhost", "https://docs.github.com", # doesn't allow checking anymore "/openapi", - "https://www.abisource.com" # has bad ssl config + "https://www.abisource.com", # has bad ssl config + "https://chromewebstore.google.com", # too many redirects reported + "https://stackoverflow.com/" # forbidden ] skip_anchor_prefixes = [ "https://github.com", diff --git a/website/site/content/blog/2022-01-31_create_post.md b/website/site/content/blog/2022-01-31_create_post.md index 69bd8ab2..e330694c 100644 --- a/website/site/content/blog/2022-01-31_create_post.md +++ b/website/site/content/blog/2022-01-31_create_post.md @@ -63,11 +63,11 @@ you can look at the results while writing. If you want to see a live view of the page while editing, some tools are required. The easiest way to get these is to install -[nix](https://nixos.org/) and run `nix-shell website/shell.nix` to get -an environment with all these tools installed. Otherwise install the -programs mentioned in `website/shell.nix`, which are: -[yarn](https://yarnpkg.com/), [zola](https://www.getzola.org/), -[elm](https://elm-lang.org) and [sbt](https://scala-sbt.org). +[nix](https://nixos.org/) and run `nix develop .#dev-vm` to get an +environment with all these tools installed. Otherwise install the +programs: [yarn](https://yarnpkg.com/), +[zola](https://www.getzola.org/), [elm](https://elm-lang.org) and +[sbt](https://scala-sbt.org). Then clone the sources to your machine and build the complete site once, so that all assets and required stuff is present: diff --git a/website/site/content/docs/configure/custom-mapping.md b/website/site/content/docs/configure/custom-mapping.md new file mode 100644 index 00000000..69289533 --- /dev/null +++ b/website/site/content/docs/configure/custom-mapping.md @@ -0,0 +1,117 @@ ++++ +title = "Custom Mappings & CJK" +insert_anchor_links = "right" +description = "Describes Custom Configuration Options in Joex and Followup for CJK and Vertical Languages" +weight = 12 +template = "docs.html" ++++ + +## Vertical Languages + +Many of the underlying tools that Docspell uses to recognize, read, and extract text from documents have mixed support for vertical languages and other specific situations, making a default implementation difficult for language specific use cases. + +As a result, Docspell has implemented custom argument mappings for individual languages so Tessearct, OCRmyPDF, or any program can process documents with specific arguments for a given language. One of the biggests use cases for these custom mappings are vertical and CJK (Chinese, Japanese, Korean) languages. + +### Custom Mappings Example (Default) + +For example, lets say you need to read a PDF in Japanese but you're unsure of what a specific kanji may be. If you insert this pdf into Docspell on Tesseract and OCRmyPDF defaults, or try to use these programs on their own, you may be greeted by encoding error outputs, resulting in something like the following: + +```bash +ス¿ンÀーùßÝ�Ï項~t®ÿÝ�Ï®þĀ +イン¿ーネッø募Ö} +``` + +Even if you don't speak Japanese, you have probably realized that this is not very helpful for you! + +To solve this problem, we need to make use of custom argument mappings. In the default docspell Joex file, there are two existing custom mappings for Japanese (`jpn`) and Vertical Japanese (`jpn_vert`). Let's take a look at the default OCRmyPDF mapping below: + +```bash + ocrmypdf = { + enabled = true + command = { + program = "ocrmypdf" + # Custom argument mappings for this program. + arg-mappings = { + "ocr_lang" = { + value = "{{lang}}" + # Custom Language Mappings Below + # Japanese Vertical Mapping + mappings = [ + { + matches = "jpn_vert" + args = [ "-l", "jpn_vert", "--pdf-renderer", "sandwich", "--tesseract-pagesegmode", "5", "--output-type", "pdf" ] + }, + # Japanese Mapping for OCR Optimization + { + matches = "jpn" + args = [ "-l", "jpn", "--output-type", "pdf" ] + }, + # Start Other Custom Language Mappings Here + # Default Mapping Below + { + matches = ".*" + args = [ "-l", "{{lang}}" ] + } + ] + } + } + +``` + +OCRmyPDF is used anytime you upload a PDF document. Here we see (2) custom mappings. The mapping for `jpn_vert` includes options such as `--tesseract-pageesgmode=5`. Page segmentation mode 5 helps with reading vertical text and sets the expected page layout. The mapping for `jpn` and `jpn_vert` both have `--output-type` set to accept PDF rather than the default PDF/A. This is to help read files that may have special encoding schemes and reduce them to PDF so that they can be read with more compatibility. + +The result winds up that our above document winds up outputting the following: + +```bash +契約概要のご説明・注意喚起情報のご説明 +``` + +And now you can easily look up these words or use 3rd party translation tools to get the meaning. + +This is only one such example of the power of custom mappings, and advanced users of Tesseract, OCRmyPDF, or other tools will enjoy customizing Docspell with the defaults best for their use case. + +### Converting Vertical Text to Horizontal + +Currently, Vertical Japanese (JpnVert) supports converting vertical text from images directly to horizontal metadata. However, if you use a PDF or other format, OCRmyPDF will read the text as newlines, so you may wind up with an output from a vertical scan that has metadata like the following: + +```bash +や +さ +し +い +``` + +Obviously we want that written out nicely `やさしい`, but the file could be much longer. There are multiple ways to accomplish this, but the easiest way on small scale is to run the extracted metadata through a script. + +Here's a simple bash script to very roughly convert vertical text to horizontal text, and adds in a new line if the line is empty to get you most of the way there. Take the text extracted from docspell, copy and paste it into something like `vertical.txt` and then run the following; + +```bash +#!/bin/bash + +while IFS= read -r line; do + if [ -z "$line" ]; then + echo + else + echo -n "$line" + fi +done < "$1" >> horizontal_output.txt +``` + +Run chmod +x `text_converter.sh` on this script to make it executable. + +Then put both files in the same directory and run `./text_converter.sh vertical.txt` and it will output `horizontal_output.txt` for you so you can work with horizontal text. + +### Converting Vertical Text to Horizontal (Using OCRmyPDF) + +If you want to try and force `ocrmypdf` to do this directly, just run (you can replace `jpn_vert` with any vertical language in theory): + +`ocrmypdf --force-ocr -l jpn_vert --sidecar horizontal_ocr_output.txt input.pdf output.converted.pdf --tesseract-pagesegmode 5 --tesseract-config cfg.file --pdf-renderer sandwich` + +With the `cfg.file` content in the directory you run `ocrmypdf` being: +``` +preserve_interword_spaces 1 +``` + +Your horizontal data will then be in `horizontal_ocr_output.txt` or whatever you named it above. + +That should help anyone where ocrmypdf skips text in the docspell defaults if they desperately need the metadata out of a vertical file. Docspell may be able to directly support this `--sidecar` output in the future with additional open source contributions. diff --git a/website/site/content/docs/dev/add-language.md b/website/site/content/docs/dev/add-language.md index 479111bc..f3fdb325 100644 --- a/website/site/content/docs/dev/add-language.md +++ b/website/site/content/docs/dev/add-language.md @@ -11,7 +11,7 @@ Then there are other commits and issues to look at: - [Add Polish](https://github.com/eikek/docspell/issues/1345) and [PR](https://github.com/eikek/docspell/pull/1559/commits/5ec311c331f1f78cc483cce54d5ab0e08454fea8) - [Add Spanish language](https://github.com/eikek/docspell/commit/26dff18ae0d32ce2b32b4d11ce381ada0e99314f) - [Add Latvian language](https://github.com/eikek/docspell/issues/679) and [PR](https://github.com/eikek/docspell/pull/694/commits/9991ad5fcc43ccefe011a6cc4d01bdae4bcd4573) -- [Add Japanese language](https://github.com/eikek/docspell/issues/948) and [PR](https://github.com/eikek/docspell/pull/961/commits/f994d4b2488e64668ee064676f8c6469d9ccc1be), had some corrections: [1](https://github.com/eikek/docspell/commit/c59d4f8a6d021ec4b01a92320c211248503f16a5), [Issue](https://github.com/eikek/docspell/issues/973) +- [Add Japanese language](https://github.com/eikek/docspell/issues/948) and [PR](https://github.com/eikek/docspell/pull/961/commits/f994d4b2488e64668ee064676f8c6469d9ccc1be), had some corrections: [1](https://github.com/eikek/docspell/commit/c59d4f8a6d021ec4b01a92320c211248503f16a5), [Issue](https://github.com/eikek/docspell/issues/973), [2](https://github.com/eikek/docspell/pull/2505), [Issue](https://github.com/eikek/docspell/issues/2445) - [Add Hebrew language](https://github.com/eikek/docspell/pull/1027) Some older commits may be a bit out of date, but still show the diff --git a/website/site/content/docs/dev/development.md b/website/site/content/docs/dev/development.md index 3cc95543..5316603b 100644 --- a/website/site/content/docs/dev/development.md +++ b/website/site/content/docs/dev/development.md @@ -65,6 +65,159 @@ docspell.joex { } ``` +## Installing Nix + +It is recommended to install [nix](https://nixos.org/nix). You can use +the official installer or [this +one](https://github.com/DeterminateSystems/nix-installer), which will +enable Flakes by default. + +If not enabled, enable flakes by creating a config file: + +``` +mkdir -p ~/.config/nix #on Linux +echo "experimental-features = nix-command flakes" >> ~/.config/nix/nix.conf +``` + +With nix installed you can use the provided development environments +to get started quickly. + +# Nix Expressions + +The soure root contains a `flake.nix` file to install docspell via the +nix package manager and to integrate it into NixOS. + +The flake provides docspell packages of the latest release and NixOS +modules. It doesn't provide package builds from the current source +tree. + +## Dev Environments + +Additionally it provides devshells that can be used to create a +development environment for docspell. + +These two `devShell` definitions address two different setups: one +uses a NixOS container and the other a VM. Both provide the same set +of services that can be used with the local docspell instance: + +- postgresql database, with a database `docspell` and user `dev` +- solr with a core `docspell` +- email setup with smtp/imap and webmail +- minio with root user `minioadmin` + +If you are on NixOS the container is probably more convenient to use. +For other systems, the vm should be good. Drop into either shell by +running: + +``` bash +# drop into the environment setup for using a vm +nix develop .#dev-vm + +# drop into the environment setup for using a container +nix develop .#docsp-dev +``` + +Once in such an environment, you can create the container or vm like +this: + +```bash +# dev-vm env +# - build the vm +vm-build + +# -run the vm +vm-run + +# - ssh into the vm +vm-ssh + +# docsp-dev container env +# - create the container +cnt-recreate + +# - login +cnt-login +``` + +You can use tab completion on `vm-` or `cnt-` and see other useful +commands. For instance it allows to recreate solr cores or check logs +of services on the container or vm. + +Then you can adjust your dev config file in `local/dev.conf` to +connect to the services on the vm or container. The container exposes +the default ports while the vm uses port-forwarding from the host to +the guest machine. The ports are define in `flake.nix`. For example, a +jdbc connection to postgres on the container can look like this: + +``` +jdbc.url = "jdbc:postgresql://docsp-dev:5432/docspelldev" +``` + +on the vm, it would be +``` +jdbc.url = "jdbc:postgresql://localhost:6543/docspelldev" +``` + +You can reach the webmail on both versions at port `8080`. In order to +enable sending mails between users, you need to login as some +arbitrary user so the underlying services can create the data +directories. In your dev docspell you can then connect to smtp on the +vm or container. Mails send from docspell can be checked in the +webmail. Conversely, you can send mails using webmail to any user and +have their mailbox scanned by docspell. + +### Direnv + +Using [direnv](https://direnv.net) entering the dev environment is +very convenient. Install this tool (it also has integration in several +IDEs and editors) and create a file `.envrc` in the source root: + +``` +use flake .# +``` + +The file `.envrc` is git-ignored, because different ones are possible. +Here `` refers to either `dev-cnt` or `dev-vm` - one of the +devshells defined in `flake.nix`. + +After allowing direnv to execute this file via `direnv allow` you will +be dropped into this environment whenever you enter the directory. It +will also preserve your shell, don't need to use bash. + +## Checks + +The command `nix flake check` would run all checks defined in the +flake. It will build both packages and runs a vm with docspell +installed (via NixOS modules) and check whether the services come up. + +## Test VM + +There is another VM defined in the flake that provides a full setup +for docspell. It contains docspell server and joex, a postgresql, a +solr and a email setup. The intention is to use it as an easy 'getting +started' approach with nix. + +Once it has started, you can connect to `localhost:7881` to reach +docspell. The webmail will be available at `localhost:8080`. + +You can run this vm with a single command: + +``` +nix run github:eikek/docspell#nixosConfigurations.test-vm.config.system.build.vm +``` + +It uses the same setup as the dev-vm, so you can drop into the +`.#dev-vm` development shell and use `vm-ssh` to connect to the +running test vm. + +Once connected to the machine, you can see the docspell config file via + +```bash +systemctl show docspell-joex.service | grep "ExecStart=" | sed 's/^ExecStart=.*path=\([^;]*\).*/\1/' | xargs tac | grep -m 1 . | awk '{print $NF}' | tr -d '"' | xargs jq '.' +# or replace "joex" with "restserver" +systemctl show docspell-restserver.service | grep "ExecStart=" | sed 's/^ExecStart=.*path=\([^;]*\).*/\1/' | xargs tac | grep -m 1 . | awk '{print $NF}' | tr -d '"' | xargs jq '.' +``` + # Developing Frontend The frontend is a SPA written in [Elm](https://elm-lang.org). The UI @@ -124,39 +277,6 @@ These tasks must not show any errors (it is checked by the CI). The warnings should also be fixed. -# Nix Expressions - -The directory `/nix` contains Nix Flake to install docspell via -the nix package manager and to integrate it into NixOS. - -Flake implements `checks` output which can be run with `nix flake check` -and it defines a development VM which can be used to interactively work -with docspell. - -To run the VM, issue: - -```bash -cd $PROJECT_ROOT/nix -nix run '.#nixosConfigurations.dev-vm.config.system.build.vm -``` - -To open docspell, wait for docspell-restserver service to report that -http listener is up and connect to `localhost:64080`. - -To ssh into the machine, run: - -```bash -ssh -o StrictHostKeyChecking=no \ - -o UserKnownHostsFile=/dev/null \ - -p 64022 root@localhost -``` - -Once connected to the machine, you can see the docspell config file via - -```bash -systemd-show docspell-joex.service | grep ExecStart | cut -d'=' -f2 | xargs cat | tail -n1 | awk '{print $NF}'| sed 's/.$//' | xargs cat | jq -``` - # Release The CI and making a release is done via github actions. The workflow diff --git a/website/site/content/docs/dev/documentation.md b/website/site/content/docs/dev/documentation.md new file mode 100644 index 00000000..9fd2e554 --- /dev/null +++ b/website/site/content/docs/dev/documentation.md @@ -0,0 +1,59 @@ ++++ +title = "Documentation" +weight = 0 ++++ + +# Documentation + +## About + +Docspell's documentation primarily lives on this website, but +there is also valuable information contained with in the main +[README.md](https://github.com/eikek/docspell/blob/master/README.md) +and [various other +READMEs](https://github.com/search?q=repo%3Aeikek%2Fdocspell+path%3A.md+NOT+path%3A%2F%5Ewebsite%5C%2Fsite%5C%2F%2F&type=code) +in the repository. + +## Contributing + +First, please take a look at the ["Documentation" portion of the +README](https://github.com/eikek/docspell/blob/master/Contributing.md#Documentation). + +Please note that the documentation hosted at https://docspell.org/ is for +the current version of Docspell and will not reflect any unreleased changes +to the code or documentation. Given that, before proposing a documentation +improvement, please check the latest version of the documentation (on the +`master` branch) to avoid potentially duplicating effort. + +### Simple Changes + +If you would like to contribute to this documentation website, simple edits +to existing pages can be made by clicking the "Edit" button at the bottom +of the live website page you wish to propose changes to. Doing so will take +you to GitHub where you can make your changes, commit them to a branch on +your fork of the repository, and ultimately create a pull request to get +them reviewed and merged into the official documentation. + +Similarly, READMEs in the `docspell` repository can be made by opening +the file on GitHub and clicking the "Edit" icon. New files can be added as +well. The process is then the same as above. + +Of course, if you would like to make your changes locally or make more complex +changes, you can fork the repository, clone your fork, make your changes, +push them to the fork, and then open a pull request. + +### Local Preview + +If you would like to also preview your local changes, you can do so as follows. + +The subsequent commands assume you have already locally cloned the repository +(or a fork), and have a working development environment. + +```bash +# in repository root +sbt website/zolaBuild +cd website/site && zola serve +``` + +As you write changes to the website content (to disk), Zola will live-reload +the site. diff --git a/website/site/content/docs/install/download_run.md b/website/site/content/docs/install/download_run.md index aecfe49b..9ce95d30 100644 --- a/website/site/content/docs/install/download_run.md +++ b/website/site/content/docs/install/download_run.md @@ -102,16 +102,71 @@ your package manager or download and unpack the new zip files. You might want to have a look at the changelog, since it is sometimes necessary to modify the config file. -## More +## Backup & Restore + +There are several supported [databases](https://docspell.org/docs/configure/database/) but PostgreSQL is recommended for Docspell. + +First to prevent any currently queued data from being lost, it's good practice to +shutdown `docspell-joex` and `docspell-restserver` system services +before taking a database backup of Docspell. In order to stop Docspell, +you need to perform these on the system that docspell is running on. +```bash +sudo systemctl stop docspell-joex +sudo systemctl stop docspell-restserver +``` + +Next, you can become the `postgres` user or database admin user on +your PostgreSQL server/microservice and backup the database. +Note that this will take some time to complete depending on the size of your database. +We'll assume in our guide example that `docspelldb` is the name of your database: +```bash +pg_dump docspelldb > docspelldb_backup.sql +``` + +Optionally, once the docspell backup is complete you can +use `rsync` or `scp` to send `docspelldb_backup.sql` to a backup server. +Now that you have known backup(s) of Docspell's database, you may one day have to restore this backup. + +Let's test try restoring it. You can start a PostgreSQL shell by using +the `psql` command as the `postgres` user or a PostgreSQL admin account. +If the database is corrupted or still exists, you will first need to remove it. +Warning: By performing this next step you are **deleting** your database. +```sql +DROP DATABASE docspelldb; +``` + +And now we'll create a new database for your backup to restore to. +Optionally, you can add UTF-8 encoding for better multilingual support. +This example will assume the owner of the database is named `docspell`. +```sql +CREATE DATABASE docspelldb WITH OWNER = 'docspell' ENCODING = 'UTF8' template = 'template0'; +``` + +Now that we have a new database, we can restore the backup. +Exit your database with `\q` and in bash execute the following +commands as the `postgres` or admin user. +This command will also take some time to complete. +```bash +psql docspelldb < docspelldb_backup.sql +``` + +Now your database should be fully restored from your backup! +Let's go to the Docspell server and restart the Docspell services. +```bash +sudo systemctl start docspell-joex +sudo systemctl start docspell-restserver +``` + +If your database and owner are the same as your initial configuration, +and you see your docspell data restored, you have sucessfully restored +your PostgreSQL backup of Docspell manually. ### Fulltext Search -Fulltext search is powered by [SOLR](https://solr.apache.org). You -need to install solr and create a core for docspell. Then cange the +Fulltext search can also be powered by [SOLR](https://solr.apache.org). +You need to install solr and create a core for docspell. Then cange the solr url for both components (restserver and joex) accordingly. See -the relevant section in the [config -page](@/docs/configure/fulltext-search.md). - +the relevant section in the [config page](@/docs/configure/fulltext-search.md). ### Watching a directory diff --git a/website/site/content/docs/install/nix.md b/website/site/content/docs/install/nix.md index 343b4e0c..be705a14 100644 --- a/website/site/content/docs/install/nix.md +++ b/website/site/content/docs/install/nix.md @@ -5,12 +5,50 @@ weight = 24 # Nix +Docspell is a flake, you need to enable flakes in order to make use of +it. You can also use the provided expressions without Flakes, which is +described below. + +## Try it out {try-it-out} + +You can try out the server and joex packages by running the following: + +``` +nix run github:eikek/docspell#docspell-restserver +nix run github:eikek/docspell#docspell-joex +``` + +While this works, it will be only a very basic setup. The database +defaults to a directory in `/tmp` and no fulltext search enabled. Then +for processing documents, some external tools are required which would +need to be present on yout system to make it work. + +A more elaborate setup with PostgreSQL and SOLR can be started using +the `test-vm`: + +``` +nix run github:eikek/docspell#nixosConfigurations.test-vm.config.system.build.vm +``` + +The vm contains all the required tools. After starting up, you can +find docspell at `http://localhost:7881`. + ## Install via Nix Docspell can be installed via the [nix](https://nixos.org/nix) package -manager, which is available for Linux and OSX. Docspell is currently not -part of the [nixpkgs collection](https://nixos.org/nixpkgs/), but you -can use the flake from this repository. +manager. Docspell is currently not part of the [nixpkgs +collection](https://nixos.org/nixpkgs/), but you can use the flake +from this repository. + +You could install the server and joex by running the following: +``` +nix profile install github:eikek/docspell#docspell-restserver +nix profile install github:eikek/docspell#docspell-joex +``` + +This would install the packages on your system. If you use NixOS you +probably want to use the provided [NixOS modules](#nixos) instead. + ## Upgrading @@ -31,7 +69,7 @@ There are the following modules provided: ```nix # flake.nix -inputs.docspell.url = "github:eikek/docspell?dir=nix/"; +inputs.docspell.url = "github:eikek/docspell"; # in modules imports = [ @@ -134,10 +172,37 @@ inputs.docspell.url = "github:eikek/docspell?dir=nix/"; ''; }; - networking = { hostName = "docspellexample"; firewall.allowedTCPPorts = [7880]; }; } ``` + +You can also look at `nix/test-vm.nix` for another example. + +## Without Flakes + +Of course, you can also use it without flakes. There is `nix/pkg.nix` +which contains the derivation of both packages, `docspell-restserver` and +`docspell-joex`. Just call it with your nixpkgs instance as usual: + +``` nix +let + repo = fetchurl { + url = "https://github.com/eikek/docspell"; + sha256 = "sha256-X2mM+Z5s8Xm1E6zrZ0wcRaivLEvqbk5Dn+GSXkZHdLM="; + }; + docspellPkgs = pkgs.callPackage (import "${repo}/nix/pkg.nix") {}; +in + # + # use docspellPkgs.docspell-restserver or docspellPkgs.docspell-joex + # +``` + +The same way import NixOS modules from +`nix/modules/{joex|server}.nix`. + +An alternative can be to use `builtins.getFlake` to fetch the flake +and get access to its output. But this requires to use a flake enabled +nix, which then defeats the idea of "not using flakes". diff --git a/website/site/content/docs/install/prereq.md b/website/site/content/docs/install/prereq.md index 00d648cd..6111b180 100644 --- a/website/site/content/docs/install/prereq.md +++ b/website/site/content/docs/install/prereq.md @@ -105,7 +105,7 @@ contains all data (including binary files by default) and is the central component of docspell. Docspell has support these databases: - PostreSQL -- MariaDB +- MariaDB (>= 10.6) - H2 The H2 database is an interesting option for personal and mid-size @@ -120,6 +120,6 @@ add the options of the url. See the [config page](@/docs/configure/database.md) for an example. -For large installations, PostgreSQL or MariaDB is recommended. Create -a database and a user with enough privileges (read, write, create -table) to that database. +For larger installations, PostgreSQL is recommended. Create a database +and a user with enough privileges (read, write, create table) to that +database. diff --git a/website/site/content/docs/install/quickstart.md b/website/site/content/docs/install/quickstart.md index fa02b4e1..4aaefdb7 100644 --- a/website/site/content/docs/install/quickstart.md +++ b/website/site/content/docs/install/quickstart.md @@ -20,10 +20,10 @@ To get started, here are some quick links: applies to the `zip` and `deb` files. The files can be downloaded from the [release page](https://github.com/eikek/docspell/releases/latest). -- via the [nix package manager](@/docs/install/nix.md) and/or as a - [NixOS module](@/docs/install/nix.md#nixos) through a flake. - If you use nix/nixos, you know what to do. The linked page contains - some examples. +- via the [nix package manager](@/docs/install/nix.md#try-it-out) + and/or as a [NixOS module](@/docs/install/nix.md#nixos) through a + flake. If you use nix/nixos, you know what to do. The linked page + contains some examples. - [Unraid](https://www.unraid.net/): There are user provided [notes and unraid templates](https://github.com/vakilando/unraid-docker-templates) diff --git a/website/yarn.lock b/website/yarn.lock index ccd8de05..c23023de 100644 --- a/website/yarn.lock +++ b/website/yarn.lock @@ -8,24 +8,24 @@ integrity sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw== "@fontsource/montserrat@^5.0.0": - version "5.0.16" - resolved "https://registry.yarnpkg.com/@fontsource/montserrat/-/montserrat-5.0.16.tgz#caa1b11b1d0ee1d6a028a73cedb5b27f8d881242" - integrity sha512-g27g1cvkyVm74QM0HKOCnI4iifMqf/3cSJYedjbjtW/Ygb271qfDz5gGMJCl9MinD4nimDdENsU3K1vGR50S2Q== + version "5.0.18" + resolved "https://registry.yarnpkg.com/@fontsource/montserrat/-/montserrat-5.0.18.tgz#eecb91b0f0062787a0eee5622988ed21f2899a90" + integrity sha512-85JBs2rCdFK/VBdSb401e2lXk5gynVo2zi3Rh2Guem4WNtT2q52+V90o3KzjmajY3TPJvCZA/kI7R05ev7148g== "@fontsource/source-code-pro@^5.0.0": - version "5.0.16" - resolved "https://registry.yarnpkg.com/@fontsource/source-code-pro/-/source-code-pro-5.0.16.tgz#5943c67cfec5493b0f1a5bc416e14ab7d5ebe760" - integrity sha512-ErErGXjKo9/fAJE49fyU8M6DuJUpdqR5YLM8jGJOC5ZcKIDSTQ5m+R3DTa0VYHAGGFbk2qLWVWD/r5sfCLA/jQ== + version "5.0.18" + resolved "https://registry.yarnpkg.com/@fontsource/source-code-pro/-/source-code-pro-5.0.18.tgz#fbb6989cdae05e4717c82c5da6b99ed5817c2c2c" + integrity sha512-5z+MFKaj+qs0PGAzv+WpMBTd8wEvAJEqATj6cGFVFJmFk6A6liJB07F2HAzLe/83FYikGeE4okh1sHM2JDVV+Q== "@fontsource/spectral@^5.0.0": - version "5.0.8" - resolved "https://registry.yarnpkg.com/@fontsource/spectral/-/spectral-5.0.8.tgz#013d48a177ce6b9eba8bdb4ed99a8a37aac57fd2" - integrity sha512-Gp/tqCe9scBJHwH0RgGasf5KkLYgW4Y2rKgQqMe3j5cYpZyCJA2g0OOVVvF8U7VQfvfw3TW8d3hWT4IISXqQCQ== + version "5.0.13" + resolved "https://registry.yarnpkg.com/@fontsource/spectral/-/spectral-5.0.13.tgz#decc0b840c31972000917c9678f86a562e09038e" + integrity sha512-t/E81Rp78LtpwSO19BErGP2HxWAib2/lBriYqJ1OsmYwdFTS4k3wqUJ6+vlr1dKWvjbMks+M3e999JyQC5JaMA== "@fortawesome/fontawesome-free@^6.0.0": - version "6.5.1" - resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-free/-/fontawesome-free-6.5.1.tgz#55cc8410abf1003b726324661ce5b0d1c10de258" - integrity sha512-CNy5vSwN3fsUStPRLX7fUYojyuzoEMSXPl7zSLJ8TgtRfjv24LOnOWKT2zYwaHZCJGkdyRnTmstR0P+Ah503Gw== + version "6.6.0" + resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-free/-/fontawesome-free-6.6.0.tgz#0e984f0f2344ee513c185d87d77defac4c0c8224" + integrity sha512-60G28ke/sXdtS9KZCpZSHHkCbdsOGEhIUGlwq6yhY74UpTiToIh8np7A8yphhM4BWsvNFtIvLpi4co+h9Mr9Ow== "@isaacs/cliui@^8.0.2": version "8.0.2" @@ -40,33 +40,33 @@ wrap-ansi-cjs "npm:wrap-ansi@^7.0.0" "@jridgewell/gen-mapping@^0.3.2": - version "0.3.3" - resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz#7e02e6eb5df901aaedb08514203b096614024098" - integrity sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ== + version "0.3.5" + resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz#dcce6aff74bdf6dad1a95802b69b04a2fcb1fb36" + integrity sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg== dependencies: - "@jridgewell/set-array" "^1.0.1" + "@jridgewell/set-array" "^1.2.1" "@jridgewell/sourcemap-codec" "^1.4.10" - "@jridgewell/trace-mapping" "^0.3.9" + "@jridgewell/trace-mapping" "^0.3.24" "@jridgewell/resolve-uri@^3.1.0": - version "3.1.1" - resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz#c08679063f279615a3326583ba3a90d1d82cc721" - integrity sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA== + version "3.1.2" + resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz#7a0ee601f60f99a20c7c7c5ff0c80388c1189bd6" + integrity sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw== -"@jridgewell/set-array@^1.0.1": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72" - integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw== +"@jridgewell/set-array@^1.2.1": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.2.1.tgz#558fb6472ed16a4c850b889530e6b36438c49280" + integrity sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A== "@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.14": - version "1.4.15" - resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32" - integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== + version "1.5.0" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz#3188bcb273a414b0d215fd22a58540b989b9409a" + integrity sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ== -"@jridgewell/trace-mapping@^0.3.9": - version "0.3.20" - resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz#72e45707cf240fa6b081d0366f8265b0cd10197f" - integrity sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q== +"@jridgewell/trace-mapping@^0.3.24": + version "0.3.25" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz#15f190e98895f3fc23276ee14bc76b675c2e50f0" + integrity sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ== dependencies: "@jridgewell/resolve-uri" "^3.1.0" "@jridgewell/sourcemap-codec" "^1.4.14" @@ -155,12 +155,12 @@ arg@^5.0.2: integrity sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg== autoprefixer@^10.4: - version "10.4.17" - resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-10.4.17.tgz#35cd5695cbbe82f536a50fa025d561b01fdec8be" - integrity sha512-/cpVNRLSfhOtcGflT13P2794gVSgmPgTR+erw5ifnMLZb0UnSlkK4tquLmkd3BhA+nLo5tX8Cu0upUsGKvKbmg== + version "10.4.19" + resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-10.4.19.tgz#ad25a856e82ee9d7898c59583c1afeb3fa65f89f" + integrity sha512-BaENR2+zBZ8xXhM4pUaKUxlVdxZ0EZhjvbopwnXmxRUfqDmwSpC2lAi/QXvx7NRdPCo1WKEcEF6mV64si1z4Ew== dependencies: - browserslist "^4.22.2" - caniuse-lite "^1.0.30001578" + browserslist "^4.23.0" + caniuse-lite "^1.0.30001599" fraction.js "^4.3.7" normalize-range "^0.1.2" picocolors "^1.0.0" @@ -172,9 +172,9 @@ balanced-match@^1.0.0: integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== binary-extensions@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" - integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== + version "2.3.0" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.3.0.tgz#f6e14a97858d327252200242d4ccfe522c445522" + integrity sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw== boolbase@^1.0.0: version "1.0.0" @@ -188,20 +188,30 @@ brace-expansion@^2.0.1: dependencies: balanced-match "^1.0.0" -braces@^3.0.2, braces@~3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" - integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== +braces@^3.0.3, braces@~3.0.2: + version "3.0.3" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789" + integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA== dependencies: - fill-range "^7.0.1" + fill-range "^7.1.1" -browserslist@^4.0.0, browserslist@^4.22.2: - version "4.22.2" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.22.2.tgz#704c4943072bd81ea18997f3bd2180e89c77874b" - integrity sha512-0UgcrvQmBDvZHFGdYUehrCNIazki7/lUP3kkoi/r3YB2amZbFM9J43ZRkJTXBUZK4gmx56+Sqk9+Vs9mwZx9+A== +browserslist@^4.0.0, browserslist@^4.23.1: + version "4.23.1" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.23.1.tgz#ce4af0534b3d37db5c1a4ca98b9080f985041e96" + integrity sha512-TUfofFo/KsK/bWZ9TWQ5O26tsWW4Uhmt8IYklbnUa70udB6P2wA7w7o4PY4muaEPBQaAX+CEnmmIA41NVHtPVw== dependencies: - caniuse-lite "^1.0.30001565" - electron-to-chromium "^1.4.601" + caniuse-lite "^1.0.30001629" + electron-to-chromium "^1.4.796" + node-releases "^2.0.14" + update-browserslist-db "^1.0.16" + +browserslist@^4.23.0: + version "4.23.0" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.23.0.tgz#8f3acc2bbe73af7213399430890f86c63a5674ab" + integrity sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ== + dependencies: + caniuse-lite "^1.0.30001587" + electron-to-chromium "^1.4.668" node-releases "^2.0.14" update-browserslist-db "^1.0.13" @@ -220,17 +230,22 @@ caniuse-api@^3.0.0: lodash.memoize "^4.1.2" lodash.uniq "^4.5.0" -caniuse-lite@^1.0.0: - version "1.0.30001572" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001572.tgz#1ccf7dc92d2ee2f92ed3a54e11b7b4a3041acfa0" - integrity sha512-1Pbh5FLmn5y4+QhNyJE9j3/7dK44dGB83/ZMjv/qJk86TvDbjk0LosiZo0i0WB0Vx607qMX9jYrn1VLHCkN4rw== +caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001629: + version "1.0.30001640" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001640.tgz#32c467d4bf1f1a0faa63fc793c2ba81169e7652f" + integrity sha512-lA4VMpW0PSUrFnkmVuEKBUovSWKhj7puyCg8StBChgu298N1AtuF1sKWEvfDuimSEDbhlb/KqPKC3fs1HbuQUA== -caniuse-lite@^1.0.30001565, caniuse-lite@^1.0.30001578: - version "1.0.30001578" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001578.tgz#11741580434ce60aae4b4a9abee9f9f8d7bf5be5" - integrity sha512-J/jkFgsQ3NEl4w2lCoM9ZPxrD+FoBNJ7uJUpGVjIg/j0OwJosWM36EPDv+Yyi0V4twBk9pPmlFS+PLykgEvUmg== +caniuse-lite@^1.0.30001587: + version "1.0.30001636" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001636.tgz#b15f52d2bdb95fad32c2f53c0b68032b85188a78" + integrity sha512-bMg2vmr8XBsbL6Lr0UHXy/21m84FTxDLWn2FSqMd5PrlbMxwJlQnC2YWYxVgp66PZE+BBNF2jYQUBKCo1FDeZg== -chokidar@^3.3.0, chokidar@^3.5.3: +caniuse-lite@^1.0.30001599: + version "1.0.30001599" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001599.tgz#571cf4f3f1506df9bf41fcbb6d10d5d017817bce" + integrity sha512-LRAQHZ4yT1+f9LemSMeqdMpMxZcc4RMWdj4tiFe3G8tNkWK+E58g+/tzotb5cU6TbcVJLr4fySiAW7XmxQvZQA== + +chokidar@^3.3.0: version "3.5.3" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== @@ -245,6 +260,21 @@ chokidar@^3.3.0, chokidar@^3.5.3: optionalDependencies: fsevents "~2.3.2" +chokidar@^3.5.3: + version "3.6.0" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.6.0.tgz#197c6cc669ef2a8dc5e7b4d97ee4e092c3eb0d5b" + integrity sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw== + dependencies: + anymatch "~3.1.2" + braces "~3.0.2" + glob-parent "~5.1.2" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.6.0" + optionalDependencies: + fsevents "~2.3.2" + cliui@^8.0.1: version "8.0.1" resolved "https://registry.yarnpkg.com/cliui/-/cliui-8.0.1.tgz#0c04b075db02cbfe60dc8e6cf2f5486b1a3608aa" @@ -266,7 +296,7 @@ color-name@~1.1.4: resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== -colord@^2.9.1: +colord@^2.9.3: version "2.9.3" resolved "https://registry.yarnpkg.com/colord/-/colord-2.9.3.tgz#4f8ce919de456f1d5c1c368c307fe20f3e59fb43" integrity sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw== @@ -295,10 +325,10 @@ cross-spawn@^7.0.0: shebang-command "^2.0.0" which "^2.0.1" -css-declaration-sorter@^7.1.1: - version "7.1.1" - resolved "https://registry.yarnpkg.com/css-declaration-sorter/-/css-declaration-sorter-7.1.1.tgz#9796bcc257b4647c39993bda8d431ce32b666f80" - integrity sha512-dZ3bVTEEc1vxr3Bek9vGwfB5Z6ESPULhcRvO472mfjVnj8jRcTnKO8/JTczlvxM10Myb+wBM++1MtdO76eWcaQ== +css-declaration-sorter@^7.2.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/css-declaration-sorter/-/css-declaration-sorter-7.2.0.tgz#6dec1c9523bc4a643e088aab8f09e67a54961024" + integrity sha512-h70rUM+3PNFuaBDTLe8wF/cdWu+dOZmb7pJt8Z2sedYbAcQVQV/tEchueg3GWxwqS0cxtbxmaHEdkNACqcvsow== css-select@^5.1.0: version "5.1.0" @@ -337,53 +367,54 @@ cssesc@^3.0.0: resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee" integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg== -cssnano-preset-default@^6.0.3: - version "6.0.3" - resolved "https://registry.yarnpkg.com/cssnano-preset-default/-/cssnano-preset-default-6.0.3.tgz#b4ce755974f4dc8d3d09ac13bb6281cce3ced45e" - integrity sha512-4y3H370aZCkT9Ev8P4SO4bZbt+AExeKhh8wTbms/X7OLDo5E7AYUUy6YPxa/uF5Grf+AJwNcCnxKhZynJ6luBA== +cssnano-preset-default@^7.0.4: + version "7.0.4" + resolved "https://registry.yarnpkg.com/cssnano-preset-default/-/cssnano-preset-default-7.0.4.tgz#9cfcd25f85bfedc84367b881dad56b75a0f976b5" + integrity sha512-jQ6zY9GAomQX7/YNLibMEsRZguqMUGuupXcEk2zZ+p3GUxwCAsobqPYE62VrJ9qZ0l9ltrv2rgjwZPBIFIjYtw== dependencies: - css-declaration-sorter "^7.1.1" - cssnano-utils "^4.0.1" - postcss-calc "^9.0.1" - postcss-colormin "^6.0.2" - postcss-convert-values "^6.0.2" - postcss-discard-comments "^6.0.1" - postcss-discard-duplicates "^6.0.1" - postcss-discard-empty "^6.0.1" - postcss-discard-overridden "^6.0.1" - postcss-merge-longhand "^6.0.2" - postcss-merge-rules "^6.0.3" - postcss-minify-font-values "^6.0.1" - postcss-minify-gradients "^6.0.1" - postcss-minify-params "^6.0.2" - postcss-minify-selectors "^6.0.2" - postcss-normalize-charset "^6.0.1" - postcss-normalize-display-values "^6.0.1" - postcss-normalize-positions "^6.0.1" - postcss-normalize-repeat-style "^6.0.1" - postcss-normalize-string "^6.0.1" - postcss-normalize-timing-functions "^6.0.1" - postcss-normalize-unicode "^6.0.2" - postcss-normalize-url "^6.0.1" - postcss-normalize-whitespace "^6.0.1" - postcss-ordered-values "^6.0.1" - postcss-reduce-initial "^6.0.2" - postcss-reduce-transforms "^6.0.1" - postcss-svgo "^6.0.2" - postcss-unique-selectors "^6.0.2" + browserslist "^4.23.1" + css-declaration-sorter "^7.2.0" + cssnano-utils "^5.0.0" + postcss-calc "^10.0.0" + postcss-colormin "^7.0.1" + postcss-convert-values "^7.0.2" + postcss-discard-comments "^7.0.1" + postcss-discard-duplicates "^7.0.0" + postcss-discard-empty "^7.0.0" + postcss-discard-overridden "^7.0.0" + postcss-merge-longhand "^7.0.2" + postcss-merge-rules "^7.0.2" + postcss-minify-font-values "^7.0.0" + postcss-minify-gradients "^7.0.0" + postcss-minify-params "^7.0.1" + postcss-minify-selectors "^7.0.2" + postcss-normalize-charset "^7.0.0" + postcss-normalize-display-values "^7.0.0" + postcss-normalize-positions "^7.0.0" + postcss-normalize-repeat-style "^7.0.0" + postcss-normalize-string "^7.0.0" + postcss-normalize-timing-functions "^7.0.0" + postcss-normalize-unicode "^7.0.1" + postcss-normalize-url "^7.0.0" + postcss-normalize-whitespace "^7.0.0" + postcss-ordered-values "^7.0.1" + postcss-reduce-initial "^7.0.1" + postcss-reduce-transforms "^7.0.0" + postcss-svgo "^7.0.1" + postcss-unique-selectors "^7.0.1" -cssnano-utils@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/cssnano-utils/-/cssnano-utils-4.0.1.tgz#fd18b42f95938bf55ab47967705355d6047bf1da" - integrity sha512-6qQuYDqsGoiXssZ3zct6dcMxiqfT6epy7x4R0TQJadd4LWO3sPR6JH6ZByOvVLoZ6EdwPGgd7+DR1EmX3tiXQQ== +cssnano-utils@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/cssnano-utils/-/cssnano-utils-5.0.0.tgz#b53a0343dd5d21012911882db6ae7d2eae0e3687" + integrity sha512-Uij0Xdxc24L6SirFr25MlwC2rCFX6scyUmuKpzI+JQ7cyqDEwD42fJ0xfB3yLfOnRDU5LKGgjQ9FA6LYh76GWQ== -cssnano@^6.0.0: - version "6.0.3" - resolved "https://registry.yarnpkg.com/cssnano/-/cssnano-6.0.3.tgz#46db972da71aa159437287fb4c6bc9c5d3cc5d93" - integrity sha512-MRq4CIj8pnyZpcI2qs6wswoYoDD1t0aL28n+41c1Ukcpm56m1h6mCexIHBGjfZfnTqtGSSCP4/fB1ovxgjBOiw== +cssnano@^7.0.0: + version "7.0.4" + resolved "https://registry.yarnpkg.com/cssnano/-/cssnano-7.0.4.tgz#13a4fb4dd14f3b1ee0cd51e6404ae4656f8ad9a0" + integrity sha512-rQgpZra72iFjiheNreXn77q1haS2GEy69zCMbu4cpXCFPMQF+D4Ik5V7ktMzUF/sA7xCIgcqHwGPnCD+0a1vHg== dependencies: - cssnano-preset-default "^6.0.3" - lilconfig "^3.0.0" + cssnano-preset-default "^7.0.4" + lilconfig "^3.1.2" csso@^5.0.5: version "5.0.5" @@ -442,10 +473,15 @@ eastasianwidth@^0.2.0: resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb" integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA== -electron-to-chromium@^1.4.601: - version "1.4.636" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.636.tgz#302cf4c3016d9d714ba246243a7c97b528e22fe7" - integrity sha512-NLE0GIy1OL9wRiKL20h9TkctBEYZuc99tquSS9MVdTahnuHputoETHeqDzgqGqyOY9NUH0g9wjfEuw5OD+wRcQ== +electron-to-chromium@^1.4.668: + version "1.4.806" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.806.tgz#2cb046631cbabceb26fc72be68d273fa183e36bc" + integrity sha512-nkoEX2QIB8kwCOtvtgwhXWy2IHVcOLQZu9Qo36uaGB835mdX/h8uLRlosL6QIhLVUnAiicXRW00PwaPZC74Nrg== + +electron-to-chromium@^1.4.796: + version "1.4.816" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.816.tgz#3624649d1e7fde5cdbadf59d31a524245d8ee85f" + integrity sha512-EKH5X5oqC6hLmiS7/vYtZHZFTNdhsYG5NVPRN6Yn0kQHNBlT59+xSM8HBy66P5fxWpKgZbPqb+diC64ng295Jw== emoji-regex@^8.0.0: version "8.0.0" @@ -462,10 +498,10 @@ entities@^4.2.0: resolved "https://registry.yarnpkg.com/entities/-/entities-4.5.0.tgz#5d268ea5e7113ec74c4d033b79ea5a35a488fb48" integrity sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw== -escalade@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" - integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== +escalade@^3.1.1, escalade@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.2.tgz#54076e9ab29ea5bf3d8f1ed62acffbb88272df27" + integrity sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA== fast-glob@^3.3.0, fast-glob@^3.3.2: version "3.3.2" @@ -479,23 +515,23 @@ fast-glob@^3.3.0, fast-glob@^3.3.2: micromatch "^4.0.4" fastq@^1.6.0: - version "1.16.0" - resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.16.0.tgz#83b9a9375692db77a822df081edb6a9cf6839320" - integrity sha512-ifCoaXsDrsdkWTtiNJX5uzHDsrck5TzfKKDcuFFTIrrc/BS076qgEIfoIy1VeZqViznfKiysPYTh/QeHtnIsYA== + version "1.17.1" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.17.1.tgz#2a523f07a4e7b1e81a42b91b8bf2254107753b47" + integrity sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w== dependencies: reusify "^1.0.4" -fill-range@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" - integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== +fill-range@^7.1.1: + version "7.1.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292" + integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg== dependencies: to-regex-range "^5.0.1" foreground-child@^3.1.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-3.1.1.tgz#1d173e776d75d2772fed08efe4a0de1ea1b12d0d" - integrity sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg== + version "3.2.1" + resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-3.2.1.tgz#767004ccf3a5b30df39bed90718bab43fe0a59f7" + integrity sha512-PXUUyLqrR2XCWICfv6ukppP96sdFwWbNEnfEMt7jNsISjMsvaLNinAHNDYyvkyU+SZG2BTSbT5NjG+vZslfGTA== dependencies: cross-spawn "^7.0.0" signal-exit "^4.0.1" @@ -554,15 +590,16 @@ glob-parent@^6.0.2: is-glob "^4.0.3" glob@^10.3.10: - version "10.3.10" - resolved "https://registry.yarnpkg.com/glob/-/glob-10.3.10.tgz#0351ebb809fd187fe421ab96af83d3a70715df4b" - integrity sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g== + version "10.4.5" + resolved "https://registry.yarnpkg.com/glob/-/glob-10.4.5.tgz#f4d9f0b90ffdbab09c9d77f5f29b4262517b0956" + integrity sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg== dependencies: foreground-child "^3.1.0" - jackspeak "^2.3.5" - minimatch "^9.0.1" - minipass "^5.0.0 || ^6.0.2 || ^7.0.0" - path-scurry "^1.10.1" + jackspeak "^3.1.2" + minimatch "^9.0.4" + minipass "^7.1.2" + package-json-from-dist "^1.0.0" + path-scurry "^1.11.1" glob@^8.0.3: version "8.1.0" @@ -592,10 +629,10 @@ graceful-fs@^4.1.6, graceful-fs@^4.2.0: resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== -hasown@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.0.tgz#f4c513d454a57b7c7e1650778de226b11700546c" - integrity sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA== +hasown@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003" + integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ== dependencies: function-bind "^1.1.2" @@ -625,11 +662,11 @@ is-binary-path@~2.1.0: binary-extensions "^2.0.0" is-core-module@^2.13.0: - version "2.13.1" - resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.13.1.tgz#ad0d7532c6fea9da1ebdc82742d74525c6273384" - integrity sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw== + version "2.15.0" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.15.0.tgz#71c72ec5442ace7e76b306e9d48db361f22699ea" + integrity sha512-Dd+Lb2/zvk9SKy1TGCt1wFJFo/MWBPMX5x7KcvLajWTGuomczdQX61PvY5yK6SVACwpoexWo81IfFyoKY2QnTA== dependencies: - hasown "^2.0.0" + hasown "^2.0.2" is-extglob@^2.1.1: version "2.1.1" @@ -658,19 +695,19 @@ isexe@^2.0.0: resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== -jackspeak@^2.3.5: - version "2.3.6" - resolved "https://registry.yarnpkg.com/jackspeak/-/jackspeak-2.3.6.tgz#647ecc472238aee4b06ac0e461acc21a8c505ca8" - integrity sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ== +jackspeak@^3.1.2: + version "3.4.3" + resolved "https://registry.yarnpkg.com/jackspeak/-/jackspeak-3.4.3.tgz#8833a9d89ab4acde6188942bd1c53b6390ed5a8a" + integrity sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw== dependencies: "@isaacs/cliui" "^8.0.2" optionalDependencies: "@pkgjs/parseargs" "^0.11.0" -jiti@^1.19.1: - version "1.21.0" - resolved "https://registry.yarnpkg.com/jiti/-/jiti-1.21.0.tgz#7c97f8fe045724e136a397f7340475244156105d" - integrity sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q== +jiti@^1.21.0: + version "1.21.6" + resolved "https://registry.yarnpkg.com/jiti/-/jiti-1.21.6.tgz#6c7f7398dd4b3142767f9a168af2f317a428d268" + integrity sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w== jsonfile@^6.0.1: version "6.1.0" @@ -686,10 +723,10 @@ lilconfig@^2.1.0: resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-2.1.0.tgz#78e23ac89ebb7e1bfbf25b18043de756548e7f52" integrity sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ== -lilconfig@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-3.0.0.tgz#f8067feb033b5b74dab4602a5f5029420be749bc" - integrity sha512-K2U4W2Ff5ibV7j7ydLr+zLAkIg5JJ4lPn1Ltsdt+Tz/IjQ8buJ55pZAxoP34lqIiwtF9iAvtLv3JGv7CAyAg+g== +lilconfig@^3.0.0, lilconfig@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-3.1.2.tgz#e4a7c3cb549e3a606c8dcc32e5ae1005e62c05cb" + integrity sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow== lines-and-columns@^1.1.6: version "1.2.4" @@ -706,10 +743,10 @@ lodash.uniq@^4.5.0: resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" integrity sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ== -"lru-cache@^9.1.1 || ^10.0.0": - version "10.1.0" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.1.0.tgz#2098d41c2dc56500e6c88584aa656c84de7d0484" - integrity sha512-/1clY/ui8CzjKFyjdvwPWJUYKiFVXG2I2cY0ssG7h4+hwk+XOIX7ZSG9Q7TW8TW3Kp3BUSqgFWBLgL4PJ+Blag== +lru-cache@^10.2.0: + version "10.4.3" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.4.3.tgz#410fc8a17b70e598013df257c2446b7f3383f119" + integrity sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ== mdn-data@2.0.28: version "2.0.28" @@ -727,11 +764,11 @@ merge2@^1.3.0: integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== micromatch@^4.0.4, micromatch@^4.0.5: - version "4.0.5" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6" - integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA== + version "4.0.7" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.7.tgz#33e8190d9fe474a9895525f5618eee136d46c2e5" + integrity sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q== dependencies: - braces "^3.0.2" + braces "^3.0.3" picomatch "^2.3.1" mini-svg-data-uri@^1.2.3: @@ -746,17 +783,17 @@ minimatch@^5.0.1: dependencies: brace-expansion "^2.0.1" -minimatch@^9.0.1: - version "9.0.3" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.3.tgz#a6e00c3de44c3a542bfaae70abfc22420a6da825" - integrity sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg== +minimatch@^9.0.4: + version "9.0.5" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.5.tgz#d74f9dd6b57d83d8e98cfb82133b03978bc929e5" + integrity sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow== dependencies: brace-expansion "^2.0.1" -"minipass@^5.0.0 || ^6.0.2 || ^7.0.0": - version "7.0.4" - resolved "https://registry.yarnpkg.com/minipass/-/minipass-7.0.4.tgz#dbce03740f50a4786ba994c1fb908844d27b038c" - integrity sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ== +"minipass@^5.0.0 || ^6.0.2 || ^7.0.0", minipass@^7.1.2: + version "7.1.2" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-7.1.2.tgz#93a9626ce5e5e66bd4db86849e7515e92340a707" + integrity sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw== mz@^2.7.0: version "2.7.0" @@ -811,6 +848,11 @@ once@^1.3.0: dependencies: wrappy "1" +package-json-from-dist@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/package-json-from-dist/-/package-json-from-dist-1.0.0.tgz#e501cd3094b278495eb4258d4c9f6d5ac3019f00" + integrity sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw== + path-key@^3.1.0: version "3.1.1" resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" @@ -821,12 +863,12 @@ path-parse@^1.0.7: resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== -path-scurry@^1.10.1: - version "1.10.1" - resolved "https://registry.yarnpkg.com/path-scurry/-/path-scurry-1.10.1.tgz#9ba6bf5aa8500fe9fd67df4f0d9483b2b0bfc698" - integrity sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ== +path-scurry@^1.11.1: + version "1.11.1" + resolved "https://registry.yarnpkg.com/path-scurry/-/path-scurry-1.11.1.tgz#7960a668888594a0720b12a911d1a742ab9f11d2" + integrity sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA== dependencies: - lru-cache "^9.1.1 || ^10.0.0" + lru-cache "^10.2.0" minipass "^5.0.0 || ^6.0.2 || ^7.0.0" path-type@^5.0.0: @@ -834,10 +876,10 @@ path-type@^5.0.0: resolved "https://registry.yarnpkg.com/path-type/-/path-type-5.0.0.tgz#14b01ed7aea7ddf9c7c3f46181d4d04f9c785bb8" integrity sha512-5HviZNaZcfqP95rwpv+1HDgUamezbqdSYTyzjTvwtJSnIH+3vnbmWsItli8OFEndS984VT55M3jduxZbX351gg== -picocolors@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" - integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== +picocolors@^1.0.0, picocolors@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.1.tgz#a8ad579b571952f0e5d25892de5445bcfe25aaa1" + integrity sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew== picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.3.1: version "2.3.1" @@ -854,12 +896,12 @@ pirates@^4.0.1: resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.6.tgz#3018ae32ecfcff6c29ba2267cbf21166ac1f36b9" integrity sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg== -postcss-calc@^9.0.1: - version "9.0.1" - resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-9.0.1.tgz#a744fd592438a93d6de0f1434c572670361eb6c6" - integrity sha512-TipgjGyzP5QzEhsOZUaIkeO5mKeMFpebWzRogWG/ysonUlnHcq5aJe0jOjpfzUU8PeSaBQnrE8ehR0QA5vs8PQ== +postcss-calc@^10.0.0: + version "10.0.0" + resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-10.0.0.tgz#aca29a1c66dd481ca30d08f6932b1274a1003716" + integrity sha512-OmjhudoNTP0QleZCwl1i6NeBwN+5MZbY5ersLZz69mjJiDVv/p57RjRuKDkHeDWr4T+S97wQfsqRTNoDHB2e3g== dependencies: - postcss-selector-parser "^6.0.11" + postcss-selector-parser "^6.0.16" postcss-value-parser "^4.2.0" postcss-cli@^11.0.0: @@ -880,43 +922,45 @@ postcss-cli@^11.0.0: slash "^5.0.0" yargs "^17.0.0" -postcss-colormin@^6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/postcss-colormin/-/postcss-colormin-6.0.2.tgz#2af9ce753937b08e058dbc6879e4aedfab42806b" - integrity sha512-TXKOxs9LWcdYo5cgmcSHPkyrLAh86hX1ijmyy6J8SbOhyv6ua053M3ZAM/0j44UsnQNIWdl8gb5L7xX2htKeLw== +postcss-colormin@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/postcss-colormin/-/postcss-colormin-7.0.1.tgz#6534c7d1175e30f788d4ced891436ad2fa3bd173" + integrity sha512-uszdT0dULt3FQs47G5UHCduYK+FnkLYlpu1HpWu061eGsKZ7setoG7kA+WC9NQLsOJf69D5TxGHgnAdRgylnFQ== dependencies: - browserslist "^4.22.2" + browserslist "^4.23.1" caniuse-api "^3.0.0" - colord "^2.9.1" + colord "^2.9.3" postcss-value-parser "^4.2.0" -postcss-convert-values@^6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/postcss-convert-values/-/postcss-convert-values-6.0.2.tgz#c4a7509aeb1cc7ac3f6948fcbffc2bf8cac7c56a" - integrity sha512-aeBmaTnGQ+NUSVQT8aY0sKyAD/BaLJenEKZ03YK0JnDE1w1Rr8XShoxdal2V2H26xTJKr3v5haByOhJuyT4UYw== +postcss-convert-values@^7.0.2: + version "7.0.2" + resolved "https://registry.yarnpkg.com/postcss-convert-values/-/postcss-convert-values-7.0.2.tgz#8a33265f5f1decfc93328e2a23e03e8491a3d9ae" + integrity sha512-MuZIF6HJ4izko07Q0TgW6pClalI4al6wHRNPkFzqQdwAwG7hPn0lA58VZdxyb2Vl5AYjJ1piO+jgF9EnTjQwQQ== dependencies: - browserslist "^4.22.2" + browserslist "^4.23.1" postcss-value-parser "^4.2.0" -postcss-discard-comments@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/postcss-discard-comments/-/postcss-discard-comments-6.0.1.tgz#46176212bd9c3e5f48aa4b8b4868786726c41d36" - integrity sha512-f1KYNPtqYLUeZGCHQPKzzFtsHaRuECe6jLakf/RjSRqvF5XHLZnM2+fXLhb8Qh/HBFHs3M4cSLb1k3B899RYIg== +postcss-discard-comments@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/postcss-discard-comments/-/postcss-discard-comments-7.0.1.tgz#00b01c5a99e95f97927b0ba12a1c422ab90bf55f" + integrity sha512-GVrQxUOhmle1W6jX2SvNLt4kmN+JYhV7mzI6BMnkAWR9DtVvg8e67rrV0NfdWhn7x1zxvzdWkMBPdBDCls+uwQ== + dependencies: + postcss-selector-parser "^6.1.0" -postcss-discard-duplicates@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/postcss-discard-duplicates/-/postcss-discard-duplicates-6.0.1.tgz#112b1a95948e69b3484fdd43584dda6930977939" - integrity sha512-1hvUs76HLYR8zkScbwyJ8oJEugfPV+WchpnA+26fpJ7Smzs51CzGBHC32RS03psuX/2l0l0UKh2StzNxOrKCYg== +postcss-discard-duplicates@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/postcss-discard-duplicates/-/postcss-discard-duplicates-7.0.0.tgz#47ae1154cc89ad0a50099fbac1f74c942214c961" + integrity sha512-bAnSuBop5LpAIUmmOSsuvtKAAKREB6BBIYStWUTGq8oG5q9fClDMMuY8i4UPI/cEcDx2TN+7PMnXYIId20UVDw== -postcss-discard-empty@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/postcss-discard-empty/-/postcss-discard-empty-6.0.1.tgz#b34cb45ec891246da4506b53e352390fdef126c4" - integrity sha512-yitcmKwmVWtNsrrRqGJ7/C0YRy53i0mjexBDQ9zYxDwTWVBgbU4+C9jIZLmQlTDT9zhml+u0OMFJh8+31krmOg== +postcss-discard-empty@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/postcss-discard-empty/-/postcss-discard-empty-7.0.0.tgz#218829d1ef0a5d5142dd62f0aa60e00e599d2033" + integrity sha512-e+QzoReTZ8IAwhnSdp/++7gBZ/F+nBq9y6PomfwORfP7q9nBpK5AMP64kOt0bA+lShBFbBDcgpJ3X4etHg4lzA== -postcss-discard-overridden@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/postcss-discard-overridden/-/postcss-discard-overridden-6.0.1.tgz#c63c559237758d74bc505452393a64dda9b19ef4" - integrity sha512-qs0ehZMMZpSESbRkw1+inkf51kak6OOzNRaoLd/U7Fatp0aN2HQ1rxGOrJvYcRAN9VpX8kUF13R2ofn8OlvFVA== +postcss-discard-overridden@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/postcss-discard-overridden/-/postcss-discard-overridden-7.0.0.tgz#b123ea51e3d4e1d0a254cf71eaff1201926d319c" + integrity sha512-GmNAzx88u3k2+sBTZrJSDauR0ccpE24omTQCVmaTTZFz1du6AasspjaUPMJ2ud4RslZpoFKyf+6MSPETLojc6w== postcss-import@^15.1.0: version "15.1.0" @@ -928,9 +972,9 @@ postcss-import@^15.1.0: resolve "^1.1.7" postcss-import@^16.0.0: - version "16.0.0" - resolved "https://registry.yarnpkg.com/postcss-import/-/postcss-import-16.0.0.tgz#2be1c78391b3f43f129fccfe5cc0cc1a11baef54" - integrity sha512-e77lhVvrD1I2y7dYmBv0k9ULTdArgEYZt97T4w6sFIU5uxIHvDFQlKgUUyY7v7Barj0Yf/zm5A4OquZN7jKm5Q== + version "16.1.0" + resolved "https://registry.yarnpkg.com/postcss-import/-/postcss-import-16.1.0.tgz#258732175518129667fe1e2e2a05b19b5654b96a" + integrity sha512-7hsAZ4xGXl4MW+OKEWCnF6T5jqBw80/EE9aXg1r2yyn1RsVEU8EtKXbijEODa+rg7iih4bKf7vlvTGYR4CnPNg== dependencies: postcss-value-parser "^4.0.0" read-cache "^1.0.0" @@ -959,131 +1003,132 @@ postcss-load-config@^5.0.0: lilconfig "^3.0.0" yaml "^2.3.4" -postcss-merge-longhand@^6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/postcss-merge-longhand/-/postcss-merge-longhand-6.0.2.tgz#cd4e83014851da59545e9a906b245615550f4064" - integrity sha512-+yfVB7gEM8SrCo9w2lCApKIEzrTKl5yS1F4yGhV3kSim6JzbfLGJyhR1B6X+6vOT0U33Mgx7iv4X9MVWuaSAfw== +postcss-merge-longhand@^7.0.2: + version "7.0.2" + resolved "https://registry.yarnpkg.com/postcss-merge-longhand/-/postcss-merge-longhand-7.0.2.tgz#b9fddce88498ca7e45ff130163b69864b25c05dc" + integrity sha512-06vrW6ZWi9qeP7KMS9fsa9QW56+tIMW55KYqF7X3Ccn+NI2pIgPV6gFfvXTMQ05H90Y5DvnCDPZ2IuHa30PMUg== dependencies: postcss-value-parser "^4.2.0" - stylehacks "^6.0.2" + stylehacks "^7.0.2" -postcss-merge-rules@^6.0.3: - version "6.0.3" - resolved "https://registry.yarnpkg.com/postcss-merge-rules/-/postcss-merge-rules-6.0.3.tgz#08fcf714faaad75b1980ecd961b080ae2f8ddeb3" - integrity sha512-yfkDqSHGohy8sGYIJwBmIGDv4K4/WrJPX355XrxQb/CSsT4Kc/RxDi6akqn5s9bap85AWgv21ArcUWwWdGNSHA== +postcss-merge-rules@^7.0.2: + version "7.0.2" + resolved "https://registry.yarnpkg.com/postcss-merge-rules/-/postcss-merge-rules-7.0.2.tgz#f7c991576cff4c7d0a8f16101c20bbfa9426695c" + integrity sha512-VAR47UNvRsdrTHLe7TV1CeEtF9SJYR5ukIB9U4GZyZOptgtsS20xSxy+k5wMrI3udST6O1XuIn7cjQkg7sDAAw== dependencies: - browserslist "^4.22.2" + browserslist "^4.23.1" caniuse-api "^3.0.0" - cssnano-utils "^4.0.1" - postcss-selector-parser "^6.0.15" + cssnano-utils "^5.0.0" + postcss-selector-parser "^6.1.0" -postcss-minify-font-values@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/postcss-minify-font-values/-/postcss-minify-font-values-6.0.1.tgz#788eb930168be90225f3937f0b70aa19d8b532b2" - integrity sha512-tIwmF1zUPoN6xOtA/2FgVk1ZKrLcCvE0dpZLtzyyte0j9zUeB8RTbCqrHZGjJlxOvNWKMYtunLrrl7HPOiR46w== +postcss-minify-font-values@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/postcss-minify-font-values/-/postcss-minify-font-values-7.0.0.tgz#d16a75a2548e000779566b3568fc874ee5d0aa17" + integrity sha512-2ckkZtgT0zG8SMc5aoNwtm5234eUx1GGFJKf2b1bSp8UflqaeFzR50lid4PfqVI9NtGqJ2J4Y7fwvnP/u1cQog== dependencies: postcss-value-parser "^4.2.0" -postcss-minify-gradients@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/postcss-minify-gradients/-/postcss-minify-gradients-6.0.1.tgz#4faf1880b483dc37016658aa186b42194ff9b5bc" - integrity sha512-M1RJWVjd6IOLPl1hYiOd5HQHgpp6cvJVLrieQYS9y07Yo8itAr6jaekzJphaJFR0tcg4kRewCk3kna9uHBxn/w== +postcss-minify-gradients@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/postcss-minify-gradients/-/postcss-minify-gradients-7.0.0.tgz#f6d84456e6d49164a55d0e45bb1b1809c6cf0959" + integrity sha512-pdUIIdj/C93ryCHew0UgBnL2DtUS3hfFa5XtERrs4x+hmpMYGhbzo6l/Ir5de41O0GaKVpK1ZbDNXSY6GkXvtg== dependencies: - colord "^2.9.1" - cssnano-utils "^4.0.1" + colord "^2.9.3" + cssnano-utils "^5.0.0" postcss-value-parser "^4.2.0" -postcss-minify-params@^6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/postcss-minify-params/-/postcss-minify-params-6.0.2.tgz#bd64af642fa5610281b8a9461598bbb91f92ae05" - integrity sha512-zwQtbrPEBDj+ApELZ6QylLf2/c5zmASoOuA4DzolyVGdV38iR2I5QRMsZcHkcdkZzxpN8RS4cN7LPskOkTwTZw== +postcss-minify-params@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/postcss-minify-params/-/postcss-minify-params-7.0.1.tgz#08d753bb09d3ebf1a6d6fb0968d60bb3b981e513" + integrity sha512-e+Xt8xErSRPgSRFxHeBCSxMiO8B8xng7lh8E0A5ep1VfwYhY8FXhu4Q3APMjgx9YDDbSp53IBGENrzygbUvgUQ== dependencies: - browserslist "^4.22.2" - cssnano-utils "^4.0.1" + browserslist "^4.23.1" + cssnano-utils "^5.0.0" postcss-value-parser "^4.2.0" -postcss-minify-selectors@^6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/postcss-minify-selectors/-/postcss-minify-selectors-6.0.2.tgz#62065b38d3453ddc6627ba50e4f4a2154b031aa0" - integrity sha512-0b+m+w7OAvZejPQdN2GjsXLv5o0jqYHX3aoV0e7RBKPCsB7TYG5KKWBFhGnB/iP3213Ts8c5H4wLPLMm7z28Sg== +postcss-minify-selectors@^7.0.2: + version "7.0.2" + resolved "https://registry.yarnpkg.com/postcss-minify-selectors/-/postcss-minify-selectors-7.0.2.tgz#869c8ef885a4f9c2550d0d5ec1a2876027d3965c" + integrity sha512-dCzm04wqW1uqLmDZ41XYNBJfjgps3ZugDpogAmJXoCb5oCiTzIX4oPXXKxDpTvWOnKxQKR4EbV4ZawJBLcdXXA== dependencies: - postcss-selector-parser "^6.0.15" + cssesc "^3.0.0" + postcss-selector-parser "^6.1.0" postcss-nested@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/postcss-nested/-/postcss-nested-6.0.1.tgz#f83dc9846ca16d2f4fa864f16e9d9f7d0961662c" - integrity sha512-mEp4xPMi5bSWiMbsgoPfcP74lsWLHkQbZc3sY+jWYd65CUwXrUaTp0fmNpa01ZcETKlIgUdFN/MpS2xZtqL9dQ== + version "6.2.0" + resolved "https://registry.yarnpkg.com/postcss-nested/-/postcss-nested-6.2.0.tgz#4c2d22ab5f20b9cb61e2c5c5915950784d068131" + integrity sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ== dependencies: - postcss-selector-parser "^6.0.11" + postcss-selector-parser "^6.1.1" -postcss-normalize-charset@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/postcss-normalize-charset/-/postcss-normalize-charset-6.0.1.tgz#5f70e1eb8bbdbcfcbed060ef70f179e8fef57d0c" - integrity sha512-aW5LbMNRZ+oDV57PF9K+WI1Z8MPnF+A8qbajg/T8PP126YrGX1f9IQx21GI2OlGz7XFJi/fNi0GTbY948XJtXg== +postcss-normalize-charset@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/postcss-normalize-charset/-/postcss-normalize-charset-7.0.0.tgz#92244ae73c31bf8f8885d5f16ff69e857ac6c001" + integrity sha512-ABisNUXMeZeDNzCQxPxBCkXexvBrUHV+p7/BXOY+ulxkcjUZO0cp8ekGBwvIh2LbCwnWbyMPNJVtBSdyhM2zYQ== -postcss-normalize-display-values@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/postcss-normalize-display-values/-/postcss-normalize-display-values-6.0.1.tgz#ff9aa30bbf1283294bfd9cc8b6fb81ff060a7f2d" - integrity sha512-mc3vxp2bEuCb4LgCcmG1y6lKJu1Co8T+rKHrcbShJwUmKJiEl761qb/QQCfFwlrvSeET3jksolCR/RZuMURudw== +postcss-normalize-display-values@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/postcss-normalize-display-values/-/postcss-normalize-display-values-7.0.0.tgz#01fb50e5e97ef8935363629bea5a6d3b3aac1342" + integrity sha512-lnFZzNPeDf5uGMPYgGOw7v0BfB45+irSRz9gHQStdkkhiM0gTfvWkWB5BMxpn0OqgOQuZG/mRlZyJxp0EImr2Q== dependencies: postcss-value-parser "^4.2.0" -postcss-normalize-positions@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/postcss-normalize-positions/-/postcss-normalize-positions-6.0.1.tgz#41ffdc72994f024c6cd6e91dbfb40ab9abe6fe90" - integrity sha512-HRsq8u/0unKNvm0cvwxcOUEcakFXqZ41fv3FOdPn916XFUrympjr+03oaLkuZENz3HE9RrQE9yU0Xv43ThWjQg== +postcss-normalize-positions@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/postcss-normalize-positions/-/postcss-normalize-positions-7.0.0.tgz#4eebd7c9d3dde40c97b8047cad38124fc844c463" + integrity sha512-I0yt8wX529UKIGs2y/9Ybs2CelSvItfmvg/DBIjTnoUSrPxSV7Z0yZ8ShSVtKNaV/wAY+m7bgtyVQLhB00A1NQ== dependencies: postcss-value-parser "^4.2.0" -postcss-normalize-repeat-style@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-6.0.1.tgz#55dc54b6f80305b280a379899a6626e0a07b04a8" - integrity sha512-Gbb2nmCy6tTiA7Sh2MBs3fj9W8swonk6lw+dFFeQT68B0Pzwp1kvisJQkdV6rbbMSd9brMlS8I8ts52tAGWmGQ== +postcss-normalize-repeat-style@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-7.0.0.tgz#0cb784655d5714d29bd3bda6dee2fb628aa7227b" + integrity sha512-o3uSGYH+2q30ieM3ppu9GTjSXIzOrRdCUn8UOMGNw7Af61bmurHTWI87hRybrP6xDHvOe5WlAj3XzN6vEO8jLw== dependencies: postcss-value-parser "^4.2.0" -postcss-normalize-string@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/postcss-normalize-string/-/postcss-normalize-string-6.0.1.tgz#7605e0fb4ec7bf2709709991d13a949e4419db1d" - integrity sha512-5Fhx/+xzALJD9EI26Aq23hXwmv97Zfy2VFrt5PLT8lAhnBIZvmaT5pQk+NuJ/GWj/QWaKSKbnoKDGLbV6qnhXg== +postcss-normalize-string@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/postcss-normalize-string/-/postcss-normalize-string-7.0.0.tgz#a119d3e63a9614570d8413d572fb9fc8c6a64e8c" + integrity sha512-w/qzL212DFVOpMy3UGyxrND+Kb0fvCiBBujiaONIihq7VvtC7bswjWgKQU/w4VcRyDD8gpfqUiBQ4DUOwEJ6Qg== dependencies: postcss-value-parser "^4.2.0" -postcss-normalize-timing-functions@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-6.0.1.tgz#ef937b7ca2fd62ed0b46645ea5728b842a3600db" - integrity sha512-4zcczzHqmCU7L5dqTB9rzeqPWRMc0K2HoR+Bfl+FSMbqGBUcP5LRfgcH4BdRtLuzVQK1/FHdFoGT3F7rkEnY+g== +postcss-normalize-timing-functions@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-7.0.0.tgz#99d0ee8c4b23b7f4355fafb91385833b9b07108b" + integrity sha512-tNgw3YV0LYoRwg43N3lTe3AEWZ66W7Dh7lVEpJbHoKOuHc1sLrzMLMFjP8SNULHaykzsonUEDbKedv8C+7ej6g== dependencies: postcss-value-parser "^4.2.0" -postcss-normalize-unicode@^6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/postcss-normalize-unicode/-/postcss-normalize-unicode-6.0.2.tgz#361026744ff11baebaec771b60c2a5f36f274fd0" - integrity sha512-Ff2VdAYCTGyMUwpevTZPZ4w0+mPjbZzLLyoLh/RMpqUqeQKZ+xMm31hkxBavDcGKcxm6ACzGk0nBfZ8LZkStKA== +postcss-normalize-unicode@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/postcss-normalize-unicode/-/postcss-normalize-unicode-7.0.1.tgz#6545debfff2b4b154583cb24bb388b9681ffa119" + integrity sha512-PTPGdY9xAkTw+8ZZ71DUePb7M/Vtgkbbq+EoI33EuyQEzbKemEQMhe5QSr0VP5UfZlreANDPxSfcdSprENcbsg== dependencies: - browserslist "^4.22.2" + browserslist "^4.23.1" postcss-value-parser "^4.2.0" -postcss-normalize-url@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/postcss-normalize-url/-/postcss-normalize-url-6.0.1.tgz#eae58cb4f5f9a4fa5bbbf6d4222dff534ad46186" - integrity sha512-jEXL15tXSvbjm0yzUV7FBiEXwhIa9H88JOXDGQzmcWoB4mSjZIsmtto066s2iW9FYuIrIF4k04HA2BKAOpbsaQ== +postcss-normalize-url@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/postcss-normalize-url/-/postcss-normalize-url-7.0.0.tgz#c88cb7cf8952d3ff631e4eba924e7b060ca802f6" + integrity sha512-+d7+PpE+jyPX1hDQZYG+NaFD+Nd2ris6r8fPTBAjE8z/U41n/bib3vze8x7rKs5H1uEw5ppe9IojewouHk0klQ== dependencies: postcss-value-parser "^4.2.0" -postcss-normalize-whitespace@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/postcss-normalize-whitespace/-/postcss-normalize-whitespace-6.0.1.tgz#b5933750b938814c028d3d2b2e5c0199e0037b53" - integrity sha512-76i3NpWf6bB8UHlVuLRxG4zW2YykF9CTEcq/9LGAiz2qBuX5cBStadkk0jSkg9a9TCIXbMQz7yzrygKoCW9JuA== +postcss-normalize-whitespace@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/postcss-normalize-whitespace/-/postcss-normalize-whitespace-7.0.0.tgz#46b025f0bea72139ddee63015619b0c21cebd845" + integrity sha512-37/toN4wwZErqohedXYqWgvcHUGlT8O/m2jVkAfAe9Bd4MzRqlBmXrJRePH0e9Wgnz2X7KymTgTOaaFizQe3AQ== dependencies: postcss-value-parser "^4.2.0" -postcss-ordered-values@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/postcss-ordered-values/-/postcss-ordered-values-6.0.1.tgz#553e735d009065b362da93340e57f43d5f2d0fbc" - integrity sha512-XXbb1O/MW9HdEhnBxitZpPFbIvDgbo9NK4c/5bOfiKpnIGZDoL2xd7/e6jW5DYLsWxBbs+1nZEnVgnjnlFViaA== +postcss-ordered-values@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/postcss-ordered-values/-/postcss-ordered-values-7.0.1.tgz#8b4b5b8070ca7756bd49f07d5edf274b8f6782e0" + integrity sha512-irWScWRL6nRzYmBOXReIKch75RRhNS86UPUAxXdmW/l0FcAsg0lvAXQCby/1lymxn/o0gVa6Rv/0f03eJOwHxw== dependencies: - cssnano-utils "^4.0.1" + cssnano-utils "^5.0.0" postcss-value-parser "^4.2.0" postcss-purgecss@^5.0.0: @@ -1093,18 +1138,18 @@ postcss-purgecss@^5.0.0: dependencies: purgecss "^5.0.0" -postcss-reduce-initial@^6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/postcss-reduce-initial/-/postcss-reduce-initial-6.0.2.tgz#763d25902406c872264041df69f182eb15a5d9be" - integrity sha512-YGKalhNlCLcjcLvjU5nF8FyeCTkCO5UtvJEt0hrPZVCTtRLSOH4z00T1UntQPj4dUmIYZgMj8qK77JbSX95hSw== +postcss-reduce-initial@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/postcss-reduce-initial/-/postcss-reduce-initial-7.0.1.tgz#d5308153f757ff9dd5b041cd4954a7592ef0d43b" + integrity sha512-0JDUSV4bGB5FGM5g8MkS+rvqKukJZ7OTHw/lcKn7xPNqeaqJyQbUO8/dJpvyTpaVwPsd3Uc33+CfNzdVowp2WA== dependencies: - browserslist "^4.22.2" + browserslist "^4.23.1" caniuse-api "^3.0.0" -postcss-reduce-transforms@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/postcss-reduce-transforms/-/postcss-reduce-transforms-6.0.1.tgz#7bf59d7c6e7066e3b18ef17237d2344bd3da6d75" - integrity sha512-fUbV81OkUe75JM+VYO1gr/IoA2b/dRiH6HvMwhrIBSUrxq3jNZQZitSnugcTLDi1KkQh1eR/zi+iyxviUNBkcQ== +postcss-reduce-transforms@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/postcss-reduce-transforms/-/postcss-reduce-transforms-7.0.0.tgz#0386080a14e5faad9f8eda33375b79fe7c4f9677" + integrity sha512-pnt1HKKZ07/idH8cpATX/ujMbtOGhUfE+m8gbqwJE05aTaNw8gbo34a2e3if0xc0dlu75sUOiqvwCGY3fzOHew== dependencies: postcss-value-parser "^4.2.0" @@ -1116,10 +1161,18 @@ postcss-reporter@^7.0.0: picocolors "^1.0.0" thenby "^1.3.4" -postcss-selector-parser@^6.0.11, postcss-selector-parser@^6.0.15: - version "6.0.15" - resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.15.tgz#11cc2b21eebc0b99ea374ffb9887174855a01535" - integrity sha512-rEYkQOMUCEMhsKbK66tbEU9QVIxbhN18YiniAwA7XQYTVBqrBy+P2p5JcdqsHgKM2zWylp8d7J6eszocfds5Sw== +postcss-selector-parser@^6.0.11, postcss-selector-parser@^6.1.1: + version "6.1.1" + resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.1.1.tgz#5be94b277b8955904476a2400260002ce6c56e38" + integrity sha512-b4dlw/9V8A71rLIDsSwVmak9z2DuBUB7CA1/wSdelNEzqsjoSPeADTWNO09lpH49Diy3/JIZ2bSPB1dI3LJCHg== + dependencies: + cssesc "^3.0.0" + util-deprecate "^1.0.2" + +postcss-selector-parser@^6.0.16, postcss-selector-parser@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.1.0.tgz#49694cb4e7c649299fea510a29fa6577104bcf53" + integrity sha512-UMz42UD0UY0EApS0ZL9o1XnLhSTtvvvLe5Dc2H2O56fvRZi+KulDyf5ctDhhtYJBGKStV2FL1fy6253cmLgqVQ== dependencies: cssesc "^3.0.0" util-deprecate "^1.0.2" @@ -1132,20 +1185,20 @@ postcss-selector-parser@^6.0.7: cssesc "^3.0.0" util-deprecate "^1.0.2" -postcss-svgo@^6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/postcss-svgo/-/postcss-svgo-6.0.2.tgz#dbc9d03e7f346bc0d82443078602a951e0214836" - integrity sha512-IH5R9SjkTkh0kfFOQDImyy1+mTCb+E830+9SV1O+AaDcoHTvfsvt6WwJeo7KwcHbFnevZVCsXhDmjFiGVuwqFQ== +postcss-svgo@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/postcss-svgo/-/postcss-svgo-7.0.1.tgz#2b63571d8e9568384df334bac9917baff4d23f58" + integrity sha512-0WBUlSL4lhD9rA5k1e5D8EN5wCEyZD6HJk0jIvRxl+FDVOMlJ7DePHYWGGVc5QRqrJ3/06FTXM0bxjmJpmTPSA== dependencies: postcss-value-parser "^4.2.0" - svgo "^3.2.0" + svgo "^3.3.2" -postcss-unique-selectors@^6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/postcss-unique-selectors/-/postcss-unique-selectors-6.0.2.tgz#09a34a5a31a649d3e9bca5962af0616f39d071d2" - integrity sha512-8IZGQ94nechdG7Y9Sh9FlIY2b4uS8/k8kdKRX040XHsS3B6d1HrJAkXrBSsSu4SuARruSsUjW3nlSw8BHkaAYQ== +postcss-unique-selectors@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/postcss-unique-selectors/-/postcss-unique-selectors-7.0.1.tgz#3e4e7c408ca5cd57e834d197e9c96111fc163237" + integrity sha512-MH7QE/eKUftTB5ta40xcHLl7hkZjgDFydpfTK+QWXeHxghVt3VoPqYL5/G+zYZPPIs+8GuqFXSTgxBSoB1RZtQ== dependencies: - postcss-selector-parser "^6.0.15" + postcss-selector-parser "^6.1.0" postcss-value-parser@^4.0.0, postcss-value-parser@^4.2.0: version "4.2.0" @@ -1153,13 +1206,13 @@ postcss-value-parser@^4.0.0, postcss-value-parser@^4.2.0: integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ== postcss@^8.4.23, postcss@^8.4.4, postcss@^8.4.5: - version "8.4.35" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.35.tgz#60997775689ce09011edf083a549cea44aabe2f7" - integrity sha512-u5U8qYpBCpN13BsiEB0CbR1Hhh4Gc0zLFuedrHJKMctHCHAGrMdG0PRM/KErzAL3CU6/eckEtmHNB3x6e3c0vA== + version "8.4.40" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.40.tgz#eb81f2a4dd7668ed869a6db25999e02e9ad909d8" + integrity sha512-YF2kKIUzAofPMpfH6hOi2cGnv/HrUlfucspc7pDyvv7kGdqXrfj8SCl/t8owkEgKEuu8ZcRjSOxFxVLqwChZ2Q== dependencies: nanoid "^3.3.7" - picocolors "^1.0.0" - source-map-js "^1.0.2" + picocolors "^1.0.1" + source-map-js "^1.2.0" pretty-hrtime@^1.0.3: version "1.0.3" @@ -1243,12 +1296,21 @@ slash@^5.0.0, slash@^5.1.0: resolved "https://registry.yarnpkg.com/slash/-/slash-5.1.0.tgz#be3adddcdf09ac38eebe8dcdc7b1a57a75b095ce" integrity sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg== -source-map-js@^1.0.1, source-map-js@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c" - integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw== +source-map-js@^1.0.1, source-map-js@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.2.0.tgz#16b809c162517b5b8c3e7dcd315a2a5c2612b2af" + integrity sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg== -"string-width-cjs@npm:string-width@^4.2.0", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: +"string-width-cjs@npm:string-width@^4.2.0": + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -1266,7 +1328,14 @@ string-width@^5.0.1, string-width@^5.1.2: emoji-regex "^9.2.2" strip-ansi "^7.0.1" -"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: +"strip-ansi-cjs@npm:strip-ansi@^6.0.1": + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -1280,13 +1349,13 @@ strip-ansi@^7.0.1: dependencies: ansi-regex "^6.0.1" -stylehacks@^6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/stylehacks/-/stylehacks-6.0.2.tgz#5bf2654561752547d4548765f35c9a49659b3742" - integrity sha512-00zvJGnCu64EpMjX8b5iCZ3us2Ptyw8+toEkb92VdmkEaRaSGBNKAoK6aWZckhXxmQP8zWiTaFaiMGIU8Ve8sg== +stylehacks@^7.0.2: + version "7.0.2" + resolved "https://registry.yarnpkg.com/stylehacks/-/stylehacks-7.0.2.tgz#cc0ec317e9d5b30fdbdfe7ed6b8d3b1a8c57fa06" + integrity sha512-HdkWZS9b4gbgYTdMg4gJLmm7biAUug1qTqXjS+u8X+/pUd+9Px1E+520GnOW3rST9MNsVOVpsJG+mPHNosxjOQ== dependencies: - browserslist "^4.22.2" - postcss-selector-parser "^6.0.15" + browserslist "^4.23.1" + postcss-selector-parser "^6.1.0" sucrase@^3.32.0: version "3.35.0" @@ -1306,10 +1375,10 @@ supports-preserve-symlinks-flag@^1.0.0: resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== -svgo@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/svgo/-/svgo-3.2.0.tgz#7a5dff2938d8c6096e00295c2390e8e652fa805d" - integrity sha512-4PP6CMW/V7l/GmKRKzsLR8xxjdHTV4IMvhTnpuHwwBazSIlw5W/5SmPjN8Dwyt7lKbSJrRDgp4t9ph0HgChFBQ== +svgo@^3.3.2: + version "3.3.2" + resolved "https://registry.yarnpkg.com/svgo/-/svgo-3.3.2.tgz#ad58002652dffbb5986fc9716afe52d869ecbda8" + integrity sha512-OoohrmuUlBs8B8o6MB2Aevn+pRIH9zDALSR+6hhqVfa6fRwG/Qw9VUMSMW9VNg2CFc/MTIfabtdOVl9ODIJjpw== dependencies: "@trysound/sax" "0.2.0" commander "^7.2.0" @@ -1320,9 +1389,9 @@ svgo@^3.2.0: picocolors "^1.0.0" tailwindcss@^3.0: - version "3.4.1" - resolved "https://registry.yarnpkg.com/tailwindcss/-/tailwindcss-3.4.1.tgz#f512ca5d1dd4c9503c7d3d28a968f1ad8f5c839d" - integrity sha512-qAYmXRfk3ENzuPBakNK0SRrUDipP8NQnEY6772uDhflcQz5EhRdD7JNZxyrFHVQNCwULPBn6FNPp9brpO7ctcA== + version "3.4.7" + resolved "https://registry.yarnpkg.com/tailwindcss/-/tailwindcss-3.4.7.tgz#6092f18767f5933f59375b9afe558e592fc77201" + integrity sha512-rxWZbe87YJb4OcSopb7up2Ba4U82BoiSGUdoDr3Ydrg9ckxFS/YWsvhN323GMcddgU65QRy7JndC7ahhInhvlQ== dependencies: "@alloc/quick-lru" "^5.2.0" arg "^5.0.2" @@ -1332,7 +1401,7 @@ tailwindcss@^3.0: fast-glob "^3.3.0" glob-parent "^6.0.2" is-glob "^4.0.3" - jiti "^1.19.1" + jiti "^1.21.0" lilconfig "^2.1.0" micromatch "^4.0.5" normalize-path "^3.0.0" @@ -1389,12 +1458,20 @@ universalify@^2.0.0: integrity sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw== update-browserslist-db@^1.0.13: - version "1.0.13" - resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz#3c5e4f5c083661bd38ef64b6328c26ed6c8248c4" - integrity sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg== + version "1.0.16" + resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.16.tgz#f6d489ed90fb2f07d67784eb3f53d7891f736356" + integrity sha512-KVbTxlBYlckhF5wgfyZXTWnMn7MMZjMu9XG8bPlliUOP9ThaF4QnhP8qrjrH7DRzHfSk0oQv1wToW+iA5GajEQ== dependencies: - escalade "^3.1.1" - picocolors "^1.0.0" + escalade "^3.1.2" + picocolors "^1.0.1" + +update-browserslist-db@^1.0.16: + version "1.1.0" + resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz#7ca61c0d8650766090728046e416a8cde682859e" + integrity sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ== + dependencies: + escalade "^3.1.2" + picocolors "^1.0.1" util-deprecate@^1.0.2: version "1.0.2" @@ -1408,7 +1485,16 @@ which@^2.0.1: dependencies: isexe "^2.0.0" -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +wrap-ansi@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== @@ -1437,9 +1523,9 @@ y18n@^5.0.5: integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== yaml@^2.3.4: - version "2.3.4" - resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.3.4.tgz#53fc1d514be80aabf386dc6001eb29bf3b7523b2" - integrity sha512-8aAvwVUSHpfEqTQ4w/KMlf3HcRdt50E5ODIQJBw1fQ5RL34xabzxtUlzTXVqc4rkZsPbvrXKWnABCD7kWSmocA== + version "2.5.0" + resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.5.0.tgz#c6165a721cf8000e91c36490a41d7be25176cf5d" + integrity sha512-2wWLbGbYDiSqqIKoPjar3MPgB94ErzCtrNE1FdqGuaO0pi2JGjmE8aW8TDZwzU7vuxcGRdL/4gPQwQ7hD5AMSw== yargs-parser@^21.1.1: version "21.1.1"